Skip to content

A lightweight Rust library providing efficient event parsing and subscription capabilities for PumpFun, PumpSwap, Bonk, and Raydium protocols.

License

Notifications You must be signed in to change notification settings

0xfnzero/sol-parser-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

103 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

⚑ Sol Parser SDK

Ultra-low latency Solana DEX event parser with SIMD optimization

High-performance Rust library for parsing Solana DEX events with microsecond-level latency

Crates.io Documentation License

Rust Solana SIMD gRPC

δΈ­ζ–‡ | English | Website | Telegram | Discord


πŸ“Š 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 Full slot ordering, wait for complete slot

πŸš€ 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"] }

Performance Testing

Test parsing latency with the optimized examples:

# PumpFun with detailed metrics
cargo run --example pumpfun_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ζŽ₯ζ”Άζ—Άι—΄: 1234567890 ΞΌs
# δΊ‹δ»ΆζŽ₯ζ”Άζ—Άι—΄: 1234567900 ΞΌs
# ε»ΆθΏŸζ—Άι—΄: 10 ΞΌs  <-- Ultra-low latency!

Examples

Example Description Command
PumpFun Examples
pumpfun_with_metrics PumpFun event parsing with detailed performance metrics cargo run --example pumpfun_with_metrics --release
pumpfun_trade_filter PumpFun trade type filtering (Buy/Sell/BuyExactSolIn) - Unordered cargo run --example pumpfun_trade_filter --release
pumpfun_trade_filter_ordered PumpFun trade filtering with StreamingOrdered mode cargo run --example pumpfun_trade_filter_ordered --release
pumpfun_quick_test Quick PumpFun connection test (receives first 10 events) cargo run --example pumpfun_quick_test --release
parse_pump_tx Parse specific PumpFun transaction from RPC TX_SIGNATURE=<sig> cargo run --example parse_pump_tx --release
debug_pump_tx Debug PumpFun transaction parsing cargo run --example debug_pump_tx --release
PumpSwap Examples
pumpswap_low_latency PumpSwap ultra-low latency testing (Unordered, full event data) cargo run --example pumpswap_low_latency --release
pumpswap_ordered PumpSwap Buy/Sell/CreatePool with MicroBatch ordering cargo run --example pumpswap_ordered --release
parse_pumpswap_tx Parse specific PumpSwap transaction from RPC TX_SIGNATURE=<sig> cargo run --example parse_pumpswap_tx --release
debug_pumpswap_tx Debug PumpSwap transaction parsing cargo run --example debug_pumpswap_tx --release
Meteora DAMM Examples
meteora_damm_grpc Meteora DAMM gRPC streaming (Swap/Swap2/AddLiquidity/RemoveLiquidity) cargo run --example meteora_damm_grpc --release
parse_meteora_damm_tx Parse specific Meteora DAMM transaction from RPC TX_SIGNATURE=<sig> cargo run --example parse_meteora_damm_tx --release
Utility Examples
dynamic_subscription Dynamic filter updates without reconnecting cargo run --example dynamic_subscription --release

Basic Usage

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

#[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,
    )?;

    // Filter for PumpFun Trade events only (ultra-fast path)
    let event_filter = EventTypeFilter::include_only(vec![
        EventType::PumpFunTrade
    ]);

    // 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(())
}

πŸ—οΈ Supported Protocols

DEX Protocols

  • βœ… PumpFun - Meme coin trading (ultra-fast zero-copy path)
  • βœ… PumpSwap - PumpFun swap protocol
  • βœ… Raydium AMM V4 - Automated Market Maker
  • βœ… Raydium CLMM - Concentrated Liquidity
  • βœ… Raydium CPMM - Concentrated Pool
  • βœ… Orca Whirlpool - Concentrated liquidity AMM
  • βœ… Meteora AMM - Dynamic AMM
  • βœ… Meteora DAMM - Dynamic AMM V2
  • βœ… Meteora DLMM - Dynamic Liquidity Market Maker
  • βœ… Bonk Launchpad - Token launch platform

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)

⚑ 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::PumpFunTrade,
    EventType::RaydiumAmmV4Swap,
    EventType::RaydiumClmmSwap,
    EventType::OrcaWhirlpoolSwap,
]);

Example: Pool Monitor

let event_filter = EventTypeFilter::include_only(vec![
    EventType::PumpFunCreate,
    EventType::RaydiumClmmCreatePool,
    EventType::OrcaWhirlpoolInitialize,
]);

Performance Impact:

  • 60-80% reduction in processing
  • 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;
}

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()
};

// Full slot ordering (1-50ms, wait for complete slot)
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
β”œβ”€β”€ 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 - Filter at the source for 60-80% performance gain
  2. Run in Release Mode - cargo build --release for full optimization
  3. Test with sudo - sudo cargo run --example basic --release for accurate timing
  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

About

A lightweight Rust library providing efficient event parsing and subscription capabilities for PumpFun, PumpSwap, Bonk, and Raydium protocols.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 6

Languages