defituna-client 3.6.1

Rust client to interact with DefiTuna's on-chain program.
Documentation
use crate::accounts::{fetch_all_vault, fetch_market, fetch_tuna_lp_position};
use crate::utils::get_create_ata_instructions;
use crate::{
    close_tuna_lp_position_orca_instruction, decrease_tuna_lp_position_orca_instruction, get_market_address, get_tuna_liquidity_position_address,
    CloseActiveTunaLpPositionArgs, DecreaseTunaLpPositionArgs, HUNDRED_PERCENT,
};
use anyhow::{anyhow, Result};
use orca_whirlpools_client::fetch_whirlpool;
use solana_client::rpc_client::RpcClient;
use solana_instruction::Instruction;
use solana_pubkey::Pubkey;

// TODO: rewards support
pub fn close_active_tuna_lp_position_orca_instructions(
    rpc: &RpcClient,
    authority: &Pubkey,
    position_mint: &Pubkey,
    args: CloseActiveTunaLpPositionArgs,
) -> Result<Vec<Instruction>> {
    let tuna_position = fetch_tuna_lp_position(&rpc, &get_tuna_liquidity_position_address(&position_mint).0)?;

    let whirlpool = fetch_whirlpool(rpc, &tuna_position.data.pool)?;
    let mint_a_address = whirlpool.data.token_mint_a;
    let mint_b_address = whirlpool.data.token_mint_b;

    let market_address = get_market_address(&tuna_position.data.pool).0;
    let market = fetch_market(&rpc, &market_address)?;

    let vaults = fetch_all_vault(&rpc, &[market.data.vault_a, market.data.vault_b])?;
    let (vault_a, vault_b) = (&vaults[0], &vaults[1]);

    let mut all_mint_addresses = vec![mint_a_address, mint_b_address];
    for reward_info in &whirlpool.data.reward_infos {
        if reward_info.mint != Pubkey::default() {
            all_mint_addresses.push(reward_info.mint);
        }
    }

    let mint_accounts = rpc.get_multiple_accounts(all_mint_addresses[0..all_mint_addresses.len()].into())?;
    let mint_a_account = mint_accounts[0].as_ref().ok_or(anyhow!("Token A mint account not found"))?;
    let mint_b_account = mint_accounts[1].as_ref().ok_or(anyhow!("Token B mint account not found"))?;

    let authority_ata_a_instructions = get_create_ata_instructions(&mint_a_address, authority, authority, &mint_a_account.owner, 0);
    let authority_ata_b_instructions = get_create_ata_instructions(&mint_b_address, authority, authority, &mint_b_account.owner, 0);

    let mut instructions = vec![];
    instructions.extend(authority_ata_a_instructions.create);
    instructions.extend(authority_ata_b_instructions.create);

    instructions.push(decrease_tuna_lp_position_orca_instruction(
        authority,
        &tuna_position.data,
        &vault_a.address,
        &vault_a.data,
        &vault_b.address,
        &vault_b.data,
        &whirlpool.data,
        &mint_a_account.owner,
        &mint_b_account.owner,
        DecreaseTunaLpPositionArgs {
            decrease_percent: HUNDRED_PERCENT,
            swap_to_token: args.swap_to_token,
            min_removed_amount_a: args.min_removed_amount_a,
            min_removed_amount_b: args.min_removed_amount_b,
            max_swap_slippage: args.max_swap_slippage,
        },
    ));

    instructions.extend(authority_ata_a_instructions.cleanup);
    instructions.extend(authority_ata_b_instructions.cleanup);

    instructions.push(close_tuna_lp_position_orca_instruction(&authority, &tuna_position.data, &mint_a_account.owner, &mint_b_account.owner));

    Ok(instructions)
}