mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-08-08 04:57:45 +00:00
02343b775b
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>
256 lines
10 KiB
Markdown
256 lines
10 KiB
Markdown
# Pump Bot Development Guide
|
|
|
|
This is a trading bot for pump.fun and letsbonk.fun platforms that snipes new tokens and implements various trading strategies.
|
|
|
|
## Project Structure
|
|
|
|
- `src/` - Main source code
|
|
- `learning-examples/` - Educational scripts and examples
|
|
- `bots/` - Bot configuration files (YAML)
|
|
- `logs/` - Log files from bot executions
|
|
- `idl/` - Interface definition files for Solana programs
|
|
|
|
## Bash Commands & Development
|
|
|
|
### Setup Commands
|
|
```bash
|
|
# Install dependencies
|
|
uv sync
|
|
|
|
# Activate virtual environment (Unix/macOS)
|
|
source .venv/bin/activate
|
|
|
|
# Install as editable package
|
|
uv pip install -e .
|
|
```
|
|
|
|
### Running the Bot
|
|
```bash
|
|
# Run as installed package
|
|
pump_bot
|
|
|
|
# Run directly
|
|
uv run src/bot_runner.py
|
|
```
|
|
|
|
### Learning Examples
|
|
```bash
|
|
# Bonding curve status
|
|
uv run learning-examples/bonding-curve-progress/get_bonding_curve_status.py TOKEN_ADDRESS
|
|
|
|
# Listen to migrations
|
|
uv run learning-examples/listen-migrations/listen_logsubscribe.py
|
|
uv run learning-examples/listen-migrations/listen_blocksubscribe_old_raydium.py
|
|
|
|
# Compute associated bonding curve
|
|
uv run learning-examples/compute_associated_bonding_curve.py
|
|
|
|
# Listen to new tokens
|
|
uv run learning-examples/listen-new-tokens/listen_logsubscribe_abc.py
|
|
uv run learning-examples/listen-new-tokens/compare_listeners.py
|
|
```
|
|
|
|
### Verifying pump.fun v2 trade instructions
|
|
```bash
|
|
# Offline: cross-check buy_v2/sell_v2 account layouts, PDA/ATA derivations,
|
|
# instruction encoding and quote-asset config against idl/pump_fun_idl.json
|
|
uv run learning-examples/verify_v2_account_layout.py
|
|
|
|
# Mainnet, no funds moved: simulate buy_v2/sell_v2 for one coin, report CU
|
|
uv run learning-examples/simulate_v2_trades.py <MINT>
|
|
|
|
# Mainnet, no funds moved: run the bot's whole buy path against a fresh coin
|
|
uv run learning-examples/simulate_bot_buy_path.py
|
|
uv run learning-examples/simulate_bot_buy_path.py --no-extreme-fast
|
|
```
|
|
Run all three after any pump.fun program upgrade. The simulations report
|
|
`unitsConsumed`; use it to retune `get_buy_compute_unit_limit` /
|
|
`get_sell_compute_unit_limit` in `platforms/pumpfun/instruction_builder.py`.
|
|
|
|
### Code Quality
|
|
```bash
|
|
# Format code
|
|
ruff format
|
|
|
|
# Lint code
|
|
ruff check
|
|
|
|
# Fix linting issues
|
|
ruff check --fix
|
|
```
|
|
|
|
## Pump.fun protocol notes (gotchas)
|
|
|
|
The IDLs under `idl/` are vendored verbatim from `github.com/pump-fun/pump-public-docs`
|
|
(`idl/pump.json` → `pump_fun_idl.json`, `pump_amm.json` → `pump_swap_idl.json`,
|
|
`pump_fees.json`). Refresh them from upstream rather than hand-editing.
|
|
|
|
### Quote assets and the v2 trade instructions (current path)
|
|
|
|
- pump.fun supports quote assets other than SOL. `BondingCurve.quote_mint` is
|
|
`Pubkey::default()` (all zeros) for SOL-paired coins; USDC
|
|
(`EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`) is whitelisted in `Global`.
|
|
**Legacy `buy`/`sell` cannot trade non-SOL-paired coins at all.**
|
|
- The bot uses **`buy_v2` (27 accounts)** and **`sell_v2` (26 accounts)**. Every
|
|
account is mandatory and the order is identical for every coin — SOL or USDC
|
|
paired, mayhem or not, cashback or not. `sell_v2` is `buy_v2` minus
|
|
`global_volume_accumulator`. Layouts live in `_BUY_V2_ACCOUNTS` /
|
|
`_SELL_V2_ACCOUNTS` in `platforms/pumpfun/instruction_builder.py` and are
|
|
machine-checked against the IDL by `learning-examples/verify_v2_account_layout.py`.
|
|
- v2 args carry **no `track_volume` OptionBool** (24-byte data: discriminator +
|
|
two u64). Volume tracking is unconditional now that `user_volume_accumulator`
|
|
is mandatory. `max_sol_cost`/`min_sol_output` are in the **quote mint's** raw
|
|
units — lamports for SOL, 1e-6 for USDC.
|
|
- Even for SOL-paired coins you must pass **wrapped SOL** as `quote_mint`, not
|
|
`Pubkey::default()`. Transfers still happen in native SOL, and the
|
|
`associated_quote_*` accounts are only seed-constrained — do **not** create the
|
|
user's WSOL ATA, it would burn ~0.002 SOL of rent for nothing.
|
|
- Fee recipients: 24 total, in three sets of 8 (`NORMAL_FEE_RECIPIENTS`,
|
|
`RESERVED_FEE_RECIPIENTS` for mayhem coins, `BUYBACK_FEE_RECIPIENTS`). Every
|
|
v2 buy/sell needs a `fee_recipient` **and** a `buyback_fee_recipient`.
|
|
- `sharing_config` (PDA `["sharing-config", base_mint]`) lives under the **pump
|
|
fees program**, not the pump program. Easy to derive against the wrong program.
|
|
|
|
### BondingCurve account layout
|
|
|
|
- The account is **151 bytes**: 8-byte discriminator, then
|
|
`virtual_token_reserves, virtual_quote_reserves, real_token_reserves,
|
|
real_quote_reserves, token_total_supply` (u64 each), `complete` (1B, offset 48),
|
|
`creator` (32B, offset 49), `is_mayhem_mode` (offset 81),
|
|
`is_cashback_coin` (offset 82), `quote_mint` (32B, offset 83), then 36 reserved
|
|
zero bytes. The documented struct is 115 bytes; the extra 36 are padding.
|
|
- The SOL-named fields were **renamed**: `virtual_sol_reserves` →
|
|
`virtual_quote_reserves`, `real_sol_reserves` → `real_quote_reserves`. The
|
|
curve manager still exposes the old names as aliases, so pre-existing callers
|
|
keep working for SOL-paired coins — but anything doing arithmetic must scale by
|
|
the quote mint's decimals (`quote_units_per_token`), not a hardcoded 1e9.
|
|
- PumpSwap `Pool` gained a trailing **`virtual_quote_reserves: i128`** (16 bytes,
|
|
offset 245). Pool fields end at 261; live accounts are **301 bytes** with
|
|
trailing padding. Quote against **effective** reserves:
|
|
`pool_quote_token_account.amount + virtual_quote_reserves`.
|
|
**Upstream's release note claims it is 0 on all pools — that is out of date.**
|
|
Verified on mainnet: pool `6Bv1JM1deBPe…` carries 17.584505433 SOL of virtual
|
|
reserves against a 148.455 SOL vault, so quoting off the raw vault balance
|
|
under-prices by ~10.6%. It is `i128`, not `u64` — reading 8 bytes happens to
|
|
work only while the high half is zero.
|
|
|
|
### Coin creation
|
|
|
|
- The IDL instruction is `create_v2` (snake_case). Args: `name (str),
|
|
symbol (str), uri (str), creator (pubkey), is_mayhem_mode (bool),
|
|
is_cashback_enabled (OptionBool 1B)`. `OptionBool` is a struct wrapping a single
|
|
bool — serialized as 1 byte, not 2.
|
|
- `create_v2` accounts 1-16 are in the IDL; accounts **17-19 are optional
|
|
remaining accounts** (`quote_mint`, `associated_quote_bonding_curve`,
|
|
`quote_token_program`) appended only for a non-SOL quote mint. All three or
|
|
none. This is the only way to read a new coin's quote asset from the
|
|
instruction rather than the event.
|
|
- `extreme_fast_mode` skips the curve-state price fetch but still refreshes
|
|
mayhem/cashback/creator/**quote_mint** from chain, because the wrong quote mint
|
|
means spending the wrong balance entirely. Event parsers also populate
|
|
`quote_mint` from `CreateEvent` (which gained `quote_mint` and
|
|
`virtual_quote_reserves` as trailing fields).
|
|
|
|
### Legacy instructions (fallback only)
|
|
|
|
Retained behind `PumpFunInstructionBuilder(..., use_legacy_instructions=True)`.
|
|
The IDL under-reports these: `buy` is **18 accounts** on-chain (IDL lists 16) and
|
|
`sell` is **16 non-cashback / 17 cashback** (IDL lists 14). The extras are
|
|
`bonding-curve-v2` (PDA `["bonding-curve-v2", mint]`) followed by a buyback fee
|
|
recipient (mutable); the cashback sell path also inserts
|
|
`user_volume_accumulator` before `bonding-curve-v2`. Prefer v2 — it is the
|
|
interface pump.fun maintains.
|
|
|
|
## Code Style & Conventions
|
|
|
|
### Python Style (Ruff Configuration)
|
|
- **Line length**: 88 characters
|
|
- **Indentation**: 4 spaces
|
|
- **Target Python**: 3.11+
|
|
- **Quote style**: Double quotes
|
|
- **Import sorting**: Enabled
|
|
|
|
### Linting Rules
|
|
- Security best practices (S)
|
|
- Type annotations (ANN)
|
|
- Exception handling (BLE, TRY)
|
|
- Code complexity (C90)
|
|
- Pylint conventions (PL)
|
|
- No commented-out code (ERA)
|
|
|
|
### Code Organization
|
|
- **Imports**: Standard library, third-party, local imports
|
|
- **Docstrings**: Google-style for functions and classes
|
|
- **Type hints**: Required for all public functions
|
|
- **Logging**: Use `get_logger(__name__)` pattern
|
|
- **Error handling**: Comprehensive try-catch with proper logging
|
|
|
|
### File Structure Patterns
|
|
- `__init__.py` files for all packages
|
|
- Separate concerns: client, trading, monitoring, platforms
|
|
- Abstract base classes in `interfaces/`
|
|
- Platform-specific implementations in `platforms/`
|
|
|
|
## Workflow & Development Practices
|
|
|
|
### Configuration Management
|
|
- Environment variables in `.env` file
|
|
- Bot configurations in YAML files under `bots/`
|
|
- Platform detection from config files
|
|
- Validation of platform-listener combinations
|
|
|
|
### Logging
|
|
- Timestamped log files in `logs/` directory
|
|
- Format: `{bot_name}_{timestamp}.log`
|
|
- Different log levels for development vs production
|
|
- Centralized logger utility in `utils/logger.py`
|
|
|
|
### Trading Architecture
|
|
- Universal trader pattern for platform abstraction
|
|
- Platform-specific implementations (pumpfun, letsbonk)
|
|
- Position tracking and management
|
|
- Priority fee management (dynamic/fixed)
|
|
|
|
### Monitoring Systems
|
|
- Multiple listener types: logs, blocks, geyser, pumpportal
|
|
- Universal listeners with platform abstraction
|
|
- Event parsing and processing
|
|
- Real-time data stream handling
|
|
|
|
### Development Workflow
|
|
1. Make changes to source code
|
|
2. Run `ruff check --fix` for linting
|
|
3. Run `ruff format` for formatting
|
|
4. Test with learning examples (standalone scripts) before deploying bots
|
|
5. Use separate processes for production bot instances
|
|
|
|
### Bot Configuration
|
|
- YAML-based configuration files
|
|
- Environment variable interpolation
|
|
- Platform-specific settings
|
|
- Trading parameters (slippage, amounts, timeouts)
|
|
- Filter configurations for token selection
|
|
- Cleanup and account management settings
|
|
|
|
### Testing Strategy
|
|
- Learning examples serve as integration tests
|
|
- Manual testing with learning scripts
|
|
- Configuration validation before bot startup
|
|
- Logging verification for debugging
|
|
|
|
## Key Features
|
|
|
|
- **Multi-platform support**: pump.fun and letsbonk.fun
|
|
- **Multiple listening methods**: WebSocket logs, block subscription, Geyser
|
|
- **Trading strategies**: Time-based, take profit/stop loss, manual
|
|
- **Priority fee management**: Dynamic and fixed fee strategies
|
|
- **Account cleanup**: Automated token account management
|
|
- **Extreme fast mode**: Skip validation for faster execution
|
|
|
|
## Security Considerations
|
|
|
|
- Private keys stored in environment variables
|
|
- No sensitive data in configuration files
|
|
- Comprehensive input validation
|
|
- Error handling to prevent crashes
|
|
- Rate limiting and retry mechanisms |