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
13 changes: 10 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ src/pumpfun_cli/
├── crypto.py # AES-256-GCM wallet encryption (scrypt KDF)
├── 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, quote)
├── core/ # Business logic (config, info, launch, launchlab, pumpswap, tokens, trade, tx_status, validate, wallet)
└── protocol/ # Solana primitives (address, client, contracts, curve, idl_parser, instructions, launchlab, pumpswap, quote)

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

**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.
**Auto-routing:** `_route` in `commands/trade.py` picks the venue from the errors core returns: `{"error": "graduated"}` from `buy_token` / `sell_token` retries on PumpSwap, `{"error": "not_found"}` retries on LaunchLab (`buy_launchlab` / `sell_launchlab`). Never suppress or swallow those errors in core — the routing decision belongs in the command layer. `info` falls back to LaunchLab the same way in `core/info.py`.

**Imports:** stdlib → third-party → local. Example:
```python
Expand Down Expand Up @@ -133,6 +133,13 @@ lists; these are the ones this CLI depends on.
- `migrate_v2` also carries accounts the IDL omits: after its 27, the new pool's
boost vault authority (`["boost_vault", pool]` on PumpSwap) and that
authority's quote token account. Without them PumpSwap reverts with 6027.
- LaunchLab (`protocol/launchlab.py`) pools are keyed by base and quote mint.
The SOL pool is derived; any other quote is found by `getProgramAccounts`
on the base mint (PoolState offset 205). Swaps are the IDL's 15 accounts plus
the system program and the platform and creator fee vaults
(`[platform_config, quote]`, `[creator, quote]`). The curve fee is
GlobalConfig's trade fee plus PlatformConfig's fee and creator fee, read
live; a Token-2022 coin's transfer fee comes off what arrives.
- `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.
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ 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.

`buy`, `sell` and `info` also work on coins launched on Raydium LaunchLab, the
program behind letsbonk.fun, StonkFun and other launchpads: a mint with no
pump.fun bonding curve is looked up there, and the output says `"venue":
"launchlab"` and which launchpad (`platform`). A LaunchLab coin priced in
anything but SOL is found with `getProgramAccounts`, so it needs an RPC that
serves it. Token-2022 transfer fees are taken into account in the amounts.

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
Expand Down Expand Up @@ -106,7 +113,7 @@ Token discovery (zero config; price and progress added when an RPC is set):
pumpfun tokens search <query> Search by name or ticker

Token info (requires RPC):
pumpfun info <mint> Price, bonding progress, reserves
pumpfun info <mint> Price, bonding progress, reserves (pump.fun or LaunchLab)

Trading (requires RPC + wallet):
pumpfun buy <mint> <amount> [--slippage N] [--force-amm] [--dry-run] [--confirm]
Expand Down Expand Up @@ -157,9 +164,9 @@ Global options:
| `tokens recommended` | `frontend-api-v3.pump.fun/coins/recommendations` | HTTPS |
| `tokens search` | `frontend-api-v3.pump.fun/coins/search-unrestricted` | HTTPS |
| `tokens *` with an RPC set | + Solana RPC (`getMultipleAccounts` for the bonding curves) | JSON-RPC |
| `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 |
| `info` | Solana RPC (`getAccountInfo` for bonding curve PDA; LaunchLab: `getMultipleAccounts`, `getProgramAccounts`) | JSON-RPC |
| `buy` | Solana RPC (`getAccountInfo`, `getLatestBlockhash`, `sendTransaction`; LaunchLab adds `getMultipleAccounts`, `getProgramAccounts`) | JSON-RPC |
| `sell` | Solana RPC (`getAccountInfo`, `getTokenAccountBalance`, `getLatestBlockhash`, `sendTransaction`; LaunchLab as `buy`) | 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 |
Expand Down
Loading
Loading