mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-08-24 20:58:05 +00:00
* fix(trading): price tp/sl exits off the trigger price and retry a reverted sell `_monitor_position_until_exit` handed `position.entry_price` to the sell while the `current_price` that had just triggered the exit sat in the same scope, one line up. `PlatformAwareSeller.execute` does not read a price - the `token_price` it receives *is* the slippage floor - so a stop-loss priced off the entry demands more quote asset than the curve can pay and reverts with 6003 `TooLittleSolReceived`, during the very drop the stop-loss exists to escape. On a take-profit the same mistake runs the other way and the floor protects nothing. `current_price` costs no extra RPC call; `_handle_time_based_exit` has nothing fresher and keeps passing the buy price. The `break` also sat outside both branches of `if sell_result.success:`, so the loop exited whether the sell landed or not - contradicting the "Keep monitoring in case sell can be retried" comment directly above it. The seller's `max_retries` covers transaction submission only, so an on-chain revert was never retried and the position was abandoned mid-crash with `is_active=True`. A failed exit sell now retries on the next price check, re-reading the price so the floor tracks the market, bounded by `trade.max_exit_sell_attempts` (default 3, validated to 1..100) so a permanently reverting token cannot pin the bot on one position. The counter resets if the price recovers out of the exit band, and giving up is logged loudly since the tokens are still held. Fixes #189 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(learning-examples): machine-check the tp/sl exit price and retry path Drives the real `_monitor_position_until_exit` with a stub curve manager serving a scripted price series and a stub seller that records the price it is handed. Offline, no network and no funds moved, per the `verify_*` convention. Eight checks: both exit kinds sell at the triggering price, the entry-price floor is arithmetically unpayable on a drop while the trigger-price floor is payable, a reverted sell is retried and a landing retry closes the position, retries stay bounded, a price recovery resets the counter, a successful sell still closes on the first attempt, and the cap comes from `trade.max_exit_sell_attempts` wired through bot_runner and config_loader. Mutation-tested rather than trusted on a green run - reintroducing the stale entry price drops it to 4/8, giving up after one failure to 4/8, and ignoring the config knob to 7/8. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: document the tp/sl exit path and its verifier The caller owns the sell's slippage floor, which is not obvious from `PlatformAwareSeller.execute` - it never reads a price, it just turns `token_price` into `min_quote_output`. Records that, why an exit must price off the triggering price, and that the seller's `max_retries` covers submission only so an on-chain revert has to be retried in the monitor loop. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
121 lines
5.9 KiB
YAML
121 lines
5.9 KiB
YAML
# This file defines comprehensive parameters and settings for the trading bot.
|
|
# Carefully review and adjust values to match your trading strategy and risk tolerance.
|
|
|
|
# Bot identification and connection settings
|
|
name: "bot-sniper-2"
|
|
env_file: ".env"
|
|
rpc_endpoint: "${SOLANA_NODE_RPC_ENDPOINT}"
|
|
wss_endpoint: "${SOLANA_NODE_WSS_ENDPOINT}"
|
|
private_key: "${SOLANA_PRIVATE_KEY}"
|
|
|
|
enabled: false # You can turn off the bot w/o removing its config
|
|
separate_process: true
|
|
|
|
# Options: "pump_fun" (default), "lets_bonk"
|
|
platform: "pump_fun"
|
|
|
|
# Geyser configuration (fastest method for getting updates)
|
|
geyser:
|
|
endpoint: "${GEYSER_ENDPOINT}"
|
|
api_token: "${GEYSER_API_TOKEN}"
|
|
auth_type: "basic" # or "x-token"
|
|
|
|
# Trading parameters
|
|
# Control trade execution: amount of SOL per trade and acceptable price deviation
|
|
trade:
|
|
buy_amount: 0.0001 # Amount of SOL to spend when buying (in SOL)
|
|
buy_slippage: 0.3 # Maximum acceptable price deviation (0.3 = 30%)
|
|
sell_slippage: 0.3
|
|
|
|
# Exit strategy configuration
|
|
exit_strategy: "time_based" # Options: "time_based", "tp_sl", "manual"
|
|
take_profit_percentage: 0.4 # Take profit at 40% gain (0.4 = 40%)
|
|
stop_loss_percentage: 0.4 # Stop loss at 40% loss (0.4 = 40%)
|
|
max_hold_time: 15 # Maximum hold time in seconds for TP/SL strategy, for time_based - see wait_after_buy
|
|
price_check_interval: 2 # Check price every 2 seconds
|
|
# A tp/sl exit sell that reverts on-chain (slippage, curve moved under it) is
|
|
# retried on the next price check, re-reading the price first so the slippage
|
|
# floor matches the market. After this many attempts the bot gives up and
|
|
# leaves the position open - tokens are still held.
|
|
max_exit_sell_attempts: 3
|
|
|
|
# EXTREME FAST mode configuration
|
|
# When enabled, skips waiting for the bonding curve to stabilize and RPC price check.
|
|
# The bot buys the specified number of tokens directly, making the process faster but less precise.
|
|
# For geyser/logs/blocks listeners the buy is built entirely from the on-chain
|
|
# CreateEvent — ZERO RPC calls between detection and submission (see
|
|
# trust_create_event below). pumpportal payloads lack the needed fields, so
|
|
# that listener does one batched read first (see curve_refresh_budget).
|
|
extreme_fast_mode: true
|
|
extreme_fast_token_amount: 20 # Amount of tokens to buy
|
|
|
|
# Pre-buy curve refresh (issue #170). The buyer re-reads the bonding curve /
|
|
# pool at `processed` before building the buy so fee_recipient, creator_vault,
|
|
# quote_mint and the token program are current. If the account is not readable
|
|
# within this budget (seconds), the token is SKIPPED instead of submitting a
|
|
# buy built from listener-guessed defaults, which tends to revert on-chain.
|
|
curve_refresh_budget: 2.0
|
|
|
|
# When the create event carried the canonical creator, mayhem/cashback flags
|
|
# and quote_mint (geyser/logs/blocks listeners), skip the pre-buy read
|
|
# entirely: extreme_fast_mode then submits with ZERO RPC calls after
|
|
# detection. pumpportal events never carry these, so they always refresh.
|
|
# Set false to force the refresh for every listener.
|
|
trust_create_event: true
|
|
|
|
# Priority fee configuration
|
|
# Manage transaction speed and cost on the Solana network.
|
|
# Note: dynamic mode requires an additional RPC call, which slows down the buying process.
|
|
priority_fees:
|
|
enable_dynamic: false # Use latest transactions to estimate required fee (getRecentPrioritizationFees)
|
|
enable_fixed: true # Use fixed amount below
|
|
fixed_amount: 200_000 # Base fee in microlamports
|
|
extra_percentage: 0.0 # Percentage increase on riority fee regardless of the calculation method (0.1 = 10%)
|
|
hard_cap: 200_000 # Maximum allowable fee in microlamports to prevent excessive spending
|
|
|
|
# Compute unit limits for transaction processing
|
|
# Operation-specific defaults are used if not specified: buy=100K, sell=60K
|
|
compute_units:
|
|
# Override default CU limits for this platform
|
|
# buy: 100_000 # Buy operations (ATA creation + trading)
|
|
# sell: 60_000 # Sell operations (just trading)
|
|
|
|
# Account data size optimization (reduces CU cost and improves tx priority)
|
|
# Reduces CU cost from 16k to ~128 CU by limiting loaded account data.
|
|
# Default is 64MB (16k CU). Setting to 512KB significantly reduces overhead.
|
|
# Note: Savings don't show in "consumed CU" but improve tx priority/cost.
|
|
# Note (Nov 23, 2025): with data size set to 512KB, transactions fail - increasing to 12.5MB resolves the issue.
|
|
# Reference: https://www.anza.xyz/blog/cu-optimization-with-setloadedaccountsdatasizelimit
|
|
# account_data_size: 12_500_000 # Disabled: causes MaxLoadedAccountsDataSizeExceeded with Token-2022
|
|
|
|
# Filters for token selection
|
|
filters:
|
|
match_string: null # Only process tokens with this string in name/symbol
|
|
bro_address: null # Only trade tokens created by this user address
|
|
listener_type: "logs" # Method for detecting new tokens: "logs", "blocks", or "geyser"
|
|
max_token_age: 0.001 # Maximum token age in seconds for processing
|
|
marry_mode: false # Only buy tokens, skip selling
|
|
yolo_mode: false # Continuously trade tokens
|
|
|
|
# Retry and timeout settings
|
|
retries:
|
|
max_attempts: 1 # Number of attempts for transaction submission
|
|
wait_after_creation: 15 # Seconds to wait after token creation (only if EXTREME FAST is disabled)
|
|
wait_after_buy: 15 # Holding period after buy transaction
|
|
wait_before_new_token: 15 # Pause between token trades
|
|
|
|
# Token and account management
|
|
cleanup:
|
|
# Cleanup mode determines when to manage token accounts. Options:
|
|
# "disabled": no cleanup will occur.
|
|
# "on_fail": only clean up if a buy transaction fails.
|
|
# "after_sell": clean up after selling.
|
|
# "post_session": clean up all empty accounts after a trading session ends.
|
|
mode: "post_session"
|
|
force_close_with_burn: false # Force burning remaining tokens before closing account
|
|
with_priority_fee: false # Use priority fees for cleanup transactions
|
|
|
|
# Node provider configuration
|
|
node:
|
|
max_rps: 25 # Maximum requests per second
|