clmm-common 0.1.39

Blockchain, Clmm for Solana
Documentation
use solana_client::rpc_client::RpcClient;
use solana_program::instruction::{AccountMeta, Instruction};
use solana_program::pubkey::Pubkey;
use spl_associated_token_account::get_associated_token_address;

use crate::program::{SWAP_PROGRAM_ID};
use crate::utils::sighash;
use crate::command::CliConfig;
use crate::contract::instructions::tick::get_tick_info;
use crate::contract::state::{Clmmpool, TickArray};
use crate::contract::state::position::Position;
use crate::contract::state::tick::Tick;

pub fn new_collect_fee(
    clmmpool: &Pubkey,
    position: &Pubkey,
    position_ata: &Pubkey,
    token_a_ata: &Pubkey,
    token_b_ata: &Pubkey,
    token_a_vault: &Pubkey,
    token_b_vault: &Pubkey,
    tick_array_lower: &Pubkey,
    tick_array_upper: &Pubkey,
    payer: Pubkey,
) -> Instruction {
    let distor = sighash::sighash("global", "collect_fee").to_vec();
    Instruction {
        program_id: SWAP_PROGRAM_ID,
        accounts: vec![
            AccountMeta::new(payer, true),
            AccountMeta::new_readonly(*clmmpool, false),
            AccountMeta::new(*position, false),
            AccountMeta::new_readonly(*position_ata, false),
            AccountMeta::new(*token_a_ata, false),
            AccountMeta::new(*token_b_ata, false),
            AccountMeta::new(*token_a_vault, false),
            AccountMeta::new(*token_b_vault, false),
            AccountMeta::new_readonly(*tick_array_lower, false),
            AccountMeta::new_readonly(*tick_array_upper, false),
            AccountMeta::new_readonly(spl_token::id(), false),
        ],
        data: distor,
    }
}


pub fn new_collect_fee_tx(
    rpc_client: &RpcClient,
    config: &CliConfig,
    mint: &Pubkey,
) -> Option<Instruction> {
    let (position, _) = Pubkey::find_program_address(
        &[b"position", mint.as_ref()],
        &SWAP_PROGRAM_ID,
    );
    let mut position_info = Position::get_info(rpc_client, &position);

    let clmmpool_info = Clmmpool::get_info(rpc_client, &position_info.clmmpool);

    let position_ata =
        get_associated_token_address(&config.pubkey().unwrap(), &position_info.position_nft_mint);
    let token_a_ata =
        get_associated_token_address(&config.pubkey().unwrap(), &clmmpool_info.token_a);
    let token_b_ata =
        get_associated_token_address(&config.pubkey().unwrap(), &clmmpool_info.token_b);

    let array_lower_index =
        TickArray::array_index(position_info.tick_lower_index, clmmpool_info.tick_spacing).unwrap();
    let (tick_array_lower_pubkey, _) = TickArray::calculate_tick_array_key(
        position_info.clmmpool.as_ref(),
        array_lower_index.to_le_bytes().as_ref(),
    );

    let array_upper_index =
        TickArray::array_index(position_info.tick_upper_index, clmmpool_info.tick_spacing).unwrap();
    let (tick_array_upper_pubkey, _) = TickArray::calculate_tick_array_key(
        position_info.clmmpool.as_ref(),
        array_upper_index.to_le_bytes().as_ref(),
    );

    let tick_lower = get_tick_info(rpc_client, position_info.tick_lower_index, &position_info.clmmpool);
    let tick_upper = get_tick_info(rpc_client, position_info.tick_upper_index, &position_info.clmmpool);

    let (fee_growth_inside_a, fee_growth_inside_b) = Tick::get_fee_in_tick_range(&clmmpool_info, Some(&tick_lower), Some(&tick_upper), position_info.tick_lower_index, position_info.tick_upper_index);
    position_info.update_fee(fee_growth_inside_a, fee_growth_inside_b);

    if position_info.fee_owed_a == 0 && position_info.fee_owed_b == 0 {
        return None;
    }

    Some(new_collect_fee(
        &position_info.clmmpool,
        &position,
        &position_ata,
        &token_a_ata,
        &token_b_ata,
        &clmmpool_info.token_a_vault,
        &clmmpool_info.token_b_vault,
        &tick_array_lower_pubkey,
        &tick_array_upper_pubkey,
        config.pubkey().unwrap(),
    ))
}