How It Works
The bot executes a fully automated token launch lifecycle:
- Load config and primary wallet. Reads
config.toml,.env, and verifies the primary wallet has enough SOL for the entire run. - Pick a random token. Selects an unused token from
tokenlist.jsonalong with its image from theimages/directory. - Generate wallets. Creates a fresh creator wallet, mint keypair, and N buyer wallets. All keypairs are saved to disk before any funds are transferred.
- Fund wallets. Transfers SOL from the primary wallet to the creator and each buyer. Funding includes retry logic with balance verification.
- Create token on pump.fun. Uploads metadata and image to IPFS, then calls PumpPortal's
/api/trade-localto create the token on-chain. - Staggered buys. Buyer wallets take turns purchasing the token in random amounts at random intervals, simulating organic volume.
- Market cap monitoring. Polls the pump.fun API at a configurable interval and alerts when the target market cap is reached. A separate milestone tick computes a
PROFITABLE/UNPROFITABLEreading by comparing observed external SOL value to estimated bot overhead. - Exit. Depending on
execution_mode: manual — typingEXITtriggers an immediate sell, withPAUSE/RESUMEhalting and resuming new buy/sell txs without exiting. auto — the bot self-exits afterprofitable_streak_requiredconsecutivePROFITABLEmilestone ticks, ORmax_duration_secsseconds after the first buy tx, whichever comes first.EXITstill works as a manual override. - Sell verification. After selling, the bot re-checks every buyer's on-chain token balance. If any buyer still holds tokens, it retries the sell (up to 3 rounds).
- Sweep. All remaining SOL from buyer and creator wallets is transferred back to the primary wallet.
- Run summary. At the end of every run, the bot writes
run_summary.jsonto the run directory with execution mode, exit reason, timings, milestone tick counts, and peak market cap / external SOL / our SOL observed.
Architecture
src/
main.rs Orchestrates the 21-step run lifecycle
lib.rs Module declarations
config.rs TOML config deserialization with defaults and validation
wallet.rs Keypair load/save/generate, SOL transfers, SPL token balance queries
token_list.rs JSON token catalog with unused/used tracking
error.rs Unified error enum (BotError)
logging.rs Tracing subscriber initialization
pumpfun/
mod.rs PumpFunClient trait (create, buy, sell, get_market_cap)
types.rs Data structures for API params and responses
portal.rs PumpPortal API client (IPFS upload, trade-local, sell with retries)
config.toml Bot configuration
tokenlist.json Token catalog (unused/used arrays)
images/ Token images (PNG, JPG, GIF, WEBP)
runs/ Keypair persistence (one subdirectory per run)
.env RPC endpoint and log levelPrerequisites
- Rust — cargo 1.89+
- Solana CLI — 1.18+
- Git — 2.42+
- A Solana keypair wallet with SOL on mainnet
- A PumpPortal API key
Setup
1. Clone the repository
$ git clone https://github.com/hadesbaker/hades-spider-bot.git
$ cd hades-spider-bot2. Create your .env file
RPC_URL="https://your-rpc-endpoint.example.com"
RUST_LOG="info"
PUMPPORTAL_API_URL="https://pumpportal.fun"
PUMPPORTAL_API_KEY="your-pumpportal-api-key-here"
RPC_URL should point to a Solana mainnet RPC endpoint. Free tiers
from QuickNode, Helius, or Alchemy work fine.
RUST_LOG controls log verbosity. Options:
trace, debug, info, warn, error.
PUMPPORTAL_API_URL and PUMPPORTAL_API_KEY
come from your PumpPortal account. They're loaded from .env
so your API key never lands in config.toml (or git).
3. Add your primary wallet keypair
Place your Solana keypair JSON file (the 64-byte array format from
solana-keygen) in the project root. The filename should
match primary_wallet_path in config.toml. You
can generate one with:
$ solana-keygen new -o myWallet.jsonThen fund it with SOL on mainnet.
4. Configure config.toml
Edit config.toml to match your desired run parameters.
See the Configuration Reference below for all available options.
5. Add tokens to tokenlist.json
Add entries to the unused array. Each token needs a name,
ticker, description, and an image file in the images/
directory.
{
"unused": [
{
"name": "mytoken",
"ticker": "MYTK",
"description": "my first token",
"image": "images/mytoken.png"
}
],
"used": []
}6. Add token images
Place image files in the images/ directory. Supported
formats: PNG, JPG, JPEG, GIF, WEBP. The filename should match the
token's name field (e.g., images/mytoken.png).
Maximum file size: 15MB.
7. Build and run
$ cargo run --release
# Save logs to a file while still seeing them in the terminal:
$ cargo run --release 2>&1 | tee logs/run.log
# Save logs without ASCI colors:
$ cargo run --release 2>&1 | tee >(sed 's/\x1b\[[0-9;]*m//g' > logs/run.log)Configuration Reference
Strategy
| Variable | Type | Default | Description |
|---|---|---|---|
| strategy | integer | 1 | 1 = deploy + staggered buys, 2 = creator buy + initial buyers + staggered buys, 3 = creator buy + initial buyers + staggered buy/sell simulation |
Wallet
| Variable | Type | Default | Description |
|---|---|---|---|
| primary_wallet_path | string | required | Path to the primary wallet keypair JSON file |
| interaction_mode | string | "portal" | API mode. Only "portal" is currently implemented |
| selected_token | string | "none" | "none" picks randomly from tokenlist.json, or specify "name,TICKER" to choose a specific token |
Funding
| Variable | Type | Default | Description |
|---|---|---|---|
| creator_fund_sol | float | 0.03 | SOL to fund the creator wallet (pays for token creation tx) |
| buyer_fund_sol | float | 1.0 | SOL to fund each buyer wallet |
| buyer_count | integer | 20 | Number of buyer wallets to generate |
Transaction
| Variable | Type | Default | Description |
|---|---|---|---|
| priority_fee_lamports | integer | 100000 | Priority fee per transaction in lamports (1 SOL = 1,000,000,000 lamports) |
| slippage_bps | integer | 1000 | Slippage tolerance in basis points (1500 = 15%) |
Strategy 2 / 3
These variables are used when strategy = 2 or strategy = 3.
| Variable | Type | Default | Description |
|---|---|---|---|
| creator_min_buy_amount | float | 0.0 | Minimum SOL the creator buys after deploying the token |
| creator_max_buy_amount | float | 0.0 | Maximum SOL the creator buys after deploying the token |
| initial_buyer_count | integer | 0 | Number of initial buyer wallets (rapid-fire, no delay) |
| initial_buyer_min_buy_amount | float | 0.0 | Minimum SOL each initial buyer spends |
| initial_buyer_max_buy_amount | float | 0.0 | Maximum SOL each initial buyer spends |
Trade Behavior
| Variable | Type | Default | Description |
|---|---|---|---|
| buy_amount_min_sol | float | 0.01 | Minimum SOL per buy transaction |
| buy_amount_max_sol | float | 0.05 | Maximum SOL per buy transaction. Wider range = more variance |
| trade_delay_min_ms | integer | 500 | Minimum delay between trades in milliseconds |
| trade_delay_max_ms | integer | 3000 | Maximum delay between trades in milliseconds |
Strategy 3
These variables are only used when strategy = 3.
| Variable | Type | Default | Description |
|---|---|---|---|
| buy_probability | float | 0.70 | Probability (0.0–1.0) each trade action is a buy vs a sell |
| sell_pct_min | float | 0.10 | Minimum % of token holdings to sell per sell action (0.0–1.0) |
| sell_pct_max | float | 0.50 | Maximum % of token holdings to sell per sell action (0.0–1.0) |
Market Cap Monitoring
| Variable | Type | Default | Description |
|---|---|---|---|
| target_mc_sol | float | 40.0 | Target market cap in SOL. An alert is logged when this is reached |
| mc_poll_interval_ms | integer | 5000 | How often to check market cap in milliseconds |
Exit and Sell
| Variable | Type | Default | Description |
|---|---|---|---|
| escape_prompt | string | "SELL" | Word to type into the terminal to trigger selling all positions |
| pause_prompt | string | "PAUSE" | Word to type to pause new buy/sell txs without exiting (manual mode) |
| resume_prompt | string | "RESUME" | Word to type to resume after a pause (manual mode) |
| sell_max_retries | integer | 10 | Maximum retry attempts per sell transaction |
Execution Mode
Controls how the bot decides when to exit. manual is interactive;
auto is hands-off.
| Variable | Type | Default | Description |
|---|---|---|---|
| execution_mode | string | "manual" | "manual" = operator drives via EXIT/PAUSE/RESUME. "auto" = bot self-exits on profitable streak or max duration; EXIT still works as override |
| max_duration_secs | integer | 240 | Auto mode only. Hard cap on time-after-first-buy in seconds. If no profitable streak fires before this, the bot exits anyway |
| profitable_streak_required | integer | 2 | Auto mode only. Number of consecutive PROFITABLE milestone ticks required to trigger auto-exit. 1 = exit on first reading |
The max_duration_secs timer starts at the
first successful buy transaction (creator buy,
initial buyer buy, or first staggered buy — whichever fires first),
not at bot launch. This way wallet funding, IPFS upload, and
token-creation overhead don't count against your exposure window.
A milestone tick is PROFITABLE when the observed
external SOL value (held by non-bot wallets) exceeds
5× the bot's estimated overhead. The streak counter resets on any
UNPROFITABLE tick — only consecutive
PROFITABLE readings count.
Directories
| Variable | Type | Default | Description |
|---|---|---|---|
| images_dir | string | "images" | Directory containing token images |
| runs_dir | string | "runs" | Directory for run keypair persistence |
PumpPortal Credentials
PumpPortal credentials are loaded from .env,
not config.toml.
| Env var | Default | Description |
|---|---|---|
| PUMPPORTAL_API_URL | required | PumpPortal API base URL |
| PUMPPORTAL_API_KEY | required | PumpPortal API key |
Run Output
Each run creates a timestamped directory under runs/:
creator.json Creator wallet keypair
mint.json Mint keypair
buyer_00.json Buyer 0 keypair
buyer_01.json Buyer 1 keypair
...
run_info.json Run metadata (pubkeys, token info, timestamp) — written before token creation
run_summary.json Run results (execution mode, exit reason, timings, peak metrics) — written after sweepAll keypairs are saved before funds are transferred. If the bot crashes mid-run, you can use these keypairs to manually recover funds.
run_summary.json fields
| Field | Description |
|---|---|
| execution_mode | "manual" or "auto" |
| exit_reason | "manual_exit", "profitable_streak (xN)", "max_duration (Ns)", or "buy_phase_complete_no_signal" |
| elapsed_total_secs | Wall-clock seconds from strategy start (after wallet selection) |
| elapsed_after_first_buy_secs | Seconds since the first successful buy tx (null if no buy ever succeeded) |
| max_duration_secs | The configured cap (echoed for analysis) |
| profitable_streak_required | The configured streak length (echoed for analysis) |
| profitable_ticks | Total PROFITABLE milestone ticks observed |
| unprofitable_ticks | Total UNPROFITABLE milestone ticks observed |
| first_profitable_at_secs | Seconds after first buy when the first PROFITABLE tick fired (null if never) |
| target_mc_hit_at_secs | Seconds since MC monitor start when target_mc_sol was reached (null if never) |
| target_mc_sol | The configured target (echoed) |
| peak_mc_sol | Highest market cap (SOL) observed during the run |
| peak_ext_sol | Highest external-holder SOL value observed |
| peak_our_sol | Highest bot-held SOL value observed |
SOL Requirements
The bot calculates the total SOL needed before starting:
total = creator_fund_sol + (buyer_count * buyer_fund_sol) + fee_buffer
where: fee_buffer = 0.01 * (buyer_count + 1)For example, with 8 buyers at 1 SOL each:
total = 0.03 + (8 * 1.0) + (0.01 * 9) = 8.12 SOLThe bot will refuse to start if the primary wallet balance is below this amount.
Interested in hades-spider-bot?
This system is proprietary and not open-source. Access is granted on a case-by-case basis through our standard engagement process. If you'd like to evaluate, license, or build on top of hades-spider-bot, reach out through the Request Engagement feature.
Request Engagement