From 47a390a8bf4c609059e25acdb567a12c6bf9ae01 Mon Sep 17 00:00:00 2001 From: zhaoguojie2010 Date: Sat, 29 Nov 2025 17:27:49 +0800 Subject: [PATCH] support ray clmm bitmap extension account event --- src/streaming/event_parser/common/types.rs | 5 + src/streaming/event_parser/core/traits.rs | 3 + .../protocols/raydium_clmm/events.rs | 15 ++- .../protocols/raydium_clmm/parser.rs | 3 + .../protocols/raydium_clmm/types.rs | 106 +++++++++++++++++- 5 files changed, 130 insertions(+), 2 deletions(-) diff --git a/src/streaming/event_parser/common/types.rs b/src/streaming/event_parser/common/types.rs index fb0f81c..626226b 100755 --- a/src/streaming/event_parser/common/types.rs +++ b/src/streaming/event_parser/common/types.rs @@ -132,6 +132,7 @@ pub enum EventType { AccountRaydiumClmmAmmConfig, AccountRaydiumClmmPoolState, AccountRaydiumClmmTickArrayState, + AccountRaydiumClmmTickArrayBitmapExtension, AccountRaydiumCpmmAmmConfig, AccountRaydiumCpmmPoolState, AccountMeteoraDlmmLbPair, @@ -159,6 +160,7 @@ pub const ACCOUNT_EVENT_TYPES: &[EventType] = &[ EventType::AccountRaydiumClmmAmmConfig, EventType::AccountRaydiumClmmPoolState, EventType::AccountRaydiumClmmTickArrayState, + EventType::AccountRaydiumClmmTickArrayBitmapExtension, EventType::AccountRaydiumCpmmAmmConfig, EventType::AccountRaydiumCpmmPoolState, EventType::AccountMeteoraDlmmLbPair, @@ -233,6 +235,9 @@ impl fmt::Display for EventType { EventType::AccountRaydiumClmmTickArrayState => { write!(f, "AccountRaydiumClmmTickArrayState") } + EventType::AccountRaydiumClmmTickArrayBitmapExtension => { + write!(f, "AccountRaydiumClmmTickArrayBitmapExtension") + } EventType::AccountRaydiumCpmmAmmConfig => write!(f, "AccountRaydiumCpmmAmmConfig"), EventType::AccountRaydiumCpmmPoolState => write!(f, "AccountRaydiumCpmmPoolState"), EventType::AccountMeteoraDlmmLbPair => write!(f, "AccountMeteoraDlmmLbPair"), diff --git a/src/streaming/event_parser/core/traits.rs b/src/streaming/event_parser/core/traits.rs index 7014373..13e4c83 100755 --- a/src/streaming/event_parser/core/traits.rs +++ b/src/streaming/event_parser/core/traits.rs @@ -66,6 +66,7 @@ pub enum DexEvent { RaydiumClmmAmmConfigAccountEvent(RaydiumClmmAmmConfigAccountEvent), RaydiumClmmPoolStateAccountEvent(RaydiumClmmPoolStateAccountEvent), RaydiumClmmTickArrayStateAccountEvent(RaydiumClmmTickArrayStateAccountEvent), + RaydiumClmmTickArrayBitmapExtensionAccountEvent(RaydiumClmmTickArrayBitmapExtensionAccountEvent), // Raydium CPMM events RaydiumCpmmSwapEvent(RaydiumCpmmSwapEvent), @@ -134,6 +135,7 @@ impl DexEvent { DexEvent::RaydiumClmmAmmConfigAccountEvent(e) => &e.metadata, DexEvent::RaydiumClmmPoolStateAccountEvent(e) => &e.metadata, DexEvent::RaydiumClmmTickArrayStateAccountEvent(e) => &e.metadata, + DexEvent::RaydiumClmmTickArrayBitmapExtensionAccountEvent(e) => &e.metadata, DexEvent::RaydiumCpmmSwapEvent(e) => &e.metadata, DexEvent::RaydiumCpmmDepositEvent(e) => &e.metadata, DexEvent::RaydiumCpmmWithdrawEvent(e) => &e.metadata, @@ -194,6 +196,7 @@ impl DexEvent { DexEvent::RaydiumClmmAmmConfigAccountEvent(e) => &mut e.metadata, DexEvent::RaydiumClmmPoolStateAccountEvent(e) => &mut e.metadata, DexEvent::RaydiumClmmTickArrayStateAccountEvent(e) => &mut e.metadata, + DexEvent::RaydiumClmmTickArrayBitmapExtensionAccountEvent(e) => &mut e.metadata, DexEvent::RaydiumCpmmSwapEvent(e) => &mut e.metadata, DexEvent::RaydiumCpmmDepositEvent(e) => &mut e.metadata, DexEvent::RaydiumCpmmWithdrawEvent(e) => &mut e.metadata, diff --git a/src/streaming/event_parser/protocols/raydium_clmm/events.rs b/src/streaming/event_parser/protocols/raydium_clmm/events.rs index 492fa57..c360fd2 100755 --- a/src/streaming/event_parser/protocols/raydium_clmm/events.rs +++ b/src/streaming/event_parser/protocols/raydium_clmm/events.rs @@ -1,5 +1,5 @@ use crate::streaming::event_parser::common::EventMetadata; -use crate::streaming::event_parser::protocols::raydium_clmm::types::{PoolState, TickArrayState}; +use crate::streaming::event_parser::protocols::raydium_clmm::types::{PoolState, TickArrayBitmapExtension, TickArrayState}; use crate::{ streaming::event_parser::protocols::raydium_clmm::types::AmmConfig, }; @@ -247,6 +247,18 @@ pub struct RaydiumClmmTickArrayStateAccountEvent { pub tick_array_state: TickArrayState, } +/// TickArrayBitmapExtension 账户事件 +#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct RaydiumClmmTickArrayBitmapExtensionAccountEvent { + pub metadata: EventMetadata, + pub pubkey: Pubkey, + pub executable: bool, + pub lamports: u64, + pub owner: Pubkey, + pub rent_epoch: u64, + pub tick_array_bitmap_extension: TickArrayBitmapExtension, +} + /// 事件鉴别器常量 pub mod discriminators { // 指令鉴别器 @@ -263,4 +275,5 @@ pub mod discriminators { pub const AMM_CONFIG: &[u8] = &[218, 244, 33, 104, 203, 203, 43, 111]; pub const POOL_STATE: &[u8] = &[247, 237, 227, 245, 215, 195, 222, 70]; pub const TICK_ARRAY_STATE: &[u8] = &[192, 155, 85, 205, 49, 249, 129, 42]; + pub const TICK_ARRAY_BITMAP_EXTENSION: &[u8] = &[80, 111, 124, 113, 55, 237, 18, 5]; } diff --git a/src/streaming/event_parser/protocols/raydium_clmm/parser.rs b/src/streaming/event_parser/protocols/raydium_clmm/parser.rs index b127644..7901104 100755 --- a/src/streaming/event_parser/protocols/raydium_clmm/parser.rs +++ b/src/streaming/event_parser/protocols/raydium_clmm/parser.rs @@ -79,6 +79,9 @@ pub fn parse_raydium_clmm_account_data( discriminators::TICK_ARRAY_STATE => { crate::streaming::event_parser::protocols::raydium_clmm::types::tick_array_state_parser(account, metadata) } + discriminators::TICK_ARRAY_BITMAP_EXTENSION => { + crate::streaming::event_parser::protocols::raydium_clmm::types::tick_array_bitmap_extension_parser(account, metadata) + } _ => None, } } diff --git a/src/streaming/event_parser/protocols/raydium_clmm/types.rs b/src/streaming/event_parser/protocols/raydium_clmm/types.rs index 5f3695c..c06a240 100644 --- a/src/streaming/event_parser/protocols/raydium_clmm/types.rs +++ b/src/streaming/event_parser/protocols/raydium_clmm/types.rs @@ -7,7 +7,7 @@ use crate::streaming::{ common::{EventMetadata, EventType}, protocols::raydium_clmm::{ RaydiumClmmAmmConfigAccountEvent, RaydiumClmmPoolStateAccountEvent, - RaydiumClmmTickArrayStateAccountEvent, + RaydiumClmmTickArrayBitmapExtensionAccountEvent, RaydiumClmmTickArrayStateAccountEvent, }, DexEvent, }, @@ -231,3 +231,107 @@ pub fn tick_array_state_parser( None } } + +// EXTENSION_TICKARRAY_BITMAP_SIZE 常量,根据 Raydium CLMM 实现,通常为 14 +pub const EXTENSION_TICKARRAY_BITMAP_SIZE: usize = 14; + +#[repr(C, packed)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct TickArrayBitmapExtension { + pub pool_id: Pubkey, + /// Packed initialized tick array state for start_tick_index is positive + pub positive_tick_array_bitmap: [[u64; 8]; EXTENSION_TICKARRAY_BITMAP_SIZE], + /// Packed initialized tick array state for start_tick_index is negative + pub negative_tick_array_bitmap: [[u64; 8]; EXTENSION_TICKARRAY_BITMAP_SIZE], +} + +impl Default for TickArrayBitmapExtension { + fn default() -> Self { + Self { + pool_id: Pubkey::default(), + positive_tick_array_bitmap: [[0u64; 8]; EXTENSION_TICKARRAY_BITMAP_SIZE], + negative_tick_array_bitmap: [[0u64; 8]; EXTENSION_TICKARRAY_BITMAP_SIZE], + } + } +} + +// 计算大小:Pubkey (32) + positive_bitmap (12 * 8 * 8) + negative_bitmap (12 * 8 * 8) +pub const TICK_ARRAY_BITMAP_EXTENSION_SIZE: usize = 32 + (EXTENSION_TICKARRAY_BITMAP_SIZE * 8 * 64) + (EXTENSION_TICKARRAY_BITMAP_SIZE * 8 * 64); + +pub fn tick_array_bitmap_extension_decode(data: &[u8]) -> Option { + if data.len() < TICK_ARRAY_BITMAP_EXTENSION_SIZE { + return None; + } + + // 由于使用了 #[repr(C, packed)],我们需要手动解析 + let mut offset = 0; + + // 读取 pool_id (32 bytes) + if data.len() < offset + 32 { + return None; + } + let pool_id = Pubkey::try_from(&data[offset..offset + 32]).ok()?; + offset += 32; + + // 读取 positive_tick_array_bitmap + let mut positive_tick_array_bitmap = [[0u64; 8]; EXTENSION_TICKARRAY_BITMAP_SIZE]; + for i in 0..EXTENSION_TICKARRAY_BITMAP_SIZE { + for j in 0..8 { + if data.len() < offset + 8 { + return None; + } + positive_tick_array_bitmap[i][j] = u64::from_le_bytes( + data[offset..offset + 8].try_into().ok()? + ); + offset += 8; + } + } + + // 读取 negative_tick_array_bitmap + let mut negative_tick_array_bitmap = [[0u64; 8]; EXTENSION_TICKARRAY_BITMAP_SIZE]; + for i in 0..EXTENSION_TICKARRAY_BITMAP_SIZE { + for j in 0..8 { + if data.len() < offset + 8 { + return None; + } + negative_tick_array_bitmap[i][j] = u64::from_le_bytes( + data[offset..offset + 8].try_into().ok()? + ); + offset += 8; + } + } + + Some(TickArrayBitmapExtension { + pool_id, + positive_tick_array_bitmap, + negative_tick_array_bitmap, + }) +} + +pub fn tick_array_bitmap_extension_parser( + account: &AccountPretty, + mut metadata: EventMetadata, +) -> Option { + metadata.event_type = EventType::AccountRaydiumClmmTickArrayBitmapExtension; + + if account.data.len() < TICK_ARRAY_BITMAP_EXTENSION_SIZE + 8 { + return None; + } + if let Some(tick_array_bitmap_extension) = + tick_array_bitmap_extension_decode(&account.data[8..TICK_ARRAY_BITMAP_EXTENSION_SIZE + 8]) + { + Some(DexEvent::RaydiumClmmTickArrayBitmapExtensionAccountEvent( + RaydiumClmmTickArrayBitmapExtensionAccountEvent { + metadata, + pubkey: account.pubkey, + executable: account.executable, + lamports: account.lamports, + owner: account.owner, + rent_epoch: account.rent_epoch, + tick_array_bitmap_extension, + }, + )) + } else { + None + } +}