Skip to main content

sol_parser_sdk/logs/
meteora_dlmm.rs

1//! Meteora DLMM log parser
2//!
3//! Parse Meteora DLMM program log events
4
5use super::utils::*;
6use crate::core::events::*;
7use solana_sdk::signature::Signature;
8
9/// Meteora DLMM 事件 discriminator 常量
10pub mod discriminators {
11    pub const SWAP_EVENT: [u8; 8] = [143, 190, 90, 218, 196, 30, 51, 222];
12    pub const ADD_LIQUIDITY_EVENT: [u8; 8] = [181, 157, 89, 67, 143, 182, 52, 72];
13    pub const REMOVE_LIQUIDITY_EVENT: [u8; 8] = [80, 85, 209, 72, 24, 206, 35, 178];
14    pub const INITIALIZE_BIN_ARRAY_EVENT: [u8; 8] = [11, 18, 155, 194, 33, 115, 238, 119];
15    pub const INITIALIZE_POOL_EVENT: [u8; 8] = [95, 180, 10, 172, 84, 174, 232, 40];
16    pub const CREATE_POSITION_EVENT: [u8; 8] = [123, 233, 11, 43, 146, 180, 97, 119];
17    pub const CLOSE_POSITION_EVENT: [u8; 8] = [94, 168, 102, 45, 59, 122, 137, 54];
18    pub const CLAIM_FEE_EVENT: [u8; 8] = [152, 70, 208, 111, 104, 91, 44, 1];
19}
20
21/// 主要的 Meteora DLMM 日志解析函数
22pub fn parse_log(
23    log: &str,
24    signature: Signature,
25    slot: u64,
26    tx_index: u64,
27    block_time_us: Option<i64>,
28    grpc_recv_us: i64,
29) -> Option<DexEvent> {
30    parse_structured_log(log, signature, slot, tx_index, block_time_us, grpc_recv_us)
31}
32
33/// 解析结构化日志(基于 discriminator)
34fn parse_structured_log(
35    log: &str,
36    signature: Signature,
37    slot: u64,
38    tx_index: u64,
39    block_time_us: Option<i64>,
40    grpc_recv_us: i64,
41) -> Option<DexEvent> {
42    let program_data = extract_program_data(log)?;
43    if program_data.len() < 8 {
44        return None;
45    }
46
47    let discriminator: [u8; 8] = program_data[0..8].try_into().ok()?;
48    let data = &program_data[8..];
49
50    match discriminator {
51        discriminators::SWAP_EVENT => {
52            parse_swap_event(data, signature, slot, tx_index, block_time_us, grpc_recv_us)
53        }
54        discriminators::ADD_LIQUIDITY_EVENT => {
55            parse_add_liquidity_event(data, signature, slot, tx_index, block_time_us, grpc_recv_us)
56        }
57        discriminators::REMOVE_LIQUIDITY_EVENT => parse_remove_liquidity_event(
58            data,
59            signature,
60            slot,
61            tx_index,
62            block_time_us,
63            grpc_recv_us,
64        ),
65        discriminators::INITIALIZE_BIN_ARRAY_EVENT => parse_initialize_bin_array_event(
66            data,
67            signature,
68            slot,
69            tx_index,
70            block_time_us,
71            grpc_recv_us,
72        ),
73        discriminators::INITIALIZE_POOL_EVENT => parse_initialize_pool_event(
74            data,
75            signature,
76            slot,
77            tx_index,
78            block_time_us,
79            grpc_recv_us,
80        ),
81        discriminators::CREATE_POSITION_EVENT => parse_create_position_event(
82            data,
83            signature,
84            slot,
85            tx_index,
86            block_time_us,
87            grpc_recv_us,
88        ),
89        discriminators::CLOSE_POSITION_EVENT => {
90            parse_close_position_event(data, signature, slot, tx_index, block_time_us, grpc_recv_us)
91        }
92        discriminators::CLAIM_FEE_EVENT => {
93            parse_claim_fee_event(data, signature, slot, tx_index, block_time_us, grpc_recv_us)
94        }
95        _ => None,
96    }
97}
98
99// =============================================================================
100// Public from_data parsers - Accept pre-decoded data, eliminate double decode
101// =============================================================================
102
103#[inline(always)]
104pub fn parse_swap_from_data(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
105    let mut offset = 0;
106
107    let pool = read_pubkey(data, offset)?;
108    offset += 32;
109
110    let from = read_pubkey(data, offset)?;
111    offset += 32;
112
113    let start_bin_id = read_i32_le(data, offset)?;
114    offset += 4;
115
116    let end_bin_id = read_i32_le(data, offset)?;
117    offset += 4;
118
119    let amount_in = read_u64_le(data, offset)?;
120    offset += 8;
121
122    let amount_out = read_u64_le(data, offset)?;
123    offset += 8;
124
125    let swap_for_y = read_bool(data, offset)?;
126    offset += 1;
127
128    let fee = read_u64_le(data, offset)?;
129    offset += 8;
130
131    let protocol_fee = read_u64_le(data, offset)?;
132    offset += 8;
133
134    let fee_bps = read_u128_le(data, offset)?;
135    offset += 16;
136
137    let host_fee = read_u64_le(data, offset)?;
138
139    Some(DexEvent::MeteoraDlmmSwap(MeteoraDlmmSwapEvent {
140        metadata,
141        pool,
142        from,
143        start_bin_id,
144        end_bin_id,
145        amount_in,
146        amount_out,
147        swap_for_y,
148        fee,
149        protocol_fee,
150        fee_bps,
151        host_fee,
152    }))
153}
154
155#[inline(always)]
156pub fn parse_add_liquidity_from_data(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
157    let mut offset = 0;
158
159    let pool = read_pubkey(data, offset)?;
160    offset += 32;
161
162    let from = read_pubkey(data, offset)?;
163    offset += 32;
164
165    let position = read_pubkey(data, offset)?;
166    offset += 32;
167
168    let amount_0 = read_u64_le(data, offset)?;
169    offset += 8;
170
171    let amount_1 = read_u64_le(data, offset)?;
172    offset += 8;
173
174    let active_bin_id = read_i32_le(data, offset)?;
175
176    Some(DexEvent::MeteoraDlmmAddLiquidity(MeteoraDlmmAddLiquidityEvent {
177        metadata,
178        pool,
179        from,
180        position,
181        amounts: [amount_0, amount_1],
182        active_bin_id,
183    }))
184}
185
186#[inline(always)]
187pub fn parse_remove_liquidity_from_data(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
188    let mut offset = 0;
189
190    let pool = read_pubkey(data, offset)?;
191    offset += 32;
192
193    let from = read_pubkey(data, offset)?;
194    offset += 32;
195
196    let position = read_pubkey(data, offset)?;
197    offset += 32;
198
199    let amount_0 = read_u64_le(data, offset)?;
200    offset += 8;
201
202    let amount_1 = read_u64_le(data, offset)?;
203    offset += 8;
204
205    let active_bin_id = read_i32_le(data, offset)?;
206
207    Some(DexEvent::MeteoraDlmmRemoveLiquidity(MeteoraDlmmRemoveLiquidityEvent {
208        metadata,
209        pool,
210        from,
211        position,
212        amounts: [amount_0, amount_1],
213        active_bin_id,
214    }))
215}
216
217#[inline(always)]
218pub fn parse_initialize_pool_from_data(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
219    let mut offset = 0;
220
221    let pool = read_pubkey(data, offset)?;
222    offset += 32;
223
224    let creator = read_pubkey(data, offset)?;
225    offset += 32;
226
227    let active_bin_id = read_i32_le(data, offset)?;
228    offset += 4;
229
230    let bin_step = read_u16_le(data, offset)?;
231
232    Some(DexEvent::MeteoraDlmmInitializePool(MeteoraDlmmInitializePoolEvent {
233        metadata,
234        pool,
235        creator,
236        active_bin_id,
237        bin_step,
238    }))
239}
240
241#[inline(always)]
242pub fn parse_initialize_bin_array_from_data(
243    data: &[u8],
244    metadata: EventMetadata,
245) -> Option<DexEvent> {
246    let mut offset = 0;
247
248    let pool = read_pubkey(data, offset)?;
249    offset += 32;
250
251    let bin_array = read_pubkey(data, offset)?;
252    offset += 32;
253
254    let index = read_i64_le(data, offset)?;
255
256    Some(DexEvent::MeteoraDlmmInitializeBinArray(MeteoraDlmmInitializeBinArrayEvent {
257        metadata,
258        pool,
259        bin_array,
260        index,
261    }))
262}
263
264#[inline(always)]
265pub fn parse_create_position_from_data(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
266    let mut offset = 0;
267
268    let pool = read_pubkey(data, offset)?;
269    offset += 32;
270
271    let position = read_pubkey(data, offset)?;
272    offset += 32;
273
274    let owner = read_pubkey(data, offset)?;
275    offset += 32;
276
277    let lower_bin_id = read_i32_le(data, offset)?;
278    offset += 4;
279
280    let width = read_u32_le(data, offset)?;
281
282    Some(DexEvent::MeteoraDlmmCreatePosition(MeteoraDlmmCreatePositionEvent {
283        metadata,
284        pool,
285        position,
286        owner,
287        lower_bin_id,
288        width,
289    }))
290}
291
292#[inline(always)]
293pub fn parse_close_position_from_data(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
294    let mut offset = 0;
295
296    let pool = read_pubkey(data, offset)?;
297    offset += 32;
298
299    let position = read_pubkey(data, offset)?;
300    offset += 32;
301
302    let owner = read_pubkey(data, offset)?;
303
304    Some(DexEvent::MeteoraDlmmClosePosition(MeteoraDlmmClosePositionEvent {
305        metadata,
306        pool,
307        position,
308        owner,
309    }))
310}
311
312#[inline(always)]
313pub fn parse_claim_fee_from_data(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
314    let mut offset = 0;
315
316    let pool = read_pubkey(data, offset)?;
317    offset += 32;
318
319    let position = read_pubkey(data, offset)?;
320    offset += 32;
321
322    let owner = read_pubkey(data, offset)?;
323    offset += 32;
324
325    let fee_x = read_u64_le(data, offset)?;
326    offset += 8;
327
328    let fee_y = read_u64_le(data, offset)?;
329
330    Some(DexEvent::MeteoraDlmmClaimFee(MeteoraDlmmClaimFeeEvent {
331        metadata,
332        pool,
333        position,
334        owner,
335        fee_x,
336        fee_y,
337    }))
338}
339
340/// 解析交换事件
341fn parse_swap_event(
342    data: &[u8],
343    signature: Signature,
344    slot: u64,
345    tx_index: u64,
346    block_time_us: Option<i64>,
347    grpc_recv_us: i64,
348) -> Option<DexEvent> {
349    let mut offset = 0;
350
351    let pool = read_pubkey(data, offset)?;
352    offset += 32;
353
354    let from = read_pubkey(data, offset)?;
355    offset += 32;
356
357    let start_bin_id = read_i32_le(data, offset)?;
358    offset += 4;
359
360    let end_bin_id = read_i32_le(data, offset)?;
361    offset += 4;
362
363    let amount_in = read_u64_le(data, offset)?;
364    offset += 8;
365
366    let amount_out = read_u64_le(data, offset)?;
367    offset += 8;
368
369    let swap_for_y = read_bool(data, offset)?;
370    offset += 1;
371
372    let fee = read_u64_le(data, offset)?;
373    offset += 8;
374
375    let protocol_fee = read_u64_le(data, offset)?;
376    offset += 8;
377
378    let fee_bps = read_u128_le(data, offset)?;
379    offset += 16;
380
381    let host_fee = read_u64_le(data, offset)?;
382
383    let metadata =
384        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
385
386    Some(DexEvent::MeteoraDlmmSwap(MeteoraDlmmSwapEvent {
387        metadata,
388        pool,
389        from,
390        start_bin_id,
391        end_bin_id,
392        amount_in,
393        amount_out,
394        swap_for_y,
395        fee,
396        protocol_fee,
397        fee_bps,
398        host_fee,
399    }))
400}
401
402/// 解析添加流动性事件
403fn parse_add_liquidity_event(
404    data: &[u8],
405    signature: Signature,
406    slot: u64,
407    tx_index: u64,
408    block_time_us: Option<i64>,
409    grpc_recv_us: i64,
410) -> Option<DexEvent> {
411    let mut offset = 0;
412
413    let pool = read_pubkey(data, offset)?;
414    offset += 32;
415
416    let from = read_pubkey(data, offset)?;
417    offset += 32;
418
419    let position = read_pubkey(data, offset)?;
420    offset += 32;
421
422    let amount_0 = read_u64_le(data, offset)?;
423    offset += 8;
424
425    let amount_1 = read_u64_le(data, offset)?;
426    offset += 8;
427
428    let active_bin_id = read_i32_le(data, offset)?;
429
430    let metadata =
431        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
432
433    Some(DexEvent::MeteoraDlmmAddLiquidity(MeteoraDlmmAddLiquidityEvent {
434        metadata,
435        pool,
436        from,
437        position,
438        amounts: [amount_0, amount_1],
439        active_bin_id,
440    }))
441}
442
443/// 解析移除流动性事件
444fn parse_remove_liquidity_event(
445    data: &[u8],
446    signature: Signature,
447    slot: u64,
448    tx_index: u64,
449    block_time_us: Option<i64>,
450    grpc_recv_us: i64,
451) -> Option<DexEvent> {
452    let mut offset = 0;
453
454    let pool = read_pubkey(data, offset)?;
455    offset += 32;
456
457    let from = read_pubkey(data, offset)?;
458    offset += 32;
459
460    let position = read_pubkey(data, offset)?;
461    offset += 32;
462
463    let amount_0 = read_u64_le(data, offset)?;
464    offset += 8;
465
466    let amount_1 = read_u64_le(data, offset)?;
467    offset += 8;
468
469    let active_bin_id = read_i32_le(data, offset)?;
470
471    let metadata =
472        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
473
474    Some(DexEvent::MeteoraDlmmRemoveLiquidity(MeteoraDlmmRemoveLiquidityEvent {
475        metadata,
476        pool,
477        from,
478        position,
479        amounts: [amount_0, amount_1],
480        active_bin_id,
481    }))
482}
483
484/// 解析池初始化事件
485fn parse_initialize_pool_event(
486    data: &[u8],
487    signature: Signature,
488    slot: u64,
489    tx_index: u64,
490    block_time_us: Option<i64>,
491    grpc_recv_us: i64,
492) -> Option<DexEvent> {
493    let mut offset = 0;
494
495    let pool = read_pubkey(data, offset)?;
496    offset += 32;
497
498    let creator = read_pubkey(data, offset)?;
499    offset += 32;
500
501    let active_bin_id = read_i32_le(data, offset)?;
502    offset += 4;
503
504    let bin_step = read_u16_le(data, offset)?;
505
506    let metadata =
507        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
508
509    Some(DexEvent::MeteoraDlmmInitializePool(MeteoraDlmmInitializePoolEvent {
510        metadata,
511        pool,
512        creator,
513        active_bin_id,
514        bin_step,
515    }))
516}
517
518/// 解析 Bin Array 初始化事件
519fn parse_initialize_bin_array_event(
520    data: &[u8],
521    signature: Signature,
522    slot: u64,
523    tx_index: u64,
524    block_time_us: Option<i64>,
525    grpc_recv_us: i64,
526) -> Option<DexEvent> {
527    let mut offset = 0;
528
529    let pool = read_pubkey(data, offset)?;
530    offset += 32;
531
532    let bin_array = read_pubkey(data, offset)?;
533    offset += 32;
534
535    let index = read_i64_le(data, offset)?;
536
537    let metadata =
538        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
539
540    Some(DexEvent::MeteoraDlmmInitializeBinArray(MeteoraDlmmInitializeBinArrayEvent {
541        metadata,
542        pool,
543        bin_array,
544        index,
545    }))
546}
547
548/// 解析创建头寸事件
549fn parse_create_position_event(
550    data: &[u8],
551    signature: Signature,
552    slot: u64,
553    tx_index: u64,
554    block_time_us: Option<i64>,
555    grpc_recv_us: i64,
556) -> Option<DexEvent> {
557    let mut offset = 0;
558
559    let pool = read_pubkey(data, offset)?;
560    offset += 32;
561
562    let position = read_pubkey(data, offset)?;
563    offset += 32;
564
565    let owner = read_pubkey(data, offset)?;
566    offset += 32;
567
568    let lower_bin_id = read_i32_le(data, offset)?;
569    offset += 4;
570
571    let width = read_u32_le(data, offset)?;
572
573    let metadata =
574        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
575
576    Some(DexEvent::MeteoraDlmmCreatePosition(MeteoraDlmmCreatePositionEvent {
577        metadata,
578        pool,
579        position,
580        owner,
581        lower_bin_id,
582        width,
583    }))
584}
585
586/// 解析关闭头寸事件
587fn parse_close_position_event(
588    data: &[u8],
589    signature: Signature,
590    slot: u64,
591    tx_index: u64,
592    block_time_us: Option<i64>,
593    grpc_recv_us: i64,
594) -> Option<DexEvent> {
595    let mut offset = 0;
596
597    let pool = read_pubkey(data, offset)?;
598    offset += 32;
599
600    let position = read_pubkey(data, offset)?;
601    offset += 32;
602
603    let owner = read_pubkey(data, offset)?;
604
605    let metadata =
606        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
607
608    Some(DexEvent::MeteoraDlmmClosePosition(MeteoraDlmmClosePositionEvent {
609        metadata,
610        pool,
611        position,
612        owner,
613    }))
614}
615
616/// 解析费用领取事件
617fn parse_claim_fee_event(
618    data: &[u8],
619    signature: Signature,
620    slot: u64,
621    tx_index: u64,
622    block_time_us: Option<i64>,
623    grpc_recv_us: i64,
624) -> Option<DexEvent> {
625    let mut offset = 0;
626
627    let pool = read_pubkey(data, offset)?;
628    offset += 32;
629
630    let position = read_pubkey(data, offset)?;
631    offset += 32;
632
633    let owner = read_pubkey(data, offset)?;
634    offset += 32;
635
636    let fee_x = read_u64_le(data, offset)?;
637    offset += 8;
638
639    let fee_y = read_u64_le(data, offset)?;
640
641    let metadata =
642        create_metadata_simple(signature, slot, tx_index, block_time_us, pool, grpc_recv_us);
643
644    Some(DexEvent::MeteoraDlmmClaimFee(MeteoraDlmmClaimFeeEvent {
645        metadata,
646        pool,
647        position,
648        owner,
649        fee_x,
650        fee_y,
651    }))
652}
653
654/// 文本回退解析
655fn parse_text_log(
656    log: &str,
657    signature: Signature,
658    slot: u64,
659    tx_index: u64,
660    block_time_us: Option<i64>,
661    grpc_recv_us: i64,
662) -> Option<DexEvent> {
663    use super::utils::text_parser::*;
664
665    if log.contains("swap") || log.contains("Swap") {
666        return parse_swap_from_text(log, signature, slot, tx_index, block_time_us, grpc_recv_us);
667    }
668
669    if log.contains("add") && log.contains("liquidity") {
670        return parse_add_liquidity_from_text(
671            log,
672            signature,
673            slot,
674            tx_index,
675            block_time_us,
676            grpc_recv_us,
677        );
678    }
679
680    if log.contains("remove") && log.contains("liquidity") {
681        return parse_remove_liquidity_from_text(
682            log,
683            signature,
684            slot,
685            tx_index,
686            block_time_us,
687            grpc_recv_us,
688        );
689    }
690
691    if log.contains("initialize") && log.contains("pool") {
692        return parse_initialize_pool_from_text(
693            log,
694            signature,
695            slot,
696            tx_index,
697            block_time_us,
698            grpc_recv_us,
699        );
700    }
701
702    None
703}
704
705/// 从文本解析交换事件
706fn parse_swap_from_text(
707    log: &str,
708    signature: Signature,
709    slot: u64,
710    tx_index: u64,
711    block_time_us: Option<i64>,
712    grpc_recv_us: i64,
713) -> Option<DexEvent> {
714    use super::utils::text_parser::*;
715
716    let metadata = create_metadata_simple(
717        signature,
718        slot,
719        tx_index,
720        block_time_us,
721        solana_sdk::pubkey::Pubkey::default(),
722        grpc_recv_us,
723    );
724
725    Some(DexEvent::MeteoraDlmmSwap(MeteoraDlmmSwapEvent {
726        metadata,
727        pool: solana_sdk::pubkey::Pubkey::default(),
728        from: solana_sdk::pubkey::Pubkey::default(),
729        start_bin_id: 0,
730        end_bin_id: 0,
731        amount_in: extract_number_from_text(log, "amount_in").unwrap_or(1_000_000),
732        amount_out: extract_number_from_text(log, "amount_out").unwrap_or(950_000),
733        swap_for_y: detect_trade_type(log).unwrap_or(true),
734        fee: extract_number_from_text(log, "fee").unwrap_or(3000),
735        protocol_fee: 0,
736        fee_bps: 0,
737        host_fee: 0,
738    }))
739}
740
741/// 从文本解析添加流动性事件
742fn parse_add_liquidity_from_text(
743    log: &str,
744    signature: Signature,
745    slot: u64,
746    tx_index: u64,
747    block_time_us: Option<i64>,
748    grpc_recv_us: i64,
749) -> Option<DexEvent> {
750    use super::utils::text_parser::*;
751
752    let metadata = create_metadata_simple(
753        signature,
754        slot,
755        tx_index,
756        block_time_us,
757        solana_sdk::pubkey::Pubkey::default(),
758        grpc_recv_us,
759    );
760
761    Some(DexEvent::MeteoraDlmmAddLiquidity(MeteoraDlmmAddLiquidityEvent {
762        metadata,
763        pool: solana_sdk::pubkey::Pubkey::default(),
764        from: solana_sdk::pubkey::Pubkey::default(),
765        position: solana_sdk::pubkey::Pubkey::default(),
766        amounts: [
767            extract_number_from_text(log, "amount_x").unwrap_or(500_000),
768            extract_number_from_text(log, "amount_y").unwrap_or(500_000),
769        ],
770        active_bin_id: 0,
771    }))
772}
773
774/// 从文本解析移除流动性事件
775fn parse_remove_liquidity_from_text(
776    log: &str,
777    signature: Signature,
778    slot: u64,
779    tx_index: u64,
780    block_time_us: Option<i64>,
781    grpc_recv_us: i64,
782) -> Option<DexEvent> {
783    use super::utils::text_parser::*;
784
785    let metadata = create_metadata_simple(
786        signature,
787        slot,
788        tx_index,
789        block_time_us,
790        solana_sdk::pubkey::Pubkey::default(),
791        grpc_recv_us,
792    );
793
794    Some(DexEvent::MeteoraDlmmRemoveLiquidity(MeteoraDlmmRemoveLiquidityEvent {
795        metadata,
796        pool: solana_sdk::pubkey::Pubkey::default(),
797        from: solana_sdk::pubkey::Pubkey::default(),
798        position: solana_sdk::pubkey::Pubkey::default(),
799        amounts: [
800            extract_number_from_text(log, "amount_x").unwrap_or(500_000),
801            extract_number_from_text(log, "amount_y").unwrap_or(500_000),
802        ],
803        active_bin_id: 0,
804    }))
805}
806
807/// 从文本解析池初始化事件
808fn parse_initialize_pool_from_text(
809    log: &str,
810    signature: Signature,
811    slot: u64,
812    tx_index: u64,
813    block_time_us: Option<i64>,
814    grpc_recv_us: i64,
815) -> Option<DexEvent> {
816    use super::utils::text_parser::*;
817
818    let metadata = create_metadata_simple(
819        signature,
820        slot,
821        tx_index,
822        block_time_us,
823        solana_sdk::pubkey::Pubkey::default(),
824        grpc_recv_us,
825    );
826
827    Some(DexEvent::MeteoraDlmmInitializePool(MeteoraDlmmInitializePoolEvent {
828        metadata,
829        pool: solana_sdk::pubkey::Pubkey::default(),
830        creator: solana_sdk::pubkey::Pubkey::default(),
831        active_bin_id: extract_number_from_text(log, "bin_id").unwrap_or(0) as i32,
832        bin_step: extract_number_from_text(log, "bin_step").unwrap_or(1) as u16,
833    }))
834}