release: solana-streamer 5.0.1

This commit is contained in:
0xfnzero
2026-10-26 05:36:59 +08:00
parent 0b721e59e1
commit 9e471c36a2
11 changed files with 2639 additions and 82 deletions
+3 -4
View File
@@ -1,10 +1,9 @@
# Standard Cargo settings; sccache is optional, and no local path is required.
# Optional: RUSTC_WRAPPER=sccache SCCACHE_CACHE_SIZE=10G cargo build --release
# Keep target-dir, release optimization and linker settings project-specific.
[build]
incremental = false
# Standard Cargo settings; sccache is optional, and no local path is required.
# Optional: RUSTC_WRAPPER=sccache SCCACHE_CACHE_SIZE=10G cargo build --release
# Keep target-dir, release optimization and linker settings project-specific.
[profile.dev]
debug = 1
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "solana-streamer-sdk"
version = "5.0.0"
version = "5.0.1"
edition = "2021"
rust-version = "1.91"
authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"]
@@ -22,7 +22,7 @@ sdk-perf-stats = ["sol-parser-sdk/perf-stats"]
sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"]
[dependencies]
sol-parser-sdk = { version = "=0.9.1", default-features = false }
sol-parser-sdk = { version = "=0.10.0", default-features = false }
solana-sdk = "=4.0.1"
solana-client = "=4.2.2"
solana-transaction-status = { version = "=4.2.2", features = ["agave-unstable-api"] }
+18 -16
View File
@@ -40,7 +40,7 @@
<a href="https://discord.gg/vuazbGkqQE">Discord</a>
</p>
Current version: **5.0.0**. Read the [migration notes](RELEASE_NOTES.md) before upgrading; see the [changelog](CHANGELOG.md) for historical changes.
Current version: **5.0.1**. Read the [migration notes](RELEASE_NOTES.md) before upgrading; see the [changelog](CHANGELOG.md) for historical changes.
## Contents
@@ -63,17 +63,17 @@ Repositories are versioned independently; follow each SDK’s installation guide
| Language | Repository | Purpose | Version |
|----------|------------|-------------|---------|
| Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) | DEX transaction and account event parsing | `v0.9.1` |
| Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) | DEX transaction and account event parsing | `v0.9.1` |
| Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) | DEX transaction and account event parsing | `v0.9.1` |
| Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) | DEX transaction and account event parsing | `v0.9.1` |
| Rust | [sol-trade-sdk](https://github.com/0xfnzero/sol-trade-sdk) | Transaction building, signing and multi-channel submission | `v9.0.1` |
| Node.js | [sol-trade-sdk-nodejs](https://github.com/0xfnzero/sol-trade-sdk-nodejs) | Transaction building, signing and multi-channel submission | `v9.0.1` |
| Python | [sol-trade-sdk-python](https://github.com/0xfnzero/sol-trade-sdk-python) | Transaction building, signing and multi-channel submission | `v9.0.1` |
| Go | [sol-trade-sdk-golang](https://github.com/0xfnzero/sol-trade-sdk-golang) | Transaction building, signing and multi-channel submission | `v9.0.1` |
| Rust | [sol-shred-sdk](https://github.com/0xfnzero/sol-shred-sdk) | Raw shred decoding and ShredStream instruction events | `v6.0.1` |
| Rust | [solana-streamer](https://github.com/0xfnzero/solana-streamer) | gRPC / ShredStream subscriptions and event streaming | `v5.0.0` |
| Rust | [sol-trade-router-sdk](https://github.com/0xfnzero/sol-trade-router-sdk) | On-chain multi-hop router and client SDK | `v0.3.0` |
| Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) | DEX transaction and account event parsing | `v0.10.0` |
| Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) | DEX transaction and account event parsing | `v0.10.0` |
| Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) | DEX transaction and account event parsing | `v0.10.0` |
| Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) | DEX transaction and account event parsing | `v0.10.0` |
| Rust | [sol-trade-sdk](https://github.com/0xfnzero/sol-trade-sdk) | Transaction building, signing and multi-channel submission | `v10.0.0` |
| Node.js | [sol-trade-sdk-nodejs](https://github.com/0xfnzero/sol-trade-sdk-nodejs) | Transaction building, signing and multi-channel submission | `v10.0.0` |
| Python | [sol-trade-sdk-python](https://github.com/0xfnzero/sol-trade-sdk-python) | Transaction building, signing and multi-channel submission | `v10.0.0` |
| Go | [sol-trade-sdk-golang](https://github.com/0xfnzero/sol-trade-sdk-golang) | Transaction building, signing and multi-channel submission | `v10.0.0` |
| Rust | [sol-shred-sdk](https://github.com/0xfnzero/sol-shred-sdk) | Raw shred decoding and ShredStream instruction events | `v6.0.2` |
| Rust | [solana-streamer](https://github.com/0xfnzero/solana-streamer) | gRPC / ShredStream subscriptions and event streaming | `v5.0.1` |
| Rust | [sol-trade-router-sdk](https://github.com/0xfnzero/sol-trade-router-sdk) | On-chain multi-hop router and client SDK | `v0.4.0` |
<a id="installation"></a>
@@ -81,17 +81,17 @@ Repositories are versioned independently; follow each SDK’s installation guide
```toml
# Add to your Cargo.toml
solana-streamer-sdk = "5.0.0"
solana-streamer-sdk = "5.0.1"
```
Parser backend features:
```toml
# Default: sol-parser-sdk parse-borsh backend
solana-streamer-sdk = "5.0.0"
solana-streamer-sdk = "5.0.1"
# Zero-copy parser backend for latency-sensitive bots
solana-streamer-sdk = { version = "5.0.0", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "5.0.1", default-features = false, features = ["sdk-parse-zero-copy"] }
```
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.6.1+` uses the zero-copy backend.
@@ -109,7 +109,7 @@ Add the dependency to your `Cargo.toml`:
```toml
# Add to your Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "5.0.0" }
solana-streamer-sdk = { path = "./solana-streamer", version = "5.0.1" }
```
<a id="what-this-sdk-is-for"></a>
@@ -309,6 +309,8 @@ gRPC/RPC use supplied execution metadata and actual CPI instructions; Shred sees
The parsing hot path performs no RPC. Check `parse_status` before interpreting defaults as amounts. Original account order and instruction bytes remain in `third_program`; transaction position and receive time remain in event metadata. A local Shred index is not confirmed slot-wide execution order. See [wrapped transactions](docs/wrapped-pumpfun.md).
Known Pump.fun create/trade instructions keep their callbacks with unresolved ALT accounts; unknown addresses stay unknown. The bridge preserves `create_v2`, V2/V3 method names, original creation accounts and official `multi_hop_swap` provenance. Run `cargo run --example rpc_transaction_replay` to compare the reported signed transactions through the static Shred and execution facades offline. Shred route budgets are not per-hop fill amounts; execution metadata supplies actual quote/token amounts.
<a id="configuration-system"></a>
## ⚙️ Configuration System
+18 -16
View File
@@ -40,7 +40,7 @@
<a href="https://discord.gg/vuazbGkqQE">Discord</a>
</p>
当前版本:**5.0.0**。升级前请阅读 [迁移说明](RELEASE_NOTES.md);历史变更见 [版本记录](CHANGELOG_CN.md)。
当前版本:**5.0.1**。升级前请阅读 [迁移说明](RELEASE_NOTES.md);历史变更见 [版本记录](CHANGELOG_CN.md)。
## 目录
@@ -63,17 +63,17 @@
| 语言 | 仓库 | 用途 | 版本 |
|----------|------------|-------------|---------|
| Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) | DEX 交易与账户事件解析 | `v0.9.1` |
| Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) | DEX 交易与账户事件解析 | `v0.9.1` |
| Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) | DEX 交易与账户事件解析 | `v0.9.1` |
| Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) | DEX 交易与账户事件解析 | `v0.9.1` |
| Rust | [sol-trade-sdk](https://github.com/0xfnzero/sol-trade-sdk) | 交易构建、签名与多通道提交 | `v9.0.1` |
| Node.js | [sol-trade-sdk-nodejs](https://github.com/0xfnzero/sol-trade-sdk-nodejs) | 交易构建、签名与多通道提交 | `v9.0.1` |
| Python | [sol-trade-sdk-python](https://github.com/0xfnzero/sol-trade-sdk-python) | 交易构建、签名与多通道提交 | `v9.0.1` |
| Go | [sol-trade-sdk-golang](https://github.com/0xfnzero/sol-trade-sdk-golang) | 交易构建、签名与多通道提交 | `v9.0.1` |
| Rust | [sol-shred-sdk](https://github.com/0xfnzero/sol-shred-sdk) | 原始 Shred 解码与 ShredStream 指令事件 | `v6.0.1` |
| Rust | [solana-streamer](https://github.com/0xfnzero/solana-streamer) | gRPC / ShredStream 订阅与事件流封装 | `v5.0.0` |
| Rust | [sol-trade-router-sdk](https://github.com/0xfnzero/sol-trade-router-sdk) | 链上多跳 Router 与客户端 SDK | `v0.3.0` |
| Rust | [sol-parser-sdk](https://github.com/0xfnzero/sol-parser-sdk) | DEX 交易与账户事件解析 | `v0.10.0` |
| Node.js | [sol-parser-sdk-nodejs](https://github.com/0xfnzero/sol-parser-sdk-nodejs) | DEX 交易与账户事件解析 | `v0.10.0` |
| Python | [sol-parser-sdk-python](https://github.com/0xfnzero/sol-parser-sdk-python) | DEX 交易与账户事件解析 | `v0.10.0` |
| Go | [sol-parser-sdk-golang](https://github.com/0xfnzero/sol-parser-sdk-golang) | DEX 交易与账户事件解析 | `v0.10.0` |
| Rust | [sol-trade-sdk](https://github.com/0xfnzero/sol-trade-sdk) | 交易构建、签名与多通道提交 | `v10.0.0` |
| Node.js | [sol-trade-sdk-nodejs](https://github.com/0xfnzero/sol-trade-sdk-nodejs) | 交易构建、签名与多通道提交 | `v10.0.0` |
| Python | [sol-trade-sdk-python](https://github.com/0xfnzero/sol-trade-sdk-python) | 交易构建、签名与多通道提交 | `v10.0.0` |
| Go | [sol-trade-sdk-golang](https://github.com/0xfnzero/sol-trade-sdk-golang) | 交易构建、签名与多通道提交 | `v10.0.0` |
| Rust | [sol-shred-sdk](https://github.com/0xfnzero/sol-shred-sdk) | 原始 Shred 解码与 ShredStream 指令事件 | `v6.0.2` |
| Rust | [solana-streamer](https://github.com/0xfnzero/solana-streamer) | gRPC / ShredStream 订阅与事件流封装 | `v5.0.1` |
| Rust | [sol-trade-router-sdk](https://github.com/0xfnzero/sol-trade-router-sdk) | 链上多跳 Router 与客户端 SDK | `v0.4.0` |
<a id="安装"></a>
@@ -81,17 +81,17 @@
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = "5.0.0"
solana-streamer-sdk = "5.0.1"
```
解析后端 feature:
```toml
# 默认:sol-parser-sdk parse-borsh 后端
solana-streamer-sdk = "5.0.0"
solana-streamer-sdk = "5.0.1"
# 面向低延迟 Bot 的 zero-copy 解析后端
solana-streamer-sdk = { version = "5.0.0", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "5.0.1", default-features = false, features = ["sdk-parse-zero-copy"] }
```
如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.6.1+` 会优先使用 zero-copy 后端。
@@ -109,7 +109,7 @@ git clone https://github.com/0xfnzero/solana-streamer
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "5.0.0" }
solana-streamer-sdk = { path = "./solana-streamer", version = "5.0.1" }
```
<a id="这个-sdk-适合什么场景"></a>
@@ -289,6 +289,8 @@ gRPC/RPC 使用提供的执行元数据和实际 CPI 指令;Shred 只能看到
解析热路径不调用 RPC。按 `parse_status` 判断证据,缺失字段的默认值不代表实际零成交。账户顺序与原始指令数据保留在 `third_program`;交易序号和接收时间仍在事件元数据中,本地 Shred 序号不等于全 slot 执行顺序。详见 [第三方包装交易](docs/wrapped-pumpfun.md)。
已知 Pump.fun 创建/交易指令在 ALT 未展开时仍保留回调,未知账户保持未知。适配层保留 `create_v2`、V2/V3 方法名、创建账户和官方 `multi_hop_swap` 来源。运行 `cargo run --example rpc_transaction_replay`,可用已报告的真实签名交易离线比较纯 Shred 与执行解析;Shred 路由预算不是各跳成交金额,实际报价币/代币金额来自执行元数据。
<a id="配置系统"></a>
## ⚙️ 配置系统
+6 -23
View File
@@ -1,28 +1,11 @@
# solana-streamer v5.0.0
# solana-streamer v5.0.1
Released 2026-10-22. The Rust, Node.js, Python and Go parser packages use the same family version, 0.9.0. Streamer 5.0.0 and Shred 6.0.1 are separately versioned integrations.
Released 2026-10-26.
## Default stock pools / 默认股票代币池子
Use sol-parser-sdk 0.10.0 and preserve create_v2 method names, unknown quotes and official multi-hop Pump callbacks across the streamer bridge. Update real-transaction replay examples.
Remove five pools from the default catalog: two have captured single-transaction withdrawals reducing both vault balances by at least 50%; four have less than $500 in USDC/WSOL-side reserves at the 2026-10-22 04:25 UTC+8 snapshot (one meets both criteria). Defaults now contain 58 stock pools across 33 mints; trading adds the SOL/USDC conversion pool for 59 pools total. COPX.US is no longer a default mint. See [the synchronized catalog notes](docs/STOCK_BRIDGE_SYNC.md) for addresses and evidence.
升级解析核心到 0.10.0,事件桥接保留 create_v2 指令名、未知报价和官方多跳回调,更新真实交易回放示例。
This is a static catalog refresh, not continuous liquidity monitoring, certified executable depth, or an LP-lock guarantee. Explicit custom catalogs remain supported. No RPC or history scanning was added to parsing or trading hot paths.
## Validation / 验证
中文:默认目录剔除 5 个池子,涵盖整池双边储备单笔下降至少 50% 的历史记录,以及快照中 USDC/WSOL 一侧储备不足 500 美元的池子。保留 58 个股票池、33 个 mint;交易侧加 SOL/USDC 共 59 个池子。该目录为静态快照,不保证实时深度或流动性锁定。
## Changes / 更新
- Remove standalone PumpRouteIntent and RawInstruction callbacks and their obsolete decoding helpers/examples. Wrapped Pump.fun callbacks retain the original outer program, ordered accounts and data in third_program.
- Preserve the distinction between unresolved Shred candidates, decoded instruction inputs and confirmed execution. The parser hot path performs no RPC and does not infer opaque third-party arguments.
- Synchronize Pump.fun V3 instruction handling, gRPC execution evidence and create-before-trade ordering. Preserve supplied transaction-position and receive-time metadata.
- Clean up examples and README navigation; maintain the shared stock catalog and native-language validation.
## Migration / 升级
Subscribe to PumpFunTrade and inspect third_program and parse_status. Remove matches/filters for the retired PumpRouteIntent and RawInstruction events. Unresolved is only a possible interaction; defaults are not a proven direction or zero fill. ExecutionConfirmed does not guarantee all amounts are available. Unresolved ALT addresses remain unknown.
中文:独立的路由意图和原始指令回调已删除。第三方包装信息保留在交易事件的 third_program 中;Shred 候选与实际成交必须按 parse_status 区分。SDK 不猜测第三方合约参数,热路径不调用 RPC。
Version alignment does not imply identical APIs across languages. Offline fixtures validate captured cases, not current chain state or production latency. See README and docs/wrapped-pumpfun.md for the supported surface.
Pins sol-parser-sdk =0.9.1 and forwards the simplified callback model. Update exhaustive streamer event matches when upgrading.
Native-language regression suites and replay/build checks passed for the synchronized changes. Four trade implementations completed curve buy/sell and pool buy/sell unsigned mainnet simulations (16 successful simulations); these small-amount interface checks do not replace fresh production quotes. No transaction was broadcast.
+1 -1
View File
@@ -32,7 +32,7 @@ quote/search and preparation perform no RPC; no cache miss triggers a fallback.
Parser SDKs own parsing, stock monitoring and historical identities. Streamer and
Shred transport signals; incomplete Shred observations never become confirmed
prices or executable reserves. Trade SDKs own quoting and transaction preparation.
The router reuses parser 0.9.1 and trade 9.0.1; its re-exported PumpSwapRouting
The router reuses parser 0.10.0 and trade 10.0.0; its re-exported PumpSwapRouting
builds trade-sdk direct instructions, not automatic router-program CPI dispatch.
Single-market conversion cannot resolve PumpSwapAutoRoute without a routing cache.
+58 -14
View File
@@ -1,19 +1,39 @@
//! Fetch once or replay an RPC fixture through the public streamer facade.
//! With no arguments: replay the 2026-10-19 Delta SellV2 transaction offline.
//! With no arguments: replay the reported ALT creates and official multi-hop offline.
//! cargo run --example rpc_transaction_replay -- --fetch SIGNATURE OUTPUT.json
//! cargo run --example rpc_transaction_replay -- --fixture OUTPUT.json
use anyhow::{bail, ensure, Context, Result};
use solana_client::{rpc_client::RpcClient, rpc_config::RpcTransactionConfig};
use solana_sdk::signature::Signature;
use solana_streamer_sdk::parse_encoded_rpc_transaction_as_streamer_events;
use solana_streamer_sdk::{
parse_encoded_rpc_transaction_as_streamer_events,
streaming::{
common::event_processor::process_shred_transaction,
event_parser::{DexEvent, Protocol},
shred::TransactionWithSlot,
},
};
use solana_transaction_status::{EncodedConfirmedTransactionWithStatusMeta, UiTransactionEncoding};
use std::{fs, str::FromStr, time::Duration};
fn main() -> Result<()> {
#[tokio::main]
async fn main() -> Result<()> {
let args: Vec<_> = std::env::args().skip(1).collect();
let tx: EncodedConfirmedTransactionWithStatusMeta = match args.as_slice() {
[] => serde_json::from_str(include_str!("../tests/fixtures/pump_execution_20261019.json"))?,
[mode, path] if mode == "--fixture" => serde_json::from_slice(&fs::read(path)?)?,
let transactions: Vec<EncodedConfirmedTransactionWithStatusMeta> = match args.as_slice() {
[] => {
let mut transactions = Vec::new();
for source in [
include_str!("../tests/fixtures/pump_create_alt_20261026.json"),
include_str!("../tests/fixtures/pump_multi_hop_20261025.json"),
] {
let fixture: serde_json::Value = serde_json::from_str(source)?;
for case in fixture["cases"].as_array().context("Missing cases")? {
transactions.push(serde_json::from_value(case["wire_rpc"].clone())?);
}
}
transactions
}
[mode, path] if mode == "--fixture" => vec![serde_json::from_slice(&fs::read(path)?)?],
[mode, signature, path] if mode == "--fetch" => {
let signature = Signature::from_str(signature)?;
let url = std::env::var("SOLANA_RPC_URL")
@@ -35,16 +55,40 @@ fn main() -> Result<()> {
"RPC returned a different signature"
);
fs::write(path, serde_json::to_vec_pretty(&tx)?)?;
tx
vec![tx]
}
_ => bail!("usage: --fetch SIGNATURE OUTPUT.json | --fixture INPUT.json"),
};
let events = parse_encoded_rpc_transaction_as_streamer_events(&tx, 0, &[], None)?;
println!(
"{{\"slot\":{},\"execution_error\":{},\"events\":{}}}",
tx.slot,
serde_json::to_string(&tx.transaction.meta.as_ref().and_then(|meta| meta.err.as_ref()))?,
serde_json::to_string_pretty(&events)?
);
for tx in transactions {
let signed = tx.transaction.transaction.decode().context("Invalid wire transaction")?;
let captured = std::sync::Arc::new(std::sync::Mutex::new(Vec::<DexEvent>::new()));
let output = captured.clone();
process_shred_transaction(
TransactionWithSlot::new(signed, tx.slot, 123456, Some(888)),
&[Protocol::PumpFun],
None,
std::sync::Arc::new(move |e| output.lock().unwrap().push(e)),
None,
)
.await?;
println!(
"{}",
serde_json::json!({"source":"shred_static", "slot":tx.slot, "events":*captured.lock().unwrap()})
);
let events = parse_encoded_rpc_transaction_as_streamer_events(
&tx,
123456,
&[Protocol::PumpFun],
None,
)?;
println!(
"{{\"slot\":{},\"execution_error\":{},\"events\":{}}}",
tx.slot,
serde_json::to_string(
&tx.transaction.meta.as_ref().and_then(|meta| meta.err.as_ref())
)?,
serde_json::to_string_pretty(&events)?
);
}
Ok(())
}
@@ -52,14 +52,27 @@ pub(crate) fn pumpfun_create_token_from_parser(
token_program: c.token_program,
is_mayhem_mode: c.is_mayhem_mode,
is_cashback_enabled: c.is_cashback_enabled,
quote_mint: normalize_pumpfun_quote_mint(c.quote_mint),
quote_mint: c.quote_mint,
quote_vault: c.quote_vault,
quote_token_program: c.quote_token_program,
virtual_quote_reserves: c.virtual_quote_reserves,
creator_fee_bps: c.creator_fee_bps,
is_holder_reward: c.is_holder_reward,
depth: c.depth,
ix_name: "create".to_string(),
ix_name: if c.ix_name.is_empty() { "create".into() } else { c.ix_name },
mint_authority: c.mint_authority,
associated_bonding_curve: c.associated_bonding_curve,
global: c.global,
system_program: c.system_program,
associated_token_program: c.associated_token_program,
mayhem_program_id: c.mayhem_program_id,
global_params: c.global_params,
sol_vault: c.sol_vault,
mayhem_state: c.mayhem_state,
mayhem_token_vault: c.mayhem_token_vault,
event_authority: c.event_authority,
program: c.program,
observed_fee_recipient: c.observed_fee_recipient,
..Default::default()
}
}
@@ -85,7 +98,7 @@ pub(crate) fn pumpfun_create_token_from_parser_v2(
token_program: c.token_program,
is_mayhem_mode: c.is_mayhem_mode,
is_cashback_enabled: c.is_cashback_enabled,
quote_mint: normalize_pumpfun_quote_mint(c.quote_mint),
quote_mint: c.quote_mint,
quote_vault: c.quote_vault,
quote_token_program: c.quote_token_program,
virtual_quote_reserves: c.virtual_quote_reserves,
@@ -776,7 +789,7 @@ pub(crate) fn pumpfun_trade_from_parser_with_event_type(
buyback_fee_basis_points: t.buyback_fee_basis_points,
buyback_fee: t.buyback_fee,
shareholders: t.shareholders.into_iter().map(pump_fees_shareholder_from_parser).collect(),
quote_mint: normalize_pumpfun_quote_mint(t.quote_mint),
quote_mint: t.quote_mint,
quote_amount: t.quote_amount,
virtual_quote_reserves: t.virtual_quote_reserves,
creator_fee_unclaimed: t.creator_fee_unclaimed,
@@ -896,7 +909,7 @@ mod tests {
use super::*;
#[test]
fn pumpfun_default_quote_mint_uses_solscan_sol_sentinel() {
fn pumpfun_unknown_quote_mint_stays_unknown() {
let ev = pumpfun_trade_from_parser_with_event_type(
sol_parser_sdk::core::events::PumpFunTradeEvent { is_buy: true, ..Default::default() },
None,
@@ -906,7 +919,7 @@ mod tests {
match ev {
DexEvent::PumpFunTradeEvent(t) => {
assert_eq!(t.quote_mint.to_string(), "So11111111111111111111111111111111111111111");
assert_eq!(t.quote_mint, Pubkey::default());
}
_ => panic!("expected PumpFunTradeEvent"),
}
File diff suppressed because it is too large Load Diff
+738
View File
@@ -0,0 +1,738 @@
{
"cases": [
{
"name": "official_pool_then_curve_multi_hop",
"signature": "g1fC9wYKdndDZAyMCWkfFAqUNBCzj1brvNb3aAnRjxkrVhaSzsvELXFXz11U3DdmbM2AeFbwcaSgG86BqxApvFZ",
"wire_rpc": {
"blockTime": 1792857598,
"meta": {
"computeUnitsConsumed": 330408,
"costUnits": 342704,
"err": null,
"fee": 110000,
"innerInstructions": [
{
"index": 0,
"instructions": [
{
"accounts": [
0,
1
],
"data": "111157R57fqNzgMjCi7yd8cD1yQhPAwhedzS6uysMaAGbDUZUYiji1TswMPKaASzZW6nQT",
"programIdIndex": 17,
"stackHeight": 2
},
{
"accounts": [
1
],
"data": "GC3i2jSx8awwe9xBfbR9LBTrzgFPUE9b56kGnez3cWMeYXKVKFy48aGGgCCFsnW7KNcwSK5HwFW1oqdg5mpGRhbRM8",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
1
],
"data": "2zt6UCCHp66bJGRS4G7bTsjdxFh6FQ9sBEyRfGyPQKxYisAw",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
0,
8
],
"data": "1111cioyWkTQuLPfwxMoT2birGzJRhJTioHPSoXiyqTZ8i2Uit2xjR4zNTmWA8HgNbgfR",
"programIdIndex": 17,
"stackHeight": 2
},
{
"accounts": [
0,
9,
8,
1,
17,
24
],
"data": "1",
"programIdIndex": 32,
"stackHeight": 2
},
{
"accounts": [
1
],
"data": "84eT",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
0,
9
],
"data": "111157Vt9WuCLrLm8Bv7v3tbuxTXo5Bq7vv6Fb1ngBYUyZPEU62jGZ4xnkMV46KCckXWDq",
"programIdIndex": 17,
"stackHeight": 3
},
{
"accounts": [
9
],
"data": "P",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
9,
1
],
"data": "6RqEKvU6HozdvNpvqsqC7pKHvLDaGf7W6JEGUaMKFsupm",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
0,
14,
8,
28,
17,
24
],
"data": "1",
"programIdIndex": 32,
"stackHeight": 2
},
{
"accounts": [
28
],
"data": "84eT",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
0,
14
],
"data": "111157Vt9WuCLrLm8Bv7v3tbuxTXo5Bq7vv6Fb1ngBYUyZPEU62jGZ4xnkMV46KCckXWDq",
"programIdIndex": 17,
"stackHeight": 3
},
{
"accounts": [
14
],
"data": "P",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
14,
28
],
"data": "6RqEKvU6HozdvNpvqsqC7pKHvLDaGf7W6JEGUaMKFsupm",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
0,
1
],
"data": "3Bxs4eQHmjXVhyyq",
"programIdIndex": 17,
"stackHeight": 2
},
{
"accounts": [
1,
22,
1,
22
],
"data": "G39KkjFmSSvsp9rL284N1x1o4GjqWfwgpvFBSUyPhnZotWbkk6er13bxKpwQRfVRsk4NNhjsdoKWXds2z4gefCtmt3AdM1nHXMr2rPTjE2SPEwx3N7u",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
1,
22
],
"data": "BjBG9fDQbu1raSNbBZQYubkmLijGDjgXJHpedBBGGrFrgSFFPaBAwnF",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
1,
9,
22
],
"data": "6ApXSNCamGdm",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
1,
22
],
"data": "31tb",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
33
],
"data": "NjG2ksDpCjg2vBAkvbNwNzbTBtkyZDQb88PDWQjMroYL6grYWjrj4qLgzhHuLuc7Vm88sE96VnmXfwWimEfoC2eFN6MSJNpCVQNoGExjPJsr9JdRbHckX5qgaozExVPbhPq6o5JF9FvJhHN9Ta7Jyg6VDzJx5PXFwNoMQPo2WHwRXSD8QguNLYwZZsykDCu1k2AxxBBY66AMJtN7qBn29s21EvXHZEYWgUsfZqiZPuWQ9yZsom7rUg5JsvGXgEoUq46TCnLSWX3Sa4njfBXQyUbNXFUHtcUNxHxWNYVJrQve34oY9MitHB3oWYYJ6bKPPLbBzynMFvZTmYUxDugS5SaVcKUwno1GtXMskmxQ77ezBXGxjjeoTLwrDavNA5pC59Q1LveSyxSrpmtDgzn3ou7FTn6hkyG7isHW6JhuakuXTMgG6TdDCDg2tFNcpEBCuVy5DKNCb5cjryaKW3dMBE",
"programIdIndex": 19,
"stackHeight": 2
}
]
},
{
"index": 1,
"instructions": [
{
"accounts": [
1
],
"data": "84eT",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
0,
3
],
"data": "111157Vt9WuCLrLm8Bv7v3tbuxTXo5Bq7vv6Fb1ngBYUyZPEU62jGZ4xnkMV46KCckXWDq",
"programIdIndex": 17,
"stackHeight": 2
},
{
"accounts": [
3
],
"data": "P",
"programIdIndex": 24,
"stackHeight": 2
},
{
"accounts": [
3,
1
],
"data": "6MeUrS32FsZaaMBU7i6ndCe6ozfwT4krHfHdvoL8eDRLZ",
"programIdIndex": 24,
"stackHeight": 2
}
]
},
{
"index": 2,
"instructions": [
{
"accounts": [
20
],
"data": "84eT",
"programIdIndex": 23,
"stackHeight": 2
},
{
"accounts": [
0,
10
],
"data": "111135fAZn8PZBEU8J8iUmUTdbmBE6po1LhhgEJXngDjhxmUTshDA8EHdXaMJUsXdMg3PE",
"programIdIndex": 17,
"stackHeight": 2
},
{
"accounts": [
10
],
"data": "P",
"programIdIndex": 23,
"stackHeight": 2
},
{
"accounts": [
10,
20
],
"data": "6MeUrS32FsZaaMBU7i6ndCe6ozfwT4krHfHdvoL8eDRLZ",
"programIdIndex": 23,
"stackHeight": 2
}
]
},
{
"index": 5,
"instructions": [
{
"accounts": [
10,
20,
13,
0
],
"data": "g7eSRZwiTurnL",
"programIdIndex": 23,
"stackHeight": 2
},
{
"accounts": [
13,
20,
16,
7
],
"data": "hdAm9QA8DyPL4",
"programIdIndex": 23,
"stackHeight": 2
},
{
"accounts": [
35
],
"data": "F5sjDwsY6unG7Vuxump49QEE6GPqsKRRjbYtvmBf93sHQrJjyd2SWsqYMsC3jRbZjYqC6TpPoCa9YVFFmTuM7KrrgBEzsecRKsWW35TGCY4PvSRsecK9Ak5Gi6n7Xb5FtXSL29LVpz4CkRq6ZMxBDnLaPbb2BYNhRo4jvfZBQjpUFnpcu2QHfJa2j3ZG6PjnRHiVCQekDEZn3sGBUdV9fPHCr9Y1fzEwmSFyjXhVCBJkrpTRKhN8DHJxno5haENhinpsftYV6NaT9FkfK2y5pnCYjTAFzJdNM7Me4TZ8bzh4U8krcd8qvJRz6Ss3WAogEpjGzhXf12zeX1TN7rbPpLBqfHYF71b93BUXryppLsTC6WTcqJzANfCjPSGNQLTkP2cPmL8VQvMVT1drnzAdUoz2nUgLy7P7v3EBVNhyLVSd1zwEvweMGwjRAyUx4MUe3kYtoWiXPrrYno2w3Mro8TrHBTJVrnjbfRBtTgacu1zQdFjmUhyDxnKp4LaJKFctnmn6m9978PAAXXdxvzKUwf58EXBpZrcBuei5g5f1c73J5324DB9BbQpC45nFXR1MZZDwn4qD82SQPdqd5AsanLm45tE2AHm7cQPjowZ7MpPbKNKHAJv82WCQ6ytDFhxyjCL24pU9owU2dVUG2qJyatgRxXoAaLLKmKsMpaDKUPCAR5CZfXjxTKpCBa13it2t7",
"programIdIndex": 25,
"stackHeight": 2
},
{
"accounts": [
26,
30,
31,
0,
7,
5,
3,
16,
23,
24,
17,
33,
19,
1,
28,
8,
9,
14
],
"data": "EscmTVC6NvfETrL1otmWhREDggH7X",
"programIdIndex": 19,
"stackHeight": 2
},
{
"accounts": [
5,
28,
14,
7
],
"data": "h1WdvkWkwUXW5",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
9,
1,
3,
8
],
"data": "gFVNA6XUw8Kcy",
"programIdIndex": 24,
"stackHeight": 3
},
{
"accounts": [
33
],
"data": "9TsSUqX1EufA2BpJyqWH324DfDhMu3qhRmuFSiJDzmVAyjhGyzbzB7vDVNKPSd8wv7F9VXMHiMSuqHhBsvriTrsEesvVmoJuzggcLmx6fdffKmsRrrAA3k1wPSyj8G98SkSNkrrgyu85SV5C5ibBFiVDQGPfPDakxFieYV2cxxdDDf2nUr8g9dTcy8FaDQ3kRpWzwxWo5GCooa9S6ryid1WMTbwYY5pMyr1xNGDgVFdihtQzD2qGXWCbuA4LNVyJnW9PLLVACpRxpcmza4wGubuG43yHBzBMZVkZ69fpCbnUWD3qxr7gCC1FM3swX5znzBbESLoGmBmaRhknJXfzR638oFDpGeD2tt9w24qRH6m9oFkCFqBxEZ8Qu8Td1Hv6cnu5aFGSKAzaEx3gpkfPJjH2fVgMbEEngsQt8s6mLy6k5q7coyn1HzM1ZSzquEmp49ZKiPEBCVj1CDLx95nR8CuhPJ6gDneVrewJTC5tmZBaYMaA92NDJZwkHb91cQdEHhpRMBeyN9J5ebWwzHbFqzFFhaeVpQt2fyDUXJw1xUF192f",
"programIdIndex": 19,
"stackHeight": 3
}
]
}
],
"loadedAddresses": {
"readonly": [],
"writable": []
},
"logMessages": [
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]",
"Program log: Instruction: CreateV2",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: MetadataPointerInstruction::Initialize",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1331 of 485765 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: Instruction: InitializeMint2",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2094 of 482771 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [2]",
"Program log: Create",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: GetAccountDataSize",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1426 of 460988 compute units",
"Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program 11111111111111111111111111111111 invoke [3]",
"Program 11111111111111111111111111111111 success",
"Program log: Initialize the associated token account",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: InitializeImmutableOwner",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 734 of 454740 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: InitializeAccount3",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2852 of 451670 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 19307 of 467821 compute units",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [2]",
"Program log: Create",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: GetAccountDataSize",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1495 of 385015 compute units",
"Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program 11111111111111111111111111111111 invoke [3]",
"Program 11111111111111111111111111111111 success",
"Program log: Initialize the associated token account",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: InitializeImmutableOwner",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 734 of 378698 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: InitializeAccount3",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 3107 of 375627 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 18133 of 390349 compute units",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: TokenMetadataInstruction: Initialize",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 4824 of 365854 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: TokenMetadataInstruction: UpdateAuthority",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 5166 of 358780 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: Instruction: MintTo",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2126 of 351422 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: Instruction: SetAuthority",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1477 of 347360 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program data: G3KpTd7rY3YPAAAARnJhbmNlIFZzIEphcGFuBwAAAE1lbWVXYXIqAAAAaHR0cHM6Ly9tZXRhZGF0YS5qN3RyYWNrZXIuaW8vbS9pUzFwWm5Tc1dEkGqSa3DQn5YpeAiT6kbIRpBHxziDiuRYGDjQPuonhf9F0KRI1oF1euQgDdX5W46C3mF00T8f9NRaFTpiLCbSkgeg7gUvefDJd46H38wlFS5JA8z2pDw6r2Q+fbLY0XseLfwX+3v045LhBSq17mBDRvgnGFoLrCT2EWoiOsuFdrr+1dxqAAAAAAAQ2EfjzwMAujSNABgiAAAAeMX7UdECAACAxqR+jQMABt324e51j94YQl285GzN2rYa/E2DuQ0n/r35KNihi/wAAFGnXo45VriLt1LFro/0CFI9JysLTPoCRaoGsZ5zE4bPujSNABgiAAAAAAAAAAAAAAEB",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2170 of 339678 compute units",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 164228 of 500000 compute units",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
"Program log: CreateIdempotent",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: Instruction: GetAccountDataSize",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1495 of 325865 compute units",
"Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success",
"Program log: Initialize the associated token account",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: Instruction: InitializeImmutableOwner",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 734 of 319548 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]",
"Program log: Instruction: InitializeAccount3",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 3107 of 316481 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 22715 of 335772 compute units",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
"Program log: CreateIdempotent",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 179 of 304559 compute units",
"Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success",
"Program log: Initialize the associated token account",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 37 of 299470 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 229 of 297009 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 16594 of 313057 compute units",
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
"Program 11111111111111111111111111111111 invoke [1]",
"Program 11111111111111111111111111111111 success",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 201 of 296313 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA invoke [1]",
"Program log: Instruction: MultiHopSwap",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 112 of 261523 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 112 of 248861 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program data: Z/RSHyz1d3f+1dxqAAAAAEcy3OayCgAAAPIFKgEAAAAAAAAAAAAAAADyBSoBAAAAb+BrAQXAAACVr417DwAAAADyBSoBAAAAAAAAAAAAAAAAAAAAAAAAAF0AAAAAAAAA7/6+AgAAAAAR80YnAQAAABHzRicBAAAAE/CTjcQkdFWIXilfKn8jXLG4GFA1iQxStgvX0ermnTwHoO4FL3nwyXeOh9/MJRUuSQPM9qQ8Oq9kPn2y2NF7HgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjqBnU1qOxwDQqX2cSlDp976NZXsciQaj4vjZ1Ja6ZIsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADH6PSSVbHelkGfZnq/cNN0PUojdpY4Dn486kXNTq3lIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAbXVsdGlfaG9wX3N3YXAAAAAAAAAAAAAAAAAAAAAAiBMAAAAAAAB3f18BAAAAAOCJtxAEAAAAAAAAAAAAAAABya43amJbAwAAAAAAAAAAAAAAAAAAAAAAPAa8AgAAAAAAAAAAAAAAAA==",
"Program pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA invoke [2]",
"Program pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA consumed 2116 of 240383 compute units",
"Program pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA success",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]",
"Program log: Instruction: MultiHopCurveSwap",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: TransferChecked",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2977 of 192860 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [3]",
"Program log: Instruction: TransferChecked",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 2977 of 187370 compute units",
"Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success",
"Program data: vdt/007mYe6QapJrcNCflil4CJPqRshGkEfHOIOK5FgYONA+6ieF/wAAAAAAAAAAC5HY/Y/oAAABB6DuBS958Ml3joffzCUVLkkDzPakPDqvZD59stjRex7+1dxqAAAAAAAAAAAAAAAA9X7/SVPnAgAAAAAAAAAAAPXm7P3B6AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALfwX+3v045LhBSq17mBDRvgnGFoLrCT2EWoiOsuFdroeAAAAAAAAANNdLzEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAG11bHRpX2hvcF9zd2FwAAAAAAAAAAAAAAAAAAAAAACIEwAAAAAAAAAAAAAAAAAAAAAAAFGnXo45VriLt1LFro/0CFI9JysLTPoCRaoGsZ5zE4bPdNSstaoKAAAuCTq2wiwAAHTUrLWqCgAAHgAAAAAAAADTXS8xCAAAANNdLzEIAAAAAAAAAAAAAAA=",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [3]",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2170 of 176900 compute units",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 51919 of 224564 compute units",
"Program return: 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P C5HY/Y/oAAAAAAAAAAAAAA==",
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
"Program pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA consumed 126252 of 296112 compute units",
"Program return: pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA C5HY/Y/oAAAAAAAAAAAAAA==",
"Program pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA success",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 118 of 169860 compute units",
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
"Program 11111111111111111111111111111111 invoke [1]",
"Program 11111111111111111111111111111111 success"
],
"postBalances": [
29512904014,
2590800,
11149834,
1513840,
7702527344,
1513840,
0,
2179320,
1493520,
1513840,
0,
64321466186961,
0,
71475845206,
1513840,
1346200,
1721866966,
1,
3104160,
9700912471,
1856043097572,
1009200,
1020235881,
230130698,
70228638,
1260746836,
4089842911,
33103977,
2626360,
46715680,
37292293,
9272823,
3388612899,
168261611,
1493520,
4641093
],
"postTokenBalances": [
{
"accountIndex": 3,
"mint": "Aijxkeq5L9iaDYZxfaXUhnHQj4cYeo8um6a3t5vzpump",
"owner": "WnBVqVTaiJk5hNbcwbHiffRVnMdf1aaxNU5JkSpvGub",
"programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
"uiTokenAmount": {
"amount": "255705136795915",
"decimals": 6,
"uiAmount": 255705136.795915,
"uiAmountString": "255705136.795915"
}
},
{
"accountIndex": 5,
"mint": "6Vk3fAQWYEot6JbQb8Nx8j5wZeDnMhzk8FajjHhZpump",
"owner": "2LqWmWBNPr1Jm17ovm7GmUf9qbL4Z7sh6kJvfbRpj8FM",
"programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
"uiTokenAmount": {
"amount": "199364237569576",
"decimals": 6,
"uiAmount": 199364237.569576,
"uiAmountString": "199364237.569576"
}
},
{
"accountIndex": 9,
"mint": "Aijxkeq5L9iaDYZxfaXUhnHQj4cYeo8um6a3t5vzpump",
"owner": "5hXezGZVX9N67LqKnfznLLrXqKzTFNEPbK6d5mdSamPo",
"programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
"uiTokenAmount": {
"amount": "744294863204085",
"decimals": 6,
"uiAmount": 744294863.204085,
"uiAmountString": "744294863.204085"
}
},
{
"accountIndex": 13,
"mint": "So11111111111111111111111111111111111111112",
"owner": "2LqWmWBNPr1Jm17ovm7GmUf9qbL4Z7sh6kJvfbRpj8FM",
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"uiTokenAmount": {
"amount": "71474356766",
"decimals": 9,
"uiAmount": 71.474356766,
"uiAmountString": "71.474356766"
}
},
{
"accountIndex": 14,
"mint": "6Vk3fAQWYEot6JbQb8Nx8j5wZeDnMhzk8FajjHhZpump",
"owner": "5hXezGZVX9N67LqKnfznLLrXqKzTFNEPbK6d5mdSamPo",
"programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
"uiTokenAmount": {
"amount": "11763493646919",
"decimals": 6,
"uiAmount": 11763493.646919,
"uiAmountString": "11763493.646919"
}
},
{
"accountIndex": 16,
"mint": "So11111111111111111111111111111111111111112",
"owner": "5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD",
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"uiTokenAmount": {
"amount": "1720378526",
"decimals": 9,
"uiAmount": 1.720378526,
"uiAmountString": "1.720378526"
}
}
],
"preBalances": [
34524139854,
0,
11149834,
0,
7700027344,
1513840,
0,
2179320,
0,
0,
0,
64321466186961,
0,
66498880973,
0,
1346200,
1698831199,
1,
3104160,
9700912471,
1856043097572,
1009200,
1020235881,
230130698,
70228638,
1260746836,
4089842911,
33103977,
2626360,
46715680,
37292293,
9272823,
3388612899,
168261611,
1493520,
4641093
],
"preTokenBalances": [
{
"accountIndex": 5,
"mint": "6Vk3fAQWYEot6JbQb8Nx8j5wZeDnMhzk8FajjHhZpump",
"owner": "2LqWmWBNPr1Jm17ovm7GmUf9qbL4Z7sh6kJvfbRpj8FM",
"programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
"uiTokenAmount": {
"amount": "211127731216495",
"decimals": 6,
"uiAmount": 211127731.216495,
"uiAmountString": "211127731.216495"
}
},
{
"accountIndex": 13,
"mint": "So11111111111111111111111111111111111111112",
"owner": "2LqWmWBNPr1Jm17ovm7GmUf9qbL4Z7sh6kJvfbRpj8FM",
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"uiTokenAmount": {
"amount": "66497392533",
"decimals": 9,
"uiAmount": 66.497392533,
"uiAmountString": "66.497392533"
}
},
{
"accountIndex": 16,
"mint": "So11111111111111111111111111111111111111112",
"owner": "5YxQFdt3Tr9zJLvkFccqXVUwhdTWJQc1fFg2YPbxvxeD",
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"uiTokenAmount": {
"amount": "1697342759",
"decimals": 9,
"uiAmount": 1.697342759,
"uiAmountString": "1.697342759"
}
}
],
"rewards": [],
"status": {
"Ok": null
}
},
"slot": 460910106,
"transaction": [
"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",
"base64"
],
"transactionIndex": 126,
"version": 1
}
}
]
}
+124
View File
@@ -3,6 +3,130 @@ use solana_streamer_sdk::{
};
use solana_transaction_status::EncodedConfirmedTransactionWithStatusMeta;
#[tokio::test]
async fn reported_alt_creates_and_multi_hop_survive_the_streamer_facade() {
use solana_sdk::pubkey::Pubkey;
use solana_streamer_sdk::streaming::{
common::event_processor::process_shred_transaction,
event_parser::{
common::{filter::EventTypeFilter, types::EventType},
Protocol,
},
shred::TransactionWithSlot,
};
use std::sync::{Arc, Mutex};
let filter =
EventTypeFilter::include_only(vec![EventType::PumpFunCreateToken, EventType::PumpFunTrade]);
for source in [
include_str!("fixtures/pump_create_alt_20261026.json"),
include_str!("fixtures/pump_multi_hop_20261025.json"),
] {
let fixture: serde_json::Value = serde_json::from_str(source).unwrap();
for case in fixture["cases"].as_array().unwrap() {
let rpc: EncodedConfirmedTransactionWithStatusMeta =
serde_json::from_value(case["wire_rpc"].clone()).unwrap();
let signed = rpc.transaction.transaction.decode().unwrap();
signed.verify_and_hash_message().unwrap();
let captured = Arc::new(Mutex::new(Vec::new()));
let output = captured.clone();
process_shred_transaction(
TransactionWithSlot::new(signed, rpc.slot, 123456, Some(888)),
&[Protocol::PumpFun],
Some(&filter),
Arc::new(move |e| output.lock().unwrap().push(e)),
None,
)
.await
.unwrap();
let events = captured.lock().unwrap();
assert_eq!(events.len(), 2, "{}", case["signature"]);
let DexEvent::PumpFunCreateTokenEvent(create) = &events[0] else {
panic!("create must be first")
};
let DexEvent::PumpFunTradeEvent(trade) = &events[1] else { panic!("trade missing") };
assert_eq!(create.ix_name, "create_v2");
assert_eq!(create.mint, trade.mint);
assert!(trade.is_created_buy && trade.is_buy);
for event in &*events {
assert_eq!(event.metadata().tx_index, Some(888));
assert_eq!(event.metadata().recv_us, 123456);
}
let multi_hop = trade.ix_name == "multi_hop_swap";
if multi_hop {
assert!(trade.third_program.is_some());
assert_eq!((trade.sol_amount, trade.token_amount, trade.quote_amount), (0, 0, 0));
} else {
assert_eq!(trade.token_program, Pubkey::default());
if trade.ix_name != "buy_exact_sol_in" {
assert_eq!(
trade.quote_mint,
Pubkey::default(),
"unknown quote must stay unknown"
);
}
}
for mode in 0..3 {
let mut rpc = rpc.clone();
if let Some(meta) = rpc.transaction.meta.as_mut() {
if let solana_transaction_status::option_serializer::OptionSerializer::Some(
logs,
) = &mut meta.log_messages
{
if mode == 1 {
logs.clear();
}
if mode == 2 {
logs.truncate(logs.len() / 2);
}
}
}
let rpc_events = parse_encoded_rpc_transaction_as_streamer_events(
&rpc,
123456,
&[Protocol::PumpFun],
Some(&filter),
)
.unwrap();
let (meta, transaction) =
solana_streamer_sdk::parser_sdk::convert_rpc_to_grpc(&rpc).unwrap();
let signature = transaction.signatures[0].clone();
let grpc_events = solana_streamer_sdk::streaming::common::event_processor::parse_grpc_transaction_events(
solana_streamer_sdk::streaming::grpc::TransactionPretty {
slot: rpc.slot, tx_index: Some(888), recv_us: 123456,
grpc_tx: yellowstone_grpc_proto::prelude::SubscribeUpdateTransactionInfo {
signature, transaction: Some(transaction), meta: Some(meta), index: 888,
..Default::default()
},
..Default::default()
}, &[Protocol::PumpFun], Some(&filter), None);
for executed in [rpc_events, grpc_events] {
assert!(
matches!(&executed[0], DexEvent::PumpFunCreateTokenEvent(c) if c.ix_name == "create_v2"),
"{} mode {mode}: {:?}",
case["signature"],
executed[0]
);
let fill = executed
.iter()
.find_map(|e| match e {
DexEvent::PumpFunTradeEvent(t) if t.mint == trade.mint => Some(t),
_ => None,
})
.unwrap();
assert_eq!(fill.ix_name, trade.ix_name);
if multi_hop {
assert!(fill.third_program.is_some());
assert_eq!(
(fill.sol_amount, fill.token_amount, fill.quote_amount),
(0, 255705136795915, 11728308720756)
);
}
}
}
}
}
}
#[test]
fn delta_sell_execution_survives_truncated_logs() {
let fixture: serde_json::Value =