Skip to main content

sol_parser_sdk/core/
unified_parser.rs

1//! 统一解析器 - 简化的单一入口解析器
2//!
3//! 提供完整的交易解析能力,支持指令和日志数据处理
4//!
5//! ## 零延迟优化
6//! - 使用 SmallVec 避免小数组堆分配
7//! - 内联热路径函数
8//! - 流式处理,立即回调
9//! - 分支预测提示
10
11use crate::core::events::*;
12use smallvec::{smallvec, SmallVec};
13use solana_sdk::{pubkey::Pubkey, signature::Signature};
14
15/// 主要解析函数 - 解析完整交易并返回所有 DEX 事件
16///
17/// 参数:
18/// - instruction_data: 交易指令数据
19/// - accounts: 账户列表
20/// - logs: 交易日志
21/// - signature: 交易签名
22/// - slot: 区块高度
23/// - block_time_us: 区块时间
24/// - program_id: 程序 ID
25///
26/// ## 零延迟优化
27/// - 使用 SmallVec<[DexEvent; 4]> 栈分配,大多数交易 ≤ 4 个事件
28/// - 预分配容量,避免动态扩容
29#[inline] // 零延迟优化:内联
30pub fn parse_transaction_events(
31    instruction_data: &[u8],
32    accounts: &[Pubkey],
33    logs: &[String],
34    signature: Signature,
35    slot: u64,
36    tx_index: u64,
37    block_time_us: Option<i64>,
38    program_id: &Pubkey,
39) -> SmallVec<[DexEvent; 4]> {
40    // 零延迟优化:SmallVec 栈分配
41    let mut events = smallvec![]; // 栈分配,容量 4
42
43    if let Some(instr_event) = crate::instr::parse_instruction_unified(
44        instruction_data,
45        accounts,
46        signature,
47        slot,
48        tx_index,
49        block_time_us,
50        0,
51        None,
52        program_id,
53    ) {
54        events.push(instr_event);
55    }
56
57    // 2. 解析日志事件 - 大多数日志会成功解析
58    for log in logs {
59        if let Some(log_event) = crate::logs::parse_log_unified(log, signature, slot, block_time_us)
60        {
61            events.push(log_event); // 热路径:成功解析
62        }
63        // 冷路径:解析失败,继续下一个
64    }
65
66    events
67}
68
69/// 简化版本 - 仅解析日志事件
70#[inline] // 零延迟优化:内联
71pub fn parse_logs_only(
72    logs: &[String],
73    signature: Signature,
74    slot: u64,
75    block_time_us: Option<i64>,
76) -> SmallVec<[DexEvent; 4]> {
77    // 零延迟优化:SmallVec 栈分配
78    let mut events = SmallVec::with_capacity(logs.len().min(4)); // 预分配容量
79
80    for log in logs {
81        if let Some(event) = crate::logs::parse_log_unified(log, signature, slot, block_time_us) {
82            events.push(event);
83        }
84    }
85
86    events
87}
88
89/// 事件监听器 trait - 用户可以实现此 trait 来处理解析出的事件
90pub trait EventListener {
91    fn on_dex_event(&self, event: &DexEvent);
92}
93
94/// 使用监听器解析交易的便捷函数
95pub fn parse_transaction_with_listener<T: EventListener>(
96    instruction_data: &[u8],
97    accounts: &[Pubkey],
98    logs: &[String],
99    signature: Signature,
100    slot: u64,
101    tx_index: u64,
102    block_time_us: Option<i64>,
103    program_id: &Pubkey,
104    listener: &T,
105) {
106    let events = parse_transaction_events(
107        instruction_data,
108        accounts,
109        logs,
110        signature,
111        slot,
112        tx_index,
113        block_time_us,
114        program_id,
115    );
116
117    for event in &events {
118        listener.on_dex_event(event);
119    }
120}
121
122/// 流式解析交易事件 - 每解析出一个事件就立即回调
123///
124/// 这个版本不做事件合并,确保每个事件都能立即被处理
125/// 适用于需要实时响应的场景
126pub fn parse_transaction_events_streaming<F>(
127    instruction_data: &[u8],
128    accounts: &[Pubkey],
129    logs: &[String],
130    signature: Signature,
131    slot: u64,
132    tx_index: u64,
133    block_time_us: Option<i64>,
134    program_id: &Pubkey,
135    mut callback: F,
136) where
137    F: FnMut(DexEvent),
138{
139    // 1. 先解析指令事件(如果有) - 立即回调
140    if let Some(instr_event) = crate::instr::parse_instruction_unified(
141        instruction_data,
142        accounts,
143        signature,
144        slot,
145        tx_index,
146        block_time_us,
147        0,
148        None,
149        program_id,
150    ) {
151        callback(instr_event);
152    }
153
154    // 2. 逐个解析日志事件 - 每个事件立即回调
155    for log in logs {
156        if let Some(log_event) = crate::logs::parse_log_unified(log, signature, slot, block_time_us)
157        {
158            callback(log_event); // 立即回调日志事件,不等待其他日志
159        }
160    }
161
162    // 注意:这里完全不做事件合并和缓存,确保每个事件都是立即回调
163    // 回调顺序:先指令事件,然后按日志顺序回调日志事件
164}
165
166/// 流式解析日志事件 - 每解析出一个事件就立即回调
167pub fn parse_logs_streaming<F>(
168    logs: &[String],
169    signature: Signature,
170    slot: u64,
171    block_time_us: Option<i64>,
172    mut callback: F,
173) where
174    F: FnMut(DexEvent),
175{
176    for log in logs {
177        if let Some(event) = crate::logs::parse_log_unified(log, signature, slot, block_time_us) {
178            callback(event);
179        }
180    }
181}
182
183/// 流式事件监听器 trait - 适用于流式处理
184pub trait StreamingEventListener {
185    fn on_dex_event_streaming(&mut self, event: DexEvent);
186}
187
188/// 使用流式监听器解析交易的便捷函数
189pub fn parse_transaction_with_streaming_listener<T: StreamingEventListener>(
190    instruction_data: &[u8],
191    accounts: &[Pubkey],
192    logs: &[String],
193    signature: Signature,
194    slot: u64,
195    tx_index: u64,
196    block_time_us: Option<i64>,
197    program_id: &Pubkey,
198    listener: &mut T,
199) {
200    parse_transaction_events_streaming(
201        instruction_data,
202        accounts,
203        logs,
204        signature,
205        slot,
206        tx_index,
207        block_time_us,
208        program_id,
209        |event| listener.on_dex_event_streaming(event),
210    );
211}