feat: add --cashback flag to token launch + fix create_v2 accounts#14
feat: add --cashback flag to token launch + fix create_v2 accounts#14
Conversation
Wire is_cashback_enabled (OptionBool) through all three layers for the create_v2 instruction, and fix a pre-existing bug where mayhem accounts were conditionally included — the IDL requires them always. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds a cashback flag to the token launch flow: Changes
Sequence Diagram(s)sequenceDiagram
rect rgba(235,245,255,0.5)
participant User
participant CLI
participant Core as Core.launch
participant Protocol as build_create_instructions
participant RPC as RpcClient/Blockchain
end
User->>CLI: run "launch --cashback ..."
CLI->>Core: launch_token(..., is_cashback=true)
Core->>Protocol: build_create_instructions(..., is_cashback=true)
Protocol->>RPC: submit create_v2 instruction (includes is_cashback flag, mayhem accounts)
RPC->>Blockchain: send tx
Blockchain-->>RPC: tx signature / confirmation
RPC-->>Core: return signature/result
Core-->>CLI: return result {..., "is_cashback": true}
CLI-->>User: display success and "Cashback: enabled"
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
📝 Coding Plan
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.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/pumpfun_cli/commands/launch.py`:
- Around line 68-69: The new ad-hoc typer.echo call should be removed and the
cashback information routed through the existing render(...) path: update the
data structure passed to render (the variable `result` or the response object
used by `render(...)` in launch.py) to include a "cashback" or "is_cashback"
field (e.g., set result["cashback"] = "enabled" or a boolean) and then call
render(result, json_mode) as usual; remove the standalone typer.echo("
Cashback: enabled") so TTY/JSON output remains centralized via the render(...)
function.
In `@src/pumpfun_cli/protocol/instructions.py`:
- Around line 324-330: The AccountMeta for MAYHEM_PROGRAM_ID in the create_v2
instruction block is incorrectly marked writable; update the
AccountMeta(pubkey=MAYHEM_PROGRAM_ID, is_signer=False, is_writable=True) to set
is_writable=False to match the IDL/read-only account definition for create_v2
and ensure account meta consistency with the create_v2 instruction.
In `@tests/test_protocol/test_instructions.py`:
- Around line 86-151: The tests only check trailing bytes but must also lock the
instruction account layout to prevent AccountNotEnoughKeys regressions: in each
test that calls build_create_instructions assert that the returned create_ix has
the expected 16 accounts (e.g., assert len(create_ix.keys) == 16) and, for the
mayhem variants, assert the presence/expected position of the mayhem-specific
account (referencing the known mayhem PDA symbol/name used by
build_create_instructions, e.g., MAYHEM_PDA or MAYHEM_ACCOUNT) in
create_ix.keys; add equivalent presence/position checks for any other mandatory
accounts to ensure the full 16-account layout is enforced.
In `@tests/test_surfpool/test_launch.py`:
- Around line 31-231: Tests under tests/test_surfpool/test_launch.py are making
real RPC calls via surfpool_rpc using launch_token and get_token_info, which
violates the no-network rule; refactor these to use mocked RPC responses or mark
them as integration-only: replace direct surfpool_rpc network usage in
test_launch_* functions with fixtures/mocks that stub launch_token and
get_token_info (or inject a mocked rpc client), or move the entire file/tests to
an integration test suite with a distinct marker (e.g., pytest.mark.integration)
so they are excluded from default runs while keeping unit tests in tests/**
fully mocked.
- Around line 31-231: Replace the eight near-identical tests
(test_launch_default, test_launch_cashback, test_launch_mayhem,
test_launch_mayhem_cashback, test_launch_default_with_buy,
test_launch_cashback_with_buy, test_launch_mayhem_with_buy,
test_launch_mayhem_cashback_with_buy) with a single parametrized
pytest.mark.parametrize test that iterates over combinations of is_mayhem
(bool), is_cashback (bool), and initial_buy_sol (None or 0.001); call
launch_token with those params (preserving the `@_UPLOAD_PATCH` decorator,
surfpool_rpc/funded_keypair/test_keystore/test_password fixtures and using
launch_token and get_token_info), assert the same expectations conditionally
(check result["is_cashback"], result["initial_buy_sol"] when provided,
result["signature"], and token info["graduated"] where applicable) to eliminate
duplication while keeping test behavior identical.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 605be9f5-9cc4-4383-b06e-560703c0c8ec
📒 Files selected for processing (7)
src/pumpfun_cli/commands/launch.pysrc/pumpfun_cli/core/launch.pysrc/pumpfun_cli/protocol/instructions.pytests/test_commands/test_smoke.pytests/test_core/test_launch.pytests/test_protocol/test_instructions.pytests/test_surfpool/test_launch.py
… parametrize surfpool - Set MAYHEM_PROGRAM_ID to is_writable=False in create_v2 (read-only per IDL) - Add account count + position assertions to create_v2 instruction tests - Parametrize 8 surfpool launch tests into single matrix test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pumpfun_cli/protocol/instructions.py (1)
281-291: 🧹 Nitpick | 🔵 TrivialConsider using keyword-only parameters for protocol-layer safety.
The function signature currently has adjacent bool parameters (
is_mayhem,is_cashback) with defaults. While no existing positional call sites risk misbinding, using*,afteruriwould prevent future positional argument confusion in this critical funds-handling layer:Suggested improvement
def build_create_instructions( idl: IDLParser, mint: Pubkey, user: Pubkey, name: str, symbol: str, uri: str, + *, is_mayhem: bool = False, is_cashback: bool = False, token_program: Pubkey = TOKEN_2022_PROGRAM, ) -> list[Instruction]:This is a defensive best practice that makes intent explicit without requiring any call-site changes.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pumpfun_cli/protocol/instructions.py` around lines 281 - 291, The function build_create_instructions should make the optional flags and token_program keyword-only to avoid accidental positional misbinding: change the signature so that parameters after uri (is_mayhem, is_cashback, token_program) are declared as keyword-only (e.g., add a * after the uri parameter) so callers must name is_mayhem, is_cashback, and token_program explicitly; update any internal references to those names if needed but no call-site changes should be required.
♻️ Duplicate comments (1)
tests/test_surfpool/test_launch.py (1)
61-80:⚠️ Potential issue | 🟠 MajorLive RPC calls in
tests/**violate test policy.This test still performs real network calls (
launch_token,get_token_info) viasurfpool_rpc. Please move it to an integration-only suite/marker excluded from defaulttests/**, or mock RPC responses in this path.As per coding guidelines,
tests/**: “Tests must use mocks for RPC calls, no real network.”🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_surfpool/test_launch.py` around lines 61 - 80, This test performs real RPC calls via surfpool_rpc using launch_token and get_token_info; either convert it to an integration-only test (add an integration marker/rename so it is excluded from default tests) or replace the external calls with mocks; specifically, mock the launch_token and get_token_info calls (or the underlying RPC client used by them) to return the expected result dicts and signatures, and ensure assertions remain the same while removing any network I/O in the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/pumpfun_cli/protocol/instructions.py`:
- Around line 281-291: The function build_create_instructions should make the
optional flags and token_program keyword-only to avoid accidental positional
misbinding: change the signature so that parameters after uri (is_mayhem,
is_cashback, token_program) are declared as keyword-only (e.g., add a * after
the uri parameter) so callers must name is_mayhem, is_cashback, and
token_program explicitly; update any internal references to those names if
needed but no call-site changes should be required.
---
Duplicate comments:
In `@tests/test_surfpool/test_launch.py`:
- Around line 61-80: This test performs real RPC calls via surfpool_rpc using
launch_token and get_token_info; either convert it to an integration-only test
(add an integration marker/rename so it is excluded from default tests) or
replace the external calls with mocks; specifically, mock the launch_token and
get_token_info calls (or the underlying RPC client used by them) to return the
expected result dicts and signatures, and ensure assertions remain the same
while removing any network I/O in the test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 8bf5abe7-8527-4cda-82bf-9464fa2b8ad9
📒 Files selected for processing (3)
src/pumpfun_cli/protocol/instructions.pytests/test_protocol/test_instructions.pytests/test_surfpool/test_launch.py
|
@coderabbitai resolve |
✅ Actions performedComments resolved and changes approved. |
Summary
is_cashback_enabled(OptionBool) through all three layers (commands/→core/→protocol/) for thecreate_v2instruction, exposed as--cashbackCLI flagbuild_create_instructionsonly whenis_mayhem=True, but the IDL requires them always — this caused allcreate_v2calls to fail on-chain withAccountNotEnoughKeysis_cashback_enabledas a single Borsh byte afteris_mayhem_modein instruction dataTest plan
uv run pytest tests/ -q)--cashbackflag in help outputmayhem × cashback × initial_buymatrix, all verified on-chain:test_launch_default/test_launch_cashback/test_launch_mayhem/test_launch_mayhem_cashbacktest_launch_default_with_buy/test_launch_cashback_with_buy/test_launch_mayhem_with_buy/test_launch_mayhem_cashback_with_buy🤖 Generated with Claude Code
Protocol Layer & Fund Handling
This PR directly modifies
build_create_instructions, which constructs thecreate_v2instruction sent to the pump.fun program to launch tokens with real SOL. The changes affect transaction construction in two ways:Critical Bug Fix (Protocol)
is_mayhem=True, but the on-chain IDL requires them unconditionally. This omission caused "AccountNotEnoughKeys" failures when creating tokens without the mayhem flag enabled.create_accounts(lines in protocol/instructions.py show accounts 10-14 are now always present).is_writable=True, consistent with it being a vault account that receives/manages funds.New Cashback Serialization
is_cashbackboolean flag is serialized as a single Borsh byte immediately afteris_mayhemin the instruction data usingstruct.pack("<?", is_cashback).Transaction Construction Changes
The instruction data format now includes:
This affects all create_v2 transactions sent via
client.send_tx()inlaunch_token()(core/launch.py, line 114).Architectural Flow
The change properly threads the
--cashbackflag through the system:--cashbacktyper optionis_cashbackparameter, passes to protocol layer, includes in response dictNo violations of abstraction layers—each layer has appropriate responsibility.
Testing & Verification