mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-08-24 14:28:10 +00:00
Use sol-parser-sdk 0.4.17
This commit is contained in:
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "solana-streamer-sdk"
|
name = "solana-streamer-sdk"
|
||||||
version = "1.4.11"
|
version = "1.4.12"
|
||||||
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"
|
||||||
@@ -15,13 +15,13 @@ crate-type = ["cdylib", "rlib"]
|
|||||||
[features]
|
[features]
|
||||||
default = ["sdk-parse-borsh"]
|
default = ["sdk-parse-borsh"]
|
||||||
sdk-parse-borsh = ["sol-parser-sdk/parse-borsh"]
|
sdk-parse-borsh = ["sol-parser-sdk/parse-borsh"]
|
||||||
# If both parser backend features are enabled, sol-parser-sdk 0.4.16+ uses zero-copy.
|
# If both parser backend features are enabled, sol-parser-sdk 0.4.17+ uses zero-copy.
|
||||||
sdk-parse-zero-copy = ["sol-parser-sdk/parse-zero-copy"]
|
sdk-parse-zero-copy = ["sol-parser-sdk/parse-zero-copy"]
|
||||||
sdk-perf-stats = ["sol-parser-sdk/perf-stats"]
|
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.4.16", default-features = false }
|
sol-parser-sdk = { version = "0.4.17", 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"
|
||||||
|
|||||||
@@ -123,33 +123,33 @@ 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.4.11" }
|
solana-streamer-sdk = { path = "./solana-streamer", version = "1.4.12" }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Use crates.io
|
### Use crates.io
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# Add to your Cargo.toml
|
# Add to your Cargo.toml
|
||||||
solana-streamer-sdk = "1.4.11"
|
solana-streamer-sdk = "1.4.12"
|
||||||
```
|
```
|
||||||
|
|
||||||
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.4.11"
|
solana-streamer-sdk = "1.4.12"
|
||||||
|
|
||||||
# Zero-copy parser backend for latency-sensitive bots
|
# Zero-copy parser backend for latency-sensitive bots
|
||||||
solana-streamer-sdk = { version = "1.4.11", default-features = false, features = ["sdk-parse-zero-copy"] }
|
solana-streamer-sdk = { version = "1.4.12", default-features = false, features = ["sdk-parse-zero-copy"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.4.16+` uses the zero-copy backend.
|
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.4.17+` uses the zero-copy backend.
|
||||||
|
|
||||||
## 🔄 Migration Guide
|
## 🔄 Migration Guide
|
||||||
|
|
||||||
### Upgrading to v1.4.11
|
### Upgrading to v1.4.12
|
||||||
|
|
||||||
Version 1.4.11 uses `sol-parser-sdk 0.4.16` and preserves the SDK-compatible Yellowstone gRPC ordering modes in the streamer facade while aligning PumpFun USDC/v2 create, trade, global, bonding-curve, and volume account fields with the parser SDK. `buy_exact_quote_in(_v2)` is delivered as `PumpFunBuy` with the exact quote fields preserved.
|
Version 1.4.12 uses `sol-parser-sdk 0.4.17` and normalizes legacy PumpFun SOL quote mints to the Solscan SOL sentinel while preserving real USDC quote mints and quote-reserve fields. Streamer bridge and merger paths keep the parser SDK semantics aligned for Yellowstone gRPC and ShredStream output.
|
||||||
|
|
||||||
New optional capabilities:
|
New optional capabilities:
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -122,33 +122,33 @@ git clone https://github.com/0xfnzero/solana-streamer
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
# 添加到您的 Cargo.toml
|
# 添加到您的 Cargo.toml
|
||||||
solana-streamer-sdk = { path = "./solana-streamer", version = "1.4.11" }
|
solana-streamer-sdk = { path = "./solana-streamer", version = "1.4.12" }
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用 crates.io
|
### 使用 crates.io
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# 添加到您的 Cargo.toml
|
# 添加到您的 Cargo.toml
|
||||||
solana-streamer-sdk = "1.4.11"
|
solana-streamer-sdk = "1.4.12"
|
||||||
```
|
```
|
||||||
|
|
||||||
解析后端 feature:
|
解析后端 feature:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# 默认:sol-parser-sdk parse-borsh 后端
|
# 默认:sol-parser-sdk parse-borsh 后端
|
||||||
solana-streamer-sdk = "1.4.11"
|
solana-streamer-sdk = "1.4.12"
|
||||||
|
|
||||||
# 面向低延迟 Bot 的 zero-copy 解析后端
|
# 面向低延迟 Bot 的 zero-copy 解析后端
|
||||||
solana-streamer-sdk = { version = "1.4.11", default-features = false, features = ["sdk-parse-zero-copy"] }
|
solana-streamer-sdk = { version = "1.4.12", default-features = false, features = ["sdk-parse-zero-copy"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.4.16+` 会优先使用 zero-copy 后端。
|
如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.4.17+` 会优先使用 zero-copy 后端。
|
||||||
|
|
||||||
## 🔄 迁移指南
|
## 🔄 迁移指南
|
||||||
|
|
||||||
### 升级到 v1.4.11
|
### 升级到 v1.4.12
|
||||||
|
|
||||||
v1.4.11 使用 `sol-parser-sdk 0.4.16`,保留 streamer facade 中与 SDK 兼容的 Yellowstone gRPC 输出顺序模式,并将 PumpFun USDC/v2 的 create、trade、global、bonding-curve 和 volume account 字段与 parser SDK 对齐。`buy_exact_quote_in(_v2)` 会作为 `PumpFunBuy` 投递,同时保留 exact quote 相关字段。
|
v1.4.12 使用 `sol-parser-sdk 0.4.17`,会把 legacy PumpFun SOL 的 `quote_mint` 归一为 Solscan SOL sentinel,同时保留真实 USDC quote mint 和 quote reserve 字段。Streamer bridge 与 merger 路径继续保持 Yellowstone gRPC 和 ShredStream 输出与 parser SDK 语义一致。
|
||||||
|
|
||||||
新增可选能力:
|
新增可选能力:
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
use crate::streaming::event_parser::DexEvent;
|
use crate::streaming::event_parser::DexEvent;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::{pubkey, pubkey::Pubkey};
|
||||||
|
|
||||||
|
const PUMPFUN_SOLSCAN_SOL_QUOTE_MINT: Pubkey =
|
||||||
|
pubkey!("So11111111111111111111111111111111111111111");
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fill_pubkey(to: &mut Pubkey, from: Pubkey) {
|
fn fill_pubkey(to: &mut Pubkey, from: Pubkey) {
|
||||||
@@ -8,6 +11,25 @@ fn fill_pubkey(to: &mut Pubkey, from: Pubkey) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalize_pumpfun_quote_mint(quote_mint: Pubkey) -> Pubkey {
|
||||||
|
if quote_mint == Pubkey::default() {
|
||||||
|
PUMPFUN_SOLSCAN_SOL_QUOTE_MINT
|
||||||
|
} else {
|
||||||
|
quote_mint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn fill_pumpfun_quote_mint(to: &mut Pubkey, from: Pubkey) {
|
||||||
|
let from = normalize_pumpfun_quote_mint(from);
|
||||||
|
if (*to == Pubkey::default() || *to == PUMPFUN_SOLSCAN_SOL_QUOTE_MINT)
|
||||||
|
&& from != Pubkey::default()
|
||||||
|
{
|
||||||
|
*to = from;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fill_u64(to: &mut u64, from: u64) {
|
fn fill_u64(to: &mut u64, from: u64) {
|
||||||
if *to == 0 && from != 0 {
|
if *to == 0 && from != 0 {
|
||||||
@@ -66,7 +88,7 @@ pub fn merge(instruction_event: &mut DexEvent, cpi_log_event: DexEvent) {
|
|||||||
if e.shareholders.is_empty() && !cpie.shareholders.is_empty() {
|
if e.shareholders.is_empty() && !cpie.shareholders.is_empty() {
|
||||||
e.shareholders = cpie.shareholders;
|
e.shareholders = cpie.shareholders;
|
||||||
}
|
}
|
||||||
fill_pubkey(&mut e.quote_mint, cpie.quote_mint);
|
fill_pumpfun_quote_mint(&mut e.quote_mint, cpie.quote_mint);
|
||||||
fill_u64(&mut e.quote_amount, cpie.quote_amount);
|
fill_u64(&mut e.quote_amount, cpie.quote_amount);
|
||||||
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
||||||
fill_u64(&mut e.real_quote_reserves, cpie.real_quote_reserves);
|
fill_u64(&mut e.real_quote_reserves, cpie.real_quote_reserves);
|
||||||
@@ -155,7 +177,7 @@ pub fn merge(instruction_event: &mut DexEvent, cpi_log_event: DexEvent) {
|
|||||||
if cpie.token_program != solana_sdk::pubkey::Pubkey::default() {
|
if cpie.token_program != solana_sdk::pubkey::Pubkey::default() {
|
||||||
e.token_program = cpie.token_program;
|
e.token_program = cpie.token_program;
|
||||||
}
|
}
|
||||||
fill_pubkey(&mut e.quote_mint, cpie.quote_mint);
|
fill_pumpfun_quote_mint(&mut e.quote_mint, cpie.quote_mint);
|
||||||
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
||||||
e.is_mayhem_mode |= cpie.is_mayhem_mode;
|
e.is_mayhem_mode |= cpie.is_mayhem_mode;
|
||||||
e.is_cashback_enabled |= cpie.is_cashback_enabled;
|
e.is_cashback_enabled |= cpie.is_cashback_enabled;
|
||||||
@@ -177,7 +199,7 @@ pub fn merge(instruction_event: &mut DexEvent, cpi_log_event: DexEvent) {
|
|||||||
fill_u64(&mut e.real_token_reserves, cpie.real_token_reserves);
|
fill_u64(&mut e.real_token_reserves, cpie.real_token_reserves);
|
||||||
fill_u64(&mut e.token_total_supply, cpie.token_total_supply);
|
fill_u64(&mut e.token_total_supply, cpie.token_total_supply);
|
||||||
fill_pubkey(&mut e.token_program, cpie.token_program);
|
fill_pubkey(&mut e.token_program, cpie.token_program);
|
||||||
fill_pubkey(&mut e.quote_mint, cpie.quote_mint);
|
fill_pumpfun_quote_mint(&mut e.quote_mint, cpie.quote_mint);
|
||||||
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
||||||
e.is_mayhem_mode |= cpie.is_mayhem_mode;
|
e.is_mayhem_mode |= cpie.is_mayhem_mode;
|
||||||
e.is_cashback_enabled |= cpie.is_cashback_enabled;
|
e.is_cashback_enabled |= cpie.is_cashback_enabled;
|
||||||
@@ -216,7 +238,7 @@ pub fn merge(instruction_event: &mut DexEvent, cpi_log_event: DexEvent) {
|
|||||||
if cpie.token_program != solana_sdk::pubkey::Pubkey::default() {
|
if cpie.token_program != solana_sdk::pubkey::Pubkey::default() {
|
||||||
e.token_program = cpie.token_program;
|
e.token_program = cpie.token_program;
|
||||||
}
|
}
|
||||||
fill_pubkey(&mut e.quote_mint, cpie.quote_mint);
|
fill_pumpfun_quote_mint(&mut e.quote_mint, cpie.quote_mint);
|
||||||
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
fill_u64(&mut e.virtual_quote_reserves, cpie.virtual_quote_reserves);
|
||||||
e.is_mayhem_mode |= cpie.is_mayhem_mode;
|
e.is_mayhem_mode |= cpie.is_mayhem_mode;
|
||||||
e.is_cashback_enabled |= cpie.is_cashback_enabled;
|
e.is_cashback_enabled |= cpie.is_cashback_enabled;
|
||||||
@@ -883,4 +905,22 @@ mod tests {
|
|||||||
_ => panic!("expected PumpFunTradeEvent"),
|
_ => panic!("expected PumpFunTradeEvent"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pumpfun_merge_replaces_sol_quote_sentinel_with_real_quote_mint() {
|
||||||
|
let quote_mint = Pubkey::new_unique();
|
||||||
|
let mut instruction_event = DexEvent::PumpFunTradeEvent(PumpFunTradeEvent {
|
||||||
|
quote_mint: PUMPFUN_SOLSCAN_SOL_QUOTE_MINT,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
let cpi_log_event =
|
||||||
|
DexEvent::PumpFunTradeEvent(PumpFunTradeEvent { quote_mint, ..Default::default() });
|
||||||
|
|
||||||
|
merge(&mut instruction_event, cpi_log_event);
|
||||||
|
|
||||||
|
match instruction_event {
|
||||||
|
DexEvent::PumpFunTradeEvent(t) => assert_eq!(t.quote_mint, quote_mint),
|
||||||
|
_ => panic!("expected PumpFunTradeEvent"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,23 @@ use crate::streaming::event_parser::protocols::pumpswap::events::{
|
|||||||
};
|
};
|
||||||
use crate::streaming::event_parser::DexEvent;
|
use crate::streaming::event_parser::DexEvent;
|
||||||
use prost_types::Timestamp;
|
use prost_types::Timestamp;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::{pubkey, pubkey::Pubkey};
|
||||||
|
|
||||||
use super::adapt::adapt_pm;
|
use super::adapt::adapt_pm;
|
||||||
use super::program_ids::{pump_program, pumpswap_program};
|
use super::program_ids::{pump_program, pumpswap_program};
|
||||||
|
|
||||||
|
const PUMPFUN_SOLSCAN_SOL_QUOTE_MINT: Pubkey =
|
||||||
|
pubkey!("So11111111111111111111111111111111111111111");
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalize_pumpfun_quote_mint(quote_mint: Pubkey) -> Pubkey {
|
||||||
|
if quote_mint == Pubkey::default() {
|
||||||
|
PUMPFUN_SOLSCAN_SOL_QUOTE_MINT
|
||||||
|
} else {
|
||||||
|
quote_mint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn pumpfun_create_token_from_parser(
|
pub(crate) fn pumpfun_create_token_from_parser(
|
||||||
c: sol_parser_sdk::core::events::PumpFunCreateTokenEvent,
|
c: sol_parser_sdk::core::events::PumpFunCreateTokenEvent,
|
||||||
meta: EventMetadata,
|
meta: EventMetadata,
|
||||||
@@ -47,7 +59,7 @@ pub(crate) fn pumpfun_create_token_from_parser(
|
|||||||
token_program: c.token_program,
|
token_program: c.token_program,
|
||||||
is_mayhem_mode: c.is_mayhem_mode,
|
is_mayhem_mode: c.is_mayhem_mode,
|
||||||
is_cashback_enabled: c.is_cashback_enabled,
|
is_cashback_enabled: c.is_cashback_enabled,
|
||||||
quote_mint: c.quote_mint,
|
quote_mint: normalize_pumpfun_quote_mint(c.quote_mint),
|
||||||
virtual_quote_reserves: c.virtual_quote_reserves,
|
virtual_quote_reserves: c.virtual_quote_reserves,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
@@ -74,7 +86,7 @@ pub(crate) fn pumpfun_create_v2_from_parser(
|
|||||||
token_program: c.token_program,
|
token_program: c.token_program,
|
||||||
is_mayhem_mode: c.is_mayhem_mode,
|
is_mayhem_mode: c.is_mayhem_mode,
|
||||||
is_cashback_enabled: c.is_cashback_enabled,
|
is_cashback_enabled: c.is_cashback_enabled,
|
||||||
quote_mint: c.quote_mint,
|
quote_mint: normalize_pumpfun_quote_mint(c.quote_mint),
|
||||||
virtual_quote_reserves: c.virtual_quote_reserves,
|
virtual_quote_reserves: c.virtual_quote_reserves,
|
||||||
mint_authority: c.mint_authority,
|
mint_authority: c.mint_authority,
|
||||||
associated_bonding_curve: c.associated_bonding_curve,
|
associated_bonding_curve: c.associated_bonding_curve,
|
||||||
@@ -365,7 +377,7 @@ pub(crate) fn pumpfun_bonding_curve_account_from_parser(
|
|||||||
creator: e.bonding_curve.creator,
|
creator: e.bonding_curve.creator,
|
||||||
is_mayhem_mode: e.bonding_curve.is_mayhem_mode,
|
is_mayhem_mode: e.bonding_curve.is_mayhem_mode,
|
||||||
is_cashback_coin: e.bonding_curve.is_cashback_coin,
|
is_cashback_coin: e.bonding_curve.is_cashback_coin,
|
||||||
quote_mint: e.bonding_curve.quote_mint,
|
quote_mint: normalize_pumpfun_quote_mint(e.bonding_curve.quote_mint),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -735,7 +747,7 @@ pub(crate) fn pumpfun_trade_from_parser_with_event_type(
|
|||||||
buyback_fee_basis_points: t.buyback_fee_basis_points,
|
buyback_fee_basis_points: t.buyback_fee_basis_points,
|
||||||
buyback_fee: t.buyback_fee,
|
buyback_fee: t.buyback_fee,
|
||||||
shareholders: t.shareholders.into_iter().map(pump_fees_shareholder_from_parser).collect(),
|
shareholders: t.shareholders.into_iter().map(pump_fees_shareholder_from_parser).collect(),
|
||||||
quote_mint: t.quote_mint,
|
quote_mint: normalize_pumpfun_quote_mint(t.quote_mint),
|
||||||
quote_amount: t.quote_amount,
|
quote_amount: t.quote_amount,
|
||||||
virtual_quote_reserves: t.virtual_quote_reserves,
|
virtual_quote_reserves: t.virtual_quote_reserves,
|
||||||
real_quote_reserves: t.real_quote_reserves,
|
real_quote_reserves: t.real_quote_reserves,
|
||||||
@@ -840,3 +852,25 @@ pub(crate) fn pumpswap_trade_from_parser(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pumpfun_default_quote_mint_uses_solscan_sol_sentinel() {
|
||||||
|
let ev = pumpfun_trade_from_parser_with_event_type(
|
||||||
|
sol_parser_sdk::core::events::PumpFunTradeEvent { is_buy: true, ..Default::default() },
|
||||||
|
None,
|
||||||
|
0,
|
||||||
|
EventType::PumpFunBuy,
|
||||||
|
);
|
||||||
|
|
||||||
|
match ev {
|
||||||
|
DexEvent::PumpFunTradeEvent(t) => {
|
||||||
|
assert_eq!(t.quote_mint.to_string(), "So11111111111111111111111111111111111111111");
|
||||||
|
}
|
||||||
|
_ => panic!("expected PumpFunTradeEvent"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user