From 5a282bd84d08dd696cf769bc5d34255b2f0a53f7 Mon Sep 17 00:00:00 2001 From: 0xfnzero <0xfnzero@users.noreply.github.com> Date: Thu, 28 May 2026 04:58:18 +0800 Subject: [PATCH] Release solana-streamer-sdk v1.5.4 --- Cargo.toml | 6 +-- README.md | 14 +++--- README_CN.md | 14 +++--- src/streaming/event_parser/common/filter.rs | 10 +++-- .../event_parser/protocols/pumpfun/events.rs | 12 ++++++ src/streaming/parser_sdk_bridge/convert.rs | 4 +- src/streaming/parser_sdk_bridge/mod.rs | 43 ++++++++++++++++++- .../parser_sdk_bridge/pump_pumpswap.rs | 18 ++++---- 8 files changed, 92 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0f7ab27..b205594 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "solana-streamer-sdk" -version = "1.5.3" +version = "1.5.4" edition = "2021" authors = ["William ", "sgxiang ", "wei <1415121722@qq.com>"] repository = "https://github.com/0xfnzero/solana-streamer" @@ -15,13 +15,13 @@ crate-type = ["cdylib", "rlib"] [features] default = ["sdk-parse-borsh"] sdk-parse-borsh = ["sol-parser-sdk/parse-borsh"] -# If both parser backend features are enabled, sol-parser-sdk 0.5.3+ uses zero-copy. +# If both parser backend features are enabled, sol-parser-sdk 0.5.4+ uses zero-copy. sdk-parse-zero-copy = ["sol-parser-sdk/parse-zero-copy"] sdk-perf-stats = ["sol-parser-sdk/perf-stats"] sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"] [dependencies] -sol-parser-sdk = { version = "0.5.3", default-features = false } +sol-parser-sdk = { version = "0.5.4", 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 b8dbf72..deaa834 100755 --- a/README.md +++ b/README.md @@ -123,30 +123,34 @@ Add the dependency to your `Cargo.toml`: ```toml # Add to your Cargo.toml -solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.3" } +solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.4" } ``` ### Use crates.io ```toml # Add to your Cargo.toml -solana-streamer-sdk = "1.5.3" +solana-streamer-sdk = "1.5.4" ``` Parser backend features: ```toml # Default: sol-parser-sdk parse-borsh backend -solana-streamer-sdk = "1.5.3" +solana-streamer-sdk = "1.5.4" # Zero-copy parser backend for latency-sensitive bots -solana-streamer-sdk = { version = "1.5.3", default-features = false, features = ["sdk-parse-zero-copy"] } +solana-streamer-sdk = { version = "1.5.4", 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.3+` uses the zero-copy backend. +If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.5.4+` uses the zero-copy backend. ## 🔄 Migration Guide +### Upgrading to v1.5.4 + +Version 1.5.4 uses `sol-parser-sdk 0.5.4` from crates.io. Pump.fun `create` and `create_v2` are delivered as one canonical `PumpFunCreateTokenEvent`; subscribing to either `PumpFunCreateToken` or `PumpFunCreateV2Token` receives the same complete create-family data. This prevents duplicate new-mint callbacks from gRPC log + instruction parsing while preserving create_v2 account fields on the canonical create event. + ### Upgrading to v1.5.3 Version 1.5.3 uses `sol-parser-sdk 0.5.3` from crates.io. It preserves real Pump.fun v2 `ix_name` values through the streamer bridge, improves ShredStream Pump.fun v2 best-effort parsing for short account lists, and treats `PumpFunBuy` and `PumpFunBuyExactSolIn` subscriptions as compatible buy-family filters. ShredStream still uses the direct entry-reading path with automatic reconnect; callbacks should remain non-blocking and `tx_index` remains entry-local best-effort. diff --git a/README_CN.md b/README_CN.md index d5c30bd..c8531d8 100644 --- a/README_CN.md +++ b/README_CN.md @@ -122,30 +122,34 @@ git clone https://github.com/0xfnzero/solana-streamer ```toml # 添加到您的 Cargo.toml -solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.3" } +solana-streamer-sdk = { path = "./solana-streamer", version = "1.5.4" } ``` ### 使用 crates.io ```toml # 添加到您的 Cargo.toml -solana-streamer-sdk = "1.5.3" +solana-streamer-sdk = "1.5.4" ``` 解析后端 feature: ```toml # 默认:sol-parser-sdk parse-borsh 后端 -solana-streamer-sdk = "1.5.3" +solana-streamer-sdk = "1.5.4" # 面向低延迟 Bot 的 zero-copy 解析后端 -solana-streamer-sdk = { version = "1.5.3", default-features = false, features = ["sdk-parse-zero-copy"] } +solana-streamer-sdk = { version = "1.5.4", default-features = false, features = ["sdk-parse-zero-copy"] } ``` -如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.5.3+` 会优先使用 zero-copy 后端。 +如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.5.4+` 会优先使用 zero-copy 后端。 ## 🔄 迁移指南 +### 升级到 v1.5.4 + +v1.5.4 使用 crates.io 上的 `sol-parser-sdk 0.5.4`。Pump.fun `create` 和 `create_v2` 会统一投递为 canonical `PumpFunCreateTokenEvent`;订阅 `PumpFunCreateToken` 或 `PumpFunCreateV2Token` 任意一个,都能收到同一份完整 create-family 数据。该版本避免 gRPC log + instruction 双路径解析导致新 mint 回调重复,同时在 canonical create 事件上保留 create_v2 账户字段。 + ### 升级到 v1.5.3 v1.5.3 使用 crates.io 上的 `sol-parser-sdk 0.5.3`。该版本会通过 streamer bridge 保留真实的 Pump.fun v2 `ix_name`,改进 ShredStream 对 Pump.fun v2 短账户列表的 best-effort 解析,并让订阅 `PumpFunBuy` 或 `PumpFunBuyExactSolIn` 都能匹配兼容的 buy-family 事件。ShredStream 仍使用直接读取 Entry 的自动重连低延迟路径;回调应避免阻塞,`tx_index` 仍是 Entry 内 best-effort 索引。 diff --git a/src/streaming/event_parser/common/filter.rs b/src/streaming/event_parser/common/filter.rs index e137fe5..aae9768 100644 --- a/src/streaming/event_parser/common/filter.rs +++ b/src/streaming/event_parser/common/filter.rs @@ -187,7 +187,10 @@ fn push_streamer_event_sdk_grpc_types( out.push(Sdk::PumpFunCreate); out.push(Sdk::PumpFunCreateV2); } - St::PumpFunCreateV2Token => out.push(Sdk::PumpFunCreateV2), + St::PumpFunCreateV2Token => { + out.push(Sdk::PumpFunCreate); + out.push(Sdk::PumpFunCreateV2); + } St::PumpFunBuy => { if matches!(mode, FilterMapMode::Include) { out.push(Sdk::PumpFunTrade); @@ -423,6 +426,7 @@ fn event_type_matches(filter_type: &EventType, event_type: &EventType) -> bool { || matches!( (filter_type, event_type), (EventType::PumpFunCreateToken, EventType::PumpFunCreateV2Token) + | (EventType::PumpFunCreateV2Token, EventType::PumpFunCreateToken) | (EventType::PumpFunBuy, EventType::PumpFunBuyExactSolIn) | (EventType::PumpFunBuyExactSolIn, EventType::PumpFunBuy) | (EventType::TokenAccount, EventType::TokenInfo) @@ -578,11 +582,11 @@ mod tests { include: vec![EventType::PumpFunCreateV2Token], ..Default::default() }; - assert!(!f.passes_event_type(&EventType::PumpFunCreateToken)); + assert!(f.passes_event_type(&EventType::PumpFunCreateToken)); assert!(f.passes_event_type(&EventType::PumpFunCreateV2Token)); let sdk_f = build_sdk_parse_event_filter(Some(&f)).expect("mapped"); - assert!(!sdk_f.should_include(SdkGrpcEventType::PumpFunCreate)); + assert!(sdk_f.should_include(SdkGrpcEventType::PumpFunCreate)); assert!(sdk_f.should_include(SdkGrpcEventType::PumpFunCreateV2)); } diff --git a/src/streaming/event_parser/protocols/pumpfun/events.rs b/src/streaming/event_parser/protocols/pumpfun/events.rs index 2a7ae61..3393b25 100755 --- a/src/streaming/event_parser/protocols/pumpfun/events.rs +++ b/src/streaming/event_parser/protocols/pumpfun/events.rs @@ -52,6 +52,18 @@ pub struct PumpFunCreateTokenEvent { pub event_authority: Pubkey, #[borsh(skip)] pub program: Pubkey, + #[borsh(skip)] + pub mayhem_program_id: Pubkey, + #[borsh(skip)] + pub global_params: Pubkey, + #[borsh(skip)] + pub sol_vault: Pubkey, + #[borsh(skip)] + pub mayhem_state: Pubkey, + #[borsh(skip)] + pub mayhem_token_vault: Pubkey, + #[borsh(skip)] + pub observed_fee_recipient: Pubkey, } /// CreateV2 事件:与 create_v2 指令 16 个账户一致(见 parser 注释)。 diff --git a/src/streaming/parser_sdk_bridge/convert.rs b/src/streaming/parser_sdk_bridge/convert.rs index a7afea2..caf76e4 100644 --- a/src/streaming/parser_sdk_bridge/convert.rs +++ b/src/streaming/parser_sdk_bridge/convert.rs @@ -60,10 +60,10 @@ pub(crate) fn convert_parser_event( bt, recv_wall_us, ProtocolType::PumpFun, - EventType::PumpFunCreateV2Token, + EventType::PumpFunCreateToken, pump_program(), ); - Some(DexEvent::PumpFunCreateV2TokenEvent(pumpfun_create_v2_from_parser(c, meta))) + Some(DexEvent::PumpFunCreateTokenEvent(pumpfun_create_token_from_parser_v2(c, meta))) } PbDexEvent::PumpFunMigrate(m) => { let meta = adapt_pm( diff --git a/src/streaming/parser_sdk_bridge/mod.rs b/src/streaming/parser_sdk_bridge/mod.rs index 907043f..996776f 100644 --- a/src/streaming/parser_sdk_bridge/mod.rs +++ b/src/streaming/parser_sdk_bridge/mod.rs @@ -41,8 +41,9 @@ mod tests { use crate::streaming::event_parser::{DexEvent, Protocol}; use sol_parser_sdk::core::events::{ BonkTradeEvent as PbBonkTrade, EventMetadata, MeteoraDlmmSwapEvent as PbDlmmSwap, - OrcaWhirlpoolSwapEvent as PbOrcaSwap, PumpFunTradeEvent as PbPumpTrade, - TokenInfoEvent as PbTokenInfo, TradeDirection as PbBonkDir, + OrcaWhirlpoolSwapEvent as PbOrcaSwap, PumpFunCreateV2TokenEvent as PbPumpCreateV2, + PumpFunTradeEvent as PbPumpTrade, TokenInfoEvent as PbTokenInfo, + TradeDirection as PbBonkDir, }; use sol_parser_sdk::DexEvent as PbDexEvent; use solana_sdk::{pubkey::Pubkey, signature::Signature}; @@ -141,6 +142,44 @@ mod tests { } } + #[test] + fn converts_pumpfun_create_v2_as_canonical_create() { + let mint = Pubkey::new_unique(); + let global = Pubkey::new_unique(); + let event_authority = Pubkey::new_unique(); + let c = PbPumpCreateV2 { + metadata: EventMetadata { + signature: Signature::default(), + slot: 42, + tx_index: 7, + block_time_us: 1_000_000, + grpc_recv_us: 88, + recent_blockhash: None, + }, + name: "Token".to_string(), + symbol: "TOK".to_string(), + mint, + global, + event_authority, + is_mayhem_mode: true, + is_cashback_enabled: true, + ..Default::default() + }; + + let ev = convert_parser_event(PbDexEvent::PumpFunCreateV2(c), None, 999).expect("convert"); + match ev { + DexEvent::PumpFunCreateTokenEvent(st) => { + assert_eq!(st.metadata.event_type, EventType::PumpFunCreateToken); + assert_eq!(st.mint, mint); + assert_eq!(st.global, global); + assert_eq!(st.event_authority, event_authority); + assert!(st.is_mayhem_mode); + assert!(st.is_cashback_enabled); + } + other => panic!("expected canonical PumpFunCreateTokenEvent, got {other:?}"), + } + } + #[test] fn converts_pumpfun_buy_exact_quote_in_v2_as_buy_event() { 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 79d302e..505f540 100644 --- a/src/streaming/parser_sdk_bridge/pump_pumpswap.rs +++ b/src/streaming/parser_sdk_bridge/pump_pumpswap.rs @@ -7,12 +7,11 @@ use crate::streaming::event_parser::protocols::pumpfun::events::{ PumpFeesRevokeFeeSharingAuthorityEvent, PumpFeesShareholder, PumpFeesTransferFeeSharingAuthorityEvent, PumpFeesUpdateAdminEvent, PumpFeesUpdateFeeConfigEvent, PumpFeesUpdateFeeSharesEvent, PumpFeesUpsertFeeTiersEvent, - PumpFunBondingCurveAccountEvent, PumpFunCreateTokenEvent, PumpFunCreateV2TokenEvent, - PumpFunFeeConfig, PumpFunFeeConfigAccountEvent, PumpFunGlobalAccountEvent, - PumpFunGlobalVolumeAccumulator, PumpFunGlobalVolumeAccumulatorAccountEvent, - PumpFunMigrateBondingCurveCreatorEvent, PumpFunMigrateEvent, PumpFunSharingConfig, - PumpFunSharingConfigAccountEvent, PumpFunTradeEvent, PumpFunUserVolumeAccumulator, - PumpFunUserVolumeAccumulatorAccountEvent, + PumpFunBondingCurveAccountEvent, PumpFunCreateTokenEvent, PumpFunFeeConfig, + PumpFunFeeConfigAccountEvent, PumpFunGlobalAccountEvent, PumpFunGlobalVolumeAccumulator, + PumpFunGlobalVolumeAccumulatorAccountEvent, PumpFunMigrateBondingCurveCreatorEvent, + PumpFunMigrateEvent, PumpFunSharingConfig, PumpFunSharingConfigAccountEvent, PumpFunTradeEvent, + PumpFunUserVolumeAccumulator, PumpFunUserVolumeAccumulatorAccountEvent, }; use crate::streaming::event_parser::protocols::pumpfun::types::{BondingCurve, Global}; use crate::streaming::event_parser::protocols::pumpswap::events::{ @@ -65,11 +64,11 @@ pub(crate) fn pumpfun_create_token_from_parser( } } -pub(crate) fn pumpfun_create_v2_from_parser( +pub(crate) fn pumpfun_create_token_from_parser_v2( c: sol_parser_sdk::core::events::PumpFunCreateV2TokenEvent, meta: EventMetadata, -) -> PumpFunCreateV2TokenEvent { - PumpFunCreateV2TokenEvent { +) -> PumpFunCreateTokenEvent { + PumpFunCreateTokenEvent { metadata: meta, name: c.name, symbol: c.symbol, @@ -100,6 +99,7 @@ pub(crate) fn pumpfun_create_v2_from_parser( mayhem_token_vault: c.mayhem_token_vault, event_authority: c.event_authority, program: c.program, + ..Default::default() } }