Refresh the vendored IDLs from pump-fun/pump-public-docs @ 9c82f61 and move all
pump.fun trading onto the v2 instruction interface. This is required, not
optional: legacy buy/sell cannot trade coins paired against a quote asset other
than SOL, and USDC is already whitelisted in the on-chain Global account.
Protocol changes absorbed:
- buy_v2 (27 accounts) / sell_v2 (26 accounts) replace the legacy instructions.
Every account is mandatory and the order is identical for all coins, so the
conditional cashback/mayhem account lists are gone. Legacy remains available
via PumpFunInstructionBuilder(use_legacy_instructions=True).
- BondingCurve is 151 bytes: virtual_sol_reserves -> virtual_quote_reserves,
real_sol_reserves -> real_quote_reserves, plus quote_mint at offset 83. Old
field names are kept as aliases so existing callers keep working.
- v2 instruction data drops the track_volume OptionBool; amounts are in the
quote mint's raw units rather than always lamports.
- create_v2 carries a non-SOL quote mint as optional remaining accounts 17-19,
and CreateEvent gained quote_mint, so extreme_fast_mode can resolve the quote
asset without an extra fetch.
USDC support: new trade.quote_amounts and filters.allowed_quote_mints config,
accepting "sol"/"usdc" aliases or raw mints. Amounts are per-quote-mint because
1 USDC and 1 SOL are not interchangeable. A coin whose quote mint has no
configured amount is skipped rather than traded at the wrong size, so SOL-only
configs are unaffected.
Bug fixes found while verifying:
- The logs and blocks listeners set no websocket max_size, so any frame over
1 MiB closed the connection with 1009 and the token in it was lost. Raised
to 32 MiB.
- PumpSwap priced against the raw quote vault balance, ignoring the new
Pool.virtual_quote_reserves (i128 at offset 245; live pools are 301 bytes).
Upstream's note that this field is 0 everywhere is out of date: a live pool
carries 17.58 SOL against a 148 SOL vault, a 10.15% price error.
- The seller read curve state once at confirmed commitment and silently fell
back to create-time values, risking a stale creator_vault and ConstraintSeeds.
It now retries at processed, matching the buyer.
- Account cleanup would burn wrapped SOL when force_burn was set, destroying
value that closing the account returns. WSOL is now closed without burning.
- The mint scripts treated a landed transaction as a successful one, so a
reverted buy printed as success. They now assert the on-chain result.
Compute unit limits retuned from mainnet measurements: buy 100k -> 180k,
sell 60k -> 120k. Mint-and-buy is no longer atomic, because create_v2 plus
buy_v2 exceeds the 1232-byte transaction limit; both mint scripts send two
transactions.
Adds learning-examples/pump_v2.py as one shared, standalone v2 toolkit for the
example scripts, and three verification scripts: an offline layout check
against the IDL, a no-funds mainnet simulation, and a live listener matrix that
buys, sells and closes the ATA per listener.
Verified on mainnet: all four listeners (geyser, logs, blocks, pumpportal) and
all eight example scripts completed a real buy, sell and ATA close, each
confirmed by reading the transaction result back rather than trusting
confirmation alone. The USDC path is verified structurally only; no USDC-paired
coin could be found on-chain to exercise it.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* chore(pumpswap+docs): post-2026-04-28-cutover PumpSwap unlock + IDL docs
Drops the `INCLUDE_BREAKING_FEE_ACCOUNTS = False` gate in the PumpSwap
learning examples so the +2 breaking-fee accounts (fee recipient
readonly + its quote-mint ATA mutable) are always appended after
`pool-v2`. Mainnet pump-amm rejects this format pre-cutover (verified
6023 Overflow), so this PR is intentionally **draft until 2026-04-28
16:00 UTC** when the cutover happens; mark it ready-for-review and live-
test then.
Also captures the protocol gotchas we learned during this migration:
- README: a new "2026-04-28 program upgrade" section + an explicit note
that the vendored IDL is incomplete (missing `bonding-curve-v2` and
`pool-v2` PDAs that the on-chain program actually requires) with
pointers to cross-check against on-chain txs.
- CLAUDE.md: a new "Pump.fun protocol notes" subsection summarising
the same gotchas plus the BC/Pool/CreateEvent layout details and the
extreme_fast_mode gotcha.
Open question (call out at review time, resolve post-cutover):
- BREAKING_FEE_RECIPIENT.md shows PumpSwap cashback account counts of
27 buy / 26 sell vs 26 / 24 non-cashback — the extra cashback account
seed/position isn't documented. Need to sample a real successful
cashback PumpSwap tx after cutover and add the branch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(pumpswap): wire cashback layout for post-2026-04-28 program upgrade
Cashback PumpSwap pools require extra writable accounts inserted before
pool-v2. Identified layouts by sampling on-chain post-cutover txs:
- buy: insert user_volume_accumulator_quote_ata (27 accounts vs 26)
ref tx 4JaWdExj…fvjK
- sell: insert user_volume_accumulator_quote_ata + user_volume_accumulator
(26 accounts vs 24)
ref tx 4ei1cJV7…NP3
Detect via pool account byte 244 (is_cashback_coin). Adds the standalone
sample_cashback_pumpswap.py used to reverse-engineer the layouts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three small ergonomic fixes uncovered while running every learning
example end-to-end:
copytrading/listen_wallet_transactions.py
Was hardcoded to WALLET_TO_TRACK = "...". Now accepts argv[1] so
you can run it without editing the file.
pumpswap/get_pumpswap_pools.py
Same pattern (TOKEN_MINT placeholder) and the underlying
getProgramAccounts call would also time out at the default 30s
on busy mainnet RPCs — bumped both AsyncClient timeouts to 120s.
bonding-curve-progress/get_graduating_tokens.py
Bumped RPC timeout 120s → 240s for the same reason. The threshold
scan over all pump.fun bonding curves still occasionally exceeds
even that on overloaded RPCs (it's a known-heavy query); a smaller
threshold or memcmp-narrowed filter is the proper long-term fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PumpSwap (manual_buy_pumpswap.py / manual_sell_pumpswap.py)
- Real on-chain pump-swap buys use 24 accounts; the IDL is incomplete
(lists 23). Missing 24th account is pool-v2 PDA, derived from seed
["pool-v2", base_mint] under the pump-amm program.
- Without it, pump-amm throws AnchorError 6023 (Overflow) at buy.rs:400/414
after the trade transfers complete (the source of the earlier "pre-existing
overflow" — was actually a missing account, not a math bug).
- find_pool_v2(base_mint) added; appended to both buy and sell account lists
after fee_program. The April-28 breaking-fee accounts (still gated behind
INCLUDE_BREAKING_FEE_ACCOUNTS) come after pool-v2 — matching the doc's
"All accounts till bonding-curve-v2 and pool-v2 remain the same."
- AsyncClient timeout bumped to 120s so the heavy getProgramAccounts pool
lookup doesn't time out on slower RPC paths.
- Live-verified on mainnet with 9PwadsGz...pump:
buy 2xgdJJsDMzoMyxJzrCATKwGfpX7M... err=None (24 accounts)
sell 4vdBkGpCMQYEWncj5k1suGzKPUMQ... err=None (24 accounts)
manual_buy_geyser.py
- Fixes IndexError when create tx references ALT-loaded keys
(matches the same fix applied to manual_buy.py).
- Re-enables the 15s sleep + on-chain price/fee_recipient lookup that
were commented out for testing — needed for buys on real pools.
- Live-verified: 45wSgX2Pu1LLZWLgu3e9qdhRaGJjqwMqQP5HdeV7zMBqNXziB2uEgxQd5bAqvAhBLFnAqzbuK3LAWowhxZxdemJ
(18-account buy, err=None) on Token-2022 cashback-enabled INSIDER mint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extends the 2026-04-28 program-upgrade prep (commit c25e2ed) to the
remaining trade scripts:
mint_and_buy.py — 18-account buy after bonding-curve-v2.
Tested live with a fresh TEST mint (Solscan
sig 62EZFCKVuxvqmzj...), succeeded.
mint_and_buy_v2.py — 18-account buy. Tested live with a
mayhem-mode TEST2 token (Token-2022 + 5
mayhem accounts), Solscan sig 44SvQSrhmHy...,
succeeded.
pumpswap/manual_buy_pumpswap.py / manual_sell_pumpswap.py
— Adds the 2 new pump-swap accounts (fee
recipient + its quote-mint ATA) gated behind
INCLUDE_BREAKING_FEE_ACCOUNTS = False; flip
to True after 2026-04-28 16:00 UTC.
Pre-existing program-side overflow at
buy.rs:400 (AnchorError 6023) flagged in
a comment — affects current pump-swap
buys, unrelated to this upgrade.
Both pumpswap scripts now also accept TOKEN_MINT via argv[1].
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>