sol-parser-sdk 0.8.0

A lightweight Rust library for real-time event streaming from Solana DEX trading programs. Supports PumpFun, PumpSwap, LaunchLab, and Raydium protocols with Yellowstone gRPC and ShredStream.
Documentation

Current version: 0.8.0. SDK, native-language tests, examples and documentation are synchronized in this release. See RELEASE_NOTES.md for migration details.

Examples ยท Documentation ยท Release history

v0.8.0 โ€” Trade provenance and opt-in stock prices

Uniform router provenance across supported gRPC trade families, plus an opt-in stock/ETF execution-price subscription with an extensible, screened multi-source catalog. No RPC in the parsing hot path. Missing live conversion or liquidity data stays unknown. See stock price subscriptions and trade provenance.

Cross-DEX stock routes: per-leg protocol/pool identification, Pump.fun v2 route support, and six signed mainnet replay cases. Run cargo run --example stock_route_replay offline.

Stock catalog admission uses at least $500 of verified liquid-side pool reserve, without a volume filter. Lower known fees take priority within each mint; historical fee snapshots distinguish pool fees from token transfer taxes. Parser and trade SDKs package the same 34-mint / 63-pool catalog and fee preference. Offline discovery includes Stonk, Pump.fun/PumpSwap and Raydium AMM v4/CPMM/CLMM; candidates require account, identity and depth validation.


๐Ÿ“ฆ SDK Versions and Related SDKs

Parser SDK language versions and related Rust SDKs:

Language Repository Description Version
Rust sol-parser-sdk Ultra-low latency with SIMD optimization v0.8.0
Node.js sol-parser-sdk-nodejs TypeScript/JavaScript for Node.js v0.6.0
Python sol-parser-sdk-python Async/await native support v0.6.0
Go sol-parser-sdk-golang Concurrent-safe with goroutine support v0.6.0
Rust sol-shred-sdk Raw Solana shred decoding and ShredStream DEX event parsing v5.0.0
Rust sol-trade-sdk Solana DEX trade construction and transaction execution v8.0.0

What This SDK Is For

sol-parser-sdk is the low-level Rust parser core for Solana DEX events. It is designed for trading bots, copy-trading pipelines, sniper bots, indexers, and stream processors that need fast, typed parsing from Yellowstone gRPC transactions, Jito ShredStream entries, RPC transaction payloads, or account subscriptions.

Area Coverage
Parser inputs Yellowstone gRPC, ShredStream, RPC transactions, encoded transactions, protocol account data
DEX protocols PumpFun, PumpSwap, Pump Fees, LaunchLab (including StonkFun), Raydium CPMM, Raydium CLMM, Raydium AMM V4, Meteora DAMM v2, Meteora DLMM, Meteora DBC, Orca Whirlpool
Parser backends Default Borsh parser for maintainability, optional zero-copy parser for latency-sensitive hot paths
Related SDK Use solana-streamer (3.0.16) when you want a higher-level streaming facade over this parser core

๐Ÿ“Š Performance Highlights

โšก Ultra-Low Latency

  • 10-20ฮผs parsing latency in release mode
  • Zero-copy parsing with stack-allocated buffers
  • SIMD-accelerated pattern matching (memchr)
  • Lock-free ArrayQueue for event delivery

๐ŸŽš๏ธ Flexible Order Modes

Mode Latency Description
Unordered 10-20ฮผs Immediate output, ultra-low latency
MicroBatch 50-200ฮผs Micro-batch ordering with time window
StreamingOrdered 0.1-5ms Stream ordering with continuous sequence release
Ordered 1-50ms Buffered slot ordering, flush on newer slot or timeout

Ordered output retains its last emitted (slot, tx_index) watermark. A newer-slot flush closes older slots; timeout flushing still accepts later transactions in the same slot with a higher index. Late data from closed slots or at/before the watermark is dropped with an Ordered continuity break warning. Events within one transaction preserve parser order. This mode cannot guarantee upstream completeness.

๐Ÿš€ Optimization Highlights

  • โœ… Zero heap allocation for hot paths
  • โœ… SIMD pattern matching for all protocol detection
  • โœ… Static pre-compiled finders for string search
  • โœ… Inline functions with aggressive optimization
  • โœ… Event type filtering for targeted parsing
  • โœ… Conditional Create detection (only when needed)
  • โœ… Multiple order modes for latency vs ordering trade-off

๐Ÿ”ฅ Quick Start

Installation

Clone the repository:

cd your_project_dir
git clone https://github.com/0xfnzero/sol-parser-sdk

Add to your Cargo.toml:

[dependencies]
# Default: Borsh parser
sol-parser-sdk = { path = "../sol-parser-sdk" }

# Or: Zero-copy parser (maximum performance)
sol-parser-sdk = { path = "../sol-parser-sdk", default-features = false, features = ["parse-zero-copy"] }

Use crates.io

# Add to your Cargo.toml
sol-parser-sdk = "0.8.0"

Or with the zero-copy parser (maximum performance):

sol-parser-sdk = { version = "0.8.0", default-features = false, features = ["parse-zero-copy"] }

Performance Testing

Transaction-cost parsing is opt-in and does not run on the default DEX event path:

use sol_parser_sdk::{parse_yellowstone_transaction_cost, SwqosProvider};

let cost = parse_yellowstone_transaction_cost(&transaction, &meta).unwrap();
let jito_tip = cost.tip_lamports_for(SwqosProvider::Jito);

Yellowstone and RPC results use status metadata for the authoritative transaction fee and confirmed tip status. transaction_fee_lamports already includes the priority fee; relay tips are separate transfers and are added only in total_fee_and_tip_lamports. Tip recipients for every SWQoS provider supported by sol-trade-sdk are recognized automatically, and each TipPayment identifies its provider. ShredStream can expose requested compute-budget values and outer tip transfers, but cannot confirm fees, execution, inner instructions, or ALT-loaded tip recipients.

Test parsing latency with the optimized examples:

# PumpFun with detailed metrics (per-event + 10s stats)
cargo run --example pumpfun_with_metrics --release

# PumpSwap with detailed metrics (per-event + 10s stats)
cargo run --example pumpswap_with_metrics --release

# PumpSwap ultra-low latency test
cargo run --example pumpswap_low_latency --release

# PumpSwap with MicroBatch ordering
cargo run --example pumpswap_ordered --release

# Expected output:
# gRPC receive time: 1234567890 ฮผs
# Event receive time: 1234567900 ฮผs
# Latency: 10 ฮผs  <-- Ultra-low latency!

Examples

Description Run Command Source Code
PumpFun
PumpFun event parsing with metrics cargo run --example pumpfun_with_metrics --release examples/pumpfun_with_metrics.rs
PumpFun trade type filtering cargo run --example pumpfun_trade_filter --release examples/pumpfun_trade_filter.rs
PumpFun trade with ordered mode cargo run --example pumpfun_trade_filter_ordered --release examples/pumpfun_trade_filter_ordered.rs
Quick PumpFun connection test cargo run --example pumpfun_quick_test --release examples/pumpfun_quick_test.rs
Parse PumpFun tx by signature TX_SIGNATURE=<sig> cargo run --example parse_pump_tx --release examples/parse_pump_tx.rs
Parse PumpFun quote-mint cases TX_SIGNATURES=<sig1,sig2> cargo run --example parse_pumpfun_quote_cases --release examples/parse_pumpfun_quote_cases.rs
Debug PumpFun transaction cargo run --example debug_pump_tx --release examples/debug_pump_tx.rs
PumpSwap
PumpSwap events with metrics cargo run --example pumpswap_with_metrics --release examples/pumpswap_with_metrics.rs
PumpSwap ultra-low latency cargo run --example pumpswap_low_latency --release examples/pumpswap_low_latency.rs
PumpSwap with MicroBatch ordering cargo run --example pumpswap_ordered --release examples/pumpswap_ordered.rs
Parse PumpSwap tx by signature TX_SIGNATURE=<sig> cargo run --example parse_pumpswap_tx --release examples/parse_pumpswap_tx.rs
Debug PumpSwap transaction cargo run --example debug_pumpswap_tx --release examples/debug_pumpswap_tx.rs
Meteora DAMM
Meteora DAMM V2 events cargo run --example meteora_damm_grpc --release examples/meteora_damm_grpc.rs
Parse Meteora DAMM tx by signature TX_SIGNATURE=<sig> cargo run --example parse_meteora_damm_tx --release examples/parse_meteora_damm_tx.rs
Non-Pump DEX dry-run scenarios
LaunchLab migration filter cargo run --example raydium_launchlab_migration examples/raydium_launchlab_migration.rs
Raydium CPMM new pool filter cargo run --example raydium_cpmm_new_pool examples/raydium_cpmm_new_pool.rs
Raydium CLMM token price math cargo run --example raydium_clmm_token_price examples/raydium_clmm_token_price.rs
Orca Whirlpool token price math cargo run --example orca_whirlpool_token_price examples/orca_whirlpool_token_price.rs
Meteora DAMM new pool baseline cargo run --example meteora_damm_new_pool examples/meteora_damm_new_pool.rs
Meteora DBC token price math cargo run --example meteora_dbc_token_price examples/meteora_dbc_token_price.rs
Wallet trade filter cargo run --example wallet_trade_filter examples/wallet_trade_filter.rs
gRPC latency slot compare config cargo run --example grpc_latency_slot_compare examples/grpc_latency_slot_compare.rs
Account subscription
Token account balance updates TOKEN_ACCOUNT=<pubkey> cargo run --example token_balance_listen --release examples/token_balance_listen.rs
Nonce account state changes NONCE_ACCOUNT=<pubkey> cargo run --example nonce_listen --release examples/nonce_listen.rs
Mint account info MINT_ACCOUNT=<pubkey> cargo run --example token_decimals_listen --release examples/token_decimals_listen.rs
PumpSwap pool accounts via memcmp cargo run --example pumpswap_pool_account_listen --release examples/pumpswap_pool_account_listen.rs
All ATAs for mints cargo run --example mint_all_ata_account_listen --release examples/mint_all_ata_account_listen.rs
ShredStream
Jito ShredStream subscription cargo run --example shredstream_example --release examples/shredstream_example.rs
Utility
Dynamic subscription filters cargo run --example dynamic_subscription --release examples/dynamic_subscription.rs
Debug PumpSwap account filling cargo run --example test_account_filling --release examples/test_account_filling.rs

Basic Usage

use sol_parser_sdk::grpc::{
    AccountFilter, ClientConfig, EventType, EventTypeFilter, OrderMode, Protocol,
    TransactionFilter, YellowstoneGrpc,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create gRPC client with default config (Unordered mode)
    let grpc = YellowstoneGrpc::new(
        "https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
        None,
    )?;
    
    // Or with custom config for ordered events
    let config = ClientConfig {
        order_mode: OrderMode::MicroBatch,  // Low latency + ordering
        micro_batch_us: 100,                // 100ฮผs batch window
        ..ClientConfig::default()
    };
    let grpc = YellowstoneGrpc::new_with_config(
        "https://solana-yellowstone-grpc.publicnode.com:443".to_string(),
        None,
        config,
    )?;

    let protocols = vec![Protocol::PumpFun, Protocol::PumpSwap, Protocol::RaydiumCpmm];
    let transaction_filter = TransactionFilter::for_protocols(&protocols);
    let account_filter = AccountFilter::for_protocols(&protocols);

    // Filter before parsing for the lowest-latency path.
    let event_filter = EventTypeFilter::include_only(vec![
        EventType::PumpFunBuy,
        EventType::PumpFunSell,
        EventType::PumpSwapBuy,
        EventType::PumpSwapSell,
        EventType::RaydiumCpmmSwap,
    ]);

    // Subscribe and get lock-free queue
    let queue = grpc.subscribe_dex_events(
        vec![transaction_filter],
        vec![account_filter],
        Some(event_filter),
    ).await?;

    // Consume events with minimal latency
    tokio::spawn(async move {
        let mut spin_count = 0;
        loop {
            if let Some(event) = queue.pop() {
                spin_count = 0;
                // Process event (10-20ฮผs latency!)
                println!("{:?}", event);
            } else {
                // Hybrid spin-wait strategy
                spin_count += 1;
                if spin_count < 1000 {
                    std::hint::spin_loop();
                } else {
                    tokio::task::yield_now().await;
                    spin_count = 0;
                }
            }
        }
    });

    Ok(())
}

ShredStream Usage (Jito)

ShredStream provides ultra-low latency (~50-100ms faster than gRPC) by directly subscribing to Jito's ShredStream service:

use sol_parser_sdk::grpc::{EventType, EventTypeFilter};
use sol_parser_sdk::shredstream::{ShredStreamClient, ShredStreamConfig};
use sol_parser_sdk::DexEvent;
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create ShredStream client
    let client = ShredStreamClient::new("http://127.0.0.1:10800").await?;

    // Or with custom config
    let config = ShredStreamConfig {
        connection_timeout_ms: 5000,
        request_timeout_ms: 30000,
        max_decoding_message_size: 1024 * 1024 * 1024,
        reconnect_delay_ms: 1000,
        max_reconnect_attempts: 0, // 0 = infinite reconnect
    };
    let client = ShredStreamClient::new_with_config("http://127.0.0.1:10800", config).await?;

    // Subscribe with SDK-side filtering before event conversion.
    // Use `client.subscribe().await?` to receive every supported event.
    let event_filter = EventTypeFilter::include_only(vec![
        EventType::PumpFunBuy,
        EventType::PumpSwapBuy,
        EventType::RaydiumCpmmSwap,
    ]);
    let queue = client.subscribe_with_filter(Some(event_filter)).await?;

    // Consume events
    loop {
        if let Some(event) = queue.pop() {
            match &event {
                DexEvent::PumpFunTrade(e) => {
                    println!("PumpFun Trade: mint={}, is_buy={}", e.mint, e.is_buy);
                }
                DexEvent::PumpSwapBuy(e) => {
                    println!("PumpSwap Buy: pool={}", e.pool);
                }
                _ => {}
            }
        } else {
            std::hint::spin_loop();
        }
    }
}

ShredStream Limitations:

  • The default parser requires resolved instruction keys. Supply cached ALT addresses with parse_transaction_dex_events_with_loaded_addresses or with_address_lookup_resolver; unresolved instructions are skipped. An explicit best_effort API retains provisional legacy behavior.
  • No execution metadata: supported official routes and known wrappers emit explicit route intents, while arbitrary CPI results and confirmed fills require the execution-metadata path.
  • No block_time - always 0
  • tx_index is entry-level, not slot-level

๐Ÿ—๏ธ Supported Protocols

DEX Protocols

  • โœ… PumpFun - Meme coin trading (ultra-fast zero-copy path, incl. v2 instructions)
  • โœ… Pump Fees - Pump fee-sharing configuration events
  • โœ… PumpSwap - PumpFun swap protocol
  • โœ… LaunchLab - Token launch platform, including StonkFun attribution
  • โœ… Raydium AMM V4 - Automated Market Maker
  • โœ… Raydium CLMM - Concentrated Liquidity
  • โœ… Raydium CPMM - Concentrated Pool
  • โœ… Orca Whirlpool - Concentrated liquidity AMM
  • โœ… Meteora Pools - Dynamic AMM
  • โœ… Meteora DAMM v2 - Dynamic AMM V2
  • โœ… Meteora DLMM - Dynamic Liquidity Market Maker
  • ๐Ÿšง Meteora DBC - Program id and filters added; transaction/account parser pass pending

Event Types

Each protocol supports:

  • ๐Ÿ“ˆ Trade/Swap Events - Buy/sell transactions
  • ๐Ÿ’ง Liquidity Events - Deposits/withdrawals
  • ๐ŸŠ Pool Events - Pool creation/initialization
  • ๐ŸŽฏ Position Events - Open/close positions (CLMM)

Non-Pump DEX Support Matrix

Protocol Events Accounts Examples Language constants
LaunchLab Trade, pool create, migrate Pool/config snapshots Migration, buy/sell oracle planned Rust, Node, Python, Go
Raydium CPMM Swap, deposit, withdraw, initialize AmmConfig, PoolState New pool, token price Rust, Node, Python, Go
Raydium CLMM Swap, pool, position, liquidity AmmConfig, PoolState, TickArray Token price Rust, Node, Python, Go
Raydium AMM V4 Swap, deposit, withdraw, initialize2 Pending Token price oracle planned Rust, Node, Python, Go
Orca Whirlpool Swap, liquidity, pool init Whirlpool, Position, TickArray, FeeTier, Config Token price Rust, Node, Python, Go
Meteora Pools Swap, liquidity, pool create, fees Pending Token price oracle planned Rust, Node, Python, Go
Meteora DAMM V2 Swap, liquidity, position Pending New pool, token price oracle planned Rust, Node, Python, Go
Meteora DLMM Swap, liquidity, bin/position Pool/bin array/bitmap snapshots Token price oracle planned Rust, Node, Python, Go
Meteora DBC Swap, initialize pool, curve complete (Rust log parser) Pending Token price, migration oracle planned Rust, Node, Python, Go

The canonical cross-language baseline is tracked in protocols/canonical.json. Raw account updates are opt-in via AccountRawSnapshot; specialized snapshots cover LaunchLab pools/configs, DLMM pools/bin arrays/bitmap extensions, Whirlpool dynamic arrays/adaptive Oracles and CLMM bitmap extensions.


โšก Performance Features

Zero-Copy Parsing

// Stack-allocated 512-byte buffer for PumpFun Trade
const MAX_DECODE_SIZE: usize = 512;
let mut decode_buf: [u8; MAX_DECODE_SIZE] = [0u8; MAX_DECODE_SIZE];

// Decode directly to stack, no heap allocation
general_purpose::STANDARD
    .decode_slice(data_part.as_bytes(), &mut decode_buf)
    .ok()?;

SIMD Pattern Matching

// Pre-compiled SIMD finders (initialized once)
static PUMPFUN_FINDER: Lazy<memmem::Finder> =
    Lazy::new(|| memmem::Finder::new(b"6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"));

// 3-10x faster than .contains()
if PUMPFUN_FINDER.find(log_bytes).is_some() {
    return LogType::PumpFun;
}

Event Type Filtering

// Ultra-fast path for single event type
if include_only.len() == 1 && include_only[0] == EventType::PumpFunTrade {
    if log_type == LogType::PumpFun {
        return parse_pumpfun_trade(  // Zero-copy path
            log, signature, slot, block_time, grpc_recv_us, is_created_buy
        );
    }
}

Lock-Free Queue

// ArrayQueue with 100,000 capacity
let queue = Arc::new(ArrayQueue::<DexEvent>::new(100_000));

// Non-blocking push/pop (no mutex overhead)
let _ = queue.push(event);
if let Some(event) = queue.pop() {
    // Process event
}

๐ŸŽฏ Event Filtering

Reduce processing overhead by filtering specific events:

Example: Trading Bot

let event_filter = EventTypeFilter::include_only(vec![
    EventType::PumpFunBuy,
    EventType::PumpFunSell,
    EventType::PumpFunBuyExactSolIn,
    EventType::PumpSwapBuy,
    EventType::PumpSwapSell,
    EventType::RaydiumLaunchlabTrade,
    EventType::RaydiumCpmmSwap,
    EventType::RaydiumAmmV4Swap,
    EventType::RaydiumClmmSwap,
    EventType::OrcaWhirlpoolSwap,
    EventType::MeteoraPoolsSwap,
    EventType::MeteoraDammV2Swap,
    EventType::MeteoraDlmmSwap,
]);

Example: Pool Monitor

let event_filter = EventTypeFilter::include_only(vec![
    EventType::PumpFunCreate,
    EventType::PumpFeesUpdateFeeShares,
    EventType::PumpSwapCreatePool,
    EventType::AccountPumpSwapPool,
    EventType::RaydiumCpmmInitialize,
    EventType::RaydiumClmmCreatePool,
    EventType::OrcaWhirlpoolPoolInitialized,
    EventType::MeteoraPoolsPoolCreated,
    EventType::MeteoraDammV2CreatePosition,
    EventType::MeteoraDlmmInitializePool,
]);

PumpSwapCreatePool includes is_mayhem_mode. For is_cashback_coin, ShredStream/outer-instruction parsing reads the flag from the create_pool instruction args, while log-only CreatePoolEvent payloads keep the default false because the log event IDL does not carry this field. The authoritative account value is also available from PumpSwapPoolAccountEvent.pool.is_cashback_coin.

Performance Impact:

  • Avoids decoding excluded event families; measure the benefit with your event mix
  • Lower memory usage
  • Reduced network bandwidth

๐Ÿ”ง Advanced Features

Create+Buy Detection

Automatically detects when a token is created and immediately bought in the same transaction:

// Detects "Program data: GB7IKAUcB3c..." pattern
let has_create = detect_pumpfun_create(logs);

// Sets is_created_buy flag on Trade events
if has_create {
    trade_event.is_created_buy = true;
}

Pump.fun Bonding Curve v2 (buy_v2 / sell_v2 / buy_exact_quote_in_v2)

The SDK recognizes Pump.fun's new v2 trading instructions introduced in the Bonding Curve upgrade. Event logs from buy_v2, sell_v2, and buy_exact_quote_in_v2 are parsed with the same zero-copy path and mapped to the existing event types:

ix_name in TradeEvent DexEvent Variant
"buy" / "buy_v2" / "buy_exact_quote_in" / "buy_exact_quote_in_v2" DexEvent::PumpFunBuy
"sell" / "sell_v2" DexEvent::PumpFunSell
"buy_exact_sol_in" DexEvent::PumpFunBuyExactSolIn

No changes are required in your event handling code โ€” v2 events arrive through the same PumpFunTradeEvent struct with the correct ix_name field populated. Instruction discriminators for buy_v2 ([184, 23, 238, 97, 103, 197, 211, 61]), sell_v2 ([93, 246, 130, 60, 231, 233, 64, 178]), and buy_exact_quote_in_v2 ([194, 171, 28, 70, 104, 77, 91, 47]) are recognized at the instruction parser level.

CreateEvent also exposes quote_mint and virtual_quote_reserves, so USDC quote pools can be distinguished from native SOL pools and initialized with the correct quote-side reserve.

Dynamic Subscription

Update filters without reconnecting:

grpc.update_subscription(
    vec![new_transaction_filter],
    vec![new_account_filter],
).await?;

Order Modes

Choose the right balance between latency and ordering:

use sol_parser_sdk::grpc::{ClientConfig, OrderMode};

// Ultra-low latency (no ordering guarantee)
let config = ClientConfig {
    order_mode: OrderMode::Unordered,
    ..ClientConfig::default()
};

// Low latency with micro-batch ordering (50-200ฮผs)
let config = ClientConfig {
    order_mode: OrderMode::MicroBatch,
    micro_batch_us: 100,  // 100ฮผs batch window
    ..ClientConfig::default()
};

// Stream ordering with continuous sequence release (0.1-5ms)
let config = ClientConfig {
    order_mode: OrderMode::StreamingOrdered,
    order_timeout_ms: 50,  // Timeout for incomplete sequences
    ..ClientConfig::default()
};

// Buffered slot ordering (flush on newer slot or timeout)
let config = ClientConfig {
    order_mode: OrderMode::Ordered,
    order_timeout_ms: 100,
    ..ClientConfig::default()
};

Performance Metrics

let config = ClientConfig {
    enable_metrics: true,
    ..ClientConfig::default()
};

let grpc = YellowstoneGrpc::new_with_config(endpoint, token, config)?;

๐Ÿ“ Project Structure

src/
โ”œโ”€โ”€ core/
โ”‚   โ””โ”€โ”€ events.rs          # Event definitions
โ”œโ”€โ”€ grpc/
โ”‚   โ”œโ”€โ”€ client.rs          # Yellowstone gRPC client
โ”‚   โ”œโ”€โ”€ buffers.rs         # SlotBuffer & MicroBatchBuffer
โ”‚   โ””โ”€โ”€ types.rs           # OrderMode, ClientConfig, filters
โ”œโ”€โ”€ shredstream/
โ”‚   โ”œโ”€โ”€ client.rs          # Jito ShredStream client
โ”‚   โ”œโ”€โ”€ config.rs          # ShredStreamConfig
โ”‚   โ””โ”€โ”€ proto/             # Protobuf definitions
โ”œโ”€โ”€ logs/
โ”‚   โ”œโ”€โ”€ optimized_matcher.rs  # SIMD log detection
โ”‚   โ”œโ”€โ”€ zero_copy_parser.rs   # Zero-copy parsing
โ”‚   โ”œโ”€โ”€ pumpfun.rs         # PumpFun parser
โ”‚   โ”œโ”€โ”€ raydium_*.rs       # Raydium parsers
โ”‚   โ”œโ”€โ”€ orca_*.rs          # Orca parsers
โ”‚   โ””โ”€โ”€ meteora_*.rs       # Meteora parsers
โ”œโ”€โ”€ instr/
โ”‚   โ””โ”€โ”€ *.rs               # Instruction parsers
โ”œโ”€โ”€ warmup/
โ”‚   โ””โ”€โ”€ mod.rs             # Parser warmup (auto-called)
โ””โ”€โ”€ lib.rs

๐Ÿš€ Optimization Techniques

1. SIMD String Matching

  • Replaced all .contains() with memmem::Finder
  • 3-10x performance improvement
  • Pre-compiled static finders

2. Zero-Copy Parsing

  • Stack-allocated buffers (512 bytes)
  • No heap allocation in hot path
  • Inline helper functions

3. Event Type Filtering

  • Early filtering at protocol level
  • Conditional Create detection
  • Single-type ultra-fast path

4. Lock-Free Queue

  • ArrayQueue (100K capacity)
  • Spin-wait hybrid strategy
  • No mutex overhead

5. Aggressive Inlining

#[inline(always)]
fn read_u64_le_inline(data: &[u8], offset: usize) -> Option<u64> {
    if offset + 8 <= data.len() {
        let mut bytes = [0u8; 8];
        bytes.copy_from_slice(&data[offset..offset + 8]);
        Some(u64::from_le_bytes(bytes))
    } else {
        None
    }
}

๐Ÿ“Š Benchmarks

Parsing Latency (Release Mode)

Protocol Avg Latency Min Max
PumpFun Trade (zero-copy) 10-15ฮผs 8ฮผs 20ฮผs
Raydium AMM V4 Swap 15-20ฮผs 12ฮผs 25ฮผs
Orca Whirlpool Swap 15-20ฮผs 12ฮผs 25ฮผs

SIMD Pattern Matching

Operation Before (contains) After (SIMD) Speedup
Protocol detection 50-100ns 10-20ns 3-10x
Create event detection 150ns 30ns 5x

๐Ÿ“„ License

MIT License

๐Ÿ“ž Contact


โš ๏ธ Performance Tips

  1. Use Event Filtering - Skip unneeded event families; measure with representative traffic
  2. Run in Release Mode - cargo build --release for full optimization
  3. Use repeatable measurements - Keep build profile, input corpus and machine load consistent; elevated privileges do not make timing accurate
  4. Monitor Latency - Check grpc_recv_us and queue latency in production
  5. Tune Queue Size - Adjust ArrayQueue capacity based on your throughput
  6. Spin-Wait Strategy - Tune spin count (default: 1000) for your use case

๐Ÿ”ฌ Development

# Run tests
cargo test

# Build release binary
cargo build --release

# Generate docs
cargo doc --open

Shared PumpFun create/create_v2 mainnet fixtures, replay instructions and verification limits are documented in the validation guide.

Usage documentation

Pump routes in ShredStream (offline, before execution)

The DEX shred parser recognizes official multi_hop_swap and multi_hop_curve_swap, plus the captured RapidBuy (rapidV5DAโ€ฆ, 41-byte layout) and BuyPumpDelta (J7pourVwโ€ฆ, 28-byte layout) wrapper versions. It emits DexEvent::PumpRouteIntent, with the original instruction index, user, input and output accounts, route hops and original instruction data. A two-hop route is one route event with two hops; three separate wrapper calls produce three route events. Unknown programs or changed layouts are not guessed by scanning for embedded Pump bytes.

These events are intents, not confirmed fills. They contain no execution status, actual fill amounts, reserves or post balances. amount_in and min_amount_out are explicit instruction constraints where decoded; BuyPumpDelta chooses its input at runtime, so these fields are None. Failed or conditional execution cannot be determined from raw shreds. Use execution metadata for fills.

Subscribe with EventType::PumpRouteIntent. Broad PumpFunTrade subscriptions also receive route intents; official MultiHopSwap routes can contain both Pump families and also match PumpSwapTrade. Direction-specific buy/sell and create filters do not match route intents. exclude_types([PumpRouteIntent]) suppresses all intents. Consumers must handle the new DexEvent::PumpRouteIntent variant rather than assuming every callback is a trade variant.

filter: None already includes route intents; changing the filter does not convert them into PumpFunTrade. For RapidBuy and BuyPumpDelta, is_buy is Some(true), relative to hops[0].base_mint; the payment mint is hops[0].quote_mint. RapidBuy also exposes ix_name = Some("buy_exact_quote_in_v2") from its validated embedded instruction. BuyPumpDelta's expected method is unknown (None). Both hints are None for multi-hop routes. These are pre-execution hints, not proof of a successful CPI. Older serialized events deserialize with unknown hints.

if let DexEvent::PumpRouteIntent(intent) = event {
    println!("buy intent: {:?}, expected method: {:?}",
        intent.is_buy, intent.ix_name);
    for hop in &intent.hops {
        println!("base: {}, quote: {}", hop.base_mint, hop.quote_mint);
    }
}

The new optional fields preserve JSON read compatibility, but downstream Rust code constructing PumpRouteIntentEvent literals must supply the two fields.

ALT addresses must come from a prewarmed, slot-aware local cache. Both SDKs expose shredstream::parse_transaction_dex_events_with_loaded_addresses: pass all loaded writable addresses, then all loaded readonly addresses, in the message lookup order. Count/index errors return before appending events. The caller must ensure address identity and lookup-table activation at the transaction slot. The default parser skips unresolved instruction accounts instead of emitting placeholder pubkeys. parse_transaction_dex_events_best_effort retains the older provisional behavior for direct instructions; route adapters always require resolved keys.

High-level clients accept with_address_lookup_resolver(|transaction, slot| ...), returning LoadedAddresses from your cache. Cache errors skip the transaction; without a resolver, fully static instructions can still parse. Do not perform RPC or blocking I/O in this synchronous callback. The SDK parsing path performs no RPC, simulation, or transaction submission.

Regression coverage includes the six original signed mainnet transaction wires, ALT/filter/error cases, signed static official routes, and malformed/truncated instructions. Run cargo test --test pump_shred_routes. The tests are offline; synthetic signing validates extraction and does not simulate program execution.

Repeatable offline Pump simulations

Run the native Rust example and tests:

cargo run --offline --example pump_offline_bank
cargo test --offline --test pump_offline_bank --test pump_shred_routes

The example signs and executes 20 route scenarios against frozen deployed programs in LiteSVM twice, checks rollback/signature/ALT behavior and validates SDK parsing. The integration test reuses the example code. No Python, RPC calls or broadcasts are required. See configuration, snapshot provenance and scope.

Reproducible local hot-path latency

Run the native Rust example with a configuration file (no RPC):

cargo run --release --example hotpath_latency -- examples/hotpath_latency.json

The JSON configuration controls warmup, samples, and batch. Output includes p50/p95/p99 nanoseconds per operation and the build profile. Use --release for performance comparisons and run on an otherwise idle machine. Re-run with the same configuration and fixtures before comparing changes.

Six captured signed transactions are decoded and signature-verified before the measurement. Strict parsing uses cached loaded addresses and validates expected event counts. Two unsigned synthetic cases measure irrelevant-program and unknown-discriminator rejection. Output-vector storage is reused. Measurements exclude signature verification, fixture loading, network reception, and bank execution; they do not establish production ShredStream latency.