use super::program_ids;
use super::utils::*;
use crate::core::events::*;
use solana_sdk::{pubkey::Pubkey, signature::Signature};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MeteoraDlmmInstruction {
InitializeLbPair = 0,
InitializeBinArray = 1,
AddLiquidity = 2,
AddLiquidityByWeight = 3,
AddLiquidityByStrategy = 4,
AddLiquidityByStrategyOneSide = 5,
AddLiquidityOneSide = 6,
RemoveLiquidity = 7,
InitializePosition = 8,
UpdatePosition = 9,
WithdrawIneligibleReward = 10,
Swap = 11,
ClaimReward = 12,
ClaimFee = 13,
ClosePosition = 14,
UpdateRewardFunder = 15,
UpdateRewardDuration = 16,
FundReward = 17,
InitializeReward = 18,
SetActivationSlot = 19,
UpdateWhitelistedWallet = 20,
MigratePosition = 21,
MigrateBinArray = 22,
UpdateFeesAndRewards = 23,
SwapWithPriceImpact = 24,
GoToABin = 25,
SetPreActivationSwapAddress = 26,
SetLockReleaseSlot = 27,
RemoveAllLiquidity = 28,
TogglePairStatus = 29,
UpdateSwapCapDeactivateSlot = 30,
CreateConfig = 31,
CreateClaimFeeOperator = 32,
CloseClaimFeeOperator = 33,
ClaimPartnerFee = 34,
ClaimProtocolFee = 35,
CloseConfig = 36,
SetPoolStatus = 37,
UpdateLockDuration = 38,
CreatePool = 39,
SetPresetParameter = 40,
RemovePresetParameter = 41,
}
pub const PROGRAM_ID_PUBKEY: Pubkey = program_ids::METEORA_DLMM_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.is_empty() {
return None;
}
let instruction_type = instruction_data[0];
let data = &instruction_data[1..];
match instruction_type {
0 => parse_initialize_lb_pair_instruction(
data,
accounts,
signature,
slot,
tx_index,
block_time_us,
),
1 => parse_initialize_bin_array_instruction(
data,
accounts,
signature,
slot,
tx_index,
block_time_us,
),
2 => parse_add_liquidity_instruction(
data,
accounts,
signature,
slot,
tx_index,
block_time_us,
),
7 => parse_remove_liquidity_instruction(
data,
accounts,
signature,
slot,
tx_index,
block_time_us,
),
8 => parse_initialize_position_instruction(
data,
accounts,
signature,
slot,
tx_index,
block_time_us,
),
11 => parse_swap_instruction(data, accounts, signature, slot, tx_index, block_time_us),
13 => parse_claim_fee_instruction(data, accounts, signature, slot, tx_index, block_time_us),
14 => parse_close_position_instruction(
data,
accounts,
signature,
slot,
tx_index,
block_time_us,
),
_ => None,
}
}
fn parse_initialize_lb_pair_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let active_id = read_u32_le(data, offset)? as i32;
offset += 4;
let bin_step = read_u16_le(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::MeteoraDlmmInitializePool(MeteoraDlmmInitializePoolEvent {
metadata,
pool,
creator: get_account(accounts, 1).unwrap_or_default(),
active_bin_id: active_id,
bin_step,
}))
}
fn parse_initialize_bin_array_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let offset = 0;
let index = read_u64_le(data, offset)? as i64;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::MeteoraDlmmInitializeBinArray(MeteoraDlmmInitializeBinArrayEvent {
metadata,
pool,
bin_array: get_account(accounts, 1).unwrap_or_default(),
index,
}))
}
fn parse_add_liquidity_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let _liquidity_parameter = read_bytes(data, offset, 32)?;
offset += 32;
let amounts = read_vec_u64(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::MeteoraDlmmAddLiquidity(MeteoraDlmmAddLiquidityEvent {
metadata,
pool,
from: get_account(accounts, 1).unwrap_or_default(),
position: get_account(accounts, 2).unwrap_or_default(),
amounts: [amounts.get(0).copied().unwrap_or(0), amounts.get(1).copied().unwrap_or(0)],
active_bin_id: 0, }))
}
fn parse_remove_liquidity_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let _bin_liquidity_removal = read_bytes(data, offset, 32)?;
offset += 32;
let amounts = read_vec_u64(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::MeteoraDlmmRemoveLiquidity(MeteoraDlmmRemoveLiquidityEvent {
metadata,
pool,
from: get_account(accounts, 1).unwrap_or_default(),
position: get_account(accounts, 2).unwrap_or_default(),
amounts: [amounts.get(0).copied().unwrap_or(0), amounts.get(1).copied().unwrap_or(0)],
active_bin_id: 0, }))
}
fn parse_initialize_position_instruction(
data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let mut offset = 0;
let lower_bin_id = read_u32_le(data, offset)? as i32;
offset += 4;
let width = read_u32_le(data, offset)?;
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::MeteoraDlmmCreatePosition(MeteoraDlmmCreatePositionEvent {
metadata,
pool,
position: get_account(accounts, 1).unwrap_or_default(),
owner: get_account(accounts, 2).unwrap_or_default(),
lower_bin_id,
width,
}))
}
fn parse_swap_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 _min_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::MeteoraDlmmSwap(MeteoraDlmmSwapEvent {
metadata,
pool,
from: get_account(accounts, 1).unwrap_or_default(),
start_bin_id: 0, end_bin_id: 0, amount_in,
amount_out: 0, swap_for_y: false, fee: 0, protocol_fee: 0, fee_bps: 0, host_fee: 0, }))
}
fn parse_claim_fee_instruction(
_data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::MeteoraDlmmClaimFee(MeteoraDlmmClaimFeeEvent {
metadata,
pool,
position: get_account(accounts, 1).unwrap_or_default(),
owner: get_account(accounts, 2).unwrap_or_default(),
fee_x: 0, fee_y: 0, }))
}
fn parse_close_position_instruction(
_data: &[u8],
accounts: &[Pubkey],
signature: Signature,
slot: u64,
tx_index: u64,
block_time_us: Option<i64>,
) -> Option<DexEvent> {
let pool = get_account(accounts, 0)?;
let metadata = create_metadata_simple(signature, slot, tx_index, block_time_us, pool);
Some(DexEvent::MeteoraDlmmClosePosition(MeteoraDlmmClosePositionEvent {
metadata,
pool,
position: get_account(accounts, 1).unwrap_or_default(),
owner: get_account(accounts, 2).unwrap_or_default(),
}))
}