Release solana-streamer-sdk 1.5.10

This commit is contained in:
0xfnzero
2026-06-07 02:00:14 +08:00
parent 28ffd0f566
commit 89bf36148f
8 changed files with 115 additions and 13 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "solana-streamer-sdk" name = "solana-streamer-sdk"
version = "1.5.9" version = "1.5.10"
edition = "2021" edition = "2021"
authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"] authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"]
repository = "https://github.com/0xfnzero/solana-streamer" 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"] sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"]
[dependencies] [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-sdk = "3.0.0"
solana-client = "3.1.12" solana-client = "3.1.12"
solana-transaction-status = "3.1.12" solana-transaction-status = "3.1.12"
+15 -5
View File
@@ -124,30 +124,34 @@ Add the dependency to your `Cargo.toml`:
```toml ```toml
# Add to your Cargo.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 ### Use crates.io
```toml ```toml
# Add to your Cargo.toml # Add to your Cargo.toml
solana-streamer-sdk = "1.5.9" solana-streamer-sdk = "1.5.10"
``` ```
Parser backend features: Parser backend features:
```toml ```toml
# Default: sol-parser-sdk parse-borsh backend # 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 # 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 ## 🔄 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 ### 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. 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![ let event_type_filter = Some(EventTypeFilter::include_only(vec![
EventType::PumpFeesUpdateFeeShares, EventType::PumpFeesUpdateFeeShares,
EventType::PumpSwapCreatePool, EventType::PumpSwapCreatePool,
EventType::AccountPumpSwapPool,
EventType::PumpSwapDeposit, EventType::PumpSwapDeposit,
EventType::PumpSwapWithdraw, EventType::PumpSwapWithdraw,
EventType::RaydiumCpmmInitialize, 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 ## Dynamic Subscription Management
Update subscription filters at runtime without reconnecting to the stream. Update subscription filters at runtime without reconnecting to the stream.
+15 -5
View File
@@ -123,30 +123,34 @@ git clone https://github.com/0xfnzero/solana-streamer
```toml ```toml
# 添加到您的 Cargo.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 ### 使用 crates.io
```toml ```toml
# 添加到您的 Cargo.toml # 添加到您的 Cargo.toml
solana-streamer-sdk = "1.5.9" solana-streamer-sdk = "1.5.10"
``` ```
解析后端 feature 解析后端 feature
```toml ```toml
# 默认:sol-parser-sdk parse-borsh 后端 # 默认:sol-parser-sdk parse-borsh 后端
solana-streamer-sdk = "1.5.9" solana-streamer-sdk = "1.5.10"
# 面向低延迟 Bot 的 zero-copy 解析后端 # 面向低延迟 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
v1.5.9 使用 crates.io 上的 `sol-parser-sdk 0.5.9`。该版本继承 Yellowstone gRPC stop 生命周期修复:`stop()` 现在会通知、abort 并等待当前订阅任务结束,订阅生命周期切换会串行化,并且 gRPC 流错误日志会标记为 `Grpc Stream error`,便于和 ShredStream 日志区分。 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![ let event_type_filter = Some(EventTypeFilter::include_only(vec![
EventType::PumpFeesUpdateFeeShares, EventType::PumpFeesUpdateFeeShares,
EventType::PumpSwapCreatePool, EventType::PumpSwapCreatePool,
EventType::AccountPumpSwapPool,
EventType::PumpSwapDeposit, EventType::PumpSwapDeposit,
EventType::PumpSwapWithdraw, EventType::PumpSwapWithdraw,
EventType::RaydiumCpmmInitialize, 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`
## 动态订阅管理 ## 动态订阅管理
在运行时更新订阅过滤器而无需重新连接到流。 在运行时更新订阅过滤器而无需重新连接到流。
+2
View File
@@ -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 等 | | **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 等 | | **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 ### 4.3 Bonk
| 事件 | 指令解析有(Shred 有) | 仅 CPI 合并有(Shred 缺失) | | 事件 | 指令解析有(Shred 有) | 仅 CPI 合并有(Shred 缺失) |
@@ -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_base_token_account = cpie.user_base_token_account;
e.user_quote_token_account = cpie.user_quote_token_account; e.user_quote_token_account = cpie.user_quote_token_account;
e.coin_creator = cpie.coin_creator; e.coin_creator = cpie.coin_creator;
e.is_mayhem_mode = cpie.is_mayhem_mode;
} }
_ => {} _ => {}
}, },
@@ -161,6 +161,7 @@ pub struct PumpSwapCreatePoolEvent {
pub user_base_token_account: Pubkey, pub user_base_token_account: Pubkey,
pub user_quote_token_account: Pubkey, pub user_quote_token_account: Pubkey,
pub coin_creator: Pubkey, pub coin_creator: Pubkey,
pub is_mayhem_mode: bool,
#[borsh(skip)] #[borsh(skip)]
pub user_pool_token_account: Pubkey, pub user_pool_token_account: Pubkey,
#[borsh(skip)] #[borsh(skip)]
@@ -169,7 +170,7 @@ pub struct PumpSwapCreatePoolEvent {
pub pool_quote_token_account: Pubkey, 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)] #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
+77
View File
@@ -43,6 +43,8 @@ mod tests {
use sol_parser_sdk::core::events::{ use sol_parser_sdk::core::events::{
EventMetadata, MeteoraDlmmSwapEvent as PbDlmmSwap, OrcaWhirlpoolSwapEvent as PbOrcaSwap, EventMetadata, MeteoraDlmmSwapEvent as PbDlmmSwap, OrcaWhirlpoolSwapEvent as PbOrcaSwap,
PumpFunCreateV2TokenEvent as PbPumpCreateV2, PumpFunTradeEvent as PbPumpTrade, PumpFunCreateV2TokenEvent as PbPumpCreateV2, PumpFunTradeEvent as PbPumpTrade,
PumpSwapCreatePoolEvent as PbPumpSwapCreatePool, PumpSwapPool as PbPumpSwapPool,
PumpSwapPoolAccountEvent as PbPumpSwapPoolAccount,
RaydiumLaunchlabTradeEvent as PbBonkTrade, TokenInfoEvent as PbTokenInfo, RaydiumLaunchlabTradeEvent as PbBonkTrade, TokenInfoEvent as PbTokenInfo,
TradeDirection as PbBonkDir, 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] #[test]
fn protocol_filter_keeps_pumpfun_only_when_requested() { fn protocol_filter_keeps_pumpfun_only_when_requested() {
let mut t = PbPumpTrade::default(); let mut t = PbPumpTrade::default();
@@ -612,6 +612,7 @@ pub(crate) fn pumpswap_create_pool_from_parser(
user_base_token_account: c.user_base_token_account, user_base_token_account: c.user_base_token_account,
user_quote_token_account: c.user_quote_token_account, user_quote_token_account: c.user_quote_token_account,
coin_creator: c.coin_creator, coin_creator: c.coin_creator,
is_mayhem_mode: c.is_mayhem_mode,
..Default::default() ..Default::default()
} }
} }