Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Validate: each returns valid JSON arrays, non-empty (except search which may be
Find an active bonding-curve mint and a graduated mint from the discovery results above.

```bash
uv run pumpfun info <ACTIVE_MINT> # graduated=false, price_sol > 0
uv run pumpfun info <ACTIVE_MINT> # graduated=false, price > 0, quote_symbol set
uv run pumpfun info <GRADUATED_MINT> # graduated=true, pool_address present
uv run pumpfun info 11111111111111111111111111111111 # should error
```
Expand Down Expand Up @@ -92,16 +92,16 @@ uv run pumpfun sell <ACTIVE_MINT> all --confirm
- Add a ~5 second delay between buy and sell -- immediate sell after buy often fails with "No tokens to sell" due to RPC state lag (ISSUE-3)
- If sell fails, retry after a few seconds -- this is a known timing issue, not a code bug

## Group 7: PumpSwap AMM Trading (SPENDS SOL -- CURRENTLY BROKEN)

**Known bug:** PumpSwap buys consistently fail with error 6023 (NotEnoughTokensToSell). Test anyway to check if it has been fixed.
## Group 7: PumpSwap AMM Trading (SPENDS SOL)

```bash
uv run pumpfun buy <GRADUATED_MINT> 0.001 --force-amm --confirm
uv run pumpfun buy <GRADUATED_MINT> 0.001 --confirm # auto-route
uv run pumpfun sell <GRADUATED_MINT> all --confirm
```

If still failing with 6023, document and move on.
A buy on a cashback pool exceeds a v0 transaction and is sent as v1; a failure
there points at the RPC endpoint refusing v1 sends, not at the instruction.

## Group 8: Transaction Status (safe, read-only RPC)

Expand All @@ -123,6 +123,8 @@ uv run pumpfun claim-cashback --confirm # may succeed or be no-op
uv run pumpfun close-volume-acc --confirm # may succeed or be no-op
uv run pumpfun collect-creator-fee --confirm # likely "No creator fees"
uv run pumpfun migrate <ACTIVE_MINT> --confirm # should error: "not complete"
uv run pumpfun --json launch --name X --ticker X --uri https://example.com/token-v2.json --creator-fee-bps 100 # should error: fee needs a QuoteControl mint
uv run pumpfun --json launch --name X --ticker X --uri https://example.com/token-v2.json --mayhem --quote-mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v # should error: mayhem needs SOL
```

## Group 10: Wallet Cleanup (SPENDS SOL -- recovers rent)
Expand Down
47 changes: 35 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ src/pumpfun_cli/
├── output.py # render() + error() — TTY-aware output
├── commands/ # Thin CLI layer (config, info, launch, tokens, trade, tx_status, wallet)
├── core/ # Business logic (config, info, launch, pumpswap, tokens, trade, tx_status, validate, wallet)
└── protocol/ # Solana primitives (address, client, contracts, curve, idl_parser, instructions, pumpswap)
└── protocol/ # Solana primitives (address, client, contracts, curve, idl_parser, instructions, pumpswap, quote)

tests/
├── test_commands/ # CLI smoke tests
Expand All @@ -66,7 +66,7 @@ tests/

**Output:** Use `render(data, json_mode)` for all output — returns `True` if it emitted JSON (non-TTY or `--json`), `False` in TTY mode. Commands use `if not render(...):` to branch into human-readable output. Use `error(msg, hint, exit_code)` for failures — prints to stderr and raises `SystemExit`. Never use `print()`.

**Error handling:** `error()` raises `SystemExit` — code after it is unreachable. Core functions return `dict` with `"error"` key for expected failures (graduated tokens, not found, slippage exceeded, insufficient_balance). Catch `ValueError` for wrong wallet password in every command that decrypts. Buy/sell functions perform pre-trade balance validation — SOL balance for buys (including fees + ATA rent), token balance for sells with specific amounts.
**Error handling:** `error()` raises `SystemExit` — code after it is unreachable. Core functions return `dict` with `"error"` key for expected failures (graduated tokens, not found, slippage exceeded, insufficient_balance). Catch `ValueError` for wrong wallet password in every command that decrypts. Buy/sell functions perform pre-trade balance validation — SOL for fees and rent, the quote asset for the spend, token balance for sells with specific amounts.

**Auto-routing:** When `buy_token` / `sell_token` returns `{"error": "graduated"}`, the command layer in `commands/trade.py` automatically retries via `buy_pumpswap` / `sell_pumpswap` (PumpSwap AMM). Never suppress or swallow the `"graduated"` error in core — the routing decision belongs in the command layer.

Expand Down Expand Up @@ -101,19 +101,42 @@ from pumpfun_cli.output import render, error
## Working with Solana Accounts

```python
# Derive PDA
from pumpfun_cli.protocol.address import derive_bonding_curve

# Fetch and decode
data = await client.get_account_data(address)
state = idl.decode_account_data(data, "BondingCurve", skip_discriminator=True)

# Build instructions
from pumpfun_cli.protocol.instructions import build_buy_exact_sol_in_instructions
ixs = build_buy_exact_sol_in_instructions(idl=idl, mint=mint, user=keypair.pubkey(), ...)
sig = await client.send_tx(ixs, [keypair], compute_units=..., confirm=True)
from pumpfun_cli.protocol.curve import parse_bonding_curve
from pumpfun_cli.protocol.instructions import build_buy_exact_quote_in_v2_instruction
from pumpfun_cli.protocol.quote import get_mint_info

resp = await client.get_account_info(derive_bonding_curve(mint))
state = parse_bonding_curve(bytes(resp.value.data))
quote_program, quote_decimals = await get_mint_info(client, state["quote_mint"])
ix = build_buy_exact_quote_in_v2_instruction(mint=mint, creator=state["creator"], ...)
sig = await client.send_tx([ix], [keypair], compute_units=..., confirm=True)
```

## Protocol rules

Read `docs/pumpfun-protocol.md` in pumpfun-bonkfun-bot before changing account
lists; these are the ones this CLI depends on.

- **Amounts are in the coin's quote asset**, read from `BondingCurve.quote_mint`
(all zeros means SOL; instructions take wrapped SOL there). Its decimals come
from the mint via `get_mint_info`; never assume 9.
- Bonding-curve trades use `buy_exact_quote_in_v2` / `sell_v2`: 27 / 26
accounts, identical for every coin. A SOL coin's quote accounts are only
seed-checked, so don't create the user's WSOL ATA for them.
- `creator_vault` derives from `BondingCurve.creator` as stored. On holder-reward
and fee-sharing coins that is not the wallet that launched the coin.
- PumpSwap swaps carry accounts the IDL omits: cashback account(s) on a cashback
pool, then `pool-v2` **only on a canonical pool** (`coin_creator` set), then the
buyback recipient and its quote ATA last. The canonical pool is derived from the
mint and the curve's quote mint.
- `send_tx` sends v0 and falls back to v1 when the transaction exceeds 1232
bytes (a cashback-pool buy, a launch with a buy). v1 carries the compute budget
in its header.
- `create_v2` rejects cashback (6082). A creator fee only applies on a coin
priced in a `QuoteControl` mint, and mayhem coins must be SOL-priced; launch
refuses both before sending.

## Environment

```bash
Expand Down
31 changes: 21 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,19 @@ pumpfun sell <mint> all
# Check if a transaction landed
pumpfun tx-status <signature>

# Launch a token
pumpfun launch --name "MyToken" --ticker "MTK" --desc "A great token"
# Launch a token, buying it in the same transaction
pumpfun launch --name "MyToken" --ticker "MTK" --uri https://example.com/mytoken.json --buy 0.1
```

pump.fun no longer accepts anonymous metadata uploads, so `launch` takes the
URI of a metadata JSON you host (`name`, `symbol`, `description`, `image`).
Without `--uri` it still tries the upload and says so when it is refused.

Amounts are in the coin's quote asset. Most pump.fun coins are priced in SOL,
but a coin can be priced in USDC or another admitted mint; `buy`, `sell` and
`info` read it from the coin and label their output with it. Buying such a coin
spends that asset, so the wallet has to hold it.

## Commands

```
Expand All @@ -83,18 +92,20 @@ Token info (requires RPC):
pumpfun info <mint> Price, bonding progress, reserves

Trading (requires RPC + wallet):
pumpfun buy <mint> <sol_amount> [--slippage N] [--dry-run] [--confirm]
pumpfun sell <mint> <amount|all> [--slippage N] [--dry-run] [--confirm]
pumpfun migrate <mint> [--slippage N] [--confirm]
pumpfun claim-cashback <mint> [--confirm]
pumpfun collect-creator-fee <mint> [--confirm]
pumpfun close-volume-acc <mint> [--confirm]
pumpfun buy <mint> <amount> [--slippage N] [--force-amm] [--dry-run] [--confirm]
pumpfun sell <mint> <amount|all> [--slippage N] [--force-amm] [--dry-run] [--confirm]
pumpfun migrate <mint> [--confirm]
pumpfun claim-cashback [--quote-mint M] [--confirm]
pumpfun collect-creator-fee [--quote-mint M] [--confirm]
pumpfun close-volume-acc [--confirm]

Transaction inspection (requires RPC):
pumpfun tx-status <signature> Confirmation status, slot, fee, errors

Token launch (requires RPC + wallet):
pumpfun launch --name X --ticker Y --desc Z [--image path] [--buy N]
pumpfun launch --name X --ticker Y [--uri U | --desc D --image P] [--buy N]
[--quote-mint M] [--creator-fee-bps N] [--holder-reward]
[--mayhem] [--slippage N] [--confirm]

Wallet management:
pumpfun wallet create Generate + encrypt keypair
Expand Down Expand Up @@ -131,7 +142,7 @@ Global options:
| `info` | Solana RPC (`getAccountInfo` for bonding curve PDA) | JSON-RPC |
| `buy` | Solana RPC (`getAccountInfo`, `getLatestBlockhash`, `sendTransaction`) | JSON-RPC |
| `sell` | Solana RPC (`getAccountInfo`, `getTokenAccountBalance`, `getLatestBlockhash`, `sendTransaction`) | JSON-RPC |
| `launch` | `pump.fun/api/ipfs` (metadata upload) + Solana RPC (`sendTransaction`) | HTTPS + JSON-RPC |
| `launch` | Solana RPC (`sendTransaction`); `pump.fun/api/ipfs` only without `--uri` | JSON-RPC (+ HTTPS) |
| `tx-status` | Solana RPC (`getTransaction`) | JSON-RPC |
| `migrate` | Solana RPC (`sendTransaction`) | JSON-RPC |
| `claim-cashback` | Solana RPC (`sendTransaction`) | JSON-RPC |
Expand Down
Loading
Loading