1use solana_sdk::{pubkey::Pubkey, signature::Signature};
6use crate::core::events::*;
7use super::utils::*;
8use super::program_ids;
9
10pub mod discriminators {
12 pub const SWAP: [u8; 8] = [248, 198, 158, 145, 225, 117, 135, 200];
13 pub const INCREASE_LIQUIDITY: [u8; 8] = [133, 29, 89, 223, 69, 238, 176, 10];
14 pub const DECREASE_LIQUIDITY: [u8; 8] = [160, 38, 208, 111, 104, 91, 44, 1];
15 pub const CREATE_POOL: [u8; 8] = [233, 146, 209, 142, 207, 104, 64, 188];
16 pub const OPEN_POSITION: [u8; 8] = [135, 128, 47, 77, 15, 152, 240, 49];
17 pub const CLOSE_POSITION: [u8; 8] = [123, 134, 81, 0, 49, 68, 98, 98];
18}
19
20pub const PROGRAM_ID_PUBKEY: Pubkey = program_ids::RAYDIUM_CLMM_PROGRAM_ID;
22
23pub fn parse_instruction(
25 instruction_data: &[u8],
26 accounts: &[Pubkey],
27 signature: Signature,
28 slot: u64,
29 tx_index: u64,
30 block_time: Option<i64>,
31) -> Option<DexEvent> {
32 if instruction_data.len() < 8 {
33 return None;
34 }
35
36 let discriminator: [u8; 8] = instruction_data[0..8].try_into().ok()?;
37 let data = &instruction_data[8..];
38
39 match discriminator {
40 discriminators::SWAP => {
41 parse_swap_instruction(data, accounts, signature, slot, tx_index, block_time)
42 },
43 discriminators::INCREASE_LIQUIDITY => {
44 parse_increase_liquidity_instruction(data, accounts, signature, slot, tx_index, block_time)
45 },
46 discriminators::DECREASE_LIQUIDITY => {
47 parse_decrease_liquidity_instruction(data, accounts, signature, slot, tx_index, block_time)
48 },
49 discriminators::CREATE_POOL => {
50 parse_create_pool_instruction(data, accounts, signature, slot, tx_index, block_time)
51 },
52 discriminators::OPEN_POSITION => {
53 parse_open_position_instruction(data, accounts, signature, slot, tx_index, block_time)
54 },
55 discriminators::CLOSE_POSITION => {
56 parse_close_position_instruction(data, accounts, signature, slot, tx_index, block_time)
57 },
58 _ => None,
59 }
60}
61
62fn parse_swap_instruction(
64 data: &[u8],
65 accounts: &[Pubkey],
66 signature: Signature,
67 slot: u64,
68 tx_index: u64,
69 block_time: Option<i64>,
70) -> Option<DexEvent> {
71 let mut offset = 0;
72
73 let amount = read_u64_le(data, offset)?;
74 offset += 8;
75
76 let other_amount_threshold = read_u64_le(data, offset)?;
77 offset += 8;
78
79 let sqrt_price_limit_x64 = read_u64_le(data, offset)? as u128;
80 offset += 8;
81
82 let is_base_input = data.get(offset)? == &1;
83
84 let pool = get_account(accounts, 0)?;
85 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
86
87 Some(DexEvent::RaydiumClmmSwap(RaydiumClmmSwapEvent {
88 metadata,
89
90 pool_state: pool,
92 sender: get_account(accounts, 1).unwrap_or_default(),
93 token_account_0: Pubkey::default(),
94 token_account_1: Pubkey::default(),
95 amount_0: 0, transfer_fee_0: 0, amount_1: 0, transfer_fee_1: 0, zero_for_one: is_base_input,
100 sqrt_price_x64: sqrt_price_limit_x64,
101 liquidity: 0, tick: 0, }))
111}
112
113fn parse_increase_liquidity_instruction(
115 data: &[u8],
116 accounts: &[Pubkey],
117 signature: Signature,
118 slot: u64,
119 tx_index: u64,
120 block_time: Option<i64>,
121) -> Option<DexEvent> {
122 let mut offset = 0;
123
124 let liquidity = read_u64_le(data, offset)? as u128;
125 offset += 8;
126
127 let amount_0_max = read_u64_le(data, offset)?;
128 offset += 8;
129
130 let amount_1_max = read_u64_le(data, offset)?;
131
132 let pool = get_account(accounts, 0)?;
133 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
134
135 Some(DexEvent::RaydiumClmmIncreaseLiquidity(RaydiumClmmIncreaseLiquidityEvent {
136 metadata,
137 pool,
138 user: get_account(accounts, 2).unwrap_or_default(),
139 liquidity,
140 amount0_max: amount_0_max,
141 amount1_max: amount_1_max,
142 }))
143}
144
145fn parse_decrease_liquidity_instruction(
147 data: &[u8],
148 accounts: &[Pubkey],
149 signature: Signature,
150 slot: u64,
151 tx_index: u64,
152 block_time: Option<i64>,
153) -> Option<DexEvent> {
154 let mut offset = 0;
155
156 let liquidity = read_u64_le(data, offset)? as u128;
157 offset += 8;
158
159 let amount_0_min = read_u64_le(data, offset)?;
160 offset += 8;
161
162 let amount_1_min = read_u64_le(data, offset)?;
163
164 let pool = get_account(accounts, 0)?;
165 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
166
167 Some(DexEvent::RaydiumClmmDecreaseLiquidity(RaydiumClmmDecreaseLiquidityEvent {
168 metadata,
169 pool,
170 user: get_account(accounts, 1).unwrap_or_default(),
171 liquidity,
172 amount0_min: amount_0_min,
173 amount1_min: amount_1_min,
174 }))
175}
176
177fn parse_create_pool_instruction(
179 data: &[u8],
180 accounts: &[Pubkey],
181 signature: Signature,
182 slot: u64,
183 tx_index: u64,
184 block_time: Option<i64>,
185) -> Option<DexEvent> {
186 let mut offset = 0;
187
188 let sqrt_price_x64 = read_u64_le(data, offset)? as u128;
189 offset += 8;
190
191 let open_time = read_u64_le(data, offset)?;
192
193 let pool = get_account(accounts, 0)?;
194 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
195
196 Some(DexEvent::RaydiumClmmCreatePool(RaydiumClmmCreatePoolEvent {
197 metadata,
198 pool,
199 creator: get_account(accounts, 1).unwrap_or_default(),
200 sqrt_price_x64,
201 open_time,
202 }))
203}
204
205fn parse_open_position_instruction(
207 data: &[u8],
208 accounts: &[Pubkey],
209 signature: Signature,
210 slot: u64,
211 tx_index: u64,
212 block_time: Option<i64>,
213) -> Option<DexEvent> {
214 let mut offset = 0;
215
216 let tick_lower_index = read_u32_le(data, offset)? as i32;
217 offset += 4;
218
219 let tick_upper_index = read_u32_le(data, offset)? as i32;
220 offset += 4;
221
222 let _tick_array_lower_start_index = read_u32_le(data, offset)? as i32;
223 offset += 4;
224
225 let _tick_array_upper_start_index = read_u32_le(data, offset)? as i32;
226 offset += 4;
227
228 let liquidity = read_u64_le(data, offset)? as u128;
229 offset += 8;
230
231 let _amount_0_max = read_u64_le(data, offset)?;
232 offset += 8;
233
234 let _amount_1_max = read_u64_le(data, offset)?;
235
236 let pool = get_account(accounts, 0)?;
237 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
238
239 Some(DexEvent::RaydiumClmmOpenPosition(RaydiumClmmOpenPositionEvent {
240 metadata,
241 pool,
242 user: get_account(accounts, 1).unwrap_or_default(),
243 position_nft_mint: get_account(accounts, 2).unwrap_or_default(),
244 tick_lower_index,
245 tick_upper_index,
246 liquidity,
247 }))
248}
249
250fn parse_close_position_instruction(
252 _data: &[u8],
253 accounts: &[Pubkey],
254 signature: Signature,
255 slot: u64,
256 tx_index: u64,
257 block_time: Option<i64>,
258) -> Option<DexEvent> {
259 let pool = get_account(accounts, 0)?;
260 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
261
262 Some(DexEvent::RaydiumClmmClosePosition(RaydiumClmmClosePositionEvent {
263 metadata,
264 pool,
265 user: get_account(accounts, 1).unwrap_or_default(),
266 position_nft_mint: get_account(accounts, 2).unwrap_or_default(),
267 }))
268}