1use crate::core::events::*;
20use crate::instr::inner_common::*;
21use solana_sdk::pubkey::Pubkey;
22
23
24pub mod raydium_cpmm {
29 use super::*;
30
31 pub mod discriminators {
32 pub const SWAP_BASE_IN: [u8; 16] = [143, 190, 90, 218, 196, 30, 51, 222, 155, 167, 108, 32, 122, 76, 173, 64];
33 pub const SWAP_BASE_OUT: [u8; 16] = [55, 217, 98, 86, 163, 74, 180, 173, 155, 167, 108, 32, 122, 76, 173, 64];
34 pub const CREATE_POOL: [u8; 16] = [233, 146, 209, 142, 207, 104, 64, 188, 155, 167, 108, 32, 122, 76, 173, 64];
35 pub const DEPOSIT: [u8; 16] = [242, 35, 198, 137, 82, 225, 242, 182, 155, 167, 108, 32, 122, 76, 173, 64];
36 pub const WITHDRAW: [u8; 16] = [183, 18, 70, 156, 148, 109, 161, 34, 155, 167, 108, 32, 122, 76, 173, 64];
37 }
38
39 #[inline]
41 pub fn parse(disc: &[u8; 16], data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
42 match disc {
43 &discriminators::SWAP_BASE_IN | &discriminators::SWAP_BASE_OUT => parse_swap(data, metadata),
44 &discriminators::DEPOSIT => parse_deposit(data, metadata),
45 &discriminators::WITHDRAW => parse_withdraw(data, metadata),
46 _ => None,
47 }
48 }
49
50 #[inline(always)]
56 fn parse_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
57 #[cfg(feature = "parse-borsh")]
58 {
59 parse_swap_borsh(data, metadata)
60 }
61
62 #[cfg(feature = "parse-zero-copy")]
63 {
64 parse_swap_zero_copy(data, metadata)
65 }
66 }
67
68 #[cfg(feature = "parse-borsh")]
70 #[inline(always)]
71 fn parse_swap_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
72 const EVENT_SIZE: usize = 32 + 8 + 8;
78
79 if data.len() < EVENT_SIZE {
80 return None;
81 }
82
83 let event = borsh::from_slice::<RaydiumCpmmSwapEvent>(&data[..EVENT_SIZE]).ok()?;
84
85 Some(DexEvent::RaydiumCpmmSwap(RaydiumCpmmSwapEvent {
86 metadata,
87 ..event
88 }))
89 }
90
91 #[cfg(feature = "parse-zero-copy")]
93 #[inline(always)]
94 fn parse_swap_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
95 unsafe {
96 if !check_length(data, 32 + 8 + 8) {
97 return None;
98 }
99 let pool = read_pubkey_unchecked(data, 0);
100 let input_amount = read_u64_unchecked(data, 32);
101 let output_amount = read_u64_unchecked(data, 40);
102 Some(DexEvent::RaydiumCpmmSwap(RaydiumCpmmSwapEvent {
103 metadata,
104 pool_id: pool,
105 input_amount,
106 output_amount,
107 input_vault_before: 0,
108 output_vault_before: 0,
109 input_transfer_fee: 0,
110 output_transfer_fee: 0,
111 base_input: true,
112 }))
113 }
114 }
115
116 #[inline(always)]
122 fn parse_deposit(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
123 #[cfg(feature = "parse-borsh")]
124 {
125 parse_deposit_borsh(data, metadata)
126 }
127
128 #[cfg(feature = "parse-zero-copy")]
129 {
130 parse_deposit_zero_copy(data, metadata)
131 }
132 }
133
134 #[cfg(feature = "parse-borsh")]
136 #[inline(always)]
137 fn parse_deposit_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
138 const EVENT_SIZE: usize = 32 + 8 + 8 + 8;
145
146 if data.len() < EVENT_SIZE {
147 return None;
148 }
149
150 let event = borsh::from_slice::<RaydiumCpmmDepositEvent>(&data[..EVENT_SIZE]).ok()?;
151
152 Some(DexEvent::RaydiumCpmmDeposit(RaydiumCpmmDepositEvent {
153 metadata,
154 ..event
155 }))
156 }
157
158 #[cfg(feature = "parse-zero-copy")]
160 #[inline(always)]
161 fn parse_deposit_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
162 unsafe {
163 if !check_length(data, 32 + 8 + 8 + 8) {
164 return None;
165 }
166 let pool = read_pubkey_unchecked(data, 0);
167 let token0_amount = read_u64_unchecked(data, 32);
168 let token1_amount = read_u64_unchecked(data, 40);
169 let lp_token_amount = read_u64_unchecked(data, 48);
170 Some(DexEvent::RaydiumCpmmDeposit(RaydiumCpmmDepositEvent {
171 metadata,
172 pool,
173 lp_token_amount,
174 token0_amount,
175 token1_amount,
176 user: Pubkey::default(),
177 }))
178 }
179 }
180
181 #[inline(always)]
187 fn parse_withdraw(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
188 #[cfg(feature = "parse-borsh")]
189 {
190 parse_withdraw_borsh(data, metadata)
191 }
192
193 #[cfg(feature = "parse-zero-copy")]
194 {
195 parse_withdraw_zero_copy(data, metadata)
196 }
197 }
198
199 #[cfg(feature = "parse-borsh")]
201 #[inline(always)]
202 fn parse_withdraw_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
203 const EVENT_SIZE: usize = 32 + 8 + 8 + 8;
210
211 if data.len() < EVENT_SIZE {
212 return None;
213 }
214
215 let event = borsh::from_slice::<RaydiumCpmmWithdrawEvent>(&data[..EVENT_SIZE]).ok()?;
216
217 Some(DexEvent::RaydiumCpmmWithdraw(RaydiumCpmmWithdrawEvent {
218 metadata,
219 ..event
220 }))
221 }
222
223 #[cfg(feature = "parse-zero-copy")]
225 #[inline(always)]
226 fn parse_withdraw_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
227 unsafe {
228 if !check_length(data, 32 + 8 + 8 + 8) {
229 return None;
230 }
231 let pool = read_pubkey_unchecked(data, 0);
232 let lp_token_amount = read_u64_unchecked(data, 32);
233 let token0_amount = read_u64_unchecked(data, 40);
234 let token1_amount = read_u64_unchecked(data, 48);
235 Some(DexEvent::RaydiumCpmmWithdraw(RaydiumCpmmWithdrawEvent {
236 metadata,
237 pool,
238 lp_token_amount,
239 token0_amount,
240 token1_amount,
241 user: Pubkey::default(),
242 }))
243 }
244 }
245}
246
247pub mod raydium_amm {
252 use super::*;
253
254 pub mod discriminators {
255 pub const SWAP_BASE_IN: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 9, 155, 167, 108, 32, 122, 76, 173, 64];
256 pub const SWAP_BASE_OUT: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 11, 155, 167, 108, 32, 122, 76, 173, 64];
257 pub const DEPOSIT: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 3, 155, 167, 108, 32, 122, 76, 173, 64];
258 pub const WITHDRAW: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 4, 155, 167, 108, 32, 122, 76, 173, 64];
259 pub const INITIALIZE2: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 1, 155, 167, 108, 32, 122, 76, 173, 64];
260 }
261
262 #[inline]
264 pub fn parse(disc: &[u8; 16], data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
265 match disc {
266 &discriminators::SWAP_BASE_IN | &discriminators::SWAP_BASE_OUT => parse_swap(data, metadata),
267 &discriminators::DEPOSIT => parse_deposit(data, metadata),
268 &discriminators::WITHDRAW => parse_withdraw(data, metadata),
269 _ => None,
270 }
271 }
272
273 #[inline(always)]
279 fn parse_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
280 #[cfg(feature = "parse-borsh")]
281 {
282 parse_swap_borsh(data, metadata)
283 }
284
285 #[cfg(feature = "parse-zero-copy")]
286 {
287 parse_swap_zero_copy(data, metadata)
288 }
289 }
290
291 #[cfg(feature = "parse-borsh")]
293 #[inline(always)]
294 fn parse_swap_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
295 const EVENT_SIZE: usize = 32 + 8 + 8;
301
302 if data.len() < EVENT_SIZE {
303 return None;
304 }
305
306 let event = borsh::from_slice::<RaydiumAmmV4SwapEvent>(&data[..EVENT_SIZE]).ok()?;
307
308 Some(DexEvent::RaydiumAmmV4Swap(RaydiumAmmV4SwapEvent {
309 metadata,
310 ..event
311 }))
312 }
313
314 #[cfg(feature = "parse-zero-copy")]
316 #[inline(always)]
317 fn parse_swap_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
318 unsafe {
319 if !check_length(data, 32 + 8 + 8) {
320 return None;
321 }
322 let amm = read_pubkey_unchecked(data, 0);
323 let amount_in = read_u64_unchecked(data, 32);
324 let amount_out = read_u64_unchecked(data, 40);
325 Some(DexEvent::RaydiumAmmV4Swap(RaydiumAmmV4SwapEvent {
326 metadata,
327 amm,
328 amount_in,
329 amount_out,
330 minimum_amount_out: 0,
331 max_amount_in: 0,
332 token_program: Pubkey::default(),
333 amm_authority: Pubkey::default(),
334 amm_open_orders: Pubkey::default(),
335 amm_target_orders: None,
336 pool_coin_token_account: Pubkey::default(),
337 pool_pc_token_account: Pubkey::default(),
338 serum_program: Pubkey::default(),
339 serum_market: Pubkey::default(),
340 serum_bids: Pubkey::default(),
341 serum_asks: Pubkey::default(),
342 serum_event_queue: Pubkey::default(),
343 serum_coin_vault_account: Pubkey::default(),
344 serum_pc_vault_account: Pubkey::default(),
345 serum_vault_signer: Pubkey::default(),
346 user_source_token_account: Pubkey::default(),
347 user_destination_token_account: Pubkey::default(),
348 user_source_owner: Pubkey::default(),
349 }))
350 }
351 }
352
353 #[inline(always)]
359 fn parse_deposit(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
360 #[cfg(feature = "parse-borsh")]
361 {
362 parse_deposit_borsh(data, metadata)
363 }
364
365 #[cfg(feature = "parse-zero-copy")]
366 {
367 parse_deposit_zero_copy(data, metadata)
368 }
369 }
370
371 #[cfg(feature = "parse-borsh")]
373 #[inline(always)]
374 fn parse_deposit_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
375 const EVENT_SIZE: usize = 32 + 8 + 8;
381
382 if data.len() < EVENT_SIZE {
383 return None;
384 }
385
386 let event = borsh::from_slice::<RaydiumAmmV4DepositEvent>(&data[..EVENT_SIZE]).ok()?;
387
388 Some(DexEvent::RaydiumAmmV4Deposit(RaydiumAmmV4DepositEvent {
389 metadata,
390 ..event
391 }))
392 }
393
394 #[cfg(feature = "parse-zero-copy")]
396 #[inline(always)]
397 fn parse_deposit_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
398 unsafe {
399 if !check_length(data, 32 + 8 + 8) {
400 return None;
401 }
402 let amm = read_pubkey_unchecked(data, 0);
403 let max_coin_amount = read_u64_unchecked(data, 32);
404 let max_pc_amount = read_u64_unchecked(data, 40);
405 Some(DexEvent::RaydiumAmmV4Deposit(RaydiumAmmV4DepositEvent {
406 metadata,
407 amm,
408 max_coin_amount,
409 max_pc_amount,
410 base_side: 0,
411 token_program: Pubkey::default(),
412 amm_authority: Pubkey::default(),
413 amm_open_orders: Pubkey::default(),
414 amm_target_orders: Pubkey::default(),
415 lp_mint_address: Pubkey::default(),
416 pool_coin_token_account: Pubkey::default(),
417 pool_pc_token_account: Pubkey::default(),
418 serum_market: Pubkey::default(),
419 serum_event_queue: Pubkey::default(),
420 user_coin_token_account: Pubkey::default(),
421 user_pc_token_account: Pubkey::default(),
422 user_lp_token_account: Pubkey::default(),
423 user_owner: Pubkey::default(),
424 }))
425 }
426 }
427
428 #[inline(always)]
434 fn parse_withdraw(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
435 #[cfg(feature = "parse-borsh")]
436 {
437 parse_withdraw_borsh(data, metadata)
438 }
439
440 #[cfg(feature = "parse-zero-copy")]
441 {
442 parse_withdraw_zero_copy(data, metadata)
443 }
444 }
445
446 #[cfg(feature = "parse-borsh")]
448 #[inline(always)]
449 fn parse_withdraw_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
450 const EVENT_SIZE: usize = 32 + 8;
455
456 if data.len() < EVENT_SIZE {
457 return None;
458 }
459
460 let event = borsh::from_slice::<RaydiumAmmV4WithdrawEvent>(&data[..EVENT_SIZE]).ok()?;
461
462 Some(DexEvent::RaydiumAmmV4Withdraw(RaydiumAmmV4WithdrawEvent {
463 metadata,
464 ..event
465 }))
466 }
467
468 #[cfg(feature = "parse-zero-copy")]
470 #[inline(always)]
471 fn parse_withdraw_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
472 unsafe {
473 if !check_length(data, 32 + 8) {
474 return None;
475 }
476 let amm = read_pubkey_unchecked(data, 0);
477 let amount = read_u64_unchecked(data, 32);
478 Some(DexEvent::RaydiumAmmV4Withdraw(RaydiumAmmV4WithdrawEvent {
479 metadata,
480 amm,
481 amount,
482 token_program: Pubkey::default(),
483 amm_authority: Pubkey::default(),
484 amm_open_orders: Pubkey::default(),
485 amm_target_orders: Pubkey::default(),
486 lp_mint_address: Pubkey::default(),
487 pool_coin_token_account: Pubkey::default(),
488 pool_pc_token_account: Pubkey::default(),
489 pool_withdraw_queue: Pubkey::default(),
490 pool_temp_lp_token_account: Pubkey::default(),
491 serum_program: Pubkey::default(),
492 serum_market: Pubkey::default(),
493 serum_bids: Pubkey::default(),
494 serum_asks: Pubkey::default(),
495 serum_event_queue: Pubkey::default(),
496 serum_coin_vault_account: Pubkey::default(),
497 serum_pc_vault_account: Pubkey::default(),
498 serum_vault_signer: Pubkey::default(),
499 user_lp_token_account: Pubkey::default(),
500 user_coin_token_account: Pubkey::default(),
501 user_pc_token_account: Pubkey::default(),
502 user_owner: Pubkey::default(),
503 }))
504 }
505 }
506}
507
508pub mod orca {
513 use super::*;
528
529 pub mod discriminators {
530 pub const TRADED: [u8; 16] = [225, 202, 73, 175, 147, 43, 160, 150, 155, 167, 108, 32, 122, 76, 173, 64];
531 pub const LIQUIDITY_INCREASED: [u8; 16] = [30, 7, 144, 181, 102, 254, 155, 161, 155, 167, 108, 32, 122, 76, 173, 64];
532 pub const LIQUIDITY_DECREASED: [u8; 16] = [166, 1, 36, 71, 112, 202, 181, 171, 155, 167, 108, 32, 122, 76, 173, 64];
533 pub const POOL_INITIALIZED: [u8; 16] = [100, 118, 173, 87, 12, 198, 254, 229, 155, 167, 108, 32, 122, 76, 173, 64];
534 }
535
536 #[inline]
538 pub fn parse(disc: &[u8; 16], data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
539 match disc {
540 &discriminators::TRADED => parse_swap(data, metadata),
541 &discriminators::LIQUIDITY_INCREASED => parse_liquidity_increased(data, metadata),
542 &discriminators::LIQUIDITY_DECREASED => parse_liquidity_decreased(data, metadata),
543 _ => None,
544 }
545 }
546
547 #[inline(always)]
553 fn parse_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
554 #[cfg(feature = "parse-borsh")]
555 { parse_swap_borsh(data, metadata) }
556
557 #[cfg(feature = "parse-zero-copy")]
558 { parse_swap_zero_copy(data, metadata) }
559 }
560
561 #[cfg(feature = "parse-borsh")]
563 #[inline(always)]
564 fn parse_swap_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
565 const SWAP_EVENT_SIZE: usize = 32 + 8 + 8 + 1;
567 if data.len() < SWAP_EVENT_SIZE { return None; }
568
569 let mut event = borsh::from_slice::<OrcaWhirlpoolSwapEvent>(&data[..SWAP_EVENT_SIZE]).ok()?;
570 event.metadata = metadata;
571 Some(DexEvent::OrcaWhirlpoolSwap(event))
572 }
573
574 #[cfg(feature = "parse-zero-copy")]
576 #[inline(always)]
577 fn parse_swap_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
578 unsafe {
579 if !check_length(data, 32 + 8 + 8 + 1) { return None; }
580 let whirlpool = read_pubkey_unchecked(data, 0);
581 let input_amount = read_u64_unchecked(data, 32);
582 let output_amount = read_u64_unchecked(data, 40);
583 let a_to_b = read_bool_unchecked(data, 48);
584 Some(DexEvent::OrcaWhirlpoolSwap(OrcaWhirlpoolSwapEvent {
585 metadata, whirlpool, input_amount, output_amount, a_to_b,
586 pre_sqrt_price: 0, post_sqrt_price: 0,
587 input_transfer_fee: 0, output_transfer_fee: 0,
588 lp_fee: 0, protocol_fee: 0,
589 }))
590 }
591 }
592
593 #[inline(always)]
599 fn parse_liquidity_increased(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
600 #[cfg(feature = "parse-borsh")]
601 { parse_liquidity_increased_borsh(data, metadata) }
602
603 #[cfg(feature = "parse-zero-copy")]
604 { parse_liquidity_increased_zero_copy(data, metadata) }
605 }
606
607 #[cfg(feature = "parse-borsh")]
609 #[inline(always)]
610 fn parse_liquidity_increased_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
611 const LIQUIDITY_EVENT_SIZE: usize = 32 + 16 + 8 + 8;
613 if data.len() < LIQUIDITY_EVENT_SIZE { return None; }
614
615 let mut event = borsh::from_slice::<OrcaWhirlpoolLiquidityIncreasedEvent>(&data[..LIQUIDITY_EVENT_SIZE]).ok()?;
616 event.metadata = metadata;
617 Some(DexEvent::OrcaWhirlpoolLiquidityIncreased(event))
618 }
619
620 #[cfg(feature = "parse-zero-copy")]
622 #[inline(always)]
623 fn parse_liquidity_increased_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
624 unsafe {
625 if !check_length(data, 32 + 16 + 8 + 8) { return None; }
626 let whirlpool = read_pubkey_unchecked(data, 0);
627 let liquidity = read_u128_unchecked(data, 32);
628 let token_a_amount = read_u64_unchecked(data, 48);
629 let token_b_amount = read_u64_unchecked(data, 56);
630 Some(DexEvent::OrcaWhirlpoolLiquidityIncreased(OrcaWhirlpoolLiquidityIncreasedEvent {
631 metadata, whirlpool, liquidity, token_a_amount, token_b_amount,
632 position: Pubkey::default(), tick_lower_index: 0, tick_upper_index: 0,
633 token_a_transfer_fee: 0, token_b_transfer_fee: 0,
634 }))
635 }
636 }
637
638 #[inline(always)]
644 fn parse_liquidity_decreased(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
645 #[cfg(feature = "parse-borsh")]
646 { parse_liquidity_decreased_borsh(data, metadata) }
647
648 #[cfg(feature = "parse-zero-copy")]
649 { parse_liquidity_decreased_zero_copy(data, metadata) }
650 }
651
652 #[cfg(feature = "parse-borsh")]
654 #[inline(always)]
655 fn parse_liquidity_decreased_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
656 const LIQUIDITY_EVENT_SIZE: usize = 32 + 16 + 8 + 8;
658 if data.len() < LIQUIDITY_EVENT_SIZE { return None; }
659
660 let mut event = borsh::from_slice::<OrcaWhirlpoolLiquidityDecreasedEvent>(&data[..LIQUIDITY_EVENT_SIZE]).ok()?;
661 event.metadata = metadata;
662 Some(DexEvent::OrcaWhirlpoolLiquidityDecreased(event))
663 }
664
665 #[cfg(feature = "parse-zero-copy")]
667 #[inline(always)]
668 fn parse_liquidity_decreased_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
669 unsafe {
670 if !check_length(data, 32 + 16 + 8 + 8) { return None; }
671 let whirlpool = read_pubkey_unchecked(data, 0);
672 let liquidity = read_u128_unchecked(data, 32);
673 let token_a_amount = read_u64_unchecked(data, 48);
674 let token_b_amount = read_u64_unchecked(data, 56);
675 Some(DexEvent::OrcaWhirlpoolLiquidityDecreased(OrcaWhirlpoolLiquidityDecreasedEvent {
676 metadata, whirlpool, liquidity, token_a_amount, token_b_amount,
677 position: Pubkey::default(), tick_lower_index: 0, tick_upper_index: 0,
678 token_a_transfer_fee: 0, token_b_transfer_fee: 0,
679 }))
680 }
681 }
682}
683
684pub mod meteora_amm {
689 use super::*;
690
691 pub mod discriminators {
692 pub const SWAP: [u8; 16] = [81, 108, 227, 190, 205, 208, 10, 196, 155, 167, 108, 32, 122, 76, 173, 64];
693 pub const ADD_LIQUIDITY: [u8; 16] = [31, 94, 125, 90, 227, 52, 61, 186, 155, 167, 108, 32, 122, 76, 173, 64];
694 pub const REMOVE_LIQUIDITY: [u8; 16] = [116, 244, 97, 232, 103, 31, 152, 58, 155, 167, 108, 32, 122, 76, 173, 64];
695 pub const POOL_CREATED: [u8; 16] = [202, 44, 41, 88, 104, 220, 157, 82, 155, 167, 108, 32, 122, 76, 173, 64];
696 }
697
698 #[inline]
699 pub fn parse(disc: &[u8; 16], data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
700 unsafe {
701 match disc {
702 &discriminators::SWAP => {
703 if !check_length(data, 8 + 8) { return None; }
704 let in_amount = read_u64_unchecked(data, 0);
705 let out_amount = read_u64_unchecked(data, 8);
706 Some(DexEvent::MeteoraPoolsSwap(MeteoraPoolsSwapEvent {
707 metadata, in_amount, out_amount, trade_fee: 0, admin_fee: 0, host_fee: 0,
708 }))
709 }
710 &discriminators::ADD_LIQUIDITY => {
711 if !check_length(data, 8 + 8 + 8) { return None; }
712 let lp_mint_amount = read_u64_unchecked(data, 0);
713 let token_a_amount = read_u64_unchecked(data, 8);
714 let token_b_amount = read_u64_unchecked(data, 16);
715 Some(DexEvent::MeteoraPoolsAddLiquidity(MeteoraPoolsAddLiquidityEvent {
716 metadata, lp_mint_amount, token_a_amount, token_b_amount,
717 }))
718 }
719 &discriminators::REMOVE_LIQUIDITY => {
720 if !check_length(data, 8 + 8 + 8) { return None; }
721 let lp_unmint_amount = read_u64_unchecked(data, 0);
722 let token_a_out_amount = read_u64_unchecked(data, 8);
723 let token_b_out_amount = read_u64_unchecked(data, 16);
724 Some(DexEvent::MeteoraPoolsRemoveLiquidity(MeteoraPoolsRemoveLiquidityEvent {
725 metadata, lp_unmint_amount, token_a_out_amount, token_b_out_amount,
726 }))
727 }
728 _ => None,
729 }
730 }
731 }
732}
733
734pub mod meteora_damm {
739 use super::*;
754
755 pub mod discriminators {
756 pub const SWAP: [u8; 16] = [228, 69, 165, 46, 81, 203, 154, 29, 27, 60, 21, 213, 138, 170, 187, 147];
757 pub const SWAP2: [u8; 16] = [228, 69, 165, 46, 81, 203, 154, 29, 189, 66, 51, 168, 38, 80, 117, 153];
758 pub const ADD_LIQUIDITY: [u8; 16] = [228, 69, 165, 46, 81, 203, 154, 29, 175, 242, 8, 157, 30, 247, 185, 169];
759 pub const REMOVE_LIQUIDITY: [u8; 16] = [228, 69, 165, 46, 81, 203, 154, 29, 87, 46, 88, 98, 175, 96, 34, 91];
760 pub const CREATE_POSITION: [u8; 16] = [228, 69, 165, 46, 81, 203, 154, 29, 156, 15, 119, 198, 29, 181, 221, 55];
761 pub const CLOSE_POSITION: [u8; 16] = [228, 69, 165, 46, 81, 203, 154, 29, 20, 145, 144, 68, 143, 142, 214, 178];
762 }
763
764 #[inline]
766 pub fn parse(disc: &[u8; 16], data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
767 match disc {
768 &discriminators::SWAP => parse_swap(data, metadata),
769 &discriminators::SWAP2 => parse_swap2(data, metadata),
770 &discriminators::ADD_LIQUIDITY => parse_add_liquidity(data, metadata),
771 &discriminators::REMOVE_LIQUIDITY => parse_remove_liquidity(data, metadata),
772 &discriminators::CREATE_POSITION => parse_create_position(data, metadata),
773 &discriminators::CLOSE_POSITION => parse_close_position(data, metadata),
774 _ => None,
775 }
776 }
777
778 #[inline(always)]
784 fn parse_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
785 #[cfg(feature = "parse-borsh")]
786 { parse_swap_borsh(data, metadata) }
787
788 #[cfg(feature = "parse-zero-copy")]
789 { parse_swap_zero_copy(data, metadata) }
790 }
791
792 #[cfg(feature = "parse-borsh")]
794 #[inline(always)]
795 fn parse_swap_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
796 const SWAP_EVENT_SIZE: usize = 32 + 8 + 8;
798 if data.len() < SWAP_EVENT_SIZE { return None; }
799
800 let event = borsh::from_slice::<MeteoraDammV2SwapEvent>(&data[..SWAP_EVENT_SIZE]).ok()?;
801 Some(DexEvent::MeteoraDammV2Swap(MeteoraDammV2SwapEvent { metadata, ..event }))
802 }
803
804 #[cfg(feature = "parse-zero-copy")]
806 #[inline(always)]
807 fn parse_swap_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
808 unsafe {
809 if !check_length(data, 32 + 8 + 8) { return None; }
810 let pool = read_pubkey_unchecked(data, 0);
811 let amount_in = read_u64_unchecked(data, 32);
812 let output_amount = read_u64_unchecked(data, 40);
813 Some(DexEvent::MeteoraDammV2Swap(MeteoraDammV2SwapEvent {
814 metadata, pool, amount_in, output_amount, ..Default::default()
815 }))
816 }
817 }
818
819 #[inline(always)]
825 fn parse_swap2(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
826 #[cfg(feature = "parse-borsh")]
827 { parse_swap2_borsh(data, metadata) }
828
829 #[cfg(feature = "parse-zero-copy")]
830 { parse_swap2_zero_copy(data, metadata) }
831 }
832
833 #[cfg(feature = "parse-borsh")]
835 #[inline(always)]
836 fn parse_swap2_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
837 const SWAP2_EVENT_MIN_SIZE: usize = 177;
846 if data.len() < SWAP2_EVENT_MIN_SIZE { return None; }
847
848 let mut offset = 0;
849
850 unsafe {
852 let pool = read_pubkey_unchecked(data, offset);
853 offset += 32;
854
855 let _config = read_pubkey_unchecked(data, offset);
856 offset += 32;
857
858 let trade_direction = read_u8_unchecked(data, offset);
859 offset += 1;
860
861 let has_referral = read_bool_unchecked(data, offset);
862 offset += 1;
863
864 let amount_0 = read_u64_unchecked(data, offset);
865 offset += 8;
866
867 let amount_1 = read_u64_unchecked(data, offset);
868 offset += 8;
869
870 let swap_mode = read_u8_unchecked(data, offset);
871 offset += 1;
872
873 let included_fee_input_amount = read_u64_unchecked(data, offset);
874 offset += 8;
875
876 let _excluded_fee_input_amount = read_u64_unchecked(data, offset);
877 offset += 8;
878
879 let _amount_left = read_u64_unchecked(data, offset);
880 offset += 8;
881
882 let output_amount = read_u64_unchecked(data, offset);
883 offset += 8;
884
885 let next_sqrt_price = read_u128_unchecked(data, offset);
886 offset += 16;
887
888 let lp_fee = read_u64_unchecked(data, offset);
889 offset += 8;
890
891 let protocol_fee = read_u64_unchecked(data, offset);
892 offset += 8;
893
894 let referral_fee = read_u64_unchecked(data, offset);
895 offset += 8;
896
897 let _quote_reserve_amount = read_u64_unchecked(data, offset);
898 offset += 8;
899
900 let _migration_threshold = read_u64_unchecked(data, offset);
901 offset += 8;
902
903 let current_timestamp = read_u64_unchecked(data, offset);
904
905 let (amount_in, minimum_amount_out) = if swap_mode == 0 {
907 (amount_0, amount_1)
908 } else {
909 (amount_1, amount_0)
910 };
911
912 Some(DexEvent::MeteoraDammV2Swap(MeteoraDammV2SwapEvent {
913 metadata,
914 pool,
915 trade_direction,
916 has_referral,
917 amount_in,
918 minimum_amount_out,
919 output_amount,
920 next_sqrt_price,
921 lp_fee,
922 protocol_fee,
923 partner_fee: 0,
924 referral_fee,
925 actual_amount_in: included_fee_input_amount,
926 current_timestamp,
927 ..Default::default()
928 }))
929 }
930 }
931
932 #[cfg(feature = "parse-zero-copy")]
934 #[inline(always)]
935 fn parse_swap2_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
936 const SWAP2_EVENT_MIN_SIZE: usize = 177;
944
945 unsafe {
946 if !check_length(data, SWAP2_EVENT_MIN_SIZE) { return None; }
947
948 let pool = read_pubkey_unchecked(data, 0);
949 let trade_direction = read_u8_unchecked(data, 64);
950 let has_referral = read_bool_unchecked(data, 65);
951 let amount_0 = read_u64_unchecked(data, 66);
952 let amount_1 = read_u64_unchecked(data, 74);
953 let swap_mode = read_u8_unchecked(data, 82);
954 let included_fee_input_amount = read_u64_unchecked(data, 83);
955 let output_amount = read_u64_unchecked(data, 107);
956 let next_sqrt_price = read_u128_unchecked(data, 115);
957 let lp_fee = read_u64_unchecked(data, 131);
958 let protocol_fee = read_u64_unchecked(data, 139);
959 let referral_fee = read_u64_unchecked(data, 147);
960 let current_timestamp = read_u64_unchecked(data, 169);
961
962 let (amount_in, minimum_amount_out) = if swap_mode == 0 {
964 (amount_0, amount_1)
965 } else {
966 (amount_1, amount_0)
967 };
968
969 Some(DexEvent::MeteoraDammV2Swap(MeteoraDammV2SwapEvent {
970 metadata,
971 pool,
972 trade_direction,
973 has_referral,
974 amount_in,
975 minimum_amount_out,
976 output_amount,
977 next_sqrt_price,
978 lp_fee,
979 protocol_fee,
980 partner_fee: 0,
981 referral_fee,
982 actual_amount_in: included_fee_input_amount,
983 current_timestamp,
984 ..Default::default()
985 }))
986 }
987 }
988
989 #[inline(always)]
995 fn parse_add_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
996 #[cfg(feature = "parse-borsh")]
997 { parse_add_liquidity_borsh(data, metadata) }
998
999 #[cfg(feature = "parse-zero-copy")]
1000 { parse_add_liquidity_zero_copy(data, metadata) }
1001 }
1002
1003 #[cfg(feature = "parse-borsh")]
1005 #[inline(always)]
1006 fn parse_add_liquidity_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1007 const ADD_LIQUIDITY_EVENT_SIZE: usize = 32 + 32 + 32 + 8 + 8;
1009 if data.len() < ADD_LIQUIDITY_EVENT_SIZE { return None; }
1010
1011 let event = borsh::from_slice::<MeteoraDammV2AddLiquidityEvent>(&data[..ADD_LIQUIDITY_EVENT_SIZE]).ok()?;
1012 Some(DexEvent::MeteoraDammV2AddLiquidity(MeteoraDammV2AddLiquidityEvent { metadata, ..event }))
1013 }
1014
1015 #[cfg(feature = "parse-zero-copy")]
1017 #[inline(always)]
1018 fn parse_add_liquidity_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1019 unsafe {
1020 if !check_length(data, 32 + 32 + 32 + 8 + 8) { return None; }
1021 let pool = read_pubkey_unchecked(data, 0);
1022 let position = read_pubkey_unchecked(data, 32);
1023 let owner = read_pubkey_unchecked(data, 64);
1024 let token_a_amount = read_u64_unchecked(data, 96);
1025 let token_b_amount = read_u64_unchecked(data, 104);
1026 Some(DexEvent::MeteoraDammV2AddLiquidity(MeteoraDammV2AddLiquidityEvent {
1027 metadata, pool, position, owner, token_a_amount, token_b_amount,
1028 liquidity_delta: 0, token_a_amount_threshold: 0, token_b_amount_threshold: 0,
1029 total_amount_a: 0, total_amount_b: 0,
1030 }))
1031 }
1032 }
1033
1034 #[inline(always)]
1040 fn parse_remove_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1041 #[cfg(feature = "parse-borsh")]
1042 { parse_remove_liquidity_borsh(data, metadata) }
1043
1044 #[cfg(feature = "parse-zero-copy")]
1045 { parse_remove_liquidity_zero_copy(data, metadata) }
1046 }
1047
1048 #[cfg(feature = "parse-borsh")]
1050 #[inline(always)]
1051 fn parse_remove_liquidity_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1052 const REMOVE_LIQUIDITY_EVENT_SIZE: usize = 32 + 32 + 32 + 8 + 8;
1054 if data.len() < REMOVE_LIQUIDITY_EVENT_SIZE { return None; }
1055
1056 let event = borsh::from_slice::<MeteoraDammV2RemoveLiquidityEvent>(&data[..REMOVE_LIQUIDITY_EVENT_SIZE]).ok()?;
1057 Some(DexEvent::MeteoraDammV2RemoveLiquidity(MeteoraDammV2RemoveLiquidityEvent { metadata, ..event }))
1058 }
1059
1060 #[cfg(feature = "parse-zero-copy")]
1062 #[inline(always)]
1063 fn parse_remove_liquidity_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1064 unsafe {
1065 if !check_length(data, 32 + 32 + 32 + 8 + 8) { return None; }
1066 let pool = read_pubkey_unchecked(data, 0);
1067 let position = read_pubkey_unchecked(data, 32);
1068 let owner = read_pubkey_unchecked(data, 64);
1069 let token_a_amount = read_u64_unchecked(data, 96);
1070 let token_b_amount = read_u64_unchecked(data, 104);
1071 Some(DexEvent::MeteoraDammV2RemoveLiquidity(MeteoraDammV2RemoveLiquidityEvent {
1072 metadata, pool, position, owner, token_a_amount, token_b_amount,
1073 liquidity_delta: 0, token_a_amount_threshold: 0, token_b_amount_threshold: 0,
1074 }))
1075 }
1076 }
1077
1078 #[inline(always)]
1084 fn parse_create_position(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1085 #[cfg(feature = "parse-borsh")]
1086 { parse_create_position_borsh(data, metadata) }
1087
1088 #[cfg(feature = "parse-zero-copy")]
1089 { parse_create_position_zero_copy(data, metadata) }
1090 }
1091
1092 #[cfg(feature = "parse-borsh")]
1094 #[inline(always)]
1095 fn parse_create_position_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1096 const CREATE_POSITION_EVENT_SIZE: usize = 32 + 32 + 32 + 32;
1098 if data.len() < CREATE_POSITION_EVENT_SIZE { return None; }
1099
1100 let event = borsh::from_slice::<MeteoraDammV2CreatePositionEvent>(&data[..CREATE_POSITION_EVENT_SIZE]).ok()?;
1101 Some(DexEvent::MeteoraDammV2CreatePosition(MeteoraDammV2CreatePositionEvent { metadata, ..event }))
1102 }
1103
1104 #[cfg(feature = "parse-zero-copy")]
1106 #[inline(always)]
1107 fn parse_create_position_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1108 unsafe {
1109 if !check_length(data, 32 + 32 + 32 + 32) { return None; }
1110 let pool = read_pubkey_unchecked(data, 0);
1111 let owner = read_pubkey_unchecked(data, 32);
1112 let position = read_pubkey_unchecked(data, 64);
1113 let position_nft_mint = read_pubkey_unchecked(data, 96);
1114 Some(DexEvent::MeteoraDammV2CreatePosition(MeteoraDammV2CreatePositionEvent {
1115 metadata, pool, owner, position, position_nft_mint,
1116 }))
1117 }
1118 }
1119
1120 #[inline(always)]
1126 fn parse_close_position(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1127 #[cfg(feature = "parse-borsh")]
1128 { parse_close_position_borsh(data, metadata) }
1129
1130 #[cfg(feature = "parse-zero-copy")]
1131 { parse_close_position_zero_copy(data, metadata) }
1132 }
1133
1134 #[cfg(feature = "parse-borsh")]
1136 #[inline(always)]
1137 fn parse_close_position_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1138 const CLOSE_POSITION_EVENT_SIZE: usize = 32 + 32 + 32 + 32;
1140 if data.len() < CLOSE_POSITION_EVENT_SIZE { return None; }
1141
1142 let event = borsh::from_slice::<MeteoraDammV2ClosePositionEvent>(&data[..CLOSE_POSITION_EVENT_SIZE]).ok()?;
1143 Some(DexEvent::MeteoraDammV2ClosePosition(MeteoraDammV2ClosePositionEvent { metadata, ..event }))
1144 }
1145
1146 #[cfg(feature = "parse-zero-copy")]
1148 #[inline(always)]
1149 fn parse_close_position_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1150 unsafe {
1151 if !check_length(data, 32 + 32 + 32 + 32) { return None; }
1152 let pool = read_pubkey_unchecked(data, 0);
1153 let owner = read_pubkey_unchecked(data, 32);
1154 let position = read_pubkey_unchecked(data, 64);
1155 let position_nft_mint = read_pubkey_unchecked(data, 96);
1156 Some(DexEvent::MeteoraDammV2ClosePosition(MeteoraDammV2ClosePositionEvent {
1157 metadata, pool, owner, position, position_nft_mint,
1158 }))
1159 }
1160 }
1161}
1162
1163pub mod bonk {
1168 use super::*;
1183
1184 pub mod discriminators {
1185 pub const POOL_CREATE: [u8; 16] = [100, 50, 200, 150, 75, 120, 90, 30, 155, 167, 108, 32, 122, 76, 173, 64];
1186 pub const TRADE: [u8; 16] = [80, 120, 100, 200, 150, 75, 60, 40, 155, 167, 108, 32, 122, 76, 173, 64];
1187 pub const MIGRATE: [u8; 16] = [90, 130, 110, 210, 160, 85, 70, 50, 155, 167, 108, 32, 122, 76, 173, 64];
1188 }
1189
1190 #[inline]
1192 pub fn parse(disc: &[u8; 16], data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1193 match disc {
1194 &discriminators::TRADE => parse_trade(data, metadata),
1195 _ => None,
1196 }
1197 }
1198
1199 #[inline(always)]
1205 fn parse_trade(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1206 #[cfg(feature = "parse-borsh")]
1207 { parse_trade_borsh(data, metadata) }
1208
1209 #[cfg(feature = "parse-zero-copy")]
1210 { parse_trade_zero_copy(data, metadata) }
1211 }
1212
1213 #[cfg(feature = "parse-borsh")]
1215 #[inline(always)]
1216 fn parse_trade_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1217 const TRADE_EVENT_SIZE: usize = 32 + 32 + 8 + 8 + 1;
1219 if data.len() < TRADE_EVENT_SIZE { return None; }
1220
1221 let mut event = borsh::from_slice::<BonkTradeEvent>(&data[..TRADE_EVENT_SIZE]).ok()?;
1222 event.metadata = metadata;
1223 event.trade_direction = if event.is_buy { TradeDirection::Buy } else { TradeDirection::Sell };
1224 event.exact_in = true;
1225 Some(DexEvent::BonkTrade(event))
1226 }
1227
1228 #[cfg(feature = "parse-zero-copy")]
1230 #[inline(always)]
1231 fn parse_trade_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1232 unsafe {
1233 if !check_length(data, 32 + 32 + 8 + 8 + 1) { return None; }
1234 let pool_state = read_pubkey_unchecked(data, 0);
1235 let user = read_pubkey_unchecked(data, 32);
1236 let amount_in = read_u64_unchecked(data, 64);
1237 let amount_out = read_u64_unchecked(data, 72);
1238 let is_buy = read_bool_unchecked(data, 80);
1239 Some(DexEvent::BonkTrade(BonkTradeEvent {
1240 metadata, pool_state, user, amount_in, amount_out, is_buy,
1241 trade_direction: if is_buy { TradeDirection::Buy } else { TradeDirection::Sell },
1242 exact_in: true,
1243 }))
1244 }
1245 }
1246}
1247
1248pub mod meteora_dlmm {
1253 use super::*;
1268
1269 pub mod discriminators {
1270 pub const SWAP: [u8; 16] = [143, 190, 90, 218, 196, 30, 51, 222, 155, 167, 108, 32, 122, 76, 173, 64];
1272 pub const ADD_LIQUIDITY: [u8; 16] = [181, 157, 89, 67, 143, 182, 52, 72, 155, 167, 108, 32, 122, 76, 173, 64];
1273 pub const REMOVE_LIQUIDITY: [u8; 16] = [80, 85, 209, 72, 24, 206, 35, 178, 155, 167, 108, 32, 122, 76, 173, 64];
1274 pub const INITIALIZE_POOL: [u8; 16] = [95, 180, 10, 172, 84, 174, 232, 40, 155, 167, 108, 32, 122, 76, 173, 64];
1275 pub const INITIALIZE_BIN_ARRAY: [u8; 16] = [11, 18, 155, 194, 33, 115, 238, 119, 155, 167, 108, 32, 122, 76, 173, 64];
1276 pub const CREATE_POSITION: [u8; 16] = [123, 233, 11, 43, 146, 180, 97, 119, 155, 167, 108, 32, 122, 76, 173, 64];
1277 pub const CLOSE_POSITION: [u8; 16] = [94, 168, 102, 45, 59, 122, 137, 54, 155, 167, 108, 32, 122, 76, 173, 64];
1278 pub const CLAIM_FEE: [u8; 16] = [152, 70, 208, 111, 104, 91, 44, 1, 155, 167, 108, 32, 122, 76, 173, 64];
1279 }
1280
1281 #[inline]
1283 pub fn parse(disc: &[u8; 16], data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1284 match disc {
1285 &discriminators::SWAP => parse_swap(data, metadata),
1286 &discriminators::ADD_LIQUIDITY => parse_add_liquidity(data, metadata),
1287 &discriminators::REMOVE_LIQUIDITY => parse_remove_liquidity(data, metadata),
1288 &discriminators::INITIALIZE_POOL => parse_initialize_pool(data, metadata),
1289 &discriminators::INITIALIZE_BIN_ARRAY => parse_initialize_bin_array(data, metadata),
1290 &discriminators::CREATE_POSITION => parse_create_position(data, metadata),
1291 &discriminators::CLOSE_POSITION => parse_close_position(data, metadata),
1292 &discriminators::CLAIM_FEE => parse_claim_fee(data, metadata),
1293 _ => None,
1294 }
1295 }
1296
1297 #[inline(always)]
1303 fn parse_swap(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1304 #[cfg(feature = "parse-borsh")]
1305 { parse_swap_borsh(data, metadata) }
1306
1307 #[cfg(feature = "parse-zero-copy")]
1308 { parse_swap_zero_copy(data, metadata) }
1309 }
1310
1311 #[cfg(feature = "parse-borsh")]
1313 #[inline(always)]
1314 fn parse_swap_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1315 const SWAP_EVENT_SIZE: usize = 32 + 32 + 4 + 4 + 8 + 8 + 1 + 8 + 8 + 16 + 8;
1317 if data.len() < SWAP_EVENT_SIZE { return None; }
1318
1319 let mut event = borsh::from_slice::<MeteoraDlmmSwapEvent>(&data[..SWAP_EVENT_SIZE]).ok()?;
1320 event.metadata = metadata;
1321 Some(DexEvent::MeteoraDlmmSwap(event))
1322 }
1323
1324 #[cfg(feature = "parse-zero-copy")]
1326 #[inline(always)]
1327 fn parse_swap_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1328 unsafe {
1329 if !check_length(data, 32 + 32 + 4 + 4 + 8 + 8 + 1 + 8 + 8 + 16 + 8) { return None; }
1330 let pool = read_pubkey_unchecked(data, 0);
1331 let from = read_pubkey_unchecked(data, 32);
1332 let start_bin_id = read_i32_unchecked(data, 64);
1333 let end_bin_id = read_i32_unchecked(data, 68);
1334 let amount_in = read_u64_unchecked(data, 72);
1335 let amount_out = read_u64_unchecked(data, 80);
1336 let swap_for_y = read_bool_unchecked(data, 88);
1337 let fee = read_u64_unchecked(data, 89);
1338 let protocol_fee = read_u64_unchecked(data, 97);
1339 let fee_bps = read_u128_unchecked(data, 105);
1340 let host_fee = read_u64_unchecked(data, 121);
1341 Some(DexEvent::MeteoraDlmmSwap(MeteoraDlmmSwapEvent {
1342 metadata, pool, from, start_bin_id, end_bin_id, amount_in, amount_out,
1343 swap_for_y, fee, protocol_fee, fee_bps, host_fee,
1344 }))
1345 }
1346 }
1347
1348 #[inline(always)]
1354 fn parse_add_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1355 #[cfg(feature = "parse-borsh")]
1356 { parse_add_liquidity_borsh(data, metadata) }
1357
1358 #[cfg(feature = "parse-zero-copy")]
1359 { parse_add_liquidity_zero_copy(data, metadata) }
1360 }
1361
1362 #[cfg(feature = "parse-borsh")]
1364 #[inline(always)]
1365 fn parse_add_liquidity_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1366 const ADD_LIQUIDITY_EVENT_SIZE: usize = 32 + 32 + 32 + 16 + 4;
1368 if data.len() < ADD_LIQUIDITY_EVENT_SIZE { return None; }
1369
1370 let mut event = borsh::from_slice::<MeteoraDlmmAddLiquidityEvent>(&data[..ADD_LIQUIDITY_EVENT_SIZE]).ok()?;
1371 event.metadata = metadata;
1372 Some(DexEvent::MeteoraDlmmAddLiquidity(event))
1373 }
1374
1375 #[cfg(feature = "parse-zero-copy")]
1377 #[inline(always)]
1378 fn parse_add_liquidity_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1379 unsafe {
1380 if !check_length(data, 32 + 32 + 32 + 16 + 4) { return None; }
1381 let pool = read_pubkey_unchecked(data, 0);
1382 let from = read_pubkey_unchecked(data, 32);
1383 let position = read_pubkey_unchecked(data, 64);
1384 let amount_0 = read_u64_unchecked(data, 96);
1385 let amount_1 = read_u64_unchecked(data, 104);
1386 let active_bin_id = read_i32_unchecked(data, 112);
1387 Some(DexEvent::MeteoraDlmmAddLiquidity(MeteoraDlmmAddLiquidityEvent {
1388 metadata, pool, from, position, amounts: [amount_0, amount_1], active_bin_id,
1389 }))
1390 }
1391 }
1392
1393 #[inline(always)]
1399 fn parse_remove_liquidity(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1400 #[cfg(feature = "parse-borsh")]
1401 { parse_remove_liquidity_borsh(data, metadata) }
1402
1403 #[cfg(feature = "parse-zero-copy")]
1404 { parse_remove_liquidity_zero_copy(data, metadata) }
1405 }
1406
1407 #[cfg(feature = "parse-borsh")]
1409 #[inline(always)]
1410 fn parse_remove_liquidity_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1411 const REMOVE_LIQUIDITY_EVENT_SIZE: usize = 32 + 32 + 32 + 16 + 4;
1413 if data.len() < REMOVE_LIQUIDITY_EVENT_SIZE { return None; }
1414
1415 let mut event = borsh::from_slice::<MeteoraDlmmRemoveLiquidityEvent>(&data[..REMOVE_LIQUIDITY_EVENT_SIZE]).ok()?;
1416 event.metadata = metadata;
1417 Some(DexEvent::MeteoraDlmmRemoveLiquidity(event))
1418 }
1419
1420 #[cfg(feature = "parse-zero-copy")]
1422 #[inline(always)]
1423 fn parse_remove_liquidity_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1424 unsafe {
1425 if !check_length(data, 32 + 32 + 32 + 16 + 4) { return None; }
1426 let pool = read_pubkey_unchecked(data, 0);
1427 let from = read_pubkey_unchecked(data, 32);
1428 let position = read_pubkey_unchecked(data, 64);
1429 let amount_0 = read_u64_unchecked(data, 96);
1430 let amount_1 = read_u64_unchecked(data, 104);
1431 let active_bin_id = read_i32_unchecked(data, 112);
1432 Some(DexEvent::MeteoraDlmmRemoveLiquidity(MeteoraDlmmRemoveLiquidityEvent {
1433 metadata, pool, from, position, amounts: [amount_0, amount_1], active_bin_id,
1434 }))
1435 }
1436 }
1437
1438 #[inline(always)]
1444 fn parse_initialize_pool(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1445 #[cfg(feature = "parse-borsh")]
1446 { parse_initialize_pool_borsh(data, metadata) }
1447
1448 #[cfg(feature = "parse-zero-copy")]
1449 { parse_initialize_pool_zero_copy(data, metadata) }
1450 }
1451
1452 #[cfg(feature = "parse-borsh")]
1454 #[inline(always)]
1455 fn parse_initialize_pool_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1456 const INITIALIZE_POOL_EVENT_SIZE: usize = 32 + 32 + 4 + 2;
1458 if data.len() < INITIALIZE_POOL_EVENT_SIZE { return None; }
1459
1460 let mut event = borsh::from_slice::<MeteoraDlmmInitializePoolEvent>(&data[..INITIALIZE_POOL_EVENT_SIZE]).ok()?;
1461 event.metadata = metadata;
1462 Some(DexEvent::MeteoraDlmmInitializePool(event))
1463 }
1464
1465 #[cfg(feature = "parse-zero-copy")]
1467 #[inline(always)]
1468 fn parse_initialize_pool_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1469 unsafe {
1470 if !check_length(data, 32 + 32 + 4 + 2) { return None; }
1471 let pool = read_pubkey_unchecked(data, 0);
1472 let creator = read_pubkey_unchecked(data, 32);
1473 let active_bin_id = read_i32_unchecked(data, 64);
1474 let bin_step = read_u16_unchecked(data, 68);
1475 Some(DexEvent::MeteoraDlmmInitializePool(MeteoraDlmmInitializePoolEvent {
1476 metadata, pool, creator, active_bin_id, bin_step,
1477 }))
1478 }
1479 }
1480
1481 #[inline(always)]
1487 fn parse_initialize_bin_array(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1488 #[cfg(feature = "parse-borsh")]
1489 { parse_initialize_bin_array_borsh(data, metadata) }
1490
1491 #[cfg(feature = "parse-zero-copy")]
1492 { parse_initialize_bin_array_zero_copy(data, metadata) }
1493 }
1494
1495 #[cfg(feature = "parse-borsh")]
1497 #[inline(always)]
1498 fn parse_initialize_bin_array_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1499 const INITIALIZE_BIN_ARRAY_EVENT_SIZE: usize = 32 + 32 + 8;
1501 if data.len() < INITIALIZE_BIN_ARRAY_EVENT_SIZE { return None; }
1502
1503 let mut event = borsh::from_slice::<MeteoraDlmmInitializeBinArrayEvent>(&data[..INITIALIZE_BIN_ARRAY_EVENT_SIZE]).ok()?;
1504 event.metadata = metadata;
1505 Some(DexEvent::MeteoraDlmmInitializeBinArray(event))
1506 }
1507
1508 #[cfg(feature = "parse-zero-copy")]
1510 #[inline(always)]
1511 fn parse_initialize_bin_array_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1512 unsafe {
1513 if !check_length(data, 32 + 32 + 8) { return None; }
1514 let pool = read_pubkey_unchecked(data, 0);
1515 let bin_array = read_pubkey_unchecked(data, 32);
1516 let index = read_i64_unchecked(data, 64);
1517 Some(DexEvent::MeteoraDlmmInitializeBinArray(MeteoraDlmmInitializeBinArrayEvent {
1518 metadata, pool, bin_array, index,
1519 }))
1520 }
1521 }
1522
1523 #[inline(always)]
1529 fn parse_create_position(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1530 #[cfg(feature = "parse-borsh")]
1531 { parse_create_position_borsh(data, metadata) }
1532
1533 #[cfg(feature = "parse-zero-copy")]
1534 { parse_create_position_zero_copy(data, metadata) }
1535 }
1536
1537 #[cfg(feature = "parse-borsh")]
1539 #[inline(always)]
1540 fn parse_create_position_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1541 const CREATE_POSITION_EVENT_SIZE: usize = 32 + 32 + 32 + 4 + 4;
1543 if data.len() < CREATE_POSITION_EVENT_SIZE { return None; }
1544
1545 let mut event = borsh::from_slice::<MeteoraDlmmCreatePositionEvent>(&data[..CREATE_POSITION_EVENT_SIZE]).ok()?;
1546 event.metadata = metadata;
1547 Some(DexEvent::MeteoraDlmmCreatePosition(event))
1548 }
1549
1550 #[cfg(feature = "parse-zero-copy")]
1552 #[inline(always)]
1553 fn parse_create_position_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1554 unsafe {
1555 if !check_length(data, 32 + 32 + 32 + 4 + 4) { return None; }
1556 let pool = read_pubkey_unchecked(data, 0);
1557 let position = read_pubkey_unchecked(data, 32);
1558 let owner = read_pubkey_unchecked(data, 64);
1559 let lower_bin_id = read_i32_unchecked(data, 96);
1560 let width = read_u32_unchecked(data, 100);
1561 Some(DexEvent::MeteoraDlmmCreatePosition(MeteoraDlmmCreatePositionEvent {
1562 metadata, pool, position, owner, lower_bin_id, width,
1563 }))
1564 }
1565 }
1566
1567 #[inline(always)]
1573 fn parse_close_position(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1574 #[cfg(feature = "parse-borsh")]
1575 { parse_close_position_borsh(data, metadata) }
1576
1577 #[cfg(feature = "parse-zero-copy")]
1578 { parse_close_position_zero_copy(data, metadata) }
1579 }
1580
1581 #[cfg(feature = "parse-borsh")]
1583 #[inline(always)]
1584 fn parse_close_position_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1585 const CLOSE_POSITION_EVENT_SIZE: usize = 32 + 32 + 32;
1587 if data.len() < CLOSE_POSITION_EVENT_SIZE { return None; }
1588
1589 let mut event = borsh::from_slice::<MeteoraDlmmClosePositionEvent>(&data[..CLOSE_POSITION_EVENT_SIZE]).ok()?;
1590 event.metadata = metadata;
1591 Some(DexEvent::MeteoraDlmmClosePosition(event))
1592 }
1593
1594 #[cfg(feature = "parse-zero-copy")]
1596 #[inline(always)]
1597 fn parse_close_position_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1598 unsafe {
1599 if !check_length(data, 32 + 32 + 32) { return None; }
1600 let pool = read_pubkey_unchecked(data, 0);
1601 let position = read_pubkey_unchecked(data, 32);
1602 let owner = read_pubkey_unchecked(data, 64);
1603 Some(DexEvent::MeteoraDlmmClosePosition(MeteoraDlmmClosePositionEvent {
1604 metadata, pool, position, owner,
1605 }))
1606 }
1607 }
1608
1609 #[inline(always)]
1615 fn parse_claim_fee(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1616 #[cfg(feature = "parse-borsh")]
1617 { parse_claim_fee_borsh(data, metadata) }
1618
1619 #[cfg(feature = "parse-zero-copy")]
1620 { parse_claim_fee_zero_copy(data, metadata) }
1621 }
1622
1623 #[cfg(feature = "parse-borsh")]
1625 #[inline(always)]
1626 fn parse_claim_fee_borsh(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1627 const CLAIM_FEE_EVENT_SIZE: usize = 32 + 32 + 32 + 8 + 8;
1629 if data.len() < CLAIM_FEE_EVENT_SIZE { return None; }
1630
1631 let mut event = borsh::from_slice::<MeteoraDlmmClaimFeeEvent>(&data[..CLAIM_FEE_EVENT_SIZE]).ok()?;
1632 event.metadata = metadata;
1633 Some(DexEvent::MeteoraDlmmClaimFee(event))
1634 }
1635
1636 #[cfg(feature = "parse-zero-copy")]
1638 #[inline(always)]
1639 fn parse_claim_fee_zero_copy(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
1640 unsafe {
1641 if !check_length(data, 32 + 32 + 32 + 8 + 8) { return None; }
1642 let pool = read_pubkey_unchecked(data, 0);
1643 let position = read_pubkey_unchecked(data, 32);
1644 let owner = read_pubkey_unchecked(data, 64);
1645 let fee_x = read_u64_unchecked(data, 96);
1646 let fee_y = read_u64_unchecked(data, 104);
1647 Some(DexEvent::MeteoraDlmmClaimFee(MeteoraDlmmClaimFeeEvent {
1648 metadata, pool, position, owner, fee_x, fee_y,
1649 }))
1650 }
1651 }
1652}