crema-cli 0.1.0

Blockchain, Crema for Solana
Documentation
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,
    }
}