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_BASE_IN: [u8; 8] = [143, 190, 90, 218, 196, 30, 51, 222];
13 pub const SWAP_BASE_OUT: [u8; 8] = [55, 217, 98, 86, 163, 74, 180, 173];
14 pub const INITIALIZE: [u8; 8] = [175, 175, 109, 31, 13, 152, 155, 237];
15 pub const DEPOSIT: [u8; 8] = [242, 35, 198, 137, 82, 225, 242, 182];
16 pub const WITHDRAW: [u8; 8] = [183, 18, 70, 156, 148, 109, 161, 34];
17}
18
19pub const PROGRAM_ID_PUBKEY: Pubkey = program_ids::RAYDIUM_CPMM_PROGRAM_ID;
21
22pub fn parse_instruction(
24 instruction_data: &[u8],
25 accounts: &[Pubkey],
26 signature: Signature,
27 slot: u64,
28 tx_index: u64,
29 block_time: Option<i64>,
30) -> Option<DexEvent> {
31 if instruction_data.len() < 8 {
32 return None;
33 }
34
35 let discriminator: [u8; 8] = instruction_data[0..8].try_into().ok()?;
36 let data = &instruction_data[8..];
37
38 match discriminator {
39 discriminators::SWAP_BASE_IN => {
40 parse_swap_base_in_instruction(data, accounts, signature, slot, tx_index, block_time)
41 },
42 discriminators::SWAP_BASE_OUT => {
43 parse_swap_base_out_instruction(data, accounts, signature, slot, tx_index, block_time)
44 },
45 discriminators::INITIALIZE => {
46 parse_initialize_instruction(data, accounts, signature, slot, tx_index, block_time)
47 },
48 discriminators::DEPOSIT => {
49 parse_deposit_instruction(data, accounts, signature, slot, tx_index, block_time)
50 },
51 discriminators::WITHDRAW => {
52 parse_withdraw_instruction(data, accounts, signature, slot, tx_index, block_time)
53 },
54 _ => None,
55 }
56}
57
58fn parse_swap_base_in_instruction(
60 data: &[u8],
61 accounts: &[Pubkey],
62 signature: Signature,
63 slot: u64,
64 tx_index: u64,
65 block_time: Option<i64>,
66) -> Option<DexEvent> {
67 let mut offset = 0;
68
69 let amount_in = read_u64_le(data, offset)?;
70 offset += 8;
71
72 let minimum_amount_out = read_u64_le(data, offset)?;
73
74 let pool = get_account(accounts, 0)?;
75 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
76
77 Some(DexEvent::RaydiumCpmmSwap(RaydiumCpmmSwapEvent {
78 metadata,
79
80 pool_id: Pubkey::default(), input_vault_before: 0, output_vault_before: 0, input_amount: 0, output_amount: 0, input_transfer_fee: 0, output_transfer_fee: 0, base_input: true,
89
90 }))
108}
109
110fn parse_swap_base_out_instruction(
112 data: &[u8],
113 accounts: &[Pubkey],
114 signature: Signature,
115 slot: u64,
116 tx_index: u64,
117 block_time: Option<i64>,
118) -> Option<DexEvent> {
119 let mut offset = 0;
120
121 let maximum_amount_in = read_u64_le(data, offset)?;
122 offset += 8;
123
124 let amount_out = read_u64_le(data, offset)?;
125
126 let pool = get_account(accounts, 0)?;
127 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
128
129 Some(DexEvent::RaydiumCpmmSwap(RaydiumCpmmSwapEvent {
130 metadata,
131
132 pool_id: Pubkey::default(), input_vault_before: 0, output_vault_before: 0, input_amount: 0, output_amount: 0, input_transfer_fee: 0, output_transfer_fee: 0, base_input: false,
141
142 }))
160}
161
162fn parse_initialize_instruction(
164 data: &[u8],
165 accounts: &[Pubkey],
166 signature: Signature,
167 slot: u64,
168 tx_index: u64,
169 block_time: Option<i64>,
170) -> Option<DexEvent> {
171 let mut offset = 0;
172
173 let init_amount0 = read_u64_le(data, offset)?;
174 offset += 8;
175
176 let init_amount1 = read_u64_le(data, offset)?;
177 offset += 8;
178
179 let open_time = read_u64_le(data, offset)?;
180
181 let pool = get_account(accounts, 0)?;
182 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
183
184 Some(DexEvent::RaydiumCpmmInitialize(RaydiumCpmmInitializeEvent {
185 metadata,
186 pool,
187 creator: get_account(accounts, 1).unwrap_or_default(),
188 init_amount0,
189 init_amount1,
190 }))
191}
192
193fn parse_deposit_instruction(
195 data: &[u8],
196 accounts: &[Pubkey],
197 signature: Signature,
198 slot: u64,
199 tx_index: u64,
200 block_time: Option<i64>,
201) -> Option<DexEvent> {
202 let mut offset = 0;
203
204 let lp_token_amount = read_u64_le(data, offset)?;
205 offset += 8;
206
207 let maximum_token_0_amount = read_u64_le(data, offset)?;
208 offset += 8;
209
210 let maximum_token_1_amount = read_u64_le(data, offset)?;
211
212 let pool = get_account(accounts, 0)?;
213 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
214
215 Some(DexEvent::RaydiumCpmmDeposit(RaydiumCpmmDepositEvent {
216 metadata,
217 pool,
218 user: get_account(accounts, 1).unwrap_or_default(),
219 lp_token_amount,
220 token0_amount: maximum_token_0_amount, token1_amount: maximum_token_1_amount, }))
223}
224
225fn parse_withdraw_instruction(
227 data: &[u8],
228 accounts: &[Pubkey],
229 signature: Signature,
230 slot: u64,
231 tx_index: u64,
232 block_time: Option<i64>,
233) -> Option<DexEvent> {
234 let mut offset = 0;
235
236 let lp_token_amount = read_u64_le(data, offset)?;
237 offset += 8;
238
239 let minimum_token_0_amount = read_u64_le(data, offset)?;
240 offset += 8;
241
242 let minimum_token_1_amount = read_u64_le(data, offset)?;
243
244 let pool = get_account(accounts, 0)?;
245 let metadata = create_metadata_simple(signature, slot, tx_index, block_time, pool);
246
247 Some(DexEvent::RaydiumCpmmWithdraw(RaydiumCpmmWithdrawEvent {
248 metadata,
249 pool,
250 user: get_account(accounts, 1).unwrap_or_default(),
251 lp_token_amount,
252 token0_amount: minimum_token_0_amount, token1_amount: minimum_token_1_amount, }))
255}