-
Notifications
You must be signed in to change notification settings - Fork 310
Fix/update letsbonk fun instructions in the bot #142
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
… update account handling in buy/sell instructions
…d update address provider logic
WalkthroughAdded platform-specific configuration support to LetsBonk integration by introducing global_config and platform_config fields to TokenInfo, implementing PDA derivation helpers for fee vaults, enriching pool state decoding, supporting multiple initialize instruction variants, and updating instruction account metadata and compute limits. Changes
Sequence DiagramsequenceDiagram
participant Token Creation Event
participant Event Parser
participant Address Provider
participant Instruction Builder
Token Creation Event->>Event Parser: parse_token_creation_from_instruction()
activate Event Parser
Note over Event Parser: Check against 3 initialize variants<br/>(initialize, initialize_v2, initialize_with_token_2022)
Event Parser->>Event Parser: Extract accounts indices 0-3<br/>(including global_config, platform_config)
Event Parser->>Event Parser: Construct TokenInfo with config refs
deactivate Event Parser
Event Parser-->>Address Provider: TokenInfo with global_config, platform_config
activate Address Provider
Note over Address Provider: get_buy/sell_instruction_accounts()
Address Provider->>Address Provider: Use config from TokenInfo<br/>or fallback to constants
Address Provider->>Address Provider: derive_platform_fee_vault(platform_config)
Address Provider->>Address Provider: derive_creator_fee_vault(creator, quote_mint)
deactivate Address Provider
Address Provider-->>Instruction Builder: Accounts dict with fee vaults
activate Instruction Builder
Note over Instruction Builder: Build instruction with updated<br/>payer metadata + fee accounts +<br/>150k compute units
deactivate Instruction Builder
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested labels
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 |
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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/platforms/letsbonk/event_parser.py (1)
205-218: Remove overly strict geyser prefilter tied to a single platform_config.Pools may use different
platform_configPDAs. Filtering by the default fromget_system_addresses()will drop valid initializes. Rely on program id + discriminator checks instead.Apply:
- # Check if it's the LetsBonk platform config account - has_platform_config = False - for acc_idx in ix.accounts: - if acc_idx < len(msg.account_keys): - acc_key = msg.account_keys[acc_idx] - if bytes(acc_key) == bytes( - self.address_provider.get_system_addresses()[ - "platform_config" - ] - ): - has_platform_config = True - break - - if not has_platform_config: - continue + # Do not prefilter by a single platform_config; variants exist per pool.
🧹 Nitpick comments (1)
src/platforms/letsbonk/curve_manager.py (1)
189-191: Normalize types for newly exposed fields (creator/base_vault/quote_vault).Ensure these are consistently typed (Pubkey or base58 string) to avoid downstream surprises. Consider decoding to
Pubkeyhere (and convert to string at the edges), and document the expected types in the docstring.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/interfaces/core.py(1 hunks)src/platforms/letsbonk/address_provider.py(6 hunks)src/platforms/letsbonk/curve_manager.py(1 hunks)src/platforms/letsbonk/event_parser.py(8 hunks)src/platforms/letsbonk/instruction_builder.py(6 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.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/platforms/letsbonk/curve_manager.pysrc/platforms/letsbonk/address_provider.pysrc/platforms/letsbonk/event_parser.pysrc/interfaces/core.pysrc/platforms/letsbonk/instruction_builder.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/platforms/letsbonk/curve_manager.pysrc/platforms/letsbonk/address_provider.pysrc/platforms/letsbonk/event_parser.pysrc/platforms/letsbonk/instruction_builder.py
src/platforms/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Implement platform-specific logic under src/platforms/
src/platforms/**/*.py: Platform-specific modules may only import from their own package and core/interfaces
platforms/ may depend on core/ and interfaces/ only
Implement platform-specific functionality via factory pattern using interfacesUpdate platform-specific implementations under src/platforms/ when adding features
Files:
src/platforms/letsbonk/curve_manager.pysrc/platforms/letsbonk/address_provider.pysrc/platforms/letsbonk/event_parser.pysrc/platforms/letsbonk/instruction_builder.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/platforms/letsbonk/curve_manager.pysrc/platforms/letsbonk/address_provider.pysrc/platforms/letsbonk/event_parser.pysrc/interfaces/core.pysrc/platforms/letsbonk/instruction_builder.py
src/interfaces/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Place abstract base classes in src/interfaces/
interfaces/ defines abstract base classes and protocols
Files:
src/interfaces/core.py
🧬 Code graph analysis (2)
src/platforms/letsbonk/address_provider.py (1)
src/core/pubkeys.py (1)
SystemAddresses(39-62)
src/platforms/letsbonk/event_parser.py (4)
src/interfaces/core.py (1)
get_instruction_discriminators(385-391)src/platforms/pumpfun/event_parser.py (2)
get_instruction_discriminators(386-392)get_account_key(284-290)src/utils/idl_manager.py (1)
get_instruction_discriminators(134-144)src/utils/idl_parser.py (2)
get_instruction_discriminators(67-69)get_account_key(128-133)
🪛 Ruff (0.14.1)
src/platforms/letsbonk/address_provider.py
31-33: Do not perform function call Pubkey.from_string in dataclass defaults
(RUF009)
🔇 Additional comments (7)
src/interfaces/core.py (1)
41-42: LGTM: TokenInfo gains LetsBonk config hooks.Fields align with platform needs and type hints are correct.
src/platforms/letsbonk/instruction_builder.py (2)
116-116: Confirm payer non-writable is acceptable for buy/sell CPI.Some programs mark payer writable; here it’s set to non-writable. Please validate against the LetsBonk IDL/accounts spec or a devnet tx to ensure the program doesn’t require payer to be writable.
525-526: CU limit bump to 150k: OK. Ensure CU price is set upstream.The higher limit makes sense. Verify that the transaction builder also sets a compute unit price (priority fee) and caches blockhashes as per project guidelines.
Also applies to: 539-539
src/platforms/letsbonk/event_parser.py (1)
285-299: LGTM: discriminator set checks across block paths.Using a set for O(1) membership and validating account/data sizes is solid.
Please sanity-check on a devnet block sample that includes both
initialize_v2andinitialize_with_token_2022.Also applies to: 289-289, 344-345
src/platforms/letsbonk/address_provider.py (3)
31-33: Use a regular class or module-level constants instead of ClassVar in dataclass.The suggested
ClassVarfix masks a structural issue:LetsBonkAddressesis a dataclass with zero instance fields—it's purely a constants container. RUF009 flags function calls in dataclass field defaults; usingClassVarsidesteps the warning but leaves an inappropriate dataclass decorator.Better solutions:
- Remove
@dataclassentirely and make it a regular class (cleanest for a constants container)- Move these constants to module level, outside any class
Using
ClassVartechnically silences RUF009 but leaves the code semantically confused about what the class represents.Likely an incorrect or invalid review comment.
226-272: Verified: PDA seeds are correct.Both fee vault PDA seeds match the IDL specification:
- Creator fee vault: Seeds
[creator, quote_mint]confirmed in IDLclaim_creator_feeinstruction- Platform fee vault: Seeds
[platform_config, quote_mint]confirmed in IDLclaim_platform_fee_from_vaultinstructionThe implementation correctly derives these PDAs using
Pubkey.find_program_address()with the matching seed order. Fee vaults are intentionally passed as remaining accounts beyond the 15 IDL-defined accounts, which is documented in the code and is a valid Solana pattern for optional accounts required by the on-chain program.
299-312: Make user ATA and base_token_program Token‑2022 aware, and surface base_token_program to builder.For pools initialized with Token‑2022, the ATA derivation and
base_token_programmust use the Token‑2022 program id; otherwise buys/sells will fail due to wrong accounts.Apply:
@@ def get_buy_instruction_accounts(...): - accounts = { + # Determine token program for base mint + is_token_2022 = bool(getattr(token_info, "additional_data", None) and token_info.additional_data.get("is_token_2022")) + base_token_program = ( + SystemAddresses.TOKEN_2022_PROGRAM if is_token_2022 else SystemAddresses.TOKEN_PROGRAM + ) + accounts = { "payer": user, "authority": additional_accounts["authority"], "global_config": global_config, "platform_config": platform_config, "pool_state": additional_accounts["pool_state"], - "user_base_token": self.derive_user_token_account(user, token_info.mint), + # Program-aware ATA derivation + "user_base_token": get_associated_token_address( + user, token_info.mint, base_token_program + ), "base_vault": additional_accounts["base_vault"], "quote_vault": additional_accounts["quote_vault"], "base_token_mint": token_info.mint, "quote_token_mint": SystemAddresses.SOL_MINT, - "base_token_program": SystemAddresses.TOKEN_PROGRAM, + "base_token_program": base_token_program, "quote_token_program": SystemAddresses.TOKEN_PROGRAM, "event_authority": additional_accounts["event_authority"], "program": LetsBonkAddresses.PROGRAM, "system_program": SystemAddresses.SYSTEM_PROGRAM, "platform_fee_vault": self.derive_platform_fee_vault(platform_config), } @@ def get_sell_instruction_accounts(...): - accounts = { + is_token_2022 = bool(getattr(token_info, "additional_data", None) and token_info.additional_data.get("is_token_2022")) + base_token_program = ( + SystemAddresses.TOKEN_2022_PROGRAM if is_token_2022 else SystemAddresses.TOKEN_PROGRAM + ) + accounts = { "payer": user, "authority": additional_accounts["authority"], "global_config": global_config, "platform_config": platform_config, "pool_state": additional_accounts["pool_state"], - "user_base_token": self.derive_user_token_account(user, token_info.mint), + "user_base_token": get_associated_token_address( + user, token_info.mint, base_token_program + ), "base_vault": additional_accounts["base_vault"], "quote_vault": additional_accounts["quote_vault"], "base_token_mint": token_info.mint, "quote_token_mint": SystemAddresses.SOL_MINT, - "base_token_program": SystemAddresses.TOKEN_PROGRAM, + "base_token_program": base_token_program, "quote_token_program": SystemAddresses.TOKEN_PROGRAM, "event_authority": additional_accounts["event_authority"], "program": LetsBonkAddresses.PROGRAM, "system_program": SystemAddresses.SYSTEM_PROGRAM, "platform_fee_vault": self.derive_platform_fee_vault(platform_config), }Note: Ensure
SystemAddressesexposesTOKEN_2022_PROGRAM. If not, add it insrc/core/pubkeys.pyand re-export viaSystemAddresses.Also applies to: 313-330, 368-385, 387-394
| # Get all initialize instruction discriminators from injected IDL parser | ||
| # LetsBonk has multiple initialize variants: initialize, initialize_v2, initialize_with_token_2022 | ||
| discriminators = self._idl_parser.get_instruction_discriminators() | ||
| self._initialize_discriminator_bytes = discriminators["initialize"] | ||
| self._initialize_discriminator = struct.unpack( | ||
| "<Q", self._initialize_discriminator_bytes | ||
| )[0] | ||
|
|
||
| logger.info("LetsBonk event parser initialized with injected IDL parser") | ||
| self._initialize_discriminator_bytes_list = [ | ||
| discriminators["initialize"], | ||
| discriminators["initialize_v2"], | ||
| discriminators["initialize_with_token_2022"], | ||
| ] | ||
| self._initialize_discriminators = { | ||
| struct.unpack("<Q", disc_bytes)[0] | ||
| for disc_bytes in self._initialize_discriminator_bytes_list | ||
| } | ||
|
|
||
| logger.info( | ||
| f"LetsBonk event parser initialized with {len(self._initialize_discriminators)} " | ||
| f"initialize instruction variants" | ||
| ) | ||
|
|
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.
🛠️ Refactor suggestion | 🟠 Major
Good: supporting multiple initialize variants. Add a Token‑2022 hint for downstream.
Set a flag that indicates when the initialize variant is initialize_with_token_2022 so builders/address providers can choose the correct token program.
Apply:
@@ def parse_token_creation_from_instruction(...):
- # Accept any of the initialize instruction variants
+ # Accept any of the initialize instruction variants
if not decoded or decoded["instruction_name"] not in {
"initialize",
"initialize_v2",
"initialize_with_token_2022",
}:
return None
@@
- return TokenInfo(
+ is_token_2022 = decoded["instruction_name"] == "initialize_with_token_2022"
+ return TokenInfo(
name=base_mint_param.get("name", ""),
symbol=base_mint_param.get("symbol", ""),
uri=base_mint_param.get("uri", ""),
mint=base_mint,
platform=Platform.LETS_BONK,
pool_state=pool_state,
base_vault=base_vault,
quote_vault=quote_vault,
global_config=global_config,
platform_config=platform_config,
user=creator,
creator=creator,
creation_timestamp=monotonic(),
+ additional_data={"is_token_2022": is_token_2022},
)Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/platforms/letsbonk/event_parser.py around lines 36 to 53, add a boolean
flag on the parser that records whether the initialize variant include the
initialize_with_token_2022 discriminator so downstream builders/address
providers can pick the correct token program; after you build
self._initialize_discriminator_bytes_list or self._initialize_discriminators set
self._initialize_with_token_2022 = True if
discriminators["initialize_with_token_2022"] (or its unpacked integer) is
present in the list/set, otherwise set it to False, and ensure the logger still
reports the initialized variants (you can include the new flag in the state but
do not change logging semantics unless you want to mention the flag in the
message).
| # Add remaining accounts (required by the program for fee collection) | ||
| # These are not explicitly listed in IDL but required by the program | ||
| buy_accounts.append( | ||
| AccountMeta( | ||
| pubkey=accounts_info["system_program"], | ||
| is_signer=False, | ||
| is_writable=False, | ||
| ) | ||
| ) # #16: System Program | ||
| buy_accounts.append( | ||
| AccountMeta( | ||
| pubkey=accounts_info["platform_fee_vault"], | ||
| is_signer=False, | ||
| is_writable=True, | ||
| ) | ||
| ) # #17: Platform fee vault | ||
| if "creator_fee_vault" in accounts_info: | ||
| buy_accounts.append( | ||
| AccountMeta( | ||
| pubkey=accounts_info["creator_fee_vault"], | ||
| is_signer=False, | ||
| is_writable=True, | ||
| ) | ||
| ) # #18: Creator fee vault | ||
|
|
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.
🧩 Analysis chain
Add program-aware Token-2022 handling and include new accounts in “required accounts”.
-
If a pool was initialized via
initialize_with_token_2022, you must:- Create the user ATA with Token-2022 program id.
- Pass the Token-2022 program id in
base_token_program(and keep SPL Token v1 for WSOL/quote).
Currently both are hardcoded to SPL Token v1, which will fail for Token-2022 pools.
-
Also, since you now pass
system_program,platform_fee_vault, and optionallycreator_fee_vault, include them inget_required_accounts_for_buy/sellso your priority fee sizing and access lists remain accurate.
Apply these changes:
@@ def build_buy_instruction(...):
- # 1. Create idempotent ATA for base token
- ata_instruction = create_idempotent_associated_token_account(
- user, # payer
- user, # owner
- token_info.mint, # mint
- SystemAddresses.TOKEN_PROGRAM, # token program
- )
+ # 1. Create idempotent ATA for base token (Token-2022 aware)
+ base_token_program = accounts_info.get(
+ "base_token_program", SystemAddresses.TOKEN_PROGRAM
+ )
+ ata_instruction = create_idempotent_associated_token_account(
+ user, # payer
+ user, # owner
+ token_info.mint, # mint
+ base_token_program, # token program (spl-token or token-2022)
+ )
@@
- AccountMeta(
- pubkey=SystemAddresses.TOKEN_PROGRAM, is_signer=False, is_writable=False
- ), # base_token_program
+ AccountMeta(
+ pubkey=base_token_program, is_signer=False, is_writable=False
+ ), # base_token_program (Token-2022 aware)And mirror the same for the sell path:
@@ def build_sell_instruction(...):
- # 2. Initialize WSOL account
+ # 2. Initialize WSOL account
initialize_wsol_ix = self._create_initialize_account_instruction(
wsol_account, SystemAddresses.SOL_MINT, user
)
@@
- AccountMeta(
- pubkey=SystemAddresses.TOKEN_PROGRAM, is_signer=False, is_writable=False
- ), # base_token_program
+ AccountMeta(
+ pubkey=accounts_info.get(
+ "base_token_program", SystemAddresses.TOKEN_PROGRAM
+ ),
+ is_signer=False,
+ is_writable=False,
+ ), # base_token_program (Token-2022 aware)Finally, include the new accounts in the “required accounts” sets:
@@ def get_required_accounts_for_buy(...):
- return [
+ req = [
accounts_info["pool_state"],
accounts_info["user_base_token"],
accounts_info["base_vault"],
accounts_info["quote_vault"],
token_info.mint,
SystemAddresses.SOL_MINT,
accounts_info["program"],
- ]
+ ]
+ # Include fee/system accounts for accurate access set
+ req.append(accounts_info["system_program"])
+ req.append(accounts_info["platform_fee_vault"])
+ if "creator_fee_vault" in accounts_info:
+ req.append(accounts_info["creator_fee_vault"])
+ return req
@@ def get_required_accounts_for_sell(...):
- return [
+ req = [
accounts_info["pool_state"],
accounts_info["user_base_token"],
accounts_info["base_vault"],
accounts_info["quote_vault"],
token_info.mint,
SystemAddresses.SOL_MINT,
accounts_info["program"],
- ]
+ ]
+ req.append(accounts_info["system_program"])
+ req.append(accounts_info["platform_fee_vault"])
+ if "creator_fee_vault" in accounts_info:
+ req.append(accounts_info["creator_fee_vault"])
+ return req
---
🏁 Script executed:
```shell
#!/bin/bash
# Find the instruction_builder.py file
fd -t f "instruction_builder.py" src/
# Get file info and line count
if [ -f "src/platforms/letsbonk/instruction_builder.py" ]; then
echo "=== File found ==="
wc -l "src/platforms/letsbonk/instruction_builder.py"
echo -e "\n=== Lines 169-193 (snippet context) ==="
sed -n '165,200p' "src/platforms/letsbonk/instruction_builder.py"
fi
Length of output: 1603
🏁 Script executed:
#!/bin/bash
# Find build_buy_instruction method
echo "=== build_buy_instruction method ==="
rg -n -A 30 "def build_buy_instruction" src/platforms/letsbonk/instruction_builder.py
echo -e "\n=== build_sell_instruction method ==="
rg -n -A 30 "def build_sell_instruction" src/platforms/letsbonk/instruction_builder.pyLength of output: 2540
🏁 Script executed:
#!/bin/bash
# Find get_required_accounts methods
echo "=== get_required_accounts_for_buy method ==="
rg -n -A 15 "def get_required_accounts_for_buy" src/platforms/letsbonk/instruction_builder.py
echo -e "\n=== get_required_accounts_for_sell method ==="
rg -n -A 15 "def get_required_accounts_for_sell" src/platforms/letsbonk/instruction_builder.pyLength of output: 1396
🏁 Script executed:
#!/bin/bash
# Search for TOKEN_PROGRAM and Token-2022 references
echo "=== TOKEN_PROGRAM hardcoding ==="
rg -n "TOKEN_PROGRAM" src/platforms/letsbonk/instruction_builder.py | head -20
echo -e "\n=== Token-2022 references ==="
rg -n -i "token.?2022\|token_2022" src/platforms/letsbonk/instruction_builder.pyLength of output: 786
🏁 Script executed:
#!/bin/bash
# Check if base_token_program is used in accounts_info
echo "=== base_token_program references ==="
rg -n "base_token_program" src/platforms/letsbonk/instruction_builder.pyLength of output: 119
---
🏁 Script executed:
```shell
#!/bin/bash
# Get full content of get_required_accounts_for_buy and get_required_accounts_for_sell
echo "=== get_required_accounts_for_buy (lines 373-410) ==="
sed -n '373,410p' "src/platforms/letsbonk/instruction_builder.py"
echo -e "\n=== get_required_accounts_for_sell (lines 398-435) ==="
sed -n '398,435p' "src/platforms/letsbonk/instruction_builder.py"
Length of output: 2777
🏁 Script executed:
#!/bin/bash
# Get context around lines 103 and 258 (owner=TOKEN_PROGRAM cases)
echo "=== Context around line 103 (build_buy_instruction ATA) ==="
sed -n '95,110p' "src/platforms/letsbonk/instruction_builder.py"
echo -e "\n=== Context around line 258 (build_sell_instruction WSOL) ==="
sed -n '250,265p' "src/platforms/letsbonk/instruction_builder.py"Length of output: 1329
🏁 Script executed:
#!/bin/bash
# Search for Token-2022 in entire letsbonk platform
echo "=== Token-2022 in letsbonk platform ==="
rg -i "token.?2022\|token_2022\|initialize_with_token_2022" src/platforms/letsbonk/
echo -e "\n=== Check if base_token_program key is set in address_provider ==="
rg -n "base_token_program" src/platforms/letsbonk/Length of output: 505
🏁 Script executed:
#!/bin/bash
# Check the address provider methods to see what keys are in accounts_info
echo "=== get_buy_instruction_accounts in address provider ==="
fd -t f "*.py" src/platforms/letsbonk/ -x grep -l "get_buy_instruction_accounts"
echo -e "\n=== get_sell_instruction_accounts in address provider ==="
fd -t f "*.py" src/platforms/letsbonk/ -x grep -l "get_sell_instruction_accounts"Length of output: 683
🏁 Script executed:
#!/bin/bash
# Get full build_buy_instruction to see if it references base_token_program
echo "=== Full build_buy_instruction method ==="
sed -n '53,215p' "src/platforms/letsbonk/instruction_builder.py"Length of output: 6426
---
🏁 Script executed:
```shell
#!/bin/bash
# Get full build_sell_instruction to compare
echo "=== Full build_sell_instruction method ==="
sed -n '218,370p' "src/platforms/letsbonk/instruction_builder.py"
Length of output: 6079
🏁 Script executed:
#!/bin/bash
# Check address_provider to see full get_buy/sell_instruction_accounts implementation
echo "=== get_buy_instruction_accounts method ==="
rg -n -A 50 "def get_buy_instruction_accounts" src/platforms/letsbonk/address_provider.py | head -70
echo -e "\n=== get_sell_instruction_accounts method ==="
rg -n -A 50 "def get_sell_instruction_accounts" src/platforms/letsbonk/address_provider.py | head -70Length of output: 4716
Use dynamic base_token_program from accounts_info instead of hardcoding TOKEN_PROGRAM, and include fee/system accounts in priority fee calculation.
The review identifies three critical issues:
-
Hardcoded TOKEN_PROGRAM in ATA/account creation: Lines 83 (build_buy) and 258 (build_sell) hardcode
SystemAddresses.TOKEN_PROGRAMinstead of usingaccounts_info.get("base_token_program"), which already exists in accounts_info. Token-2022 pools require the Token-2022 program ID here. -
Hardcoded token program in AccountMeta: Lines 154–157 (build_buy) and 309–312 (build_sell) also hardcode both
base_token_programandquote_token_programinstead of reading from accounts_info. -
Missing accounts in priority fee calculation:
get_required_accounts_for_buy(lines 373–397) andget_required_accounts_for_sell(lines 398–424) return only 7 accounts. They must also includesystem_program,platform_fee_vault, and optionallycreator_fee_vault—these accounts are already passed to the instruction builders and must be included in the required accounts list for accurate priority fee sizing.
Apply the suggested diffs to use accounts_info.get("base_token_program", SystemAddresses.TOKEN_PROGRAM) in lines 83, 154, 157, 258, 309, 312, and extend the return statements in both get_required_accounts_* methods to append the fee/system accounts.
🤖 Prompt for AI Agents
src/platforms/letsbonk/instruction_builder.py around lines 169-193, change
hardcoded TOKEN_PROGRAM usages to read dynamic program IDs from accounts_info
and include fee/system accounts in required-account lists: replace occurrences
where SystemAddresses.TOKEN_PROGRAM is used for base/quote token program with
accounts_info.get("base_token_program", SystemAddresses.TOKEN_PROGRAM) (and
accounts_info.get("quote_token_program", SystemAddresses.TOKEN_PROGRAM) where
appropriate) at the reported sites (build_buy lines ~83,154,157 and build_sell
lines ~258,309,312), use those variables when constructing AccountMeta entries
instead of the hardcoded constant, and update get_required_accounts_for_buy and
get_required_accounts_for_sell to append accounts_info["system_program"],
accounts_info["platform_fee_vault"], and, if present,
accounts_info["creator_fee_vault"] to their returned lists so priority fee
sizing includes system and fee vault accounts.
Summary by CodeRabbit
New Features
Performance