1use crate::core::events::{DexEvent, EventMetadata};
7use crate::grpc::types::EventType;
8
9pub type Discriminator = u64;
11
12pub type ParserFn = fn(&[u8], EventMetadata) -> Option<DexEvent>;
14
15#[derive(Debug, Clone, Copy)]
17pub struct DiscriminatorInfo {
18 pub discriminator: u64,
19 pub parser: ParserFn,
20 pub protocol: Protocol,
21 pub name: &'static str, }
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum Protocol {
27 PumpFun,
28 PumpSwap,
29 RaydiumClmm,
30 RaydiumCpmm,
31 RaydiumAmm,
32 OrcaWhirlpool,
33 MeteoraAmm,
34 MeteoraDamm,
35 MeteoraDlmm,
36}
37
38#[inline(always)]
44fn parse_pumpfun_create(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
45 crate::logs::pump::parse_create_from_data(data, metadata)
46}
47
48#[inline(always)]
49fn parse_pumpfun_trade(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
50 crate::logs::pump::parse_trade_from_data(data, metadata, false)
51}
52
53#[inline(always)]
54fn parse_pumpfun_migrate(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
55 crate::logs::pump::parse_migrate_from_data(data, metadata)
56}
57
58#[inline(always)]
60fn parse_pumpswap_buy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
61 crate::logs::pump_amm::parse_buy_from_data(data, metadata)
62}
63
64#[inline(always)]
65fn parse_pumpswap_sell(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
66 crate::logs::pump_amm::parse_sell_from_data(data, metadata)
67}
68
69#[inline(always)]
70fn parse_pumpswap_create_pool(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
71 crate::logs::pump_amm::parse_create_pool_from_data(data, metadata)
72}
73
74#[inline(always)]
75fn parse_pumpswap_add_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
76 crate::logs::pump_amm::parse_add_liquidity_from_data(data, metadata)
77}
78
79#[inline(always)]
80fn parse_pumpswap_remove_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
81 crate::logs::pump_amm::parse_remove_liquidity_from_data(data, metadata)
82}
83
84#[inline(always)]
86fn parse_raydium_clmm_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
87 crate::logs::raydium_clmm::parse_swap_from_data(data, metadata)
88}
89
90#[inline(always)]
91fn parse_raydium_clmm_increase_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
92 crate::logs::raydium_clmm::parse_increase_liquidity_from_data(data, metadata)
93}
94
95#[inline(always)]
96fn parse_raydium_clmm_decrease_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
97 crate::logs::raydium_clmm::parse_decrease_liquidity_from_data(data, metadata)
98}
99
100#[inline(always)]
101fn parse_raydium_clmm_create_pool(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
102 crate::logs::raydium_clmm::parse_create_pool_from_data(data, metadata)
103}
104
105#[inline(always)]
106fn parse_raydium_clmm_collect_fee(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
107 crate::logs::raydium_clmm::parse_collect_fee_from_data(data, metadata)
108}
109
110#[inline(always)]
112fn parse_raydium_cpmm_swap_base_in(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
113 crate::logs::raydium_cpmm::parse_swap_base_in_from_data(data, metadata)
114}
115
116#[inline(always)]
117fn parse_raydium_cpmm_swap_base_out(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
118 crate::logs::raydium_cpmm::parse_swap_base_out_from_data(data, metadata)
119}
120
121#[inline(always)]
122fn parse_raydium_cpmm_create_pool(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
123 crate::logs::raydium_cpmm::parse_create_pool_from_data(data, metadata)
124}
125
126#[inline(always)]
127fn parse_raydium_cpmm_deposit(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
128 crate::logs::raydium_cpmm::parse_deposit_from_data(data, metadata)
129}
130
131#[inline(always)]
132fn parse_raydium_cpmm_withdraw(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
133 crate::logs::raydium_cpmm::parse_withdraw_from_data(data, metadata)
134}
135
136#[inline(always)]
138fn parse_raydium_amm_swap_base_in(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
139 crate::logs::raydium_amm::parse_swap_base_in_from_data(data, metadata)
140}
141
142#[inline(always)]
143fn parse_raydium_amm_swap_base_out(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
144 crate::logs::raydium_amm::parse_swap_base_out_from_data(data, metadata)
145}
146
147#[inline(always)]
148fn parse_raydium_amm_deposit(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
149 crate::logs::raydium_amm::parse_deposit_from_data(data, metadata)
150}
151
152#[inline(always)]
153fn parse_raydium_amm_withdraw(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
154 crate::logs::raydium_amm::parse_withdraw_from_data(data, metadata)
155}
156
157#[inline(always)]
158fn parse_raydium_amm_initialize2(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
159 crate::logs::raydium_amm::parse_initialize2_from_data(data, metadata)
160}
161
162#[inline(always)]
164fn parse_orca_traded(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
165 crate::logs::orca_whirlpool::parse_traded_from_data(data, metadata)
166}
167
168#[inline(always)]
169fn parse_orca_liquidity_increased(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
170 crate::logs::orca_whirlpool::parse_liquidity_increased_from_data(data, metadata)
171}
172
173#[inline(always)]
174fn parse_orca_liquidity_decreased(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
175 crate::logs::orca_whirlpool::parse_liquidity_decreased_from_data(data, metadata)
176}
177
178#[inline(always)]
179fn parse_orca_pool_initialized(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
180 crate::logs::orca_whirlpool::parse_pool_initialized_from_data(data, metadata)
181}
182
183#[inline(always)]
185fn parse_meteora_amm_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
186 crate::logs::meteora_amm::parse_swap_from_data(data, metadata)
187}
188
189#[inline(always)]
190fn parse_meteora_amm_add_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
191 crate::logs::meteora_amm::parse_add_liquidity_from_data(data, metadata)
192}
193
194#[inline(always)]
195fn parse_meteora_amm_remove_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
196 crate::logs::meteora_amm::parse_remove_liquidity_from_data(data, metadata)
197}
198
199#[inline(always)]
200fn parse_meteora_amm_bootstrap_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
201 crate::logs::meteora_amm::parse_bootstrap_liquidity_from_data(data, metadata)
202}
203
204#[inline(always)]
205fn parse_meteora_amm_pool_created(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
206 crate::logs::meteora_amm::parse_pool_created_from_data(data, metadata)
207}
208
209macro_rules! disc_entry {
214 ($disc:expr, $name:expr, $parser:expr, $protocol:expr) => {
215 DiscriminatorInfo {
216 discriminator: $disc,
217 parser: $parser,
218 protocol: $protocol,
219 name: $name,
220 }
221 };
222}
223
224pub const DISCRIMINATOR_LUT: &[DiscriminatorInfo] = &[
229 disc_entry!(
231 0x0100000000000000,
232 "Raydium AMM Initialize2",
233 parse_raydium_amm_initialize2,
234 Protocol::RaydiumAmm
235 ),
236 disc_entry!(
237 0x012C5B686FD026A0,
238 "Raydium CLMM Decrease Liquidity",
239 parse_raydium_clmm_decrease_liquidity,
240 Protocol::RaydiumClmm
241 ),
242 disc_entry!(
243 0x0300000000000000,
244 "Raydium AMM Deposit",
245 parse_raydium_amm_deposit,
246 Protocol::RaydiumAmm
247 ),
248 disc_entry!(
249 0x0400000000000000,
250 "Raydium AMM Withdraw",
251 parse_raydium_amm_withdraw,
252 Protocol::RaydiumAmm
253 ),
254 disc_entry!(
255 0x0900000000000000,
256 "Raydium AMM Swap Base In",
257 parse_raydium_amm_swap_base_in,
258 Protocol::RaydiumAmm
259 ),
260 disc_entry!(
261 0x0AB0EE45DF591D85,
262 "Raydium CLMM Increase Liquidity",
263 parse_raydium_clmm_increase_liquidity,
264 Protocol::RaydiumClmm
265 ),
266 disc_entry!(
267 0xABB5CA7047241A6,
268 "Orca Whirlpool Liquidity Decreased",
269 parse_orca_liquidity_decreased,
270 Protocol::OrcaWhirlpool
271 ),
272 disc_entry!(
273 0x0B00000000000000,
274 "Raydium AMM Swap Base Out",
275 parse_raydium_amm_swap_base_out,
276 Protocol::RaydiumAmm
277 ),
278 disc_entry!(
280 0x22A16D949C4612B7,
281 "Raydium CPMM Withdraw",
282 parse_raydium_cpmm_withdraw,
283 Protocol::RaydiumCpmm
284 ),
285 disc_entry!(0x2ADC03A50A372F3E, "PumpSwap Sell", parse_pumpswap_sell, Protocol::PumpSwap),
287 disc_entry!(
289 0x3A981F67E861F474,
290 "Meteora AMM Remove Liquidity",
291 parse_meteora_amm_remove_liquidity,
292 Protocol::MeteoraAmm
293 ),
294 disc_entry!(
295 0x529DDC6858292CCA,
296 "Meteora AMM Pool Created",
297 parse_meteora_amm_pool_created,
298 Protocol::MeteoraAmm
299 ),
300 disc_entry!(
302 0x74A776A0D20C31B1,
303 "PumpSwap Create Pool",
304 parse_pumpswap_create_pool,
305 Protocol::PumpSwap
306 ),
307 disc_entry!(0x7663EBDE4DA91B1B, "PumpFun Create", parse_pumpfun_create, Protocol::PumpFun),
308 disc_entry!(0x7777F52C1F52F467, "PumpSwap Buy", parse_pumpswap_buy, Protocol::PumpSwap),
309 disc_entry!(
310 0x77AB68BB63CF98A4,
311 "Raydium CLMM Collect Fee",
312 parse_raydium_clmm_collect_fee,
313 Protocol::RaydiumClmm
314 ),
315 disc_entry!(
316 0x906B8E1F533DF878,
317 "PumpSwap Add Liquidity",
318 parse_pumpswap_add_liquidity,
319 Protocol::PumpSwap
320 ),
321 disc_entry!(0x94EA945DB95DE9BD, "PumpFun Migrate", parse_pumpfun_migrate, Protocol::PumpFun),
322 disc_entry!(
323 0x96A02B93AF49CAE1,
324 "Orca Whirlpool Traded",
325 parse_orca_traded,
326 Protocol::OrcaWhirlpool
327 ),
328 disc_entry!(
329 0xA19BFE6690071E1E,
330 "Orca Whirlpool Liquidity Increased",
331 parse_orca_liquidity_increased,
332 Protocol::OrcaWhirlpool
333 ),
334 disc_entry!(
335 0xADB44AA35662D937,
336 "Raydium CPMM Swap Base Out",
337 parse_raydium_cpmm_swap_base_out,
338 Protocol::RaydiumCpmm
339 ),
340 disc_entry!(
341 0xB6F2E15289C623F2,
342 "Raydium CPMM Deposit",
343 parse_raydium_cpmm_deposit,
344 Protocol::RaydiumCpmm
345 ),
346 disc_entry!(
347 0xBA3D34E35A7D5E1F,
348 "Meteora AMM Add Liquidity",
349 parse_meteora_amm_add_liquidity,
350 Protocol::MeteoraAmm
351 ),
352 disc_entry!(
353 0xBC4068CF8ED192E9,
354 "Raydium CLMM Create Pool",
355 parse_raydium_clmm_create_pool,
356 Protocol::RaydiumClmm
357 ),
358 disc_entry!(
359 0xC0472CA01A850916,
360 "PumpSwap Remove Liquidity",
361 parse_pumpswap_remove_liquidity,
362 Protocol::PumpSwap
363 ),
364 disc_entry!(
365 0xC40AD0CDBE6CE351,
366 "Meteora AMM Swap",
367 parse_meteora_amm_swap,
368 Protocol::MeteoraAmm
369 ),
370 disc_entry!(
371 0xC887759EE19EC6F8,
372 "Raydium CLMM Swap",
373 parse_raydium_clmm_swap,
374 Protocol::RaydiumClmm
375 ),
376 disc_entry!(
377 0xDE331EC4DA5ABE8F,
378 "Raydium CPMM Swap Base In",
379 parse_raydium_cpmm_swap_base_in,
380 Protocol::RaydiumCpmm
381 ),
382 disc_entry!(
383 0xE5FEC60C57AD7664,
384 "Orca Whirlpool Initialize",
385 parse_orca_pool_initialized,
386 Protocol::OrcaWhirlpool
387 ),
388 disc_entry!(0xEE61E64ED37FDBBD, "PumpFun Trade", parse_pumpfun_trade, Protocol::PumpFun),
389 disc_entry!(
390 0xF70E375C88267F79,
391 "Meteora AMM Bootstrap Liquidity",
392 parse_meteora_amm_bootstrap_liquidity,
393 Protocol::MeteoraAmm
394 ),
395];
396
397#[inline(always)]
401pub fn lookup_discriminator(discriminator: u64) -> Option<&'static DiscriminatorInfo> {
402 DISCRIMINATOR_LUT
403 .binary_search_by_key(&discriminator, |info| info.discriminator)
404 .ok()
405 .map(|idx| &DISCRIMINATOR_LUT[idx])
406}
407
408#[inline(always)]
410pub fn discriminator_to_name(discriminator: u64) -> Option<&'static str> {
411 lookup_discriminator(discriminator).map(|info| info.name)
412}
413
414#[inline(always)]
416pub fn discriminator_to_protocol(discriminator: u64) -> Option<Protocol> {
417 lookup_discriminator(discriminator).map(|info| info.protocol)
418}
419
420#[inline(always)]
422pub fn parse_with_discriminator(
423 discriminator: u64,
424 data: &[u8],
425 metadata: EventMetadata,
426) -> Option<DexEvent> {
427 let info = lookup_discriminator(discriminator)?;
428 (info.parser)(data, metadata)
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434
435 #[test]
436 fn test_lut_is_sorted() {
437 for i in 1..DISCRIMINATOR_LUT.len() {
439 assert!(
440 DISCRIMINATOR_LUT[i - 1].discriminator < DISCRIMINATOR_LUT[i].discriminator,
441 "LUT not sorted at index {}: {:x} >= {:x}",
442 i,
443 DISCRIMINATOR_LUT[i - 1].discriminator,
444 DISCRIMINATOR_LUT[i].discriminator
445 );
446 }
447 }
448
449 #[test]
450 fn test_discriminator_lookup() {
451 let disc = 0x7663EBDE4DA91B1B;
453 let info = lookup_discriminator(disc).unwrap();
454 assert_eq!(info.name, "PumpFun Create");
455 assert_eq!(info.protocol, Protocol::PumpFun);
456
457 let disc = 0xC887759EE19EC6F8;
459 let info = lookup_discriminator(disc).unwrap();
460 assert_eq!(info.name, "Raydium CLMM Swap");
461 assert_eq!(info.protocol, Protocol::RaydiumClmm);
462
463 let disc = 0xFFFFFFFFFFFFFFFF;
465 assert!(lookup_discriminator(disc).is_none());
466 }
467
468 #[test]
469 fn test_event_name_lookup() {
470 let disc = 0x7777F52C1F52F467;
472 assert_eq!(discriminator_to_name(disc), Some("PumpSwap Buy"));
473
474 let disc = 0x0900000000000000;
476 assert_eq!(discriminator_to_name(disc), Some("Raydium AMM Swap Base In"));
477 }
478
479 #[test]
480 fn test_protocol_lookup() {
481 assert_eq!(discriminator_to_protocol(0x7663EBDE4DA91B1B), Some(Protocol::PumpFun));
482 assert_eq!(discriminator_to_protocol(0xC887759EE19EC6F8), Some(Protocol::RaydiumClmm));
483 assert_eq!(discriminator_to_protocol(0x96A02B93AF49CAE1), Some(Protocol::OrcaWhirlpool));
484 }
485}