Infrastructure

PumpFun Sniper Technical Deep-Dive: Architecture, Performance, and ShredStream Integration

December 10, 2025AllenHark Engineering

The PumpFun Sniper represents a significant advancement in Solana trading bot architecture. This technical deep-dive explores the engineering decisions, performance optimizations, and infrastructure integrations that let it act on a launch while the block is still being produced, before RPC confirmation.

Table of Contents

  1. Architecture Overview
  2. ShredStream Integration
  3. Detection Pipeline
  4. Transaction Execution
  5. AllenHark Relay Integration
  6. Performance Benchmarks
  7. Configuration Deep-Dive
  8. Advanced Features

Architecture Overview

The PumpFun Sniper is built on a lock-free, event-driven architecture designed to minimize latency at every stage of the detection-to-execution pipeline.

Core Components

graph LR
    A[ShredStream] -->|UDP Packets| B[Shred Processor]
    B -->|Parsed Transactions| C[Filter Layer]
    C -->|PumpFun Creates| D[Signal Generator]
    D -->|Token Mint| E[Transaction Builder]
    E -->|Signed TX| F[AllenHark Relay]
    F -->|QUIC/UDP| G[Validator TPU]

Latency Budget:

  • ShredStream ingestion: 20-50 μs
  • Transaction parsing: 10-15 μs
  • Filter evaluation: 5-10 μs
  • Signal generation: 30-50 μs
  • Transaction building: 80-100 μs
  • Relay submission: 100-200 μs

Total internal latency: < 500 μs (0.5ms)

Why Rust?

The bot is implemented in Rust for several critical reasons:

  1. Zero-cost abstractions: No runtime overhead for high-level constructs
  2. No garbage collection: Eliminates unpredictable GC pauses (10-50ms in Node.js)
  3. Memory safety: Prevents crashes without runtime checks
  4. Lock-free concurrency: Uses atomic operations and channels for thread communication
  5. LLVM optimization: Produces highly optimized machine code

Benchmark: Transaction Parsing (10,000 iterations)

LanguageAverageP99Memory
Rust12 μs18 μs22 MB
Node.js450 μs2,100 μs450 MB
Python1,200 μs3,500 μs680 MB

ShredStream Integration

ShredStream provides access to raw Turbine protocol data - the UDP packets validators exchange before block finalization. This enables 0-slot detection: seeing transactions in the same slot they're created.

How ShredStream Works

Solana validators use the Turbine protocol to propagate blocks as "shreds" (fragments). By tapping into this stream, we can:

  1. Detect transactions before RPC confirmation (200-400ms advantage)
  2. Process transactions in parallel with validators
  3. Avoid RPC polling overhead (eliminates 500ms+ latency)

Integration Code

The bot connects to a local ShredStream proxy via gRPC:

use tonic::transport::Channel;
use shredstream_proto::shred_stream_client::ShredStreamClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to local ShredStream proxy
    let channel = Channel::from_static("http://127.0.0.1:9999")
        .connect()
        .await?;
    
    let mut client = ShredStreamClient::new(channel);
    
    // Subscribe to transaction stream
    let request = SubscribeRequest {
        filter_accounts: vec![PUMPFUN_PROGRAM_ID.to_string()],
        ..Default::default()
    };
    
    let mut stream = client.subscribe(request).await?.into_inner();
    
    // Process shreds in real-time
    while let Some(shred) = stream.message().await? {
        process_shred(shred).await;
    }
    
    Ok(())
}

Performance Characteristics

  • Latency: 20-50 μs from validator broadcast to bot receipt
  • Throughput: 50,000+ shreds/second
  • Reliability: Direct UDP multicast, no intermediary hops

Detection Pipeline

The detection pipeline uses a multi-stage filter to minimize CPU overhead while maintaining 100% detection accuracy.

Stage 1: Program ID Filter

const PUMPFUN_PROGRAM: Pubkey = pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");

fn quick_filter(tx: &VersionedTransaction) -> bool {
    // Fast path: check if PumpFun program is in account keys
    tx.message.static_account_keys().contains(&PUMPFUN_PROGRAM)
}

This eliminates 99.9% of transactions (votes, transfers, etc.) in < 5 μs.

Stage 2: Instruction Discriminator

const CREATE_DISCRIMINATOR: [u8; 8] = [24, 30, 200, 40, 5, 28, 7, 119];

fn is_create_instruction(ix: &CompiledInstruction) -> bool {
    ix.data.len() >= 8 && ix.data[..8] == CREATE_DISCRIMINATOR
}

The discriminator is computed as sha256("global:create")[..8] and identifies token creation instructions.

Stage 3: Spam Filter

The spam filter evaluates multiple heuristics to avoid rug pulls:

pub struct SpamFilter {
    min_buy_sol: f64,
    max_buy_sol: f64,
    min_tokens: u64,
    min_accounts: usize,
}

impl SpamFilter {
    fn evaluate(&self, tx: &ParsedCreate) -> bool {
        // Check dev buy amount
        if tx.dev_buy_sol < self.min_buy_sol || tx.dev_buy_sol > self.max_buy_sol {
            return false;
        }
        
        // Check token amount
        if tx.token_amount < self.min_tokens {
            return false;
        }
        
        // Check account count (malformed txs have fewer accounts)
        if tx.accounts.len() < self.min_accounts {
            return false;
        }
        
        true
    }
}

Stage 4: Blacklist Check

The blacklist is stored in a lock-free concurrent hash set for O(1) lookups:

use dashmap::DashSet;

static BLACKLIST: Lazy<DashSet<Pubkey>> = Lazy::new(DashSet::new);

fn is_blacklisted(creator: &Pubkey) -> bool {
    BLACKLIST.contains(creator)
}

The blacklist is reloaded every 10 seconds from blacklist.jsonl without blocking the hot path.


Transaction Execution

Once a token passes all filters, the bot must build and submit a transaction in < 100 μs.

Pre-computed Transaction Template

To minimize latency, we pre-build a transaction template with placeholder accounts:

struct TransactionTemplate {
    instructions: Vec<Instruction>,
    recent_blockhash: Hash,
    payer: Pubkey,
}

impl TransactionTemplate {
    fn instantiate(&self, mint: Pubkey) -> Transaction {
        // Clone template and replace mint address
        let mut tx = self.clone();
        tx.instructions[0].accounts[MINT_INDEX] = AccountMeta::new(mint, false);
        
        // Sign transaction
        tx.sign(&[&PAYER_KEYPAIR], self.recent_blockhash);
        tx
    }
}

Blockhash Management

A background thread maintains a cache of the latest blockhash:

static BLOCKHASH_CACHE: Lazy<RwLock<Hash>> = Lazy::new(|| RwLock::new(Hash::default()));

async fn blockhash_updater(rpc_client: Arc<RpcClient>) {
    loop {
        if let Ok(hash) = rpc_client.get_latest_blockhash().await {
            *BLOCKHASH_CACHE.write().unwrap() = hash;
        }
        tokio::time::sleep(Duration::from_millis(400)).await; // Update every slot
    }
}

This ensures we always have a fresh blockhash without blocking the critical path.


AllenHark Relay Integration

The AllenHark Relay provides optimized transaction submission straight to the leader's TPU.

Why Use a Relay?

Standard RPC submission has several bottlenecks:

  1. HTTP overhead: 20-50ms for connection setup and headers
  2. RPC processing: 10-30ms for validation and forwarding
  3. Gossip propagation: 100-300ms to reach the leader
  4. No priority routing: Transactions may take multiple hops

AllenHark Relay eliminates these bottlenecks:

  • QUIC protocol: 0-RTT connection resumption — no handshake when the transaction is ready
  • Direct TPU connection: Physical cables to validator racks
  • Priority routing: Jito bundle integration
  • Persistent connections: No connection setup overhead

QUIC Integration

use quinn::{ClientConfig, Endpoint};

async fn send_via_relay(tx: &Transaction) -> Result<(), Box<dyn std::error::Error>> {
    // Create QUIC endpoint
    let mut endpoint = Endpoint::client("0.0.0.0:0".parse()?)?;
    endpoint.set_default_client_config(ClientConfig::with_native_roots());
    
    // Connect to AllenHark Relay
    let connection = endpoint
        .connect("88.216.36.108:4433".parse()?, "relay.allenhark.com")?
        .await?;
    
    // Open bidirectional stream
    let (mut send, mut recv) = connection.open_bi().await?;
    
    // Serialize transaction
    let tx_bytes = bincode::serialize(tx)?;
    
    // Send transaction with tip
    let packet = build_relay_packet(&tx_bytes, TIP_LAMPORTS)?;
    send.write_all(&packet).await?;
    send.finish().await?;
    
    // Read response
    let response = recv.read_to_end(1024).await?;
    
    Ok(())
}

Performance Comparison

MethodDispatch costCost
AllenHark Relay (QUIC)No per-request handshake — the connection is already open0.001 SOL tip, in-transaction
AllenHark Relay (HTTPS)Single-digit ms near a region, tens of ms cross-region0.001 SOL tip, in-transaction
Standard RPCValidation, then gossip propagationFree
Jito (Public)Auction round before submissionVariable

What to Measure

We don't publish latency or win-rate figures for this bot, because the numbers that matter are yours: they depend on where your box sits relative to the relay and the stake, how aggressive your filters are, and what the rest of the field is doing on the day. Anyone quoting a P99 without telling you the vantage point is selling you something.

Instrument these yourself and you'll know whether your setup is actually competitive:

  • Detection: time from the entry arriving on the shred feed to your filter firing.
  • End-to-end: detection → signed transaction handed to the relay.
  • Landing: what fraction of attempts land in the intended slot, not just eventually.
  • Filter yield: how many launches survive your filters, and how many of those you'd actually have wanted.

Configuration Deep-Dive

Trading Parameters

purchase_amount_sol = 0.001
slippage_basis_points = 100
live = true
  • purchase_amount_sol: Position size per snipe. Start with 0.001 SOL for testing.
  • slippage_basis_points: 100 = 1%. Increase for volatile tokens.
  • live: Set to false for dry-run mode (no real transactions).

Dev Buy Filter

min_dev_buy_sol = 0.5
max_dev_buy_sol = 4.5

Filters tokens based on the developer's initial buy:

  • Too low (< 0.5 SOL): Likely spam or low-effort launch
  • Too high (> 4.5 SOL): Risk of immediate dump

User Volume Accumulator

The user_volume_accumulator is a PDA required by PumpFun to track trading volume:

fn derive_accumulator(user: &Pubkey) -> Pubkey {
    let pumpfun = pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
    let fee_program = pubkey!("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ");
    
    Pubkey::find_program_address(
        &[
            b"user-volume-accumulator",
            user.as_ref(),
            pumpfun.as_ref(),
        ],
        &fee_program,
    ).0
}

Advanced Features

Automatic Blacklisting

The bot tracks creator performance and automatically blacklists unprofitable wallets:

fn update_blacklist(creator: Pubkey, profit: f64) {
    if profit < -0.001 {  // Lost more than 0.001 SOL
        BLACKLIST.insert(creator);
        append_to_file("blacklist.jsonl", &creator);
    }
}

Profit Tracking

After each sell, the bot calculates profit including rent recovery:

fn calculate_profit(initial_balance: u64, final_balance: u64, rent: u64) -> f64 {
    let profit_lamports = (final_balance + rent) as i64 - initial_balance as i64;
    profit_lamports as f64 / 1e9  // Convert to SOL
}

RPC Pool Rotation

The bot rotates through multiple RPC endpoints every 20ms for load balancing and redundancy:

struct RpcPool {
    endpoints: Vec<String>,
    current: AtomicUsize,
}

impl RpcPool {
    fn next(&self) -> &str {
        let idx = self.current.fetch_add(1, Ordering::Relaxed) % self.endpoints.len();
        &self.endpoints[idx]
    }
}

Conclusion

The PumpFun Sniper demonstrates that competitive Solana trading requires:

  1. Low-level infrastructure access (ShredStream)
  2. Optimized execution (Rust, lock-free architecture)
  3. Direct network connectivity (AllenHark Relay, QUIC)
  4. Intelligent filtering (spam detection, blacklisting)

By combining these elements, the bot detects a launch while the block is still being produced — before RPC confirmation — and goes for first-block execution, which an RPC-polling bot structurally cannot do.

Download the PumpFun Sniper: Latest Release

Full Documentation: PumpFun Sniper Docs

AllenHark Services: ShredStream | Relay | Co-Location