Skip to main content

sol_parser_sdk/instr/
mod.rs

1//! 指令解析器模块
2//!
3//! 包含所有 DEX 协议的指令解析器实现
4
5pub mod meteora_amm;
6pub mod meteora_damm;
7pub mod meteora_dlmm;
8pub mod orca_whirlpool;
9pub mod program_ids;
10pub mod pump;
11pub mod pump_amm;
12pub mod pump_fees;
13pub mod raydium_amm;
14pub mod raydium_clmm;
15pub mod raydium_cpmm;
16pub mod raydium_launchpad;
17pub mod utils;
18
19// Inner instruction 解析器(16字节 discriminator)
20pub mod all_inner;
21pub mod inner_common; // 通用零拷贝读取函数
22pub mod pump_amm_inner; // PumpSwap inner instruction
23pub mod pump_inner; // PumpFun inner instruction
24pub mod raydium_clmm_inner; // Raydium CLMM inner instruction // 其他所有协议的 inner instruction(统一文件)
25use crate::grpc::types::EventTypeFilter;
26// 重新导出主要解析函数
27pub use meteora_damm::parse_instruction as parse_meteora_damm_instruction;
28pub use pump::parse_instruction as parse_pumpfun_instruction;
29pub use pump_amm::parse_instruction as parse_pumpswap_instruction;
30pub use raydium_launchpad::parse_instruction as parse_raydium_launchpad_instruction;
31
32// 重新导出工具函数
33pub use utils::*;
34
35use crate::core::events::DexEvent;
36use program_ids::*;
37use solana_sdk::{pubkey::Pubkey, signature::Signature};
38
39#[inline(always)]
40fn filter_allows_untyped_protocol(event_type_filter: Option<&EventTypeFilter>) -> bool {
41    event_type_filter.and_then(|f| f.include_only.as_ref()).is_none()
42}
43
44/// 统一的指令解析入口函数
45#[inline]
46pub fn parse_instruction_unified(
47    instruction_data: &[u8],
48    accounts: &[Pubkey],
49    signature: Signature,
50    slot: u64,
51    tx_index: u64,
52    block_time_us: Option<i64>,
53    grpc_recv_us: i64,
54    event_type_filter: Option<&EventTypeFilter>,
55    program_id: &Pubkey,
56) -> Option<DexEvent> {
57    // 快速检查指令数据长度,避免无效解析
58    if instruction_data.is_empty() {
59        return None;
60    }
61
62    // 根据程序 ID 路由到相应的解析器,按使用频率排序
63
64    // Pumpfun
65    if *program_id == PUMPFUN_PROGRAM_ID {
66        if event_type_filter.is_some() && !event_type_filter.unwrap().includes_pumpfun() {
67            return None;
68        }
69        return parse_pumpfun_instruction(
70            instruction_data,
71            accounts,
72            signature,
73            slot,
74            tx_index,
75            block_time_us,
76            grpc_recv_us,
77        );
78    }
79    // PumpSwap (Pump AMM)
80    else if *program_id == PUMPSWAP_PROGRAM_ID {
81        if event_type_filter.is_some() && !event_type_filter.unwrap().includes_pumpswap() {
82            return None;
83        }
84        return parse_pumpswap_instruction(
85            instruction_data,
86            accounts,
87            signature,
88            slot,
89            tx_index,
90            block_time_us,
91        );
92    }
93    // Meteora DAMM
94    else if *program_id == METEORA_DAMM_V2_PROGRAM_ID {
95        if event_type_filter.is_some() && !event_type_filter.unwrap().includes_meteora_damm_v2() {
96            return None;
97        }
98        return parse_meteora_damm_instruction(
99            instruction_data,
100            accounts,
101            signature,
102            slot,
103            tx_index,
104            block_time_us,
105            grpc_recv_us,
106        );
107    }
108    // Pump fees (`pfeeUx...`)
109    else if *program_id == PUMP_FEES_PROGRAM_ID {
110        if event_type_filter.is_some() && !event_type_filter.unwrap().includes_pump_fees() {
111            return None;
112        }
113        return crate::instr::pump_fees::parse_instruction(
114            instruction_data,
115            accounts,
116            signature,
117            slot,
118            tx_index,
119            block_time_us,
120            grpc_recv_us,
121        );
122    }
123    // Bonk / Raydium Launchpad
124    else if *program_id == BONK_PROGRAM_ID {
125        if event_type_filter.is_some() && !event_type_filter.unwrap().includes_raydium_launchpad() {
126            return None;
127        }
128        return parse_raydium_launchpad_instruction(
129            instruction_data,
130            accounts,
131            signature,
132            slot,
133            tx_index,
134            block_time_us,
135        );
136    }
137    // Raydium CPMM
138    else if *program_id == RAYDIUM_CPMM_PROGRAM_ID {
139        if !filter_allows_untyped_protocol(event_type_filter) {
140            return None;
141        }
142        return crate::instr::raydium_cpmm::parse_instruction(
143            instruction_data,
144            accounts,
145            signature,
146            slot,
147            tx_index,
148            block_time_us,
149        );
150    }
151    // Raydium CLMM
152    else if *program_id == RAYDIUM_CLMM_PROGRAM_ID {
153        if !filter_allows_untyped_protocol(event_type_filter) {
154            return None;
155        }
156        return crate::instr::raydium_clmm::parse_instruction(
157            instruction_data,
158            accounts,
159            signature,
160            slot,
161            tx_index,
162            block_time_us,
163        );
164    }
165    // Raydium AMM V4
166    else if *program_id == RAYDIUM_AMM_V4_PROGRAM_ID {
167        if !filter_allows_untyped_protocol(event_type_filter) {
168            return None;
169        }
170        return crate::instr::raydium_amm::parse_instruction(
171            instruction_data,
172            accounts,
173            signature,
174            slot,
175            tx_index,
176            block_time_us,
177        );
178    }
179    // Orca Whirlpool
180    else if *program_id == ORCA_WHIRLPOOL_PROGRAM_ID {
181        if !filter_allows_untyped_protocol(event_type_filter) {
182            return None;
183        }
184        return crate::instr::orca_whirlpool::parse_instruction(
185            instruction_data,
186            accounts,
187            signature,
188            slot,
189            tx_index,
190            block_time_us,
191        );
192    }
193    // Meteora Pools / AMM
194    else if *program_id == METEORA_POOLS_PROGRAM_ID {
195        if !filter_allows_untyped_protocol(event_type_filter) {
196            return None;
197        }
198        return crate::instr::meteora_amm::parse_instruction(
199            instruction_data,
200            accounts,
201            signature,
202            slot,
203            tx_index,
204            block_time_us,
205        );
206    }
207    // Meteora DLMM
208    else if *program_id == METEORA_DLMM_PROGRAM_ID {
209        if !filter_allows_untyped_protocol(event_type_filter) {
210            return None;
211        }
212        return crate::instr::meteora_dlmm::parse_instruction(
213            instruction_data,
214            accounts,
215            signature,
216            slot,
217            tx_index,
218            block_time_us,
219        );
220    }
221
222    None
223}