equanetwork-cli 0.0.4

The Equa Network command line interface
use anyhow::Result;
use equanetwork::{
    get_permission_address, VaultDeposit, VaultDepositInstructionArgs, VaultWithdraw,
    VaultWithdrawInstructionArgs,
};
use solana_instruction::Instruction;
use solana_signer::Signer;

use crate::{
    config::{Command, Config, VaultCommand},
    log_context,
    transaction::process_instructions,
};

use super::helpers::{addr, ensure_ata, require_signer, vault_pda};

pub fn handle_deposit(config: &Config) -> Result<()> {
    let Command::Vault {
        command:
            VaultCommand::Deposit {
                network,
                mint,
                amount,
            },
    } = &config.command
    else {
        unreachable!()
    };

    let signer = require_signer(config)?;
    let rpc = config.rpc_client();
    let authority = signer.pubkey();
    let (permission, _) = get_permission_address(&addr(authority));
    let vault = vault_pda(network, mint);
    let mut ixs: Vec<Instruction> = Vec::new();
    let authority_token = ensure_ata(&rpc, &mut ixs, &signer, &authority, mint);
    let network_token_ata = ensure_ata(&rpc, &mut ixs, &signer, network, mint);

    log_context!(
      action => "vault_deposit",
      authority => authority.to_string(),
      network => network.to_string(),
      mint => mint.to_string(),
      vault => vault.to_string(),
      amount => *amount,
    );

    ixs.push(
        VaultDeposit {
            authority: addr(authority),
            permission,
            vault,
            mint: addr(*mint),
            authority_token: addr(authority_token),
            network_token_ata: addr(network_token_ata),
            network: addr(*network),
            token_program: addr(spl_token_interface::ID),
            memo_program: addr(spl_memo_interface::v3::ID),
        }
        .instruction(VaultDepositInstructionArgs { amount: *amount }),
    );

    process_instructions(&rpc, &[signer], &ixs)
}

pub fn handle_withdraw(config: &Config) -> Result<()> {
    let Command::Vault {
        command:
            VaultCommand::Withdraw {
                network,
                mint,
                amount,
                destination,
            },
    } = &config.command
    else {
        unreachable!()
    };

    let signer = require_signer(config)?;
    let rpc = config.rpc_client();
    let authority = signer.pubkey();
    let destination_owner = destination.unwrap_or(authority);
    let (permission, _) = get_permission_address(&addr(authority));
    let vault = vault_pda(network, mint);
    let mut ixs: Vec<Instruction> = Vec::new();
    let destination_token = ensure_ata(&rpc, &mut ixs, &signer, &destination_owner, mint);
    let network_token_ata = ensure_ata(&rpc, &mut ixs, &signer, network, mint);

    log_context!(
      action => "vault_withdraw",
      authority => authority.to_string(),
      network => network.to_string(),
      mint => mint.to_string(),
      vault => vault.to_string(),
      destination => destination_owner.to_string(),
      amount => *amount,
    );

    ixs.push(
        VaultWithdraw {
            authority: addr(authority),
            permission,
            vault,
            mint: addr(*mint),
            destination_token: addr(destination_token),
            destination_owner: addr(destination_owner),
            network_token_ata: addr(network_token_ata),
            network: addr(*network),
            token_program: addr(spl_token_interface::ID),
            memo_program: addr(spl_memo_interface::v3::ID),
        }
        .instruction(VaultWithdrawInstructionArgs { amount: *amount }),
    );

    process_instructions(&rpc, &[signer], &ixs)
}