mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-08-23 13:58:06 +00:00
Release solana-streamer-sdk 1.5.10
This commit is contained in:
+2
-2
@@ -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"
|
||||||
|
|||||||
@@ -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
@@ -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`。
|
||||||
|
|
||||||
## 动态订阅管理
|
## 动态订阅管理
|
||||||
|
|
||||||
在运行时更新订阅过滤器而无需重新连接到流。
|
在运行时更新订阅过滤器而无需重新连接到流。
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user