use super::program_ids;
use super::utils::*;
use crate::core::events::*;
use solana_sdk::{pubkey::Pubkey, signature::Signature};
pub mod discriminators {
pub const SWAP_BASE_IN: [u8; 8] = [143, 190, 90, 218, 196, 30, 51, 222];
pub const SWAP_BASE_OUT: [u8; 8] = [55, 217, 98, 86, 163, 74, 180, 173];
pub const INITIALIZE: [u8; 8] = [175, 175, 109, 31, 13, 152, 155, 237];
pub const DEPOSIT: [u8; 8] = [242, 35, 198, 137, 82, 225, 242, 182];
pub const WITHDRAW: [u8; 8] = [183, 18, 70, 156, 148, 109, 161, 34];
}
pub const PROGRAM_ID_PUBKEY: Pubkey = program_ids::RAYDIUM_CPMM_PROGRAM_ID;
pub fn parse_instruction(
instruction_data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
if instruction_data.len() < 8 {
return None;
}
let discriminator: [u8; 8] = instruction_data[0..8].try_into().ok()?;
let data = &instruction_data[8..];
match discriminator {
discriminators::SWAP_BASE_IN => {
parse_swap_base_in_instruction(data, accounts, signature, slot, tx_index, block_time_us)
}
discriminators::SWAP_BASE_OUT => parse_swap_base_out_instruction(
data,
accounts,
signature,
slot,
tx_index,
block_time_us,
),
discriminators::INITIALIZE => {
parse_initialize_instruction(data, accounts, signature, slot, tx_index, block_time_us)
}
discriminators::DEPOSIT => {
parse_deposit_instruction(data, accounts, signature, slot, tx_index, block_time_us)
}
discriminators::WITHDRAW => {
parse_withdraw_instruction(data, accounts, signature, slot, tx_index, block_time_us)
}
_ => None,
}
}
fn parse_swap_base_in_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let _amount_in = read_u64_le(data, offset)?;
offset += 8;
let _minimum_amount_out = read_u64_le(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::RaydiumCpmmSwap(RaydiumCpmmSwapEvent {
metadata,
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,
}))
}
fn parse_swap_base_out_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let _maximum_amount_in = read_u64_le(data, offset)?;
offset += 8;
let _amount_out = read_u64_le(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::RaydiumCpmmSwap(RaydiumCpmmSwapEvent {
metadata,
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,
}))
}
fn parse_initialize_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let init_amount0 = read_u64_le(data, offset)?;
offset += 8;
let init_amount1 = read_u64_le(data, offset)?;
offset += 8;
let _open_time = read_u64_le(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::RaydiumCpmmInitialize(RaydiumCpmmInitializeEvent {
metadata,
pool,
creator: get_account(accounts, 1).unwrap_or_default(),
init_amount0,
init_amount1,
}))
}
fn parse_deposit_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let lp_token_amount = read_u64_le(data, offset)?;
offset += 8;
let maximum_token_0_amount = read_u64_le(data, offset)?;
offset += 8;
let maximum_token_1_amount = read_u64_le(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::RaydiumCpmmDeposit(RaydiumCpmmDepositEvent {
metadata,
pool,
user: get_account(accounts, 1).unwrap_or_default(),
lp_token_amount,
token0_amount: maximum_token_0_amount, token1_amount: maximum_token_1_amount, }))
}
fn parse_withdraw_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let lp_token_amount = read_u64_le(data, offset)?;
offset += 8;
let minimum_token_0_amount = read_u64_le(data, offset)?;
offset += 8;
let minimum_token_1_amount = read_u64_le(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::RaydiumCpmmWithdraw(RaydiumCpmmWithdrawEvent {
metadata,
pool,
user: get_account(accounts, 1).unwrap_or_default(),
lp_token_amount,
token0_amount: minimum_token_0_amount, token1_amount: minimum_token_1_amount, }))
}