-
Notifications
You must be signed in to change notification settings - Fork 309
Reduce RPC delays when selling #150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ameters to reduce RPC delays
WalkthroughThe PR updates four bot configuration files with trading parameter tuning and compute unit memory adjustments, adds transaction-aware methods to the client for balance and transaction detail retrieval, and refactors the buyer and seller classes to accept precomputed token amounts and prices, eliminating redundant RPC calls during trade execution. Changes
Sequence Diagram(s)sequenceDiagram
participant Trader as Universal Trader
participant Buyer as PlatformAwareBuyer
participant Client as Client
participant RPC as RPC Node
participant Seller as PlatformAwareSeller
Trader->>Buyer: execute(token_info)
activate Buyer
Note over Buyer: Build & send buy tx
Buyer->>RPC: Send transaction
RPC-->>Buyer: signature
Buyer->>Client: get_buy_transaction_details(signature, mint, sol_dest)
activate Client
Client->>RPC: Fetch transaction result
RPC-->>Client: parsed tx data
Note over Client: Compute tokens & SOL from<br/>pre/post balances
Client-->>Buyer: (tokens_received, sol_spent)
deactivate Client
Note over Buyer: Verify actual vs expected,<br/>override amounts if needed
Buyer-->>Trader: TradeResult(amount, price)
deactivate Buyer
Trader->>Seller: execute(token_info, token_amount, token_price)
activate Seller
Note over Seller: Use precomputed values<br/>Skip RPC balance/price fetch
Note over Seller: Build sell instructions<br/>with provided amounts
Seller->>RPC: Send sell transaction
RPC-->>Seller: signature
Seller-->>Trader: TradeResult
deactivate Seller
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…tion to improve accuracy
|
Thanks again, planning on testing it soon. Do you say it should work fine with Chainstack growth RPC, using pumpportal? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (4)
bots/bot-sniper-3-blocks.yaml (1)
64-66: Account data size increase is consistent with CU optimization strategyBumping
account_data_sizeto12_500_000and documenting the 512KB failure scenario makes sense and matches the other sniper configs. Just keep this value synchronized across all bots to avoid hard-to-track behavior differences.If you keep tuning this further, consider centralizing the “recommended” size in shared documentation so all YAMLs stay in lockstep.
bots/bot-sniper-1-geyser.yaml (1)
64-66: CU account_data_size increase matches other bots and is well-documentedThe
12_500_000value and Nov 23 note mirror the other sniper configs and clearly record the observed failure with 512KB. This consistency across bots should make future tuning and debugging easier.If you see different behavior per RPC provider, you might want a short note in docs describing provider-specific caveats rather than repeating long comments in each YAML.
src/core/client.py (1)
390-419: Centralized getTransaction wrapper is fine; consider reusing HTTP session
_get_transaction_resultencapsulates the rawgetTransactionRPC withjsonParsedencoding and “confirmed” commitment, and its early returns on missingresult/metakeep downstream callers simple.One performance nit:
post_rpcstill creates a freshaiohttp.ClientSessionper call. Long‑running bots that call_get_transaction_resultfrequently would benefit from a shared session (or usingAsyncClient.get_transaction) to reuse connections and reduce overhead.As per coding guidelines about HTTP connection pooling.
src/trading/platform_aware.py (1)
270-297: Seller now relies on pre-known amount/price—API and math look consistentThe updated
PlatformAwareSeller.execute:
- Validates
token_amountandtoken_priceupfront, with clear error messages.- Uses those to compute
token_balanceandexpected_sol_output, and then derivesmin_sol_outputwith slippage protection in lamports.- Logs the key quantities and builds the sell instruction with
token_balanceandmin_sol_output.This matches how
UniversalTraderand the buyer now passamount/price, and it removes duplicated RPC calls for balance and price. The only caveat is the Ruff TRY003/TRY301 hints: the longerValueErrormessages may need to be shortened or moved into helper functions/constants to satisfy your exception-handling lint rules.To keep Ruff happy, you can extract the detailed error messages into small helper functions or constants and raise shorter
ValueErrors here, or centralize validation oftoken_amount/token_pricein a shared helper.Also applies to: 307-314, 323-336
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
bots/bot-sniper-1-geyser.yaml(4 hunks)bots/bot-sniper-2-logs.yaml(2 hunks)bots/bot-sniper-3-blocks.yaml(3 hunks)bots/bot-sniper-4-pp.yaml(2 hunks)src/core/client.py(1 hunks)src/trading/platform_aware.py(4 hunks)src/trading/universal_trader.py(5 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
bots/**/*.{yaml,yml}
📄 CodeRabbit inference engine (CLAUDE.md)
bots/**/*.{yaml,yml}: Keep bot configurations in YAML files under bots/
Detect target platform from bot configuration files
Do not include sensitive data in bot configuration files
bots/**/*.{yaml,yml}: Edit bot instance configuration in YAML files under bots/
Start with conservative YAML settings (low buy_amount, high min_sol_balance, strict filters)
Files:
bots/bot-sniper-1-geyser.yamlbots/bot-sniper-4-pp.yamlbots/bot-sniper-2-logs.yamlbots/bot-sniper-3-blocks.yaml
bots/**/*.{yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
bots/**/*.{yml,yaml}: Store bot configurations as YAML files in bots/
Support ${VARIABLE} environment interpolation in bot YAML configs
Validate bot configurations before starting bots
Files:
bots/bot-sniper-1-geyser.yamlbots/bot-sniper-4-pp.yamlbots/bot-sniper-2-logs.yamlbots/bot-sniper-3-blocks.yaml
**/*.{yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/trading-bot.mdc)
**/*.{yaml,yml}: Maintain a consistent YAML structure for all bot configuration files, including keys: name, platform, enabled, separate_process, env_file, rpc_endpoint, wss_endpoint, private_key, geyser.{endpoint,api_token,auth_type}, and trade.{buy_amount,buy_slippage,sell_slippage,exit_strategy,extreme_fast_mode}
Use ${VARIABLE_NAME} syntax for environment variable interpolation in YAML configs
Never hardcode sensitive values (e.g., private keys, API tokens) in YAML configuration files
Validate YAML syntax and required configuration fields
Test environment variable interpolation in configuration filesValidate YAML configuration syntax and required fields before running
Files:
bots/bot-sniper-1-geyser.yamlbots/bot-sniper-4-pp.yamlbots/bot-sniper-2-logs.yamlbots/bot-sniper-3-blocks.yaml
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Enforce max line length of 88 characters in Python (Ruff config)
Use 4 spaces for indentation in Python files
Target Python version 3.11+ features and syntax
Prefer double quotes for strings in Python code
Enable and honor import sorting in Python modules
Apply Ruff rule sets: Security (S), Annotations (ANN), Exceptions (BLE, TRY), Complexity (C90), Pylint conventions (PL), and no commented-out code (ERA)
Order imports as: standard library, third-party, then local imports
Use Google-style docstrings for functions and classes
Provide type hints for all public functions
Use a module-level logger via get_logger(name)
Wrap risky operations in try/except with proper logging
Implement rate limiting and retry mechanisms where external calls are made
Perform comprehensive input validation for externally sourced data
**/*.py: Limit lines to 88 characters
Use 4 spaces for indentation (never tabs)
Use double quotes for strings consistently
Target Python 3.11+ features and syntax
Enable automatic import sorting and organization
Order imports: standard library first, third-party second, local last
Add type hints to all public functions and methods
Use modern typing syntax (e.g., X | Y unions)
Include explicit return type annotations
Use typing.Any for complex/unknown types (from typing import Any)
Use Google-style docstrings for all functions and classes
Wrap external operations (RPC calls, file I/O) in try/except blocks
Log exceptions with context using logging.exception()
Provide meaningful error messages when handling exceptions
Do not suppress exceptions without good reason
Use get_logger(name) with logger from utils.logger
Use appropriate log levels (DEBUG, INFO, WARNING, ERROR) with contextual messages
Never hardcode secrets (private keys, API tokens)
Use environment variables for sensitive configuration
Do not log sensitive information
Validate all external inputs
Comply with Ruff security rules (S)
Comply with Ruff type annotation rules (ANN)
Comply...
Files:
src/trading/universal_trader.pysrc/core/client.pysrc/trading/platform_aware.py
src/{client,trading,monitoring,platforms}/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Separate concerns into client, trading, monitoring, and platforms packages under src/
Files:
src/trading/universal_trader.pysrc/trading/platform_aware.py
src/**/*.py
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
src/**/*.py: Use snake_case for all Python file names
Avoid circular imports between packages
Use asyncio.create_task() for concurrent operations
Implement proper cleanup on shutdown for async tasks/resources
Files:
src/trading/universal_trader.pysrc/core/client.pysrc/trading/platform_aware.py
src/trading/universal_*.py
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
Use the 'Universal' prefix for platform-agnostic trading components (e.g., UniversalTrader)
Files:
src/trading/universal_trader.py
src/trading/**/*.py
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
trading/ may depend on core/, platforms/, and interfaces/
Files:
src/trading/universal_trader.pysrc/trading/platform_aware.py
src/trading/universal_trader.py
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
UniversalTrader should delegate to platform-specific traders via a factory method
Files:
src/trading/universal_trader.py
src/core/**/*.py
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
src/core/**/*.py: Core modules must not import from trading or monitoring
core/ may depend only on utils/ and interfaces/
Limit concurrent operations based on RPC provider limits
Files:
src/core/client.py
src/core/client.py
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
src/core/client.py: Use connection pooling for HTTP clients and backoff for failed requests
Cache recent blockhash and relevant account information where appropriate
Files:
src/core/client.py
🧠 Learnings (11)
📚 Learning: 2025-10-04T12:42:50.785Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-04T12:42:50.785Z
Learning: Applies to bots/**/*.{yaml,yml} : Start with conservative YAML settings (low buy_amount, high min_sol_balance, strict filters)
Applied to files:
bots/bot-sniper-1-geyser.yamlbots/bot-sniper-4-pp.yamlbots/bot-sniper-2-logs.yamlbots/bot-sniper-3-blocks.yaml
📚 Learning: 2025-08-21T12:08:15.475Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/trading-bot.mdc:0-0
Timestamp: 2025-08-21T12:08:15.475Z
Learning: Applies to **/*.{yaml,yml} : Maintain a consistent YAML structure for all bot configuration files, including keys: name, platform, enabled, separate_process, env_file, rpc_endpoint, wss_endpoint, private_key, geyser.{endpoint,api_token,auth_type}, and trade.{buy_amount,buy_slippage,sell_slippage,exit_strategy,extreme_fast_mode}
Applied to files:
bots/bot-sniper-1-geyser.yamlbots/bot-sniper-2-logs.yaml
📚 Learning: 2025-10-04T12:42:50.785Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-04T12:42:50.785Z
Learning: Run the main bot with `pump_bot` only after safe testing
Applied to files:
bots/bot-sniper-1-geyser.yamlbots/bot-sniper-3-blocks.yaml
📚 Learning: 2025-08-21T12:08:15.475Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/trading-bot.mdc:0-0
Timestamp: 2025-08-21T12:08:15.475Z
Learning: Applies to **/*.py : Provide a YOLO Mode with continuous trading and no cooldowns
Applied to files:
bots/bot-sniper-1-geyser.yamlbots/bot-sniper-4-pp.yamlbots/bot-sniper-2-logs.yamlbots/bot-sniper-3-blocks.yaml
📚 Learning: 2025-08-21T12:06:38.903Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-08-21T12:06:38.903Z
Learning: Applies to src/trading/universal_*.py : Use the 'Universal' prefix for platform-agnostic trading components (e.g., UniversalTrader)
Applied to files:
src/trading/universal_trader.py
📚 Learning: 2025-08-21T12:06:38.903Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-08-21T12:06:38.903Z
Learning: Applies to src/trading/universal_trader.py : UniversalTrader should delegate to platform-specific traders via a factory method
Applied to files:
src/trading/universal_trader.py
📚 Learning: 2025-08-21T12:08:15.475Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/trading-bot.mdc:0-0
Timestamp: 2025-08-21T12:08:15.475Z
Learning: Applies to **/*.py : Support multiple exit strategies: time_based, tp_sl, and manual
Applied to files:
src/trading/universal_trader.py
📚 Learning: 2025-08-21T12:08:15.475Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/trading-bot.mdc:0-0
Timestamp: 2025-08-21T12:08:15.475Z
Learning: Applies to **/*.py : Implement wallet balance checks before trading
Applied to files:
src/core/client.pysrc/trading/platform_aware.py
📚 Learning: 2025-10-04T12:42:50.785Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-04T12:42:50.785Z
Learning: Applies to learning-examples/manual_{buy,sell}.py : Test changes using manual_buy.py and manual_sell.py with minimal amounts before production use
Applied to files:
bots/bot-sniper-2-logs.yamlsrc/trading/platform_aware.py
📚 Learning: 2025-08-21T12:08:15.475Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/trading-bot.mdc:0-0
Timestamp: 2025-08-21T12:08:15.475Z
Learning: Applies to **/*.py : Apply slippage protection on all trades
Applied to files:
bots/bot-sniper-2-logs.yaml
📚 Learning: 2025-08-21T12:06:38.903Z
Learnt from: CR
Repo: chainstacklabs/pumpfun-bonkfun-bot PR: 0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-08-21T12:06:38.903Z
Learning: Applies to src/trading/**/*.py : trading/ may depend on core/, platforms/, and interfaces/
Applied to files:
src/trading/platform_aware.py
🧬 Code graph analysis (2)
src/trading/universal_trader.py (2)
src/trading/base.py (2)
TradeResult(20-43)execute(50-59)src/trading/platform_aware.py (2)
execute(46-180)execute(270-391)
src/trading/platform_aware.py (5)
src/core/client.py (1)
get_buy_transaction_details(306-388)src/interfaces/core.py (8)
TokenInfo(25-53)AddressProvider(56-118)platform(61-63)platform(126-128)platform(238-240)platform(314-316)Platform(17-21)derive_pool_address(81-93)src/platforms/letsbonk/address_provider.py (3)
platform(49-51)derive_pool_address(78-98)derive_quote_vault(125-148)src/platforms/pumpfun/address_provider.py (2)
platform(97-99)derive_pool_address(129-146)src/trading/base.py (2)
execute(50-59)TradeResult(20-43)
🪛 Ruff (0.14.5)
src/trading/platform_aware.py
157-160: Abstract raise to an inner function
(TRY301)
157-160: Avoid specifying long messages outside the exception class
(TRY003)
289-292: Avoid specifying long messages outside the exception class
(TRY003)
294-297: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (11)
bots/bot-sniper-3-blocks.yaml (1)
11-11: Conservative default (bot disabled) looks goodKeeping
enabled: falseby default is aligned with the repo guidance to start conservatively and avoid accidental live trading; users can explicitly flip this on once tested.Based on learnings, this matches the “start with conservative YAML settings” preference.
bots/bot-sniper-1-geyser.yaml (1)
34-35: Time-based hold and wait timings are internally consistentWith
exit_strategy: "time_based", the effective hold duration is governed bywait_after_buy, and you’ve aligned that to 5 seconds along withmax_hold_time: 5(used by TP/SL mode). The comments correctly point towait_after_buyfor time-based exits, so the configuration is coherent.Also applies to: 81-81
bots/bot-sniper-2-logs.yaml (1)
27-27: Trading and CU tuning aligned with other sniper configsIncreasing
buy_slippageto0.3, tighteningmax_hold_timeto 15s, and bumpingaccount_data_sizeto12_500_000brings this logs-based sniper in line with the rest of the suite. The TP/SL and time-based comments are consistent with the runtime behavior (TP/SL usesmax_hold_time, time-based useswait_after_buy).Also applies to: 34-35, 64-66
bots/bot-sniper-4-pp.yaml (2)
32-32: Shorter max_hold_time brings PumpPortal bot in line with othersReducing
max_hold_timeto 15s matches the other sniper configs and keeps TP/SL exits from lingering too long. For purely time-based exits,wait_after_buyremains the main control, so this is a safe tightening.
62-64: CU data-size change is RPC‑agnostic and should be fine with Growth + PumpPortalThe
account_data_size: 12_500_000setting and accompanying note are consistent with the other bots. This limit is enforced by the on-chainsetLoadedAccountsDataSizeLimitinstruction and doesn’t depend on a particular RPC provider, so it should work with a Chainstack Growth RPC endpoint as long as the node supports that compute budget feature. Still worth a quick end-to-end test with Growth + PumpPortal to confirm behavior.src/core/client.py (2)
274-305: Token balance helper correctly uses postTokenBalances
get_transaction_token_balancecleanly filterspostTokenBalancesbyownerandmintand returns the rawamountas anint, with safe handling for missing fields and absent meta. This is a reasonable, low-level primitive for callers that already know the mint and owner.
306-389: Buy details parsing logic is sound; handles Token2022 and bad meta defensivelyThe
get_buy_transaction_detailsimplementation correctly:
- Diffs
preTokenBalances/postTokenBalancesbyaccountIndexto derive a positive token delta for the target mint (works even when the owner is not the wallet, e.g., Token2022).- Looks up the SOL destination by matching
accountKeysagainstsol_destinationand usespostBalances[i] - preBalances[i]to get lamports sent, with sane logging when the delta is non‑positive.Returning
(None, None)on missing or malformed meta is a good defensive default; callers already treat this as an error condition.src/trading/universal_trader.py (3)
196-198: Formatting change for traded_token_programs is fineSplitting
traded_token_programsover multiple lines improves readability and keeps you within the 88‑character limit without changing behavior.
334-335: Cleanup token_program_ids derivation remains correct after formattingThe construction of
token_program_idsfromself.traded_token_programsis unchanged semantically and properly aligned with the new dict layout; cleanup behavior is preserved.
469-470: Time-based exit now correctly reuses buy_result for sell—matches new seller APIPassing
buy_resultinto_handle_time_based_exitand then intoself.seller.executeastoken_amountandtoken_priceis exactly what the newPlatformAwareSeller.executesignature expects. This avoids extra RPC reads for balance/price during simple time-based exits.You may want a small guard to log if
buy_result.amountorbuy_result.priceis unexpectedlyNone, but the current flow fromPlatformAwareBuyershould always populate them on success.Also applies to: 516-533
src/trading/platform_aware.py (1)
197-231: SOL destination helper correctly encodes pump.fun vs letsbonk semantics
_get_sol_destination’s platform-specific behavior looks right:
- For
Platform.PUMP_FUN, you usebonding_curvewhen present and otherwise derive it viaderive_pool_address.- For
Platform.LETS_BONK, you prefer the pre-fetchedquote_vaultand fall back toderive_quote_vault(token_info.mint), which matches the LetsBonk address provider’s API.The explicit
NotImplementedErrorfor new platforms is good defensive design; it forces you to decide where SOL actually lands before enabling trading.
| # Fetch actual tokens and SOL spent from transaction | ||
| # Uses preBalances/postBalances to get exact amounts | ||
| sol_destination = self._get_sol_destination( | ||
| token_info, address_provider | ||
| ) | ||
| tokens_raw, sol_spent = await self.client.get_buy_transaction_details( | ||
| str(tx_signature), token_info.mint, sol_destination | ||
| ) | ||
|
|
||
| if tokens_raw is not None and sol_spent is not None: | ||
| actual_amount = tokens_raw / 10**TOKEN_DECIMALS | ||
| actual_price = (sol_spent / LAMPORTS_PER_SOL) / actual_amount | ||
| logger.info( | ||
| f"Actual tokens received: {actual_amount:.6f} " | ||
| f"(expected: {token_amount:.6f})" | ||
| ) | ||
| logger.info( | ||
| f"Actual SOL spent: {sol_spent / LAMPORTS_PER_SOL:.10f} SOL" | ||
| ) | ||
| logger.info(f"Actual price: {actual_price:.10f} SOL/token") | ||
| token_amount = actual_amount | ||
| token_price_sol = actual_price | ||
| else: | ||
| raise ValueError( | ||
| f"Failed to parse transaction details: tokens={tokens_raw}, " | ||
| f"sol_spent={sol_spent}" | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parsing actual buy amounts via tx meta is correct but currently hard-fails on RPC issues
The new block that calls _get_sol_destination and get_buy_transaction_details is a solid improvement: it derives exact tokens_raw and sol_spent from pre/postTokenBalances and pre/postBalances, logs actual vs expected, and propagates the adjusted token_amount/token_price_sol into the TradeResult.
Right now, if tokens_raw or sol_spent is None (e.g., transient getTransaction issues), you raise a ValueError, which turns an otherwise confirmed buy into a logical failure. That’s strict but could be painful if some RPC providers occasionally omit recent transaction history.
Consider a softer fallback: log a warning and proceed with the originally computed token_amount/token_price_sol when parsing fails, instead of raising, so successful on-chain buys don’t get marked as failures solely due to a metadata fetch glitch.
🧰 Tools
🪛 Ruff (0.14.5)
157-160: Abstract raise to an inner function
(TRY301)
157-160: Avoid specifying long messages outside the exception class
(TRY003)
🤖 Prompt for AI Agents
In src/trading/platform_aware.py around lines 134 to 160, the code currently
raises ValueError when tokens_raw or sol_spent is None, causing confirmed buys
to be treated as failures on transient RPC issues; change this to a soft
fallback: if tokens_raw or sol_spent is None (or if calling
_get_sol_destination/get_buy_transaction_details raises), log a warning that
includes the tx_signature and the None/exception details, do not raise, and
continue using the precomputed token_amount and token_price_sol (i.e., leave
existing values untouched); when tokens_raw and sol_spent are present keep the
current logic that computes actual_amount/actual_price and overrides
token_amount/token_price_sol and logs the info.
| # Execute sell with position quantity and entry price to avoid RPC delays | ||
| sell_result = await self.seller.execute( | ||
| token_info, | ||
| token_amount=position.quantity, | ||
| token_price=position.entry_price, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use current market price for TP/SL exit sells instead of entry price
In _monitor_position_until_exit, you compute current_price each cycle to decide whether to exit, but the sell call uses position.entry_price:
sell_result = await self.seller.execute(
token_info,
token_amount=position.quantity,
token_price=position.entry_price,
)For stop‑loss or take‑profit exits, this can set min_sol_output based on a stale, higher entry price; on a loss this is very likely to exceed actual achievable SOL and cause the sell transaction to fail, leaving the position open despite the exit condition being met.
Apply this diff so the sell uses the same current_price you just fetched, avoiding extra RPC and aligning slippage with real market conditions:
- # Execute sell with position quantity and entry price to avoid RPC delays
- sell_result = await self.seller.execute(
- token_info,
- token_amount=position.quantity,
- token_price=position.entry_price,
- )
+ # Execute sell with position quantity and current price (already fetched)
+ sell_result = await self.seller.execute(
+ token_info,
+ token_amount=position.quantity,
+ token_price=current_price,
+ )🤖 Prompt for AI Agents
In src/trading/universal_trader.py around lines 589 to 594, the sell call uses
position.entry_price which can be stale and cause min_sol_output to be too high
for TP/SL exits; change the call to pass the already-fetched current_price (the
price used to decide the exit) as token_price so slippage/min output aligns with
market, i.e., use current_price instead of position.entry_price when calling
self.seller.execute.
Summary by CodeRabbit
New Features
Bug Fixes
Chores
✏️ Tip: You can customize this high-level summary in your review settings.