Skip to content

Conversation

@smypmsa
Copy link
Member

@smypmsa smypmsa commented Oct 22, 2025

#138

Summary by CodeRabbit

  • New Features

    • Added new buy operations for exact SOL and quote token inputs.
    • Enhanced trade events with operation names for improved traceability.
    • Added volume tracking capability for token purchases.
    • Introduced account extension functionality for token operations.
  • Improvements

    • Fee-related accounts are now required for all buy operations.
    • Expanded error handling for rent, fees, and slippage conditions.
  • Chores

    • Updated learning examples with placeholder configuration values.

@smypmsa smypmsa self-assigned this Oct 22, 2025
@smypmsa smypmsa added bug Something isn't working enhancement New feature or request labels Oct 22, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Walkthrough

Two pump fun protocol IDL files were updated to add new buy_exact instructions with corresponding error codes, while fee_config and fee_program accounts became required. TradeEvent and BuyEvent types gained ix_name fields. Learning examples were updated with placeholder addresses, and mint_and_buy.py added extend_account instruction support with track_volume parameter.

Changes

Cohort / File(s) Summary
IDL Instruction & Event Definitions
idl/pump_fun_idl.json, idl/pump_swap_idl.json
Added buy_exact_sol_in (pump_fun) and buy_exact_quote_in (pump_swap) instructions with corresponding accounts, discriminators, and arguments. Removed optional markers from fee_config and fee_program in buy/sell instructions. Extended TradeEvent/BuyEvent with ix_name field (string type) and updated event documentation. Added error codes: 6040–6042 (pump_fun: rent, fees, slippage), 6039–6040 (pump_swap: quote tokens, slippage).
Learning Example Placeholder Addresses
learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py, learning-examples/fetch_price.py, learning-examples/letsbonk-buy-sell/manual_buy_exact_in.py, learning-examples/letsbonk-buy-sell/manual_buy_exact_out.py, learning-examples/letsbonk-buy-sell/manual_sell_exact_in.py, learning-examples/letsbonk-buy-sell/manual_sell_exact_out.py
Replaced hard-coded Solana addresses (token mints, bonding curve) with placeholder strings (YOUR_TOKEN_MINT_ADDRESS_HERE, YOUR_BONDING_CURVE_ADDRESS_HERE).
Extended Buy Instruction with Volume Tracking
learning-examples/mint_and_buy.py
Added EXTEND_ACCOUNT_DISCRIMINATOR constant and create_extend_account_instruction() function to support extend_account operation. Modified create_buy_instruction() to accept track_volume parameter (default True) and encode it into instruction data. Integrated extend_account call into main transaction flow.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Program
    participant ExtendAccount
    participant BuyInstruction
    
    User->>Program: Mint Token
    Program-->>User: Bonding Curve Created
    
    rect rgb(200, 220, 255)
        Note over ExtendAccount: New Step
        User->>ExtendAccount: extend_account(bonding_curve, user)
        ExtendAccount-->>User: Account Extended
    end
    
    User->>BuyInstruction: buy(track_volume=True)
    rect rgb(220, 255, 220)
        Note over BuyInstruction: Enhanced with volume tracking
        BuyInstruction->>Program: Execute with track_volume flag
        Program-->>User: Purchase Complete
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

The changes span heterogeneous categories: IDL structure modifications (new instructions, error codes, event field additions) require careful validation of discriminators and account ordering, while learning example updates are repetitive placeholder replacements. The mint_and_buy.py logic addition is logic-dense but localized.

Possibly related PRs

  • Refactor platform support, add letsbonk #127 — Related through IDL definitions; that PR enables IDL-driven instruction and event handling while this PR expands the underlying IDL structure with new instructions and fields.

Poem

🐰 Hop into the future, new instructions bloom,
Fee accounts no longer in the optional room,
Events now whisper their operation's name,
Volume tracking adds to the trading game,
Learning by example, with addresses to fill—
The bonding curves dance to a sharper will! 🌱

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title “Fix/mint buy example” is overly narrow and fails to convey the breadth of this pull request, which not only updates the mint-and-buy example but also introduces new IDL instructions, error codes, and modifications to account requirements across multiple modules; its use of a slash also makes it unclear whether it describes a fix, a new feature, or both. Rename the pull request to clearly summarize its primary changes—such as adding buy_exact_* instructions, tightening fee account requirements, extending event schemas, and fixing the mint-and-buy example—using a concise, descriptive phrase without slashes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/mint-buy-example

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
idl/pump_fun_idl.json (1)

4848-4855: IDL OptionBool encoding likely incompatible with codegen

Defining OptionBool as a struct with a single bool omits the Option discriminant. Most Anchor-compatible IDLs represent this as {"option": "bool"} so client libraries encode [0] | [1, value].

Suggested shape:

{
  "name": "OptionBool",
  "type": { "kind": "option", "option": "bool" }
}

If the program uses a custom struct instead of Option, document the exact wire format and keep clients manually encoding it (as you do). Otherwise, switch to the standard option form to avoid mis-serialization by generators.

🧹 Nitpick comments (11)
learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py (1)

19-19: Read TOKEN_MINT from env; guard against placeholder/invalid key

Using a placeholder string passes the non-empty check then fails on Pubkey.parse.

Apply this diff:

-TOKEN_MINT: Final[str] = "YOUR_TOKEN_MINT_ADDRESS_HERE"  # Replace with actual token mint address
+TOKEN_MINT: Final[str] = os.getenv("TOKEN_MINT")  # Set in .env

And before parsing:

if not RPC_URL or not TOKEN_MINT:
    print("❌ Set SOLANA_NODE_RPC_ENDPOINT and TOKEN_MINT in .env")
    return
try:
    mint_pubkey: Pubkey = Pubkey.from_string(TOKEN_MINT)
except Exception as e:
    print(f"❌ Invalid TOKEN_MINT: {e}")
    return
idl/pump_swap_idl.json (3)

3893-3902: Error messages apply to both buy variants; minor wording tweak

  • Messages are prefixed with “buy: …” but errors also arise in buy_exact_quote_in. Consider neutral wording or “buy/buy_exact_quote_in: …”. Also prefer “cover fees” over “cover for fees.”

4010-4013: BuyEvent extension is useful; add explicit note on spendable vs max quote semantics

  • Adding ix_name and min_base_amount_out is great. Please also clarify in docs whether BuyEvent.max_quote_amount_in carries spendable_quote_in for buy_exact_quote_in, or introduce a dedicated spendable_quote_in field to avoid ambiguity.

If you stick with one field, add a doc line like: “For buy_exact_quote_in, max_quote_amount_in equals spendable_quote_in.”

Also applies to: 4130-4136


708-1135: Clarify BuyEvent mapping for buy_exact_quote_in

  • The buy_exact_quote_in instruction correctly includes fee_config/fee_program, unique discriminator, and args (spendable_quote_in, min_base_amount_out, track_volume).
  • The BuyEvent struct now has both max_quote_amount_in (legacy) and min_base_amount_out, plus ix_name. To prevent client confusion:
    • Update the event docs to state that for ix_name == "buy_exact_quote_in", quote_amount_in represents the spendable_quote_in passed in and max_quote_amount_in is unused.
    • Clarify that consumers should branch on ix_name to interpret fields correctly.
    • (Optional) Consider adding a dedicated spendable_quote_in field to the event.
learning-examples/letsbonk-buy-sell/manual_buy_exact_out.py (3)

549-555: Avoid hard-coded rent; fetch rent-exempt lamports at runtime

Using a fixed 2_039_280 can drift and cause under/over-funding. Query rent for TokenAccount size (165) and add the swap amount.

-        account_creation_lamports = 2_039_280  # Standard account creation cost
-        total_lamports = maximum_amount_in + account_creation_lamports
+        rent_lamports = await client.get_minimum_balance_for_rent_exemption(165)
+        total_lamports = maximum_amount_in + rent_lamports

676-687: Add simple retries for submission/confirmation

Network hiccups are common. Wrap send/confirm with 3 attempts and exponential backoff.

-        result = await client.send_transaction(
-            transaction,
-            opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed),
-        )
-
-        tx_signature = result.value
+        tx_signature = None
+        for attempt in range(3):
+            try:
+                result = await client.send_transaction(
+                    transaction,
+                    opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed),
+                )
+                tx_signature = result.value
+                await client.confirm_transaction(tx_signature, commitment="confirmed")
+                break
+            except Exception as e:
+                await asyncio.sleep(0.5 * (2 ** attempt))
+        if tx_signature is None:
+            print("Send/confirm retries exhausted.")
+            return None
-        print(f"Transaction sent: https://solscan.io/tx/{tx_signature}")
-
-        print("Waiting for confirmation...")
-        await client.confirm_transaction(tx_signature, commitment="confirmed")
-        print("Transaction confirmed!")
+        print(f"Transaction sent and confirmed: https://solscan.io/tx/{tx_signature}")

1-739: Optional: switch prints to centralized logger and keep lines <= 88 chars

Examples should still follow repo logging and formatting guidelines. Consider using get_logger(name) and logging.exception() in except blocks; also wrap long f-strings to respect 88-char limit.

learning-examples/letsbonk-buy-sell/manual_buy_exact_in.py (4)

516-523: Guard against None from minimum amount calc

If calculation fails and returns None, struct packing will throw. Add a check and abort early.

         minimum_amount_out = calculate_minimum_amount_out_from_pool_state(
             pool_state_data, amount_in, slippage_tolerance
         )
+        if minimum_amount_out is None:
+            print("Failed to calculate minimum_amount_out")
+            return None

539-541: Compute rent-exempt amount instead of hard-coding

Same concern as exact-out. Query rent, then add amount_in.

-        account_creation_lamports = 2_039_280  # Standard account creation cost
-        total_lamports = amount_in + account_creation_lamports
+        rent_lamports = await client.get_minimum_balance_for_rent_exemption(165)
+        total_lamports = amount_in + rent_lamports

665-677: Add retries around send/confirm

Improve resilience with a small retry loop.

-        result = await client.send_transaction(
-            transaction,
-            opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed),
-        )
-
-        tx_signature = result.value
+        tx_signature = None
+        for attempt in range(3):
+            try:
+                result = await client.send_transaction(
+                    transaction,
+                    opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed),
+                )
+                tx_signature = result.value
+                await client.confirm_transaction(tx_signature, commitment="confirmed")
+                break
+            except Exception:
+                await asyncio.sleep(0.5 * (2 ** attempt))
+        if tx_signature is None:
+            print("Send/confirm retries exhausted.")
+            return None

1-734: Optional: adopt repo logger and clamp slippage defaults

  • Use src.utils.logger.get_logger(name) and logging.exception() per guidelines.
  • Consider default SLIPPAGE_TOLERANCE of 0.01–0.05 and clamp user-provided values into [0, 0.5] for safety.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25c376d and 09fb67b.

📒 Files selected for processing (9)
  • idl/pump_fun_idl.json (4 hunks)
  • idl/pump_swap_idl.json (4 hunks)
  • learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py (1 hunks)
  • learning-examples/fetch_price.py (1 hunks)
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_in.py (1 hunks)
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_out.py (1 hunks)
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_in.py (1 hunks)
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_out.py (1 hunks)
  • learning-examples/mint_and_buy.py (6 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.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:

  • learning-examples/fetch_price.py
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_out.py
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_in.py
  • learning-examples/mint_and_buy.py
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_out.py
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_in.py
  • learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py
learning-examples/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Treat learning-examples Python scripts as integration tests for manual runs

learning-examples/**/*.py: Use learning examples to test new features before integration
Use learning examples to validate platform-specific functionality
Use learning examples for performance benchmarking
Use learning examples for educational purposes for new developers

Always test changes using scripts in learning-examples/ before modifying the main bot

Files:

  • learning-examples/fetch_price.py
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_out.py
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_in.py
  • learning-examples/mint_and_buy.py
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_out.py
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_in.py
  • learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py
learning-examples/**

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Place integration tests and validation scenarios under learning-examples/

Files:

  • learning-examples/fetch_price.py
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_out.py
  • learning-examples/letsbonk-buy-sell/manual_sell_exact_in.py
  • learning-examples/mint_and_buy.py
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_out.py
  • learning-examples/letsbonk-buy-sell/manual_buy_exact_in.py
  • learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py
learning-examples/fetch_price.py

📄 CodeRabbit inference engine (AGENTS.md)

Use uv run learning-examples/fetch_price.py for unit-level testing of price fetching

Files:

  • learning-examples/fetch_price.py
🧠 Learnings (1)
📚 Learning: 2025-10-04T12:42:50.785Z
Learnt from: CR
PR: chainstacklabs/pumpfun-bonkfun-bot#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:

  • learning-examples/letsbonk-buy-sell/manual_sell_exact_out.py
🧬 Code graph analysis (1)
learning-examples/mint_and_buy.py (1)
src/core/wallet.py (1)
  • pubkey (24-26)
🪛 Ruff (0.14.1)
learning-examples/bonding-curve-progress/poll_bonding_curve_progress.py

19-19: Possible hardcoded password assigned to: "TOKEN_MINT"

(S105)

🔇 Additional comments (7)
idl/pump_fun_idl.json (2)

827-1242: New instruction buy_exact_sol_in: accounts/args look consistent

Accounts mirror buy with fee_config/fee_program now required; args include spendable_sol_in, min_tokens_out, track_volume. LGTM. Please ensure clients pass fee_config and fee_program everywhere.

Confirm on-chain expects the exact accounts/order shown here and that rent/fee error codes (6040–6041) are surfaced by your clients.


5003-5096: TradeEvent adds ix_name: good for telemetry

No issues spotted. Ensure downstream decoders account for the extra field.

learning-examples/mint_and_buy.py (3)

73-75: Discriminator matches IDL

EXTEND_ACCOUNT_DISCRIMINATOR bytes align with IDL. LGTM.


230-231: track_volume Option encoding aligns with wire format

Encoding [1, 0|1] for Some(false|true) is consistent with Option. Keep IDL and docs in sync.

Add a brief note in README about OptionBool wire format to avoid client drift.

Also applies to: 268-271, 276-277


348-353: Extend-account placement looks correct

Extending bonding_curve right after create and before buy makes sense. LGTM.

learning-examples/letsbonk-buy-sell/manual_buy_exact_out.py (1)

42-44: Swapping hard-coded mint for a placeholder is correct

Good change. Script will now fail-fast with ValueError until users set a real mint, which is desirable for examples.

Before merging, run the example with a real mint to ensure no regressions.

learning-examples/letsbonk-buy-sell/manual_buy_exact_in.py (1)

42-44: Placeholder mint address: good safety default

Appropriate for examples; it forces users to supply a real mint.

Smoke-test with a real mint after merge.

LAMPORTS_PER_SOL: Final[int] = 1_000_000_000
TOKEN_DECIMALS: Final[int] = 6
CURVE_ADDRESS: Final[str] = "6GXfUqrmPM4VdN1NoDZsE155jzRegJngZRjMkGyby7do"
CURVE_ADDRESS: Final[str] = "YOUR_BONDING_CURVE_ADDRESS_HERE" # Replace with actual bonding curve address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Load CURVE_ADDRESS from env and validate

Avoid hardcoded placeholder; read from env and fail fast if unset/placeholder.

Apply this diff:

-CURVE_ADDRESS: Final[str] = "YOUR_BONDING_CURVE_ADDRESS_HERE"  # Replace with actual bonding curve address
+CURVE_ADDRESS: Final[str] = os.environ.get(
+    "CURVE_ADDRESS", "YOUR_BONDING_CURVE_ADDRESS_HERE"
+)

Add early check:

if not CURVE_ADDRESS or CURVE_ADDRESS.endswith("_HERE"):
    raise ValueError("Set CURVE_ADDRESS env to a valid bonding curve address")

Run as per guidelines:


🏁 Script executed:

uv run learning-examples/fetch_price.py

Length of output: 40


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' learning-examples/fetch_price.py

Length of output: 2544


Load CURVE_ADDRESS from env and validate

Replace the hardcoded placeholder at learning-examples/fetch_price.py:15 with an environment lookup and fail fast if it’s unset or still using the placeholder:

 import os
 from typing import Final

-CURVE_ADDRESS: Final[str] = "YOUR_BONDING_CURVE_ADDRESS_HERE"  # Replace with actual bonding curve address
+CURVE_ADDRESS: Final[str] = os.environ.get(
+    "CURVE_ADDRESS", "YOUR_BONDING_CURVE_ADDRESS_HERE"
+)
+
+if not CURVE_ADDRESS or CURVE_ADDRESS.endswith("_HERE"):
+    raise ValueError("Set CURVE_ADDRESS env to a valid bonding curve address")

Then verify the change by running:

python learning-examples/fetch_price.py
🤖 Prompt for AI Agents
In learning-examples/fetch_price.py around line 15, the CURVE_ADDRESS is
hardcoded to a placeholder; change it to read from an environment variable
(e.g., os.environ or os.getenv) and validate it immediately: if the env var is
missing, empty, or still equals the placeholder string, fail fast with a clear
error (raise SystemExit or log an error and exit with non-zero status) so the
script stops early; update any import (os, sys or logging) as needed and then
run python learning-examples/fetch_price.py to verify the guard triggers when
not set.

Comment on lines 42 to 44
TOKEN_MINT_ADDRESS = Pubkey.from_string(
"MYcq5mUyoAtCfyDWYAWvioou3cgnYjnCvFd7U6fspot"
"YOUR_TOKEN_MINT_ADDRESS_HERE"
) # Replace with actual token mint address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix import-time crash: lazily parse TOKEN_MINT from env

Same issue as the other script. Don’t call Pubkey.from_string at module import.

Apply this diff here:

-TOKEN_MINT_ADDRESS = Pubkey.from_string(
-    "YOUR_TOKEN_MINT_ADDRESS_HERE"
-)  # Replace with actual token mint address
+TOKEN_MINT_STR = os.environ.get("TOKEN_MINT", "YOUR_TOKEN_MINT_ADDRESS_HERE")

And in main():

try:
    token_mint = Pubkey.from_string(TOKEN_MINT_STR)
except ValueError as e:
    print(f"Invalid TOKEN_MINT: {e}")
    sys.exit(1)

# replace TOKEN_MINT_ADDRESS usages with token_mint

Based on learnings.

🤖 Prompt for AI Agents
In learning-examples/letsbonk-buy-sell/manual_sell_exact_in.py around lines
42-44, avoid calling Pubkey.from_string at module import which can crash;
instead store the mint as a raw string constant (e.g. TOKEN_MINT_STR = "..." or
read from env) and parse it lazily inside main() with a try/except that catches
ValueError, prints an error and exits; update all uses of TOKEN_MINT_ADDRESS to
use the parsed token_mint variable from main() and ensure sys.exit(1) is invoked
on parse failure.

Comment on lines 42 to 44
TOKEN_MINT_ADDRESS = Pubkey.from_string(
"MYcq5mUyoAtCfyDWYAWvioou3cgnYjnCvFd7U6fspot"
"YOUR_TOKEN_MINT_ADDRESS_HERE"
) # Replace with actual token mint address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix import-time crash: lazily parse TOKEN_MINT from env

Calling Pubkey.from_string on a placeholder raises ValueError at import time; the script never reaches main(). Parse lazily and validate.

Apply this diff here:

-TOKEN_MINT_ADDRESS = Pubkey.from_string(
-    "YOUR_TOKEN_MINT_ADDRESS_HERE"
-)  # Replace with actual token mint address
+TOKEN_MINT_STR = os.environ.get("TOKEN_MINT", "YOUR_TOKEN_MINT_ADDRESS_HERE")

Then inside main(), parse and use a local variable:

# inside main(), before first use
try:
    token_mint = Pubkey.from_string(TOKEN_MINT_STR)
except ValueError as e:
    print(f"Invalid TOKEN_MINT: {e}")
    sys.exit(1)

# replace all TOKEN_MINT_ADDRESS usages with token_mint
🤖 Prompt for AI Agents
In learning-examples/letsbonk-buy-sell/manual_sell_exact_out.py around lines
42-44, avoid calling Pubkey.from_string at import time which raises ValueError
for placeholder; change the top-level constant to a plain string (e.g.
TOKEN_MINT_STR = "YOUR_TOKEN_MINT_ADDRESS_HERE") and remove Pubkey.from_string
there, then inside main() before first use attempt to parse it with try:
token_mint = Pubkey.from_string(TOKEN_MINT_STR) except ValueError as e:
print(f"Invalid TOKEN_MINT: {e}") and call sys.exit(1); replace all usages of
TOKEN_MINT_ADDRESS with the local token_mint variable and ensure sys is imported
if not already.

+ encode_pubkey(creator)
)

return Instruction(PUMP_PROGRAM, data, accounts)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Instruction() arguments are in wrong order

solders.instruction.Instruction expects (program_id, accounts, data). Code passes (program_id, data, accounts), which will corrupt the instruction and fail at runtime.

Apply this diff:

-    return Instruction(PUMP_PROGRAM, data, accounts)
+    return Instruction(PUMP_PROGRAM, accounts, data)

Repeat the same fix for:

  • Line 197 in create_pump_create_instruction
  • Line 216 in create_extend_account_instruction
  • Line 279 in create_buy_instruction

Also applies to: 216-217, 279-279

🤖 Prompt for AI Agents
In learning-examples/mint_and_buy.py at lines 197, 216-217, and 279, the
Instruction() constructor arguments are passed in the wrong order (program_id,
data, accounts) but solders.instruction.Instruction expects (program_id,
accounts, data); update each return to call Instruction(PUMP_PROGRAM, accounts,
data) (or the corresponding program_id variable for that function) so accounts
comes second and data third for create_pump_create_instruction (line 197),
create_extend_account_instruction (lines 216-217), and create_buy_instruction
(line 279).

@smypmsa smypmsa merged commit d64b51d into main Oct 25, 2025
5 checks passed
@smypmsa smypmsa deleted the fix/mint-buy-example branch October 25, 2025 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mint_and_buy.py probably has some config wrong, doesn't show on pump fun frontend

2 participants