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 PumpFees,
29 PumpSwap,
30 RaydiumClmm,
31 RaydiumCpmm,
32 RaydiumAmm,
33 OrcaWhirlpool,
34 MeteoraAmm,
35 MeteoraDamm,
36 MeteoraDlmm,
37}
38
39#[inline(always)]
45fn parse_pumpfun_create(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
46 crate::logs::pump::parse_create_from_data(data, metadata)
47}
48
49#[inline(always)]
50fn parse_pumpfun_trade(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
51 crate::logs::pump::parse_trade_from_data(data, metadata, false)
52}
53
54#[inline(always)]
55fn parse_pumpfun_migrate(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
56 crate::logs::pump::parse_migrate_from_data(data, metadata)
57}
58
59#[inline(always)]
60fn parse_pumpfun_migrate_bonding_curve_creator(
61 data: &[u8],
62 metadata: EventMetadata,
63) -> Option<DexEvent> {
64 crate::logs::pump::parse_migrate_bonding_curve_creator_from_data(data, metadata)
65}
66
67#[inline(always)]
68fn parse_pumpfees_initialize_fee_config(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
69 crate::logs::pump_fees::parse_initialize_fee_config_from_data(data, metadata)
70}
71
72#[inline(always)]
73fn parse_pumpfees_reset(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
74 crate::logs::pump_fees::parse_reset_fee_sharing_config_from_data(data, metadata)
75}
76
77#[inline(always)]
78fn parse_pumpfees_revoke(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
79 crate::logs::pump_fees::parse_revoke_fee_sharing_authority_from_data(data, metadata)
80}
81
82#[inline(always)]
83fn parse_pumpfees_transfer(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
84 crate::logs::pump_fees::parse_transfer_fee_sharing_authority_from_data(data, metadata)
85}
86
87#[inline(always)]
88fn parse_pumpfees_update_admin(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
89 crate::logs::pump_fees::parse_update_admin_from_data(data, metadata)
90}
91
92#[inline(always)]
93fn parse_pumpfees_update_fee_config(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
94 crate::logs::pump_fees::parse_update_fee_config_from_data(data, metadata)
95}
96
97#[inline(always)]
98fn parse_pumpfees_update_fee_shares(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
99 crate::logs::pump_fees::parse_update_fee_shares_from_data(data, metadata)
100}
101
102#[inline(always)]
103fn parse_pumpfees_upsert_fee_tiers(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
104 crate::logs::pump_fees::parse_upsert_fee_tiers_from_data(data, metadata)
105}
106
107#[inline(always)]
108fn parse_pumpfun_create_fee_sharing_config(
109 data: &[u8],
110 metadata: EventMetadata,
111) -> Option<DexEvent> {
112 crate::logs::pump_fees::parse_create_fee_sharing_config_from_data(data, metadata)
113}
114
115#[inline(always)]
117fn parse_pumpswap_buy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
118 crate::logs::pump_amm::parse_buy_from_data(data, metadata)
119}
120
121#[inline(always)]
122fn parse_pumpswap_sell(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
123 crate::logs::pump_amm::parse_sell_from_data(data, metadata)
124}
125
126#[inline(always)]
127fn parse_pumpswap_create_pool(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
128 crate::logs::pump_amm::parse_create_pool_from_data(data, metadata)
129}
130
131#[inline(always)]
132fn parse_pumpswap_add_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
133 crate::logs::pump_amm::parse_add_liquidity_from_data(data, metadata)
134}
135
136#[inline(always)]
137fn parse_pumpswap_remove_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
138 crate::logs::pump_amm::parse_remove_liquidity_from_data(data, metadata)
139}
140
141#[inline(always)]
143fn parse_raydium_clmm_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
144 crate::logs::raydium_clmm::parse_swap_from_data(data, metadata)
145}
146
147#[inline(always)]
148fn parse_raydium_clmm_increase_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
149 crate::logs::raydium_clmm::parse_increase_liquidity_from_data(data, metadata)
150}
151
152#[inline(always)]
153fn parse_raydium_clmm_decrease_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
154 crate::logs::raydium_clmm::parse_decrease_liquidity_from_data(data, metadata)
155}
156
157#[inline(always)]
158fn parse_raydium_clmm_create_pool(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
159 crate::logs::raydium_clmm::parse_create_pool_from_data(data, metadata)
160}
161
162#[inline(always)]
163fn parse_raydium_clmm_collect_fee(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
164 crate::logs::raydium_clmm::parse_collect_fee_from_data(data, metadata)
165}
166
167#[inline(always)]
169fn parse_raydium_cpmm_swap_base_in(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
170 crate::logs::raydium_cpmm::parse_swap_base_in_from_data(data, metadata)
171}
172
173#[inline(always)]
174fn parse_raydium_cpmm_swap_base_out(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
175 crate::logs::raydium_cpmm::parse_swap_base_out_from_data(data, metadata)
176}
177
178#[inline(always)]
179fn parse_raydium_cpmm_create_pool(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
180 crate::logs::raydium_cpmm::parse_create_pool_from_data(data, metadata)
181}
182
183#[inline(always)]
184fn parse_raydium_cpmm_deposit(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
185 crate::logs::raydium_cpmm::parse_deposit_from_data(data, metadata)
186}
187
188#[inline(always)]
189fn parse_raydium_cpmm_withdraw(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
190 crate::logs::raydium_cpmm::parse_withdraw_from_data(data, metadata)
191}
192
193#[inline(always)]
195fn parse_raydium_amm_swap_base_in(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
196 crate::logs::raydium_amm::parse_swap_base_in_from_data(data, metadata)
197}
198
199#[inline(always)]
200fn parse_raydium_amm_swap_base_out(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
201 crate::logs::raydium_amm::parse_swap_base_out_from_data(data, metadata)
202}
203
204#[inline(always)]
205fn parse_raydium_amm_deposit(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
206 crate::logs::raydium_amm::parse_deposit_from_data(data, metadata)
207}
208
209#[inline(always)]
210fn parse_raydium_amm_withdraw(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
211 crate::logs::raydium_amm::parse_withdraw_from_data(data, metadata)
212}
213
214#[inline(always)]
215fn parse_raydium_amm_initialize2(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
216 crate::logs::raydium_amm::parse_initialize2_from_data(data, metadata)
217}
218
219#[inline(always)]
221fn parse_orca_traded(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
222 crate::logs::orca_whirlpool::parse_traded_from_data(data, metadata)
223}
224
225#[inline(always)]
226fn parse_orca_liquidity_increased(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
227 crate::logs::orca_whirlpool::parse_liquidity_increased_from_data(data, metadata)
228}
229
230#[inline(always)]
231fn parse_orca_liquidity_decreased(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
232 crate::logs::orca_whirlpool::parse_liquidity_decreased_from_data(data, metadata)
233}
234
235#[inline(always)]
236fn parse_orca_pool_initialized(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
237 crate::logs::orca_whirlpool::parse_pool_initialized_from_data(data, metadata)
238}
239
240#[inline(always)]
242fn parse_meteora_amm_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
243 crate::logs::meteora_amm::parse_swap_from_data(data, metadata)
244}
245
246#[inline(always)]
247fn parse_meteora_amm_add_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
248 crate::logs::meteora_amm::parse_add_liquidity_from_data(data, metadata)
249}
250
251#[inline(always)]
252fn parse_meteora_amm_remove_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
253 crate::logs::meteora_amm::parse_remove_liquidity_from_data(data, metadata)
254}
255
256#[inline(always)]
257fn parse_meteora_amm_bootstrap_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
258 crate::logs::meteora_amm::parse_bootstrap_liquidity_from_data(data, metadata)
259}
260
261#[inline(always)]
262fn parse_meteora_amm_pool_created(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
263 crate::logs::meteora_amm::parse_pool_created_from_data(data, metadata)
264}
265
266macro_rules! disc_entry {
271 ($disc:expr, $name:expr, $parser:expr, $protocol:expr) => {
272 DiscriminatorInfo {
273 discriminator: $disc,
274 parser: $parser,
275 protocol: $protocol,
276 name: $name,
277 }
278 };
279}
280
281pub const DISCRIMINATOR_LUT: &[DiscriminatorInfo] = &[
286 disc_entry!(
288 0x0100000000000000,
289 "Raydium AMM Initialize2",
290 parse_raydium_amm_initialize2,
291 Protocol::RaydiumAmm
292 ),
293 disc_entry!(
294 0x012C5B686FD026A0,
295 "Raydium CLMM Decrease Liquidity",
296 parse_raydium_clmm_decrease_liquidity,
297 Protocol::RaydiumClmm
298 ),
299 disc_entry!(
300 0x0300000000000000,
301 "Raydium AMM Deposit",
302 parse_raydium_amm_deposit,
303 Protocol::RaydiumAmm
304 ),
305 disc_entry!(
306 0x03F36CD5DC68A79B_u64,
307 "PumpFun Migrate Bonding Curve Creator",
308 parse_pumpfun_migrate_bonding_curve_creator,
309 Protocol::PumpFun
310 ),
311 disc_entry!(
312 0x0400000000000000,
313 "Raydium AMM Withdraw",
314 parse_raydium_amm_withdraw,
315 Protocol::RaydiumAmm
316 ),
317 disc_entry!(
318 0x0900000000000000,
319 "Raydium AMM Swap Base In",
320 parse_raydium_amm_swap_base_in,
321 Protocol::RaydiumAmm
322 ),
323 disc_entry!(
324 0x0AB0EE45DF591D85,
325 "Raydium CLMM Increase Liquidity",
326 parse_raydium_clmm_increase_liquidity,
327 Protocol::RaydiumClmm
328 ),
329 disc_entry!(
330 0xABB5CA7047241A6,
331 "Orca Whirlpool Liquidity Decreased",
332 parse_orca_liquidity_decreased,
333 Protocol::OrcaWhirlpool
334 ),
335 disc_entry!(
336 0x0B00000000000000,
337 "Raydium AMM Swap Base Out",
338 parse_raydium_amm_swap_base_out,
339 Protocol::RaydiumAmm
340 ),
341 disc_entry!(
343 0x22A16D949C4612B7,
344 "Raydium CPMM Withdraw",
345 parse_raydium_cpmm_withdraw,
346 Protocol::RaydiumCpmm
347 ),
348 disc_entry!(0x2ADC03A50A372F3E, "PumpSwap Sell", parse_pumpswap_sell, Protocol::PumpSwap),
350 disc_entry!(
352 0x3A981F67E861F474,
353 "Meteora AMM Remove Liquidity",
354 parse_meteora_amm_remove_liquidity,
355 Protocol::MeteoraAmm
356 ),
357 disc_entry!(
358 0x3E99BE0E3C651772_u64,
359 "Pump Fees Revoke Fee Sharing Authority",
360 parse_pumpfees_revoke,
361 Protocol::PumpFees
362 ),
363 disc_entry!(
364 0x529DDC6858292CCA,
365 "Meteora AMM Pool Created",
366 parse_meteora_amm_pool_created,
367 Protocol::MeteoraAmm
368 ),
369 disc_entry!(
370 0x58FB74B8C8AA6985_u64,
371 "Pump Fees Create Fee Sharing Config",
372 parse_pumpfun_create_fee_sharing_config,
373 Protocol::PumpFees
374 ),
375 disc_entry!(
377 0x74A776A0D20C31B1,
378 "PumpSwap Create Pool",
379 parse_pumpswap_create_pool,
380 Protocol::PumpSwap
381 ),
382 disc_entry!(0x7663EBDE4DA91B1B, "PumpFun Create", parse_pumpfun_create, Protocol::PumpFun),
383 disc_entry!(0x7777F52C1F52F467, "PumpSwap Buy", parse_pumpswap_buy, Protocol::PumpSwap),
384 disc_entry!(
385 0x77AB68BB63CF98A4,
386 "Raydium CLMM Collect Fee",
387 parse_raydium_clmm_collect_fee,
388 Protocol::RaydiumClmm
389 ),
390 disc_entry!(
391 0x7EE2380AE6F48A59_u64,
392 "Pump Fees Initialize Fee Config",
393 parse_pumpfees_initialize_fee_config,
394 Protocol::PumpFees
395 ),
396 disc_entry!(
397 0x906B8E1F533DF878,
398 "PumpSwap Add Liquidity",
399 parse_pumpswap_add_liquidity,
400 Protocol::PumpSwap
401 ),
402 disc_entry!(0x94EA945DB95DE9BD, "PumpFun Migrate", parse_pumpfun_migrate, Protocol::PumpFun),
403 disc_entry!(
404 0x96A02B93AF49CAE1,
405 "Orca Whirlpool Traded",
406 parse_orca_traded,
407 Protocol::OrcaWhirlpool
408 ),
409 disc_entry!(
410 0xA19BFE6690071E1E,
411 "Orca Whirlpool Liquidity Increased",
412 parse_orca_liquidity_increased,
413 Protocol::OrcaWhirlpool
414 ),
415 disc_entry!(
416 0xADB44AA35662D937,
417 "Raydium CPMM Swap Base Out",
418 parse_raydium_cpmm_swap_base_out,
419 Protocol::RaydiumCpmm
420 ),
421 disc_entry!(
422 0xB6F2E15289C623F2,
423 "Raydium CPMM Deposit",
424 parse_raydium_cpmm_deposit,
425 Protocol::RaydiumCpmm
426 ),
427 disc_entry!(
428 0xBA3D34E35A7D5E1F,
429 "Meteora AMM Add Liquidity",
430 parse_meteora_amm_add_liquidity,
431 Protocol::MeteoraAmm
432 ),
433 disc_entry!(
434 0xBC4068CF8ED192E9,
435 "Raydium CLMM Create Pool",
436 parse_raydium_clmm_create_pool,
437 Protocol::RaydiumClmm
438 ),
439 disc_entry!(
440 0xC0472CA01A850916,
441 "PumpSwap Remove Liquidity",
442 parse_pumpswap_remove_liquidity,
443 Protocol::PumpSwap
444 ),
445 disc_entry!(
446 0xC40AD0CDBE6CE351,
447 "Meteora AMM Swap",
448 parse_meteora_amm_swap,
449 Protocol::MeteoraAmm
450 ),
451 disc_entry!(
452 0xC887759EE19EC6F8,
453 "Raydium CLMM Swap",
454 parse_raydium_clmm_swap,
455 Protocol::RaydiumClmm
456 ),
457 disc_entry!(
458 0xCBE1E45BB8C4BA15_u64,
459 "Pump Fees Update Fee Shares",
460 parse_pumpfees_update_fee_shares,
461 Protocol::PumpFees
462 ),
463 disc_entry!(
464 0xCC21BA7ABBA959AB_u64,
465 "Pump Fees Upsert Fee Tiers",
466 parse_pumpfees_upsert_fee_tiers,
467 Protocol::PumpFees
468 ),
469 disc_entry!(
470 0xD0BCF43E2341175A_u64,
471 "Pump Fees Update Fee Config",
472 parse_pumpfees_update_fee_config,
473 Protocol::PumpFees
474 ),
475 disc_entry!(
476 0xDE331EC4DA5ABE8F,
477 "Raydium CPMM Swap Base In",
478 parse_raydium_cpmm_swap_base_in,
479 Protocol::RaydiumCpmm
480 ),
481 disc_entry!(
482 0xE5FEC60C57AD7664,
483 "Orca Whirlpool Initialize",
484 parse_orca_pool_initialized,
485 Protocol::OrcaWhirlpool
486 ),
487 disc_entry!(
488 0xEA423FF657AB98E1_u64,
489 "Pump Fees Update Admin",
490 parse_pumpfees_update_admin,
491 Protocol::PumpFees
492 ),
493 disc_entry!(
494 0xEC08B84DF5C68F7C_u64,
495 "Pump Fees Transfer Fee Sharing Authority",
496 parse_pumpfees_transfer,
497 Protocol::PumpFees
498 ),
499 disc_entry!(0xEE61E64ED37FDBBD, "PumpFun Trade", parse_pumpfun_trade, Protocol::PumpFun),
500 disc_entry!(
501 0xF3D63778E297CCCB_u64,
502 "Pump Fees Reset Fee Sharing Config",
503 parse_pumpfees_reset,
504 Protocol::PumpFees
505 ),
506 disc_entry!(
507 0xF70E375C88267F79,
508 "Meteora AMM Bootstrap Liquidity",
509 parse_meteora_amm_bootstrap_liquidity,
510 Protocol::MeteoraAmm
511 ),
512];
513
514#[inline(always)]
518pub fn lookup_discriminator(discriminator: u64) -> Option<&'static DiscriminatorInfo> {
519 DISCRIMINATOR_LUT
520 .binary_search_by_key(&discriminator, |info| info.discriminator)
521 .ok()
522 .map(|idx| &DISCRIMINATOR_LUT[idx])
523}
524
525#[inline(always)]
527pub fn discriminator_to_name(discriminator: u64) -> Option<&'static str> {
528 lookup_discriminator(discriminator).map(|info| info.name)
529}
530
531#[inline(always)]
533pub fn discriminator_to_protocol(discriminator: u64) -> Option<Protocol> {
534 lookup_discriminator(discriminator).map(|info| info.protocol)
535}
536
537#[inline(always)]
539pub fn parse_with_discriminator(
540 discriminator: u64,
541 data: &[u8],
542 metadata: EventMetadata,
543) -> Option<DexEvent> {
544 let info = lookup_discriminator(discriminator)?;
545 (info.parser)(data, metadata)
546}
547
548#[cfg(test)]
549mod tests {
550 use super::*;
551
552 #[test]
553 fn test_lut_is_sorted() {
554 for i in 1..DISCRIMINATOR_LUT.len() {
556 assert!(
557 DISCRIMINATOR_LUT[i - 1].discriminator < DISCRIMINATOR_LUT[i].discriminator,
558 "LUT not sorted at index {}: {:x} >= {:x}",
559 i,
560 DISCRIMINATOR_LUT[i - 1].discriminator,
561 DISCRIMINATOR_LUT[i].discriminator
562 );
563 }
564 }
565
566 #[test]
567 fn test_discriminator_lookup() {
568 let disc = 0x7663EBDE4DA91B1B;
570 let info = lookup_discriminator(disc).unwrap();
571 assert_eq!(info.name, "PumpFun Create");
572 assert_eq!(info.protocol, Protocol::PumpFun);
573
574 let disc = 0xC887759EE19EC6F8;
576 let info = lookup_discriminator(disc).unwrap();
577 assert_eq!(info.name, "Raydium CLMM Swap");
578 assert_eq!(info.protocol, Protocol::RaydiumClmm);
579
580 let disc = 0xFFFFFFFFFFFFFFFF;
582 assert!(lookup_discriminator(disc).is_none());
583 }
584
585 #[test]
586 fn test_event_name_lookup() {
587 let disc = 0x7777F52C1F52F467;
589 assert_eq!(discriminator_to_name(disc), Some("PumpSwap Buy"));
590
591 let disc = 0x0900000000000000;
593 assert_eq!(discriminator_to_name(disc), Some("Raydium AMM Swap Base In"));
594 }
595
596 #[test]
597 fn test_protocol_lookup() {
598 assert_eq!(discriminator_to_protocol(0x7663EBDE4DA91B1B), Some(Protocol::PumpFun));
599 assert_eq!(discriminator_to_protocol(0xC887759EE19EC6F8), Some(Protocol::RaydiumClmm));
600 assert_eq!(discriminator_to_protocol(0x96A02B93AF49CAE1), Some(Protocol::OrcaWhirlpool));
601 }
602}