fix: add PumpFun quote case parser example

This commit is contained in:
0xfnzero
2026-06-12 22:22:40 +08:00
parent ad166ae62e
commit e3249703a5
4 changed files with 168 additions and 12 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "solana-streamer-sdk"
version = "1.5.14"
version = "1.5.15"
edition = "2021"
authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"]
repository = "https://github.com/0xfnzero/solana-streamer"
@@ -21,7 +21,7 @@ sdk-perf-stats = ["sol-parser-sdk/perf-stats"]
sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"]
[dependencies]
sol-parser-sdk = { version = "0.5.14", default-features = false }
sol-parser-sdk = { git = "https://github.com/0xfnzero/sol-parser-sdk", rev = "4464880", version = "0.5.15", default-features = false }
solana-sdk = "3.0.0"
solana-client = "3.1.12"
solana-transaction-status = "3.1.12"
+10 -5
View File
@@ -124,30 +124,34 @@ Add the dependency to your `Cargo.toml`:
```toml
# Add to your Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.14" }
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.15" }
```
### Use crates.io
```toml
# Add to your Cargo.toml
solana-streamer-sdk = "1.5.14"
solana-streamer-sdk = "1.5.15"
```
Parser backend features:
```toml
# Default: sol-parser-sdk parse-borsh backend
solana-streamer-sdk = "1.5.14"
solana-streamer-sdk = "1.5.15"
# Zero-copy parser backend for latency-sensitive bots
solana-streamer-sdk = { version = "1.5.14", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "1.5.15", default-features = false, features = ["sdk-parse-zero-copy"] }
```
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.5.14+` uses the zero-copy backend.
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.5.15+` uses the zero-copy backend.
## 🔄 Migration Guide
### Upgrading to v1.5.15
Version 1.5.15 tracks `sol-parser-sdk 0.5.15` at GitHub rev `4464880`. Pump.fun `create_v2` now distinguishes 16-account SOL-sentinel creates from 19-account quote-pool creates, and account filling selects the actual create/create_v2 instruction before reading quote fields.
### Upgrading to v1.5.14
Version 1.5.14 uses `sol-parser-sdk 0.5.14` from crates.io. Pump.fun canonical create events now expose `quote_mint`, `quote_vault`, and `quote_token_program` for `create_v2` quote pools, including USDC pools, across gRPC/RPC parser bridge and ShredStream-backed SDK output.
@@ -350,6 +354,7 @@ grpc.subscribe_events_immediate(
| Monitor transaction events using ShredStream | `cargo run --example shred_example` | [examples/shred_example.rs](examples/shred_example.rs) |
| Parse Solana mainnet transaction data | `cargo run --example parse_tx_events` | [examples/parse_tx_events.rs](examples/parse_tx_events.rs) |
| Parse PumpFun transaction from RPC (signature: `TX_SIGNATURE` or CLI arg) | `cargo run --example parse_pump_tx --release` | [examples/parse_pump_tx.rs](examples/parse_pump_tx.rs) |
| Parse PumpFun quote-mint cases from RPC | `TX_SIGNATURES=<sig1,sig2> cargo run --example parse_pumpfun_quote_cases --release` | [examples/parse_pumpfun_quote_cases.rs](examples/parse_pumpfun_quote_cases.rs) |
| Parse PumpSwap transaction from RPC | `cargo run --example parse_pumpswap_tx --release` | [examples/parse_pumpswap_tx.rs](examples/parse_pumpswap_tx.rs) |
| Parse Meteora DAMM v2 transaction from RPC | `TX_SIGNATURE=<sig> cargo run --example parse_meteora_damm_tx --release` | [examples/parse_meteora_damm_tx.rs](examples/parse_meteora_damm_tx.rs) |
| Debug PumpFun transaction (fetch, print meta/logs, parse) | `TX_SIGNATURE=<sig> cargo run --example debug_pump_tx --release` | [examples/debug_pump_tx.rs](examples/debug_pump_tx.rs) |
+10 -5
View File
@@ -123,30 +123,34 @@ git clone https://github.com/0xfnzero/solana-streamer
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.14" }
solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.15" }
```
### 使用 crates.io
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = "1.5.14"
solana-streamer-sdk = "1.5.15"
```
解析后端 feature
```toml
# 默认:sol-parser-sdk parse-borsh 后端
solana-streamer-sdk = "1.5.14"
solana-streamer-sdk = "1.5.15"
# 面向低延迟 Bot 的 zero-copy 解析后端
solana-streamer-sdk = { version = "1.5.14", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "1.5.15", default-features = false, features = ["sdk-parse-zero-copy"] }
```
如果同时启用 `sdk-parse-borsh``sdk-parse-zero-copy``sol-parser-sdk 0.5.14+` 会优先使用 zero-copy 后端。
如果同时启用 `sdk-parse-borsh``sdk-parse-zero-copy``sol-parser-sdk 0.5.15+` 会优先使用 zero-copy 后端。
## 🔄 迁移指南
### 升级到 v1.5.15
v1.5.15 跟随 GitHub rev `4464880` 上的 `sol-parser-sdk 0.5.15`。Pump.fun `create_v2` 现在会区分 16 账户 SOL sentinel 创建和 19 账户 quote-pool 创建;填充账户时会先选择实际的 create/create_v2 指令,再读取 quote 字段。
### 升级到 v1.5.14
v1.5.14 使用 crates.io 上的 `sol-parser-sdk 0.5.14`。Pump.fun canonical create 事件现在会为 `create_v2` quote 池暴露 `quote_mint``quote_vault``quote_token_program`,包括 USDC 池;gRPC/RPC parser bridge 和 ShredStream-backed SDK 输出都会保留这些字段。
@@ -349,6 +353,7 @@ grpc.subscribe_events_immediate(
| 使用 ShredStream 监控交易事件 | `cargo run --example shred_example` | [examples/shred_example.rs](examples/shred_example.rs) |
| 解析 Solana 主网交易数据 | `cargo run --example parse_tx_events` | [examples/parse_tx_events.rs](examples/parse_tx_events.rs) |
| 从 RPC 解析 PumpFun 交易(签名:环境变量 `TX_SIGNATURE` 或 CLI 参数) | `cargo run --example parse_pump_tx --release` | [examples/parse_pump_tx.rs](examples/parse_pump_tx.rs) |
| 从 RPC 解析 PumpFun quote_mint 边界案例 | `TX_SIGNATURES=<sig1,sig2> cargo run --example parse_pumpfun_quote_cases --release` | [examples/parse_pumpfun_quote_cases.rs](examples/parse_pumpfun_quote_cases.rs) |
| 从 RPC 解析 PumpSwap 交易 | `cargo run --example parse_pumpswap_tx --release` | [examples/parse_pumpswap_tx.rs](examples/parse_pumpswap_tx.rs) |
| 从 RPC 解析 Meteora DAMM v2 交易 | `TX_SIGNATURE=<sig> cargo run --example parse_meteora_damm_tx --release` | [examples/parse_meteora_damm_tx.rs](examples/parse_meteora_damm_tx.rs) |
| 调试 PumpFun 交易(拉取、打印 meta/logs、解析) | `TX_SIGNATURE=<sig> cargo run --example debug_pump_tx --release` | [examples/debug_pump_tx.rs](examples/debug_pump_tx.rs) |
+146
View File
@@ -0,0 +1,146 @@
//! Parse Pump.fun quote-mint edge cases through solana-streamer's parser SDK re-export.
//!
//! Defaults cover:
//! - 19-account `create_v2` with explicit WSOL quote mint.
//! - 16-account `create_v2` with no quote mint account.
//!
//! Usage:
//! ```bash
//! cargo run --example parse_pumpfun_quote_cases --release
//! SOLANA_RPC_URL=https://api.mainnet-beta.solana.com cargo run --example parse_pumpfun_quote_cases --release
//! TX_SIGNATURES=sig1,sig2 cargo run --example parse_pumpfun_quote_cases --release
//! ```
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::Signature;
use solana_streamer_sdk::parser_sdk::core::events::{
DexEvent, PUMPFUN_SOLSCAN_SOL_QUOTE_MINT, PUMPFUN_WSOL_QUOTE_MINT,
};
use solana_streamer_sdk::parser_sdk::parse_transaction_from_rpc;
use std::str::FromStr;
struct Case {
name: &'static str,
signature: &'static str,
expected_create_v2_quote: Option<Pubkey>,
}
fn default_cases() -> Vec<Case> {
vec![
Case {
name: "19-account create_v2 explicit WSOL quote",
signature: "4GCVgY2FnT1s4q5zemnPL4mzSbuhUTgQo9mc9jewhLZzsCXKe8ehz6xD4QDJE853CLrF6doJbf4JNwJVeEYLA4De",
expected_create_v2_quote: Some(PUMPFUN_WSOL_QUOTE_MINT),
},
Case {
name: "16-account create_v2 no quote account",
signature: "H6azwLqtRtrnVNC5iwcjYM9idU3e9SRyLZXTwjfJGJxA4X7dZL7vyhFAJNvQy7bb6bmQNmFHUt1KkkPPmhdge3G",
expected_create_v2_quote: Some(PUMPFUN_SOLSCAN_SOL_QUOTE_MINT),
},
]
}
fn cases_from_env() -> Option<Vec<Case>> {
let raw = std::env::var("TX_SIGNATURES").ok()?;
let cases: Vec<Case> = raw
.split(',')
.map(str::trim)
.filter(|s| !s.is_empty())
.map(|signature| Case {
name: "custom signature",
signature: Box::leak(signature.to_string().into_boxed_str()),
expected_create_v2_quote: None,
})
.collect();
if cases.is_empty() {
None
} else {
Some(cases)
}
}
fn print_event_summary(index: usize, event: &DexEvent) -> Option<Pubkey> {
match event {
DexEvent::PumpFunCreate(e) => {
println!(
" #{index} PumpFunCreate ix={} mint={} quote_mint={} token_program={} user={}",
e.ix_name, e.mint, e.quote_mint, e.token_program, e.user
);
if e.ix_name == "create_v2" {
Some(e.quote_mint)
} else {
None
}
}
DexEvent::PumpFunCreateV2(e) => {
println!(
" #{index} PumpFunCreateV2 ix={} mint={} quote_mint={} token_program={} user={}",
e.ix_name, e.mint, e.quote_mint, e.token_program, e.user
);
Some(e.quote_mint)
}
DexEvent::PumpFunBuy(e)
| DexEvent::PumpFunBuyExactSolIn(e)
| DexEvent::PumpFunSell(e)
| DexEvent::PumpFunTrade(e) => {
println!(
" #{index} PumpFunTrade ix={} mint={} quote_mint={} quote_amount={} sol_amount={} token_amount={}",
e.ix_name, e.mint, e.quote_mint, e.quote_amount, e.sol_amount, e.token_amount
);
None
}
_ => None,
}
}
fn main() {
let rpc_url = std::env::var("SOLANA_RPC_URL")
.unwrap_or_else(|_| "https://api.mainnet-beta.solana.com".to_string());
let client = RpcClient::new(rpc_url.clone());
let cases = cases_from_env().unwrap_or_else(default_cases);
let mut failed = false;
println!("RPC: {rpc_url}");
println!("Cases: {}\n", cases.len());
for case in cases {
println!("=== {} ===", case.name);
println!("signature={}", case.signature);
let signature = Signature::from_str(case.signature).expect("invalid signature");
let events = match parse_transaction_from_rpc(&client, &signature, None) {
Ok(events) => events,
Err(err) => {
eprintln!(" ERROR: {err}");
failed = true;
println!();
continue;
}
};
println!(" events={}", events.len());
let mut create_v2_quotes = Vec::new();
for (i, event) in events.iter().enumerate() {
if let Some(quote) = print_event_summary(i + 1, event) {
create_v2_quotes.push(quote);
}
}
if let Some(expected) = case.expected_create_v2_quote {
let ok = create_v2_quotes.contains(&expected);
println!(
" expected_create_v2_quote={} result={}",
expected,
if ok { "ok" } else { "FAIL" }
);
failed |= !ok;
}
println!();
}
if failed {
std::process::exit(1);
}
}