use crate::core::events::*;
use solana_sdk::pubkey::Pubkey;
pub type AccountGetter<'a> = dyn Fn(usize) -> Pubkey + 'a;
pub fn fill_damm_v2_swap_accounts(
e: &mut MeteoraDammV2SwapEvent,
get: &AccountGetter<'_>,
account_count: usize,
) {
if !(13..=14).contains(&account_count) {
return;
}
e.pool_authority = get(0);
e.input_token_account = get(2);
e.output_token_account = get(3);
e.token_a_vault = get(4);
e.token_b_vault = get(5);
e.token_a_mint = get(6);
e.token_b_mint = get(7);
e.payer = get(8);
e.token_a_program = get(9);
e.token_b_program = get(10);
let authority_index = account_count - 2;
e.event_authority = get(authority_index);
e.program = get(account_count - 1);
e.referral_token_account = (account_count == 14 && get(11) != e.program).then(|| get(11));
}
#[cfg(test)]
mod damm_swap_tests {
use super::*;
#[test]
fn optional_referral_is_not_the_program_placeholder() {
let accounts: Vec<_> = (0..14).map(|_| Pubkey::new_unique()).collect();
let mut event = MeteoraDammV2SwapEvent::default();
fill_damm_v2_swap_accounts(
&mut event,
&|i| accounts.get(i).copied().unwrap_or_default(),
14,
);
assert_eq!(event.token_a_mint, accounts[6]);
assert_eq!(event.payer, accounts[8]);
assert_eq!(event.referral_token_account, Some(accounts[11]));
assert_eq!(event.event_authority, accounts[12]);
assert_eq!(event.program, accounts[13]);
let mut without_referral = accounts.clone();
without_referral[11] = accounts[13];
fill_damm_v2_swap_accounts(
&mut event,
&|i| without_referral.get(i).copied().unwrap_or_default(),
14,
);
assert_eq!(event.referral_token_account, None);
let mut omitted = MeteoraDammV2SwapEvent::default();
fill_damm_v2_swap_accounts(
&mut omitted,
&|i| accounts.get(i).copied().unwrap_or_default(),
13,
);
assert_eq!(omitted.referral_token_account, None);
assert_eq!(omitted.event_authority, accounts[11]);
assert_eq!(omitted.program, accounts[12]);
}
#[test]
fn older_swap_json_defaults_new_accounts() {
let mut json = serde_json::to_value(MeteoraDammV2SwapEvent::default()).unwrap();
let map = json.as_object_mut().unwrap();
for field in [
"pool_authority",
"input_token_account",
"output_token_account",
"payer",
"referral_token_account",
"event_authority",
"program",
] {
map.remove(field);
}
let decoded: MeteoraDammV2SwapEvent = serde_json::from_value(json).unwrap();
assert_eq!(decoded.pool_authority, Pubkey::default());
assert_eq!(decoded.referral_token_account, None);
}
#[test]
fn invalid_account_count_does_not_panic_or_fill() {
let mut event = MeteoraDammV2SwapEvent::default();
fill_damm_v2_swap_accounts(&mut event, &|_| Pubkey::new_unique(), 0);
assert_eq!(event.token_a_mint, Pubkey::default());
}
}
pub fn fill_damm_v2_create_position_accounts(
_e: &mut MeteoraDammV2CreatePositionEvent,
_get: &AccountGetter<'_>,
) {
}
pub fn fill_damm_v2_close_position_accounts(
_e: &mut MeteoraDammV2ClosePositionEvent,
_get: &AccountGetter<'_>,
) {
}
pub fn fill_damm_v2_add_liquidity_accounts(
_e: &mut MeteoraDammV2AddLiquidityEvent,
_get: &AccountGetter<'_>,
) {
}
pub fn fill_damm_v2_remove_liquidity_accounts(
_e: &mut MeteoraDammV2RemoveLiquidityEvent,
_get: &AccountGetter<'_>,
) {
}
pub fn fill_damm_v2_initialize_pool_accounts(
e: &mut MeteoraDammV2InitializePoolEvent,
get: &AccountGetter<'_>,
) {
if e.creator == Pubkey::default() {
e.creator = get(0);
}
if e.position_nft_mint == Pubkey::default() {
e.position_nft_mint = get(1);
}
if e.pool == Pubkey::default() {
e.pool = get(6);
}
if e.position == Pubkey::default() {
e.position = get(7);
}
if e.token_a_mint == Pubkey::default() {
e.token_a_mint = get(8);
}
if e.token_b_mint == Pubkey::default() {
e.token_b_mint = get(9);
}
}
pub fn fill_pools_swap_accounts(_e: &mut MeteoraPoolsSwapEvent, _get: &AccountGetter<'_>) {
}
pub fn fill_pools_add_liquidity_accounts(
_e: &mut MeteoraPoolsAddLiquidityEvent,
_get: &AccountGetter<'_>,
) {
}
pub fn fill_pools_remove_liquidity_accounts(
_e: &mut MeteoraPoolsRemoveLiquidityEvent,
_get: &AccountGetter<'_>,
) {
}
pub fn fill_dlmm_swap_accounts(e: &mut MeteoraDlmmSwapEvent, get: &AccountGetter<'_>) {
const MEMO_PROGRAM: Pubkey = solana_sdk::pubkey!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
if e.pool == Pubkey::default() {
e.pool = get(0);
}
if e.user_token_in == Pubkey::default() {
e.user_token_in = get(4);
}
if e.user_token_out == Pubkey::default() {
e.user_token_out = get(5);
}
if e.token_x_mint == Pubkey::default() {
e.token_x_mint = get(6);
}
if e.token_y_mint == Pubkey::default() {
e.token_y_mint = get(7);
}
if e.reserve_x == Pubkey::default() {
e.reserve_x = get(2);
}
if e.reserve_y == Pubkey::default() {
e.reserve_y = get(3);
}
if e.oracle == Pubkey::default() {
e.oracle = get(8);
}
if e.token_x_program == Pubkey::default() {
e.token_x_program = get(11);
}
if e.token_y_program == Pubkey::default() {
e.token_y_program = get(12);
}
let is_swap2 = get(13) == MEMO_PROGRAM;
let program_idx = if is_swap2 { 15 } else { 14 };
let bins_start = if is_swap2 { 16 } else { 15 };
if e.bitmap_extension.is_none() {
let ext = get(1);
let program = get(program_idx);
if ext != Pubkey::default() && ext != e.pool && ext != program {
e.bitmap_extension = Some(ext);
}
}
if e.bin_arrays.is_empty() {
let mut bins = Vec::new();
let mut idx = bins_start;
while idx < bins_start + 16 {
let key = get(idx);
if key == Pubkey::default() {
break;
}
bins.push(key);
idx += 1;
}
e.bin_arrays = bins;
}
}
pub fn fill_dlmm_add_liquidity_accounts(
_e: &mut MeteoraDlmmAddLiquidityEvent,
_get: &AccountGetter<'_>,
) {
}
pub fn fill_dlmm_remove_liquidity_accounts(
_e: &mut MeteoraDlmmRemoveLiquidityEvent,
_get: &AccountGetter<'_>,
) {
}
#[cfg(test)]
mod dlmm_swap_tests {
use super::*;
#[test]
fn swap2_bin_arrays_start_after_memo_and_program() {
let memo = solana_sdk::pubkey!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
let mut accounts: Vec<_> = (0..18).map(|_| Pubkey::new_unique()).collect();
accounts[13] = memo;
let bin0 = accounts[16];
let bin1 = accounts[17];
let mut e = MeteoraDlmmSwapEvent::default();
fill_dlmm_swap_accounts(&mut e, &|i| accounts.get(i).copied().unwrap_or_default());
assert_eq!(e.bin_arrays, vec![bin0, bin1]);
assert_eq!(e.reserve_x, accounts[2]);
assert_eq!(e.oracle, accounts[8]);
}
#[test]
fn swap_v1_bin_arrays_start_at_15() {
let accounts: Vec<_> = (0..17).map(|_| Pubkey::new_unique()).collect();
let bin0 = accounts[15];
let bin1 = accounts[16];
let mut e = MeteoraDlmmSwapEvent::default();
fill_dlmm_swap_accounts(&mut e, &|i| accounts.get(i).copied().unwrap_or_default());
assert_eq!(e.bin_arrays, vec![bin0, bin1]);
}
}