From 89bf36148f6fb9349a577f2253ee64a4f33f644f Mon Sep 17 00:00:00 2001 From: 0xfnzero <0xfnzero@users.noreply.github.com> Date: Sun, 7 Jun 2026 02:00:14 +0800 Subject: [PATCH] Release solana-streamer-sdk 1.5.10 --- Cargo.toml | 4 +- README.md | 20 +++-- README_CN.md | 20 +++-- docs/SHREDSTREAM_LIMITATIONS.md | 2 + .../event_parser/core/merger_event.rs | 1 + .../event_parser/protocols/pumpswap/events.rs | 3 +- src/streaming/parser_sdk_bridge/mod.rs | 77 +++++++++++++++++++ .../parser_sdk_bridge/pump_pumpswap.rs | 1 + 8 files changed, 115 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bc4ea9f..623ce9d 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "solana-streamer-sdk" -version = "1.5.9" +version = "1.5.10" edition = "2021" authors = ["William ", "sgxiang ", "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.9", default-features = false } +sol-parser-sdk = { version = "0.5.10", default-features = false } solana-sdk = "3.0.0" solana-client = "3.1.12" solana-transaction-status = "3.1.12" diff --git a/README.md b/README.md index 219c5ee..72504bb 100755 --- a/README.md +++ b/README.md @@ -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.9" } +solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.10" } ``` ### Use crates.io ```toml # Add to your Cargo.toml -solana-streamer-sdk = "1.5.9" +solana-streamer-sdk = "1.5.10" ``` Parser backend features: ```toml # Default: sol-parser-sdk parse-borsh backend -solana-streamer-sdk = "1.5.9" +solana-streamer-sdk = "1.5.10" # Zero-copy parser backend for latency-sensitive bots -solana-streamer-sdk = { version = "1.5.9", default-features = false, features = ["sdk-parse-zero-copy"] } +solana-streamer-sdk = { version = "1.5.10", 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.9+` uses the zero-copy backend. +If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.5.10+` uses the zero-copy backend. ## 🔄 Migration Guide +### Upgrading to v1.5.10 + +Version 1.5.10 uses `sol-parser-sdk 0.5.10` from crates.io. PumpSwap `CreatePoolEvent` now matches the on-chain IDL: it exposes `is_mayhem_mode` but does not expose `is_cashback_coin`. To read the cashback flag, subscribe to `AccountPumpSwapPool` and use `PumpSwapPoolAccountEvent.pool.is_cashback_coin`. The PumpSwap CreatePool log payload length check now includes the final `is_mayhem_mode` byte. + ### Upgrading to v1.5.9 Version 1.5.9 uses `sol-parser-sdk 0.5.9` from crates.io. It inherits the Yellowstone gRPC stop lifecycle fix: `stop()` now signals, aborts, and awaits the active subscription task, subscription lifecycle transitions are serialized, and gRPC stream errors are labeled as `Grpc Stream error` for easier log separation from ShredStream. @@ -409,6 +413,7 @@ let event_type_filter = Some(EventTypeFilter::include_only(vec![ let event_type_filter = Some(EventTypeFilter::include_only(vec![ EventType::PumpFeesUpdateFeeShares, EventType::PumpSwapCreatePool, + EventType::AccountPumpSwapPool, EventType::PumpSwapDeposit, EventType::PumpSwapWithdraw, EventType::RaydiumCpmmInitialize, @@ -423,6 +428,11 @@ let event_type_filter = Some(EventTypeFilter::include_only(vec![ ])); ``` +`PumpSwapCreatePool` follows the on-chain `CreatePoolEvent` IDL and includes +`is_mayhem_mode`, but it does not include `is_cashback_coin`. To read the +cashback flag, subscribe to `AccountPumpSwapPool` and use +`PumpSwapPoolAccountEvent.pool.is_cashback_coin`. + ## Dynamic Subscription Management Update subscription filters at runtime without reconnecting to the stream. diff --git a/README_CN.md b/README_CN.md index 603ec11..022263a 100644 --- a/README_CN.md +++ b/README_CN.md @@ -123,30 +123,34 @@ git clone https://github.com/0xfnzero/solana-streamer ```toml # 添加到您的 Cargo.toml -solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.9" } +solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.10" } ``` ### 使用 crates.io ```toml # 添加到您的 Cargo.toml -solana-streamer-sdk = "1.5.9" +solana-streamer-sdk = "1.5.10" ``` 解析后端 feature: ```toml # 默认:sol-parser-sdk parse-borsh 后端 -solana-streamer-sdk = "1.5.9" +solana-streamer-sdk = "1.5.10" # 面向低延迟 Bot 的 zero-copy 解析后端 -solana-streamer-sdk = { version = "1.5.9", default-features = false, features = ["sdk-parse-zero-copy"] } +solana-streamer-sdk = { version = "1.5.10", default-features = false, features = ["sdk-parse-zero-copy"] } ``` -如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.5.9+` 会优先使用 zero-copy 后端。 +如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.5.10+` 会优先使用 zero-copy 后端。 ## 🔄 迁移指南 +### 升级到 v1.5.10 + +v1.5.10 使用 crates.io 上的 `sol-parser-sdk 0.5.10`。PumpSwap `CreatePoolEvent` 现在与链上 IDL 对齐:暴露 `is_mayhem_mode`,但不暴露 `is_cashback_coin`。如果需要 cashback 标记,请订阅 `AccountPumpSwapPool`,并读取 `PumpSwapPoolAccountEvent.pool.is_cashback_coin`。PumpSwap CreatePool log payload 长度检查现在包含最后的 `is_mayhem_mode` 字节。 + ### 升级到 v1.5.9 v1.5.9 使用 crates.io 上的 `sol-parser-sdk 0.5.9`。该版本继承 Yellowstone gRPC stop 生命周期修复:`stop()` 现在会通知、abort 并等待当前订阅任务结束,订阅生命周期切换会串行化,并且 gRPC 流错误日志会标记为 `Grpc Stream error`,便于和 ShredStream 日志区分。 @@ -408,6 +412,7 @@ let event_type_filter = Some(EventTypeFilter::include_only(vec![ let event_type_filter = Some(EventTypeFilter::include_only(vec![ EventType::PumpFeesUpdateFeeShares, EventType::PumpSwapCreatePool, + EventType::AccountPumpSwapPool, EventType::PumpSwapDeposit, EventType::PumpSwapWithdraw, EventType::RaydiumCpmmInitialize, @@ -422,6 +427,11 @@ let event_type_filter = Some(EventTypeFilter::include_only(vec![ ])); ``` +`PumpSwapCreatePool` 对齐链上 `CreatePoolEvent` IDL,包含 +`is_mayhem_mode`,但不包含 `is_cashback_coin`。如果需要 cashback 标记, +请订阅 `AccountPumpSwapPool`,并读取 +`PumpSwapPoolAccountEvent.pool.is_cashback_coin`。 + ## 动态订阅管理 在运行时更新订阅过滤器而无需重新连接到流。 diff --git a/docs/SHREDSTREAM_LIMITATIONS.md b/docs/SHREDSTREAM_LIMITATIONS.md index 91137c3..57757a8 100644 --- a/docs/SHREDSTREAM_LIMITATIONS.md +++ b/docs/SHREDSTREAM_LIMITATIONS.md @@ -88,6 +88,8 @@ ShredStream 路径仍为下面的原始交易解析限制,不使用上述日 | **Deposit** | lp_token_amount_out, max_base/quote_amount_in, pool, user, 各 mint / token account | timestamp, user/pool *_reserves, base_amount_in, quote_amount_in, lp_mint_supply 等 | | **Withdraw** | lp_token_amount_in, min_base/quote_amount_out, pool, user, 各账户 | timestamp, *_reserves, base/quote_amount_out, lp_mint_supply 等 | +说明:`PumpSwapCreatePool` 对齐链上 `CreatePoolEvent` IDL,只包含 `is_mayhem_mode`,不包含 `is_cashback_coin`。`is_cashback_coin` 属于 PumpSwap `Pool` account 字段;ShredStream 不带账户 body,无法从 Shred 的 CreatePool 事件恢复该字段。需要该字段时,请在 gRPC/account 流中订阅 `AccountPumpSwapPool`,读取 `PumpSwapPoolAccountEvent.pool.is_cashback_coin`。 + ### 4.3 Bonk | 事件 | 指令解析有(Shred 有) | 仅 CPI 合并有(Shred 缺失) | diff --git a/src/streaming/event_parser/core/merger_event.rs b/src/streaming/event_parser/core/merger_event.rs index c7b5644..d8f35fe 100644 --- a/src/streaming/event_parser/core/merger_event.rs +++ b/src/streaming/event_parser/core/merger_event.rs @@ -425,6 +425,7 @@ pub fn merge(instruction_event: &mut DexEvent, cpi_log_event: DexEvent) { e.user_base_token_account = cpie.user_base_token_account; e.user_quote_token_account = cpie.user_quote_token_account; e.coin_creator = cpie.coin_creator; + e.is_mayhem_mode = cpie.is_mayhem_mode; } _ => {} }, diff --git a/src/streaming/event_parser/protocols/pumpswap/events.rs b/src/streaming/event_parser/protocols/pumpswap/events.rs index c73865a..2c94796 100755 --- a/src/streaming/event_parser/protocols/pumpswap/events.rs +++ b/src/streaming/event_parser/protocols/pumpswap/events.rs @@ -161,6 +161,7 @@ pub struct PumpSwapCreatePoolEvent { pub user_base_token_account: Pubkey, pub user_quote_token_account: Pubkey, pub coin_creator: Pubkey, + pub is_mayhem_mode: bool, #[borsh(skip)] pub user_pool_token_account: Pubkey, #[borsh(skip)] @@ -169,7 +170,7 @@ pub struct PumpSwapCreatePoolEvent { pub pool_quote_token_account: Pubkey, } -pub const PUMP_SWAP_CREATE_POOL_EVENT_LOG_SIZE: usize = 325; +pub const PUMP_SWAP_CREATE_POOL_EVENT_LOG_SIZE: usize = 326; /// 存款事件 #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)] diff --git a/src/streaming/parser_sdk_bridge/mod.rs b/src/streaming/parser_sdk_bridge/mod.rs index 26673dc..b536b92 100644 --- a/src/streaming/parser_sdk_bridge/mod.rs +++ b/src/streaming/parser_sdk_bridge/mod.rs @@ -43,6 +43,8 @@ mod tests { use sol_parser_sdk::core::events::{ EventMetadata, MeteoraDlmmSwapEvent as PbDlmmSwap, OrcaWhirlpoolSwapEvent as PbOrcaSwap, PumpFunCreateV2TokenEvent as PbPumpCreateV2, PumpFunTradeEvent as PbPumpTrade, + PumpSwapCreatePoolEvent as PbPumpSwapCreatePool, PumpSwapPool as PbPumpSwapPool, + PumpSwapPoolAccountEvent as PbPumpSwapPoolAccount, RaydiumLaunchlabTradeEvent as PbBonkTrade, TokenInfoEvent as PbTokenInfo, TradeDirection as PbBonkDir, }; @@ -200,6 +202,81 @@ mod tests { } } + #[test] + fn converts_pumpswap_create_pool_flags() { + let c = PbPumpSwapCreatePool { + metadata: EventMetadata { + signature: Signature::default(), + slot: 42, + tx_index: 7, + block_time_us: 1_000_000, + grpc_recv_us: 88, + recent_blockhash: None, + }, + pool: Pubkey::new_unique(), + base_mint: Pubkey::new_unique(), + quote_mint: Pubkey::new_unique(), + is_mayhem_mode: true, + ..Default::default() + }; + + let ev = + convert_parser_event(PbDexEvent::PumpSwapCreatePool(c), None, 999).expect("convert"); + match ev { + DexEvent::PumpSwapCreatePoolEvent(st) => { + assert_eq!(st.metadata.event_type, EventType::PumpSwapCreatePool); + assert!(st.is_mayhem_mode); + } + _ => panic!("expected PumpSwapCreatePoolEvent"), + } + } + + #[test] + fn converts_pumpswap_pool_account_cashback_flag() { + let pool_pubkey = Pubkey::new_unique(); + let e = PbPumpSwapPoolAccount { + metadata: EventMetadata { + signature: Signature::default(), + slot: 42, + tx_index: 7, + block_time_us: 1_000_000, + grpc_recv_us: 88, + recent_blockhash: None, + }, + pubkey: pool_pubkey, + executable: false, + lamports: 123, + owner: Pubkey::new_unique(), + rent_epoch: 0, + pool: PbPumpSwapPool { + pool_bump: 7, + index: 42, + creator: Pubkey::new_unique(), + base_mint: Pubkey::new_unique(), + quote_mint: Pubkey::new_unique(), + lp_mint: Pubkey::new_unique(), + pool_base_token_account: Pubkey::new_unique(), + pool_quote_token_account: Pubkey::new_unique(), + lp_supply: 999, + coin_creator: Pubkey::new_unique(), + is_mayhem_mode: true, + is_cashback_coin: true, + }, + }; + + let ev = + convert_parser_event(PbDexEvent::PumpSwapPoolAccount(e), None, 999).expect("convert"); + match ev { + DexEvent::PumpSwapPoolAccountEvent(st) => { + assert_eq!(st.metadata.event_type, EventType::AccountPumpSwapPool); + assert_eq!(st.pubkey, pool_pubkey); + assert!(st.pool.is_mayhem_mode); + assert!(st.pool.is_cashback_coin); + } + _ => panic!("expected PumpSwapPoolAccountEvent"), + } + } + #[test] fn protocol_filter_keeps_pumpfun_only_when_requested() { let mut t = PbPumpTrade::default(); diff --git a/src/streaming/parser_sdk_bridge/pump_pumpswap.rs b/src/streaming/parser_sdk_bridge/pump_pumpswap.rs index 3bea8d4..b65975d 100644 --- a/src/streaming/parser_sdk_bridge/pump_pumpswap.rs +++ b/src/streaming/parser_sdk_bridge/pump_pumpswap.rs @@ -612,6 +612,7 @@ pub(crate) fn pumpswap_create_pool_from_parser( user_base_token_account: c.user_base_token_account, user_quote_token_account: c.user_quote_token_account, coin_creator: c.coin_creator, + is_mayhem_mode: c.is_mayhem_mode, ..Default::default() } }