crema-cli 0.1.0

Blockchain, Crema for Solana
Documentation
use std::sync::Arc;

use solana_clap_utils::keypair::{CliSigners, DefaultSigner};
use solana_cli_output::OutputFormat;
use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::signer::{Signer, SignerError};

use {
    clap::ArgMatches,
    solana_client::rpc_client::RpcClient,
    solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey},
    std::{error, time::Duration},
    thiserror::Error,
};

use crate::{
    clmmpool::ticks::{
        price::{parse_tick_price_info, process_tick_price_info},
        tick::{parse_tick_info, process_tick_info},
        tick_array::{parse_tick_array_info, process_tick_array_info},
        tick_map::{parse_tick_map_info, process_tick_map_info},
    },
    math::price::{
        parse_sqrt_price_to_tick, parse_tick_to_sqrt_price, process_sqrt_price_to_tick,
        process_tick_to_sqrt_price,
    },
};
use crate::clmmpool::farming::mine_rewarder::info::{parse_farming_mine_rewarder_info, process_farming_mine_rewarder_info};
use crate::clmmpool::farming::mine_rewarder::list::{parse_farming_mine_rewarder_list, process_farming_mine_rewarder_list};
use crate::clmmpool::farming::mine_rewarder::new::{parse_farming_mine_rewarder_new, process_farming_mine_rewarder_new};
use crate::clmmpool::farming::mine_rewarder::set_annual_rate::{parse_farming_mine_rewarder_set_annual_rate, process_farming_mine_rewarder_set_annual_rate};
use crate::clmmpool::farming::mine_rewarder::sync_quarry_rewards::{parse_farming_mine_rewarder_sync_quarry_rewards, process_farming_mine_rewarder_sync_quarry_rewards};
use crate::clmmpool::farming::mint_wrapper::back_authority::{parse_farming_mint_wrapper_back_authority, process_farming_mint_wrapper_back_authority};
use crate::clmmpool::farming::mint_wrapper::info::{parse_farming_mint_wrapper_info, process_farming_mint_wrapper_info};
use crate::clmmpool::farming::mint_wrapper::list::{parse_farming_mint_wrapper_list, process_farming_mint_wrapper_list};
use crate::clmmpool::farming::mint_wrapper::new::{parse_farming_mint_wrapper_new, process_farming_mint_wrapper_new};
use crate::clmmpool::farming::mint_wrapper::transfer_authority::{parse_farming_mint_wrapper_transfer_authority, process_farming_mint_wrapper_transfer_authority};
use crate::clmmpool::farming::minter::info::{parse_farming_minter_info, process_farming_minter_info};
use crate::clmmpool::farming::minter::list::{parse_farming_minter_list, process_farming_minter_list};
use crate::clmmpool::farming::minter::mint::{parse_farming_minter_mint, process_farming_minter_mint};
use crate::clmmpool::farming::minter::new::{parse_farming_minter_new, process_farming_minter_new};
use crate::clmmpool::farming::minter::update::{parse_farming_minter_update, process_farming_minter_update};
use crate::clmmpool::farming::quarry_mine::info::{parse_farming_quarry_mine_info, process_farming_quarry_mine_info};
use crate::clmmpool::farming::quarry_mine::list::{parse_farming_quarry_mine_list, process_farming_quarry_mine_list};
use crate::clmmpool::farming::quarry_mine::new::{parse_farming_quarry_mine_new, process_farming_quarry_mine_new};
use crate::clmmpool::farming::quarry_mine::set_famine::{parse_farming_quarry_set_famine, process_farming_quarry_set_famine};
use crate::clmmpool::farming::quarry_mine::update_share::{parse_farming_quarry_update_share, process_farming_quarry_update_share};
use crate::clmmpool::fee_tier::fee_tier::{parse_fee_tier_info, process_fee_tier_info};


use crate::clmmpool::pair::config::{parse_config_info, process_config_info};


use crate::clmmpool::pair::create_config::{
    parse_create_config, parse_create_config_template, process_create_config,
    process_create_config_template,
};
use crate::clmmpool::pair::create_fee_tier::{
    parse_create_fee_tier, parse_create_fee_tier_template, process_create_fee_tier,
    process_create_fee_tier_template,
};
use crate::clmmpool::pair::create_pool::{
    parse_create_pool, parse_create_pool_template, process_create_pool,
    process_create_pool_template,
};
use crate::clmmpool::pair::create_tick_array::{
    process_create_tick_array, process_create_tick_array_template,
};
use crate::clmmpool::pair::pair::{parse_pair_info, process_pair_info};
use crate::clmmpool::pair::partner::{parse_partner_info, process_partner_info};
use crate::clmmpool::pair::swap::{parse_swap, process_swap};
use crate::clmmpool::pair::transfer_protocol_fee_authority::{
    parse_transfer_protocol_fee_authority, process_transfer_protocol_fee_authority,
};
use crate::clmmpool::pair::update_config_protocol_fee_rate::{
    parse_update_config_protocol_fee_rate, process_update_config_protocol_fee_rate,
};
use crate::clmmpool::pair::update_fee_rate::{parse_update_fee_rate, process_update_fee_rate};
use crate::clmmpool::pair::update_partner::{parse_update_partner, process_update_partner};
use crate::clmmpool::pair::update_protocol_fee_rate::{
    parse_update_protocol_fee_rate, process_update_protocol_fee_rate,
};
use crate::clmmpool::pair::{
    accept_protocol_fee_authority::{
        parse_accept_protocol_fee_authority, process_accept_protocol_fee_authority,
    },
    create_tick_array::{parse_create_tick_array, parse_create_tick_array_template},
};
use crate::clmmpool::pair::{
    collect_partner_fee::{parse_collect_partner_fee, process_collect_partner_fee},
    create_partner::{process_create_partner, process_create_partner_template},
};
use crate::clmmpool::pair::{
    collect_protocol_fee::{parse_collect_protocol_fee, process_collect_protocol_fee},
    create_partner::{parse_create_partner, parse_create_partner_template},
};
use crate::clmmpool::position::{parse_position_info, process_position_info};
use crate::clmmpool::position::collect_fee::{parse_collect_fee, process_collect_fee};
use crate::clmmpool::position::decrease_liquidity::{
    parse_decrease_liquidity, process_decrease_liquidity,
};
use crate::clmmpool::position::increase_liquidity::{
    parse_increase_liquidity, process_increase_liquidity,
};
use crate::clmmpool::position::open_position::{parse_open_position, process_open_position};
use crate::clmmpool::position::remove_position::{parse_remove_position, process_remove_position};

#[derive(Debug, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub enum CliCommand<'a> {
    // Pair Command
    PairAcceptProtocolFeeAuthority {
        clmm_config: Pubkey,
    },
    PairCollectFee {
        mint: Pubkey,
    },
    PairCollectPartnerFee {
        partner: Pubkey,
        clmmpool: Pubkey,
    },
    PairCollectProtocolFee {
        clmmpool: Pubkey,
    },
    PairCreatePoolTemplate {
        output_file: &'a str,
    },
    PairCreatePool {
        entry_file: &'a str,
    },
    PairInfo {
        pair_key: Pubkey,
    },
    PairTicks,
    PairConfigCreateTemplate {
        output_file: &'a str,
    },
    PairConfigCreate {
        entry_file: &'a str,
    },
    PairConfigInfo {
        config_key: Pubkey,
    },
    PairFeeTierCreateTemplate {
        output_file: &'a str,
    },
    PairFeeTierCreate {
        entry_file: &'a str,
    },
    PairFeeTierInfo {
        fee_tier: Pubkey,
    },
    PairPartnerCreateTemplate {
        output_file: &'a str,
    },
    PairPartnerCreate {
        entry_file: &'a str,
    },
    PairPartnerInfo {
        partner: Pubkey,
    },
    PairTickArrayCreateTemplate {
        output_file: &'a str,
    },
    PairTickArrayCreate {
        entry_file: &'a str,
    },
    PairTransferProtocolFeeAuthority {
        clmm_config: Pubkey,
        new_authority: Pubkey,
    },
    PairConfigProtocolFeeRateUpdate {
        clmm_config: Pubkey,
        new_protocol_fee_rate: u16,
    },
    PairFeeRateUpdate {
        fee_tier: Pubkey,
        clmmpool: Pubkey,
    },
    PairPartnerUpdate {
        partner: Pubkey,
        new_fee_rate: Option<u16>,
        new_claim_authority: Option<Pubkey>,
    },
    PairProtocolFeeRateUpdate {
        clmmpool: Pubkey,
    },

    PairSwap {
        clmmpool: Pubkey,
        a_to_b: bool,
        by_amount_in: bool,
        price_limit_tick: i32,
        amount: f64,
        slid: f64,
    },

    // Position Command
    PositionOpen {
        clmmpool: Pubkey,
        tick_lower_index: i32,
        tick_upper_index: i32,
    },
    PositionRemove {
        mint: Pubkey,
    },
    PositionDecrease {
        mint: Pubkey,
        amount_a: f64,
        amount_b: f64,
        slid: f64,
    },
    PositionIncrease {
        mint: Pubkey,
        amount_a: f64,
        amount_b: f64,
        slid: f64,
    },
    PositionList,
    PositionInfo {
        mint: Pubkey,
    },

    TickInfo {
        pool: Pubkey,
        tick_index: i32,
    },
    TickArrayIndex {
        pool: Pubkey,
        tick_index: Option<i32>,
        array_index: Option<u16>,
    },
    TickMapInfo {
        pool: Pubkey,
        array_index: u16,
    },
    TickPrice {
        tick: i32,
    },
    // Math Command
    MathTickToSqrtPrice {
        tick: i32,
    },
    MathSqrtPriceToTick {
        price: u128,
    },
    MathTokenAMount,
    MathLiquity,
    MathDecodeDepositFixToken,

    // farming
    // quarry-mine
    FarmingQuarryMineNew {
        rewarder: Pubkey,
        mint: Pubkey,
        famine_ts: u64,
        share: u64,
    },
    FarmingQuarryMineList,
    FarmingQuarryMineInfo {
        rewarder: Pubkey,
        mint: Pubkey,
    },
    FarmingQuarryUpdateShare {
        rewarder: Pubkey,
        mint: Pubkey,
        share: u64,
    },
    FarmingQuarrySetFamine {
        rewarder: Pubkey,
        mint: Pubkey,
        ts: u64,
    },

    // mine-rewarder
    FarmingMineRewarderNew {
        wrapper: Pubkey,
        annual_rate: u64,
    },
    FarmingMineRewarderList,
    FarmingMineRewarderInfo {
        rewarder: Pubkey,
    },
    FarmingMineRewarderSetAnnualRate {
        rewarder: Pubkey,
        rate: u64,
    },
    FarmingMineRewarderSyncQuarryRewards {
        rewarder: Pubkey,
        mint: &'a str,
    },

    // mint_wrapper
    FarmingMintWrapperNew {
        mint: Pubkey,
        hardcap: u64,
    },
    FarmingMintWrapperList,
    FarmingMintWrapperInfo {
        wrapper: Pubkey,
    },
    FarmingMintWrapperBackAuthority {
        wrapper: Pubkey,
        authority: Pubkey,
    },
    FarmingMintWrapperTransferAuthority {
        wrapper: Pubkey,
    },

    // minter
    FarmingMinterNew {
        wrapper: Pubkey,
        allowance: u64,
        authority: Pubkey,
    },
    FarmingMinterList {
        wrapper: &'a str,
    },
    FarmingMinterInfo {
        wrapper: Pubkey,
        authority: Pubkey,
    },
    FarmingMinterUpdate {
        wrapper: Pubkey,
        allowance: u64,
        authority: Pubkey,
    },
    FarmingMinterMint {
        wrapper: Pubkey,
        owner: Pubkey,
        amount: f64,
    },
}

#[derive(Debug, Error)]
pub enum CliError {
    #[error("RPC request error: {0}")]
    RpcRequestError(String),
    #[error("One of amountb and amountb must be non-null")]
    LiquidityRequestParamError(),
}

impl From<Box<dyn error::Error>> for CliError {
    fn from(error: Box<dyn error::Error>) -> Self {
        CliError::RpcRequestError(error.to_string())
    }
}

pub struct CliConfig<'a> {
    pub command: CliCommand<'a>,
    pub signers: Vec<Box<dyn Signer>>,
    pub json_rpc_url: String,
    pub rpc_timeout: Duration,
    pub commitment: CommitmentConfig,
    pub confirm_transaction_initial_timeout: Duration,
    pub output_format: OutputFormat,
}

impl CliConfig<'_> {
    pub(crate) fn pubkey(&self) -> Result<Pubkey, SignerError> {
        if !self.signers.is_empty() {
            self.signers[0].try_pubkey()
        } else {
            Err(SignerError::Custom(
                "Default keypair must be set if pubkey arg not provided".to_string(),
            ))
        }
    }
}

pub fn parse_command<'a>(
    matches: &'a ArgMatches,
    default_signer: &DefaultSigner,
    wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo<'a>, Box<dyn error::Error>> {
    let response = match matches.subcommand() {
        ("pair", Some(matches)) => match matches.subcommand() {
            ("accept_protocol_fee_authority", Some(matches)) => {
                parse_accept_protocol_fee_authority(matches, default_signer, wallet_manager)
            }
            ("collect_fee", Some(matches)) => {
                parse_collect_fee(matches, default_signer, wallet_manager)
            }
            ("collect_partner_fee", Some(matches)) => {
                parse_collect_partner_fee(matches, default_signer, wallet_manager)
            }
            ("collect_protocol_fee", Some(matches)) => {
                parse_collect_protocol_fee(matches, default_signer, wallet_manager)
            }
            ("create-pool-template", Some(matches)) => parse_create_pool_template(matches),
            ("create-pool", Some(matches)) => {
                parse_create_pool(matches, default_signer, wallet_manager)
            }
            ("info", Some(matches)) => parse_pair_info(matches, default_signer, wallet_manager),
            ("ticks", Some(matches)) => parse_create_pool_template(matches),
            ("create-config-template", Some(matches)) => parse_create_config_template(matches),
            ("create-config", Some(matches)) => {
                parse_create_config(matches, default_signer, wallet_manager)
            }
            ("config-info", Some(matches)) => parse_config_info(matches),
            ("create-fee-tier-template", Some(matches)) => parse_create_fee_tier_template(matches),
            ("create-fee-tier", Some(matches)) => {
                parse_create_fee_tier(matches, default_signer, wallet_manager)
            }
            ("fee-tier-info", Some(matches)) => parse_fee_tier_info(matches),
            ("create-partner-template", Some(matches)) => parse_create_partner_template(matches),
            ("create-partner", Some(matches)) => {
                parse_create_partner(matches, default_signer, wallet_manager)
            }
            ("partner-info", Some(matches)) => parse_partner_info(matches),
            ("create-tick-array-template", Some(matches)) => {
                parse_create_tick_array_template(matches)
            }
            ("create-tick-array", Some(matches)) => {
                parse_create_tick_array(matches, default_signer, wallet_manager)
            }
            ("transfer_protocol_fee_authority", Some(matches)) => {
                parse_transfer_protocol_fee_authority(matches, default_signer, wallet_manager)
            }
            ("update_config_protocol_fee_rate", Some(matches)) => {
                parse_update_config_protocol_fee_rate(matches, default_signer, wallet_manager)
            }
            ("update_fee_rate", Some(matches)) => {
                parse_update_fee_rate(matches, default_signer, wallet_manager)
            }
            ("update_partner", Some(matches)) => {
                parse_update_partner(matches, default_signer, wallet_manager)
            }
            ("update_protocol_fee_rate", Some(matches)) => {
                parse_update_protocol_fee_rate(matches, default_signer, wallet_manager)
            }
            ("swap", Some(matches)) => parse_swap(matches, default_signer, wallet_manager),
            _ => unreachable!(),
        },

        ("pos", Some(matches)) => match matches.subcommand() {
            ("incr", Some(matches)) => {
                parse_increase_liquidity(matches, default_signer, wallet_manager)
            }
            ("decr", Some(matches)) => {
                parse_decrease_liquidity(matches, default_signer, wallet_manager)
            }
            ("open", Some(matches)) => parse_open_position(matches, default_signer, wallet_manager),
            ("remove", Some(matches)) => {
                parse_remove_position(matches, default_signer, wallet_manager)
            }
            ("list", Some(matches)) => parse_position_info(matches, default_signer, wallet_manager),
            ("info", Some(matches)) => parse_position_info(matches, default_signer, wallet_manager),
            _ => unreachable!(),
        },
        ("ticks", Some(matches)) => match matches.subcommand() {
            ("tick", Some(matches)) => parse_tick_info(matches, default_signer, wallet_manager),
            ("array", Some(matches)) => {
                parse_tick_array_info(matches, default_signer, wallet_manager)
            }
            ("map", Some(matches)) => parse_tick_map_info(matches, default_signer, wallet_manager),
            ("price", Some(matches)) => {
                parse_tick_price_info(matches, default_signer, wallet_manager)
            }
            _ => unreachable!(),
        },
        ("math", Some(matches)) => match matches.subcommand() {
            ("tick_to_sqrt_price", Some(matches)) => parse_tick_to_sqrt_price(matches),
            ("sqrt_price_to_tick", Some(matches)) => parse_sqrt_price_to_tick(matches),
            ("token-amount", Some(matches)) => parse_create_pool_template(matches),
            ("liquity", Some(matches)) => parse_create_pool_template(matches),
            ("decode-deposit-fix-token", Some(matches)) => parse_create_pool_template(matches),
            _ => unreachable!(),
        },

        ("farming", Some(matches)) => match matches.subcommand() {
            ("quarry-mine", Some(matches)) => match matches.subcommand() {
                ("new", Some(matches)) => parse_farming_quarry_mine_new(matches, default_signer, wallet_manager),
                ("list", Some(matches)) => parse_farming_quarry_mine_list(matches, default_signer, wallet_manager),
                ("info", Some(matches)) => parse_farming_quarry_mine_info(matches, default_signer, wallet_manager),
                ("update-share", Some(matches)) => parse_farming_quarry_update_share(matches, default_signer, wallet_manager),
                ("set-famine", Some(matches)) => parse_farming_quarry_set_famine(matches, default_signer, wallet_manager),
                _ => unreachable!(),
            }

            ("mine-rewarder", Some(matches)) => match matches.subcommand() {
                ("new", Some(matches)) => parse_farming_mine_rewarder_new(matches, default_signer, wallet_manager),
                ("list", Some(matches)) => parse_farming_mine_rewarder_list(matches, default_signer, wallet_manager),
                ("info", Some(matches)) => parse_farming_mine_rewarder_info(matches, default_signer, wallet_manager),
                ("set-annual-rate", Some(matches)) => parse_farming_mine_rewarder_set_annual_rate(matches, default_signer, wallet_manager),
                ("sync-quarry-rewards", Some(matches)) => parse_farming_mine_rewarder_sync_quarry_rewards(matches, default_signer, wallet_manager),
                _ => unreachable!(),
            }

            ("mint-wrapper", Some(matches)) => match matches.subcommand() {
                ("new", Some(matches)) => parse_farming_mint_wrapper_new(matches, default_signer, wallet_manager),
                ("list", Some(matches)) => parse_farming_mint_wrapper_list(matches, default_signer, wallet_manager),
                ("info", Some(matches)) => parse_farming_mint_wrapper_info(matches, default_signer, wallet_manager),
                ("back-authority", Some(matches)) => parse_farming_mint_wrapper_back_authority(matches, default_signer, wallet_manager),
                ("transfer-authority", Some(matches)) => parse_farming_mint_wrapper_transfer_authority(matches, default_signer, wallet_manager),
                _ => unreachable!(),
            }

            ("minter", Some(matches)) => match matches.subcommand() {
                ("new", Some(matches)) => parse_farming_minter_new(matches, default_signer, wallet_manager),
                ("list", Some(matches)) => parse_farming_minter_list(matches, default_signer, wallet_manager),
                ("info", Some(matches)) => parse_farming_minter_info(matches, default_signer, wallet_manager),
                ("update", Some(matches)) => parse_farming_minter_update(matches, default_signer, wallet_manager),
                ("mint", Some(matches)) => parse_farming_minter_mint(matches, default_signer, wallet_manager),
                _ => unreachable!(),
            }
            _ => unreachable!(),
        },

        _ => unreachable!(),
    }?;
    Ok(response)
}

pub type ProcessResult = Result<String, Box<dyn std::error::Error>>;

pub fn process_result_from_str(msg: &str) -> ProcessResult {
    Err(Box::<dyn std::error::Error>::from(msg))
}

pub fn process_command(config: &mut CliConfig) -> ProcessResult {
    let rpc_client = RpcClient::new_with_timeouts_and_commitment(
        config.json_rpc_url.to_string(),
        config.rpc_timeout,
        config.commitment,
        config.confirm_transaction_initial_timeout,
    );

    match config.command {
        CliCommand::PairAcceptProtocolFeeAuthority { clmm_config } => {
            process_accept_protocol_fee_authority(&rpc_client, config, &clmm_config)
        }
        CliCommand::PairCollectFee { mint } => process_collect_fee(&rpc_client, config, &mint),
        CliCommand::PairCollectPartnerFee { partner, clmmpool } => {
            process_collect_partner_fee(&rpc_client, config, &partner, &clmmpool)
        }
        CliCommand::PairCollectProtocolFee { clmmpool } => {
            process_collect_protocol_fee(&rpc_client, config, &clmmpool)
        }
        CliCommand::PairCreatePoolTemplate { output_file } => {
            process_create_pool_template(output_file)
        }
        CliCommand::PairCreatePool { entry_file } => {
            process_create_pool(&rpc_client, config, entry_file)
        }
        CliCommand::PairPartnerCreateTemplate { output_file } => {
            process_create_partner_template(output_file)
        }
        CliCommand::PairPartnerCreate { entry_file } => {
            process_create_partner(&rpc_client, config, entry_file)
        }
        CliCommand::PairPartnerInfo { partner } => process_partner_info(&rpc_client, partner),
        CliCommand::PairTickArrayCreateTemplate { output_file } => {
            process_create_tick_array_template(output_file)
        }
        CliCommand::PairTickArrayCreate { entry_file } => {
            process_create_tick_array(&rpc_client, config, entry_file)
        }
        CliCommand::PairInfo { pair_key } => process_pair_info(&rpc_client, &pair_key),
        CliCommand::PairConfigCreateTemplate { output_file } => {
            process_create_config_template(output_file)
        }
        CliCommand::PairConfigCreate { entry_file } => {
            process_create_config(&rpc_client, config, entry_file)
        }
        CliCommand::PairConfigInfo { config_key } => process_config_info(&rpc_client, config_key),
        CliCommand::PairFeeTierCreateTemplate { output_file } => {
            process_create_fee_tier_template(output_file)
        }
        CliCommand::PairFeeTierCreate { entry_file } => {
            process_create_fee_tier(&rpc_client, config, entry_file)
        }
        CliCommand::PairFeeTierInfo { fee_tier } => process_fee_tier_info(&rpc_client, fee_tier),
        CliCommand::PairConfigProtocolFeeRateUpdate {
            clmm_config,
            new_protocol_fee_rate,
        } => process_update_config_protocol_fee_rate(
            &rpc_client,
            config,
            &clmm_config,
            &new_protocol_fee_rate,
        ),
        CliCommand::PairFeeRateUpdate { fee_tier, clmmpool } => {
            process_update_fee_rate(&rpc_client, config, &fee_tier, &clmmpool)
        }
        CliCommand::PairPartnerUpdate {
            partner,
            new_fee_rate,
            new_claim_authority,
        } => process_update_partner(
            &rpc_client,
            &config,
            &partner,
            &new_fee_rate,
            &new_claim_authority,
        ),
        CliCommand::PairProtocolFeeRateUpdate { clmmpool } => {
            process_update_protocol_fee_rate(&rpc_client, config, &clmmpool)
        }
        CliCommand::PairSwap {
            clmmpool,
            a_to_b,
            by_amount_in,
            price_limit_tick,
            amount,
            slid,
        } => process_swap(
            &rpc_client,
            config,
            &clmmpool,
            by_amount_in,
            price_limit_tick,
            a_to_b,
            &amount,
            &slid,
        ),
        CliCommand::PositionIncrease {
            mint,
            amount_a,
            amount_b,
            slid,
        } => process_increase_liquidity(&rpc_client, config, &mint, &amount_a, &amount_b, &slid),
        CliCommand::PositionDecrease {
            mint,
            amount_a,
            amount_b,
            slid,
        } => process_decrease_liquidity(&rpc_client, config, &mint, &amount_a, &amount_b, &slid),
        CliCommand::PositionOpen {
            clmmpool,
            tick_lower_index,
            tick_upper_index,
        } => process_open_position(
            &rpc_client,
            config,
            &clmmpool,
            &tick_lower_index,
            &tick_upper_index,
        ),
        CliCommand::PositionRemove { mint } => process_remove_position(&rpc_client, config, &mint),
        CliCommand::PositionInfo { mint } => process_position_info(&rpc_client, &mint),
        CliCommand::PairTransferProtocolFeeAuthority {
            clmm_config,
            new_authority,
        } => process_transfer_protocol_fee_authority(
            &rpc_client,
            config,
            &clmm_config,
            &new_authority,
        ),
        CliCommand::MathTickToSqrtPrice { tick } => process_tick_to_sqrt_price(tick),
        CliCommand::MathSqrtPriceToTick { price } => process_sqrt_price_to_tick(price),
        CliCommand::TickArrayIndex {
            pool,
            tick_index,
            array_index,
        } => process_tick_array_info(&rpc_client, tick_index, array_index, &pool),
        CliCommand::TickInfo { pool, tick_index } => {
            process_tick_info(&rpc_client, tick_index, &pool)
        }
        CliCommand::TickMapInfo { pool, array_index } => {
            process_tick_map_info(&rpc_client, array_index, &pool)
        }
        CliCommand::TickPrice { tick } => process_tick_price_info(&rpc_client, tick),

        // farming
        // quarry-mine
        CliCommand::FarmingQuarryMineNew { rewarder, mint, famine_ts, share } => { process_farming_quarry_mine_new(&rpc_client, config, rewarder, mint, famine_ts, share) }
        CliCommand::FarmingQuarryMineList {} => { process_farming_quarry_mine_list(&rpc_client, config) }
        CliCommand::FarmingQuarryMineInfo { rewarder, mint } => { process_farming_quarry_mine_info(&rpc_client, config, rewarder, mint) }
        CliCommand::FarmingQuarryUpdateShare { rewarder, mint, share } => { process_farming_quarry_update_share(&rpc_client, config, rewarder, mint, share) }
        CliCommand::FarmingQuarrySetFamine { rewarder, mint, ts } => { process_farming_quarry_set_famine(&rpc_client, config, rewarder, mint, ts) }

        // mine-rewarder
        CliCommand::FarmingMineRewarderNew { wrapper, annual_rate } => { process_farming_mine_rewarder_new(&rpc_client, config, wrapper, annual_rate) }
        CliCommand::FarmingMineRewarderList {} => { process_farming_mine_rewarder_list(&rpc_client, config) }
        CliCommand::FarmingMineRewarderInfo { rewarder } => { process_farming_mine_rewarder_info(&rpc_client, config, rewarder) }
        CliCommand::FarmingMineRewarderSetAnnualRate { rewarder, rate } => { process_farming_mine_rewarder_set_annual_rate(&rpc_client, config, rewarder, rate) }
        CliCommand::FarmingMineRewarderSyncQuarryRewards { rewarder, mint } => { process_farming_mine_rewarder_sync_quarry_rewards(&rpc_client, config, rewarder, mint) }

        // mint_wrapper
        CliCommand::FarmingMintWrapperNew { mint, hardcap } => { process_farming_mint_wrapper_new(&rpc_client, config, mint, hardcap) }
        CliCommand::FarmingMintWrapperList {} => { process_farming_mint_wrapper_list(&rpc_client, config) }
        CliCommand::FarmingMintWrapperInfo { wrapper } => { process_farming_mint_wrapper_info(&rpc_client, config, wrapper) }
        CliCommand::FarmingMintWrapperBackAuthority { wrapper, authority } => { process_farming_mint_wrapper_back_authority(&rpc_client, wrapper, config, authority) }
        CliCommand::FarmingMintWrapperTransferAuthority { wrapper } => { process_farming_mint_wrapper_transfer_authority(&rpc_client, config, wrapper) }

        // minter
        CliCommand::FarmingMinterNew { wrapper, allowance, authority } => { process_farming_minter_new(&rpc_client, config, wrapper, allowance, authority) }
        CliCommand::FarmingMinterList { wrapper } => { process_farming_minter_list(&rpc_client, config, wrapper) }
        CliCommand::FarmingMinterInfo { wrapper, authority } => { process_farming_minter_info(&rpc_client, config, wrapper, authority) }
        CliCommand::FarmingMinterUpdate { wrapper, allowance, authority } => { process_farming_minter_update(&rpc_client, config, wrapper, allowance, authority) }
        CliCommand::FarmingMinterMint { wrapper, owner, amount } => { process_farming_minter_mint(&rpc_client, config, wrapper, owner, amount) }

        _ => unreachable!(),
    }
}

#[derive(Debug, PartialEq)]
pub struct CliCommandInfo<'a> {
    pub command: CliCommand<'a>,
    pub signers: CliSigners,
}