use std::vec;
use borsh::{BorshDeserialize, BorshSerialize};
use solana_client::rpc_client::RpcClient;
use solana_program::instruction::{AccountMeta, Instruction};
use solana_program::msg;
use solana_program::pubkey::Pubkey;
use crate::contract::state::{Clmmpool, TickArray, TickArrayMap};
use crate::program::PROGRAM_ID;
use crate::utils::sighash;
#[derive(BorshSerialize, BorshDeserialize, Eq, PartialEq, Debug, Clone)]
pub struct SwapArgs {
a_to_b: bool,
by_amount_in: bool,
amount: u64,
amount_limit: u64,
sqrt_price_limit: u128,
}
#[allow(clippy::too_many_arguments)]
pub fn new_swap(
rpc_client: &RpcClient,
clmmpool: &Pubkey,
token_a: &Pubkey,
token_b: &Pubkey,
account_a: &Pubkey,
account_b: &Pubkey,
token_a_vault: &Pubkey,
token_b_vault: &Pubkey,
tick_array_map: &Pubkey,
a_to_b: bool,
amount: u64,
amount_limit: u64,
sqrt_price_limit: u128,
by_amount_in: bool,
payer: Pubkey,
) -> Instruction {
let data = &SwapArgs {
a_to_b,
by_amount_in,
amount,
amount_limit,
sqrt_price_limit,
};
msg!("swap args:{:?}", data);
let mut dsa = data.try_to_vec().unwrap();
let mut distor = sighash::sighash("global", "swap").to_vec();
distor.append(&mut dsa);
let data = rpc_client.get_account_data(clmmpool).unwrap();
let clmmpool_info: Clmmpool = Clmmpool::try_from_slice(&data[8..]).unwrap();
let tick_map_address = Clmmpool::get_tick_map_address(clmmpool);
let tick_map_data = rpc_client.get_account_data(&tick_map_address).unwrap();
let array_map: TickArrayMap = TickArrayMap::try_from_slice(&tick_map_data[8..]).unwrap();
let mut remaining_accounts: Vec<AccountMeta> = vec![];
let pool_array_index =
TickArray::array_index(clmmpool_info.current_tick_index, clmmpool_info.tick_spacing)
.unwrap() as usize;
let mut expect_array_index = if array_map.is_seted(pool_array_index) {
pool_array_index
} else {
array_map.next_seted(pool_array_index, a_to_b).unwrap()
};
for _ in 0..3 {
let array_adderss = TickArray::get_tick_array_address(clmmpool, expect_array_index as u16);
println!("array_index:{}|tick_array:{}", expect_array_index, array_adderss);
remaining_accounts.push(AccountMeta::new(array_adderss, false));
let next_idx = array_map.next_seted(expect_array_index, a_to_b);
if let Some(next_ix) = next_idx {
expect_array_index = next_ix;
} else {
break;
}
}
println!("remaing accounts len:{}", remaining_accounts.len());
let mut accounts = vec![
AccountMeta::new(*clmmpool, false),
AccountMeta::new_readonly(*token_a, false),
AccountMeta::new_readonly(*token_b, false),
AccountMeta::new(*account_a, false),
AccountMeta::new(*account_b, false),
AccountMeta::new(*token_a_vault, false),
AccountMeta::new(*token_b_vault, false),
AccountMeta::new(*tick_array_map, false),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(spl_token::id(), false),
];
accounts.extend(remaining_accounts);
Instruction {
program_id: PROGRAM_ID,
accounts,
data: distor,
}
}