mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-11-02 07:16:31 +00:00
fix: scope raw instructions by DEX and expose typed identifiers
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-streamer-sdk"
|
||||
version = "3.0.14"
|
||||
version = "3.0.15"
|
||||
edition = "2021"
|
||||
rust-version = "1.91"
|
||||
authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"]
|
||||
@@ -22,7 +22,7 @@ sdk-perf-stats = ["sol-parser-sdk/perf-stats"]
|
||||
sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"]
|
||||
|
||||
[dependencies]
|
||||
sol-parser-sdk = { path = "../sol-parser-sdk", version = "=0.7.16", default-features = false }
|
||||
sol-parser-sdk = { path = "../sol-parser-sdk", version = "=0.7.17", default-features = false }
|
||||
solana-sdk = "=4.0.1"
|
||||
solana-client = "=4.2.2"
|
||||
solana-transaction-status = { version = "=4.2.2", features = ["agave-unstable-api"] }
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<div align="center">
|
||||
|
||||
## v3.0.14 — Pump execution replay
|
||||
## v3.0.15 — DEX-scoped RawInstruction and typed DEX identifiers
|
||||
|
||||
Raw instructions now respect DEX subscriptions using programs referenced by each instruction. `RawInstructionDexType` provides typed identifiers with unchanged JSON strings. Unknown router layouts do not establish pool addresses, trade direction, or method versions.
|
||||
|
||||
|
||||
## v3.0.15 — Pump execution replay
|
||||
|
||||
Current Anchor TradeEvent CPI decoding is supported alongside the historical encoding. RPC/gRPC instruction budgets and minimum outputs remain in instruction fields. Execution fields `sol_amount`, `quote_amount`, and `token_amount` come from execution events; without logs or event CPIs they remain zero (unavailable, not a proven zero fill).
|
||||
|
||||
@@ -8,15 +13,15 @@ Run `cargo run --offline --example rpc_transaction_replay` from this repository
|
||||
|
||||
The current Delta sell signature is `4ARos3Yq1SMNE3izDpy9YdKrRgMmD7UCDxvnVrBRaGCJHiifPHSmQWc4DPfjUaEUcxS7puGmEN64K7EZdeXLJaj2` (slot 458542546). Older five-combination multi-hop fixtures are retained as regression tests, not labeled as new mainnet captures.
|
||||
|
||||
## v3.0.14 — raw Shred instructions
|
||||
## v3.0.15 — raw Shred instructions
|
||||
|
||||
Protocol narrowing (for example PumpFun with no event filter) preserves default raw unknown instructions end to end. An explicit trade-only event filter still excludes raw instructions; explicitly including RawInstruction selects all outer instructions.
|
||||
Protocol filters apply to raw DEX associations as well as decoded events.
|
||||
|
||||
Default Shred parsing emits `RawInstruction` for unsupported third-party programs, including Rapid/Delta, without inferring direction, amounts, or internal buy methods. Infrastructure programs (System, Token, ATA, ComputeBudget, etc.) are omitted by default. Supported official DEX parsers are unchanged; official Pump/PumpSwap multi-hop instructions retain `PumpRouteIntent`.
|
||||
|
||||
The payload contains `program_id`, `instruction_index`, `accounts`, `account_indices`, `instruction_data`, and transaction metadata. Account order and duplicates are preserved. Unresolved ALT addresses are null/None, with original indices retained; supply cached loaded addresses or a resolver. No hot-path RPC is performed. Data is copied verbatim without requiring a known layout.
|
||||
|
||||
No filter returns unknown third-party instructions. Explicitly including `RawInstruction` returns every outer instruction, including infrastructure. A `PumpFunTrade`-only filter does not include raw events: subscribe to both types when needed. Streamer forwards `DexEvent::RawInstructionEvent` as Common. A Pump address in accounts does not prove a CPI or a particular buy method. Event count is not fill count.
|
||||
Without a filter, unknown third-party instructions are returned. Broad trade/swap filters (for example `PumpFunTrade` or `RaydiumCpmmSwap`) also return raw instructions associated with that DEX; direction-specific filters do not infer a buy or sell. Explicit `RawInstruction` selects all outer instructions only when no protocol restriction is set; streamer protocol restrictions always apply. Excluding `RawInstruction` wins. `dex_type` uses the public `RawInstructionDexType` enum (typed string constants in Go); JSON values remain unchanged, such as `"pumpfun"` and `"raydium_cpmm"`. `dexes` contains `{ dex_type, program_id, pool }` for each recognized DEX program targeted or referenced by this instruction, not other instructions in the transaction. Multi-DEX wrappers retain every association. Unknown or unresolved ALT references cannot satisfy a DEX subscription. `pool` is currently null: an unknown wrapper layout cannot establish the pool account. A program reference is not proof of an executed CPI. Raw callbacks are not fills.
|
||||
|
||||
Wrapper adapter functions remain explicit compatibility helpers only; default Shred parsing does not call them. The released-version history below describes previous behavior.
|
||||
|
||||
@@ -151,24 +156,24 @@ Add the dependency to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
# Add to your Cargo.toml
|
||||
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.14" }
|
||||
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.15" }
|
||||
```
|
||||
|
||||
### Use crates.io
|
||||
|
||||
```toml
|
||||
# Add to your Cargo.toml
|
||||
solana-streamer-sdk = "3.0.14"
|
||||
solana-streamer-sdk = "3.0.15"
|
||||
```
|
||||
|
||||
Parser backend features:
|
||||
|
||||
```toml
|
||||
# Default: sol-parser-sdk parse-borsh backend
|
||||
solana-streamer-sdk = "3.0.14"
|
||||
solana-streamer-sdk = "3.0.15"
|
||||
|
||||
# Zero-copy parser backend for latency-sensitive bots
|
||||
solana-streamer-sdk = { version = "3.0.14", default-features = false, features = ["sdk-parse-zero-copy"] }
|
||||
solana-streamer-sdk = { version = "3.0.15", default-features = false, features = ["sdk-parse-zero-copy"] }
|
||||
```
|
||||
|
||||
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.6.1+` uses the zero-copy backend.
|
||||
|
||||
+13
-8
@@ -1,6 +1,11 @@
|
||||
<div align="center">
|
||||
|
||||
## v3.0.14 — Pump 执行事件与最新回放示例
|
||||
## v3.0.15 — RawInstruction 协议过滤与 DEX 枚举
|
||||
|
||||
修复原始指令绕过 DEX 订阅范围的问题。按单条指令引用的官方程序识别 DEX,使用 `RawInstructionDexType` 枚举;JSON 字符串保持不变。未知 router 不推断池子地址、买卖方向或方法版本。
|
||||
|
||||
|
||||
## v3.0.15 — Pump 执行事件与最新回放示例
|
||||
|
||||
修复官方 Anchor CPI TradeEvent 前缀识别,保留历史编码兼容。RPC/gRPC 的实际 `sol_amount`、`quote_amount`、`token_amount` 只从执行事件合并;预算和最小输出保留在指令参数字段。如果日志及事件 CPI 均缺失,实际金额字段为 0(表示无执行数据,不代表已确认零成交)。非 SOL 报价金额不能当作 SOL。
|
||||
|
||||
@@ -8,15 +13,15 @@
|
||||
|
||||
新 Delta 卖出样本:`4ARos3Yq1SMNE3izDpy9YdKrRgMmD7UCDxvnVrBRaGCJHiifPHSmQWc4DPfjUaEUcxS7puGmEN64K7EZdeXLJaj2`,slot 458542546。旧的五种双跳组合仅作为回归样本,未冒充本次新抓取交易。
|
||||
|
||||
## v3.0.14 — Shred 原始指令透传
|
||||
## v3.0.15 — Shred 原始指令透传
|
||||
|
||||
只限制协议(例如 PumpFun)而不设置事件过滤器时,默认未知指令透传也能到达最终回调。显式只订阅 Trade 仍不包含原始指令;显式订阅 RawInstruction 返回全部外层指令。
|
||||
协议过滤同时作用于原始指令的 DEX 关联和已解码事件。
|
||||
|
||||
默认 Shred 入口将未适配的第三方程序(包括 Rapid/Delta)作为 `RawInstruction` 返回,不再推断买卖方向、金额或内部 buy 版本。System、Token、ATA、ComputeBudget 等基础程序默认不透传;已支持的官方 DEX 指令继续正常解析,官方 Pump/PumpSwap 多跳仍返回 `PumpRouteIntent`。
|
||||
|
||||
事件包含 `program_id`、`instruction_index`、`accounts`、`account_indices`、`instruction_data` 和交易 metadata。账户保留原顺序与重复项;未解析 ALT 地址为 null/None,原始索引仍保留。使用缓存 loaded-addresses/resolver 补齐,热路径不请求 RPC。data 是完整原始字节,不要求已知布局。
|
||||
|
||||
无过滤器时返回未知第三方指令;显式订阅 `RawInstruction` 时返回所有外层指令(含基础程序)。仅订阅 `PumpFunTrade` 不包含原始事件,需要同时订阅 `RawInstruction`。Streamer 对应 `DexEvent::RawInstructionEvent`,协议为 Common。账户包含 Pump 不证明发生 CPI,更不证明具体 buy 方法;事件数量也不是成交数量。
|
||||
无过滤器时返回未知第三方指令。宽泛交易/Swap 订阅(如 `PumpFunTrade`、`RaydiumCpmmSwap`)也返回关联该 DEX 的原始指令;买/卖方向订阅不推测方向。显式 `RawInstruction` 仅在未限制协议时返回全部外层指令,streamer 的协议限制始终生效;显式排除 `RawInstruction` 优先。`dex_type` 使用公开枚举 `RawInstructionDexType`(Go 为命名字符串类型与常量);JSON 仍为 `"pumpfun"`、`"raydium_cpmm"` 等原有字符串。`dexes` 数组包含各关联 DEX 的 `{ dex_type, program_id, pool }`,只识别本条指令直接调用或账户中引用的 DEX 程序,不借用同笔其他指令的账户;多 DEX 包装保留所有关联。未知或未解析 ALT 中的程序不能匹配 DEX 订阅。`pool` 当前为 null:未知包装布局无法确定池子账户。program 引用不证明执行了 CPI,原始回调不是成交。
|
||||
|
||||
已有 wrapper 适配函数仅作为显式调用的兼容接口保留,不参与默认 Shred 解码。以下已发布版本的历史说明描述旧行为。
|
||||
|
||||
@@ -150,24 +155,24 @@ git clone https://github.com/0xfnzero/solana-streamer
|
||||
|
||||
```toml
|
||||
# 添加到您的 Cargo.toml
|
||||
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.14" }
|
||||
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.15" }
|
||||
```
|
||||
|
||||
### 使用 crates.io
|
||||
|
||||
```toml
|
||||
# 添加到您的 Cargo.toml
|
||||
solana-streamer-sdk = "3.0.14"
|
||||
solana-streamer-sdk = "3.0.15"
|
||||
```
|
||||
|
||||
解析后端 feature:
|
||||
|
||||
```toml
|
||||
# 默认:sol-parser-sdk parse-borsh 后端
|
||||
solana-streamer-sdk = "3.0.14"
|
||||
solana-streamer-sdk = "3.0.15"
|
||||
|
||||
# 面向低延迟 Bot 的 zero-copy 解析后端
|
||||
solana-streamer-sdk = { version = "3.0.14", default-features = false, features = ["sdk-parse-zero-copy"] }
|
||||
solana-streamer-sdk = { version = "3.0.15", default-features = false, features = ["sdk-parse-zero-copy"] }
|
||||
```
|
||||
|
||||
如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.6.1+` 会优先使用 zero-copy 后端。
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# v3.0.15 — DEX-scoped raw instructions and typed DEX identifiers
|
||||
|
||||
Released 2026-10-19.
|
||||
|
||||
RawInstruction callbacks now match the subscribed DEX using only the outer instruction's program and referenced accounts. Unrelated instructions in the same transaction no longer inherit a DEX association. Streamer protocol restrictions apply even when RawInstruction is explicitly selected; legacy sol-shred-sdk PumpFun callbacks only forward PumpFun-associated wrappers.
|
||||
|
||||
The dexes array preserves all detected DEX associations for multi-DEX wrappers. Each entry contains dex_type, program_id and a nullable pool. RawInstructionDexType is a public enum in Rust, TypeScript and Python, and a named string type with constants in Go. JSON identifiers remain pumpfun, raydium_cpmm, etc. Unknown router layouts leave pool null and do not imply CPI execution, trade direction, amounts or buy-method versions. Unresolved ALT references cannot match a DEX subscription.
|
||||
|
||||
## Compatibility
|
||||
|
||||
- Broad trade/swap filters now include associated raw instructions. Excluding RawInstruction takes precedence; direction/method-specific subscriptions do not infer unknown router behavior.
|
||||
- Without protocol restrictions, explicit RawInstruction still selects all outer instructions.
|
||||
- Rust callers constructing RawInstructionEvent must populate dexes; RawInstructionDex.dex_type is now an enum. Historical JSON without dexes remains readable with an empty list.
|
||||
- No third-party router payload decoding or guessed pool-account positions were added.
|
||||
|
||||
## Validation
|
||||
|
||||
Regression coverage includes instruction-local DEX scope, multi-DEX references, duplicate accounts, unresolved ALT addresses, raw exclusions, streamer protocol gates, enum exports and JSON round trips. Signed replay examples compare PumpFun, Raydium CPMM and all-raw subscriptions across language implementations.
|
||||
@@ -286,29 +286,6 @@ pub(crate) fn parse_shred_transaction_events(
|
||||
&mut events,
|
||||
);
|
||||
|
||||
// Protocol narrowing must not suppress protocol-independent default raw
|
||||
// events. Explicit RawInstruction subscriptions are handled by the main
|
||||
// parser (all outer instructions); this pass returns unknown programs only.
|
||||
let wants_default_raw = event_type_filter.is_none_or(|f| {
|
||||
f.include.is_empty()
|
||||
&& !f
|
||||
.exclude
|
||||
.contains(&crate::streaming::event_parser::common::EventType::RawInstruction)
|
||||
});
|
||||
if wants_default_raw
|
||||
&& sdk_parse_filter
|
||||
.as_ref()
|
||||
.is_some_and(|f| !f.should_include(sol_parser_sdk::grpc::EventType::RawInstruction))
|
||||
{
|
||||
sol_parser_sdk::shredstream::parse_transaction_unknown_instructions(
|
||||
tx,
|
||||
signature,
|
||||
slot,
|
||||
tx_index.unwrap_or(0),
|
||||
recv_us,
|
||||
&mut events,
|
||||
);
|
||||
}
|
||||
for sdk_event in events.drain(..) {
|
||||
if let Some(mut event) =
|
||||
adapt_parser_event(sdk_event, None, recv_us, protocols, event_type_filter)
|
||||
@@ -524,6 +501,118 @@ mod tests {
|
||||
None,
|
||||
|e| events.push(e),
|
||||
);
|
||||
assert_eq!(events.len(), 1);
|
||||
assert!(
|
||||
matches!(&events[0], DexEvent::RawInstructionEvent(raw) if raw.dexes.iter().any(|d| d.dex_type == sol_parser_sdk::core::events::RawInstructionDexType::PumpFun))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_callbacks_respect_protocol_even_with_explicit_raw_subscription() {
|
||||
use sol_parser_sdk::grpc::program_ids::{PUMPFUN_PROGRAM, RAYDIUM_CPMM_PROGRAM};
|
||||
use solana_sdk::{
|
||||
instruction::{AccountMeta, Instruction},
|
||||
message::{Message, VersionedMessage},
|
||||
signature::Signature,
|
||||
transaction::VersionedTransaction,
|
||||
};
|
||||
let wrapper = Pubkey::new_unique();
|
||||
let tx = VersionedTransaction {
|
||||
signatures: vec![Signature::default()],
|
||||
message: VersionedMessage::Legacy(Message::new(
|
||||
&[
|
||||
Instruction {
|
||||
program_id: wrapper,
|
||||
accounts: vec![AccountMeta::new_readonly(PUMPFUN_PROGRAM, false)],
|
||||
data: vec![255],
|
||||
},
|
||||
Instruction {
|
||||
program_id: wrapper,
|
||||
accounts: vec![AccountMeta::new_readonly(RAYDIUM_CPMM_PROGRAM, false)],
|
||||
data: vec![254],
|
||||
},
|
||||
Instruction { program_id: wrapper, accounts: vec![], data: vec![253] },
|
||||
Instruction {
|
||||
program_id: wrapper,
|
||||
accounts: vec![
|
||||
AccountMeta::new_readonly(PUMPFUN_PROGRAM, false),
|
||||
AccountMeta::new_readonly(RAYDIUM_CPMM_PROGRAM, false),
|
||||
],
|
||||
data: vec![252],
|
||||
},
|
||||
],
|
||||
Some(&Pubkey::new_unique()),
|
||||
)),
|
||||
};
|
||||
for (protocols, expected) in [
|
||||
(vec![Protocol::PumpFun], vec![0, 3]),
|
||||
(vec![Protocol::RaydiumCpmm], vec![1, 3]),
|
||||
(vec![Protocol::MeteoraDammV2], vec![]),
|
||||
(vec![], vec![0, 1, 2, 3]),
|
||||
] {
|
||||
for filter in
|
||||
[None, Some(EventTypeFilter::include_only(vec![EventType::RawInstruction]))]
|
||||
{
|
||||
let mut events = vec![];
|
||||
super::parse_shred_transaction_events(
|
||||
&tx,
|
||||
tx.signatures[0],
|
||||
1,
|
||||
None,
|
||||
0,
|
||||
&protocols,
|
||||
filter.as_ref(),
|
||||
None,
|
||||
|e| events.push(e),
|
||||
);
|
||||
let indices: Vec<_> = events
|
||||
.iter()
|
||||
.map(|e| match e {
|
||||
DexEvent::RawInstructionEvent(raw) => raw.instruction_index,
|
||||
_ => panic!("not raw"),
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(indices, expected, "{protocols:?}");
|
||||
}
|
||||
}
|
||||
for (protocol, event_type) in [
|
||||
(Protocol::PumpFun, EventType::PumpFunBuy),
|
||||
(Protocol::RaydiumCpmm, EventType::RaydiumCpmmSwapBaseInput),
|
||||
] {
|
||||
let mut events = vec![];
|
||||
let filter = EventTypeFilter::include_only(vec![event_type]);
|
||||
super::parse_shred_transaction_events(
|
||||
&tx,
|
||||
tx.signatures[0],
|
||||
1,
|
||||
None,
|
||||
0,
|
||||
&[protocol],
|
||||
Some(&filter),
|
||||
None,
|
||||
|e| events.push(e),
|
||||
);
|
||||
assert!(
|
||||
events.is_empty(),
|
||||
"execution-specific filter must not infer router instruction"
|
||||
);
|
||||
}
|
||||
let filter = EventTypeFilter::include_exclude(
|
||||
vec![EventType::PumpFunTrade],
|
||||
vec![EventType::RawInstruction],
|
||||
);
|
||||
let mut events = vec![];
|
||||
super::parse_shred_transaction_events(
|
||||
&tx,
|
||||
tx.signatures[0],
|
||||
1,
|
||||
None,
|
||||
0,
|
||||
&[Protocol::PumpFun],
|
||||
Some(&filter),
|
||||
None,
|
||||
|e| events.push(e),
|
||||
);
|
||||
assert!(events.is_empty());
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,43 @@ impl EventTypeFilter {
|
||||
|
||||
#[inline]
|
||||
pub fn passes_for_event(&self, ev: &DexEvent) -> bool {
|
||||
if let DexEvent::RawInstructionEvent(raw) = ev {
|
||||
// Execution-specific aliases must not become broad raw subscriptions
|
||||
// merely because the upstream execution parser uses one family enum.
|
||||
let map = |types: &[EventType], mode| {
|
||||
let mut out = vec![];
|
||||
for t in types {
|
||||
if matches!(
|
||||
t,
|
||||
EventType::BonkBuyExactIn
|
||||
| EventType::BonkBuyExactOut
|
||||
| EventType::BonkSellExactIn
|
||||
| EventType::BonkSellExactOut
|
||||
| EventType::RaydiumCpmmSwapBaseInput
|
||||
| EventType::RaydiumCpmmSwapBaseOutput
|
||||
| EventType::RaydiumAmmV4SwapBaseIn
|
||||
| EventType::RaydiumAmmV4SwapBaseOut
|
||||
| EventType::RaydiumClmmSwap
|
||||
| EventType::RaydiumClmmSwapV2
|
||||
| EventType::MeteoraDammV2Swap
|
||||
| EventType::MeteoraDammV2Swap2
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
push_streamer_event_sdk_grpc_types(t, &mut out, mode);
|
||||
}
|
||||
out
|
||||
};
|
||||
let sdk = SdkGrpcEventTypeFilter {
|
||||
include_only: if self.include.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(map(&self.include, FilterMapMode::Include))
|
||||
},
|
||||
exclude_types: Some(map(&self.exclude, FilterMapMode::Exclude)),
|
||||
};
|
||||
return sol_parser_sdk::core::events::raw_instruction_matches_filter(&raw.dexes, &sdk);
|
||||
}
|
||||
if let DexEvent::PumpRouteIntentEvent(_) = ev {
|
||||
if self.exclude.contains(&EventType::PumpRouteIntent) {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::streaming::event_parser::common::EventMetadata;
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub use sol_parser_sdk::core::events::{RawInstructionDex, RawInstructionDexType};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
/// `sol-parser-sdk` 错误占位(无有效 EventMetadata 字段)
|
||||
@@ -469,6 +470,8 @@ pub struct MeteoraDlmmClaimFeeEvent {
|
||||
/// Outer instruction bytes; no claim about internal CPI calls or trade direction.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RawInstructionEvent {
|
||||
#[serde(default)]
|
||||
pub dexes: Vec<RawInstructionDex>,
|
||||
pub metadata: EventMetadata,
|
||||
pub program_id: Pubkey,
|
||||
pub instruction_index: usize,
|
||||
|
||||
@@ -34,6 +34,7 @@ pub(crate) fn convert_parser_event(
|
||||
e.program_id,
|
||||
);
|
||||
Some(DexEvent::RawInstructionEvent(RawInstructionEvent {
|
||||
dexes: e.dexes,
|
||||
metadata,
|
||||
program_id: e.program_id,
|
||||
instruction_index: e.instruction_index,
|
||||
|
||||
@@ -16,7 +16,6 @@ fn is_protocol_independent_event(ev: &DexEvent) -> bool {
|
||||
matches!(
|
||||
ev,
|
||||
DexEvent::TokenAccountEvent(_)
|
||||
| DexEvent::RawInstructionEvent(_)
|
||||
| DexEvent::TokenInfoEvent(_)
|
||||
| DexEvent::NonceAccountEvent(_)
|
||||
| DexEvent::BlockMetaEvent(_)
|
||||
@@ -29,6 +28,11 @@ fn is_protocol_independent_event(ev: &DexEvent) -> bool {
|
||||
|
||||
#[allow(clippy::match_like_matches_macro)]
|
||||
fn protocol_matches_event(p: &Protocol, ev: &DexEvent) -> bool {
|
||||
if let DexEvent::RawInstructionEvent(raw) = ev {
|
||||
// LaunchLab's program alone cannot establish StonkFun platform attribution.
|
||||
return *p != Protocol::StonkFun
|
||||
&& raw.dexes.iter().any(|dex| p.get_program_id().contains(&dex.program_id));
|
||||
}
|
||||
match (p, ev) {
|
||||
(Protocol::PumpFun, DexEvent::PumpRouteIntentEvent(_)) => true,
|
||||
(Protocol::PumpSwap, DexEvent::PumpRouteIntentEvent(e)) => {
|
||||
|
||||
@@ -65,6 +65,7 @@ mod tests {
|
||||
let source = PbDexEvent::RawInstruction(Box::new(
|
||||
sol_parser_sdk::core::events::RawInstructionEvent {
|
||||
metadata: EventMetadata { slot: 42, ..Default::default() },
|
||||
dexes: vec![],
|
||||
program_id: program,
|
||||
instruction_index: 3,
|
||||
accounts: vec![Some(account), None, Some(account)],
|
||||
@@ -72,8 +73,8 @@ mod tests {
|
||||
instruction_data: vec![255, 0, 1],
|
||||
},
|
||||
));
|
||||
let event =
|
||||
adapt_parser_event(source.clone(), None, 999, &[Protocol::PumpFun], None).unwrap();
|
||||
let event = adapt_parser_event(source.clone(), None, 999, &[], None).unwrap();
|
||||
assert!(adapt_parser_event(source.clone(), None, 999, &[Protocol::PumpFun], None).is_none());
|
||||
let DexEvent::RawInstructionEvent(ref raw) = event else { panic!() };
|
||||
assert_eq!(raw.metadata.protocol, ProtocolType::Common);
|
||||
assert_eq!(raw.metadata.event_type, EventType::RawInstruction);
|
||||
|
||||
Reference in New Issue
Block a user