use anchor_lang::{InstructionData, ToAccountMetas};
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
};
use crate::constants::SYSTEM_PROGRAM_ID;
pub struct FulfillWithdrawParams {
pub withdraw_order: Pubkey,
pub owner: Pubkey,
pub order_payer: Pubkey,
pub admin: Pubkey,
pub payer: Pubkey,
pub destination: Pubkey,
pub mint: Pubkey,
pub token_program: Pubkey,
pub asset_id: pyra_tokens::AssetId,
pub amount_base_units: u64,
pub destination_spl: Option<Pubkey>,
pub remaining_accounts: Vec<AccountMeta>,
}
pub fn fulfill_withdraw(params: &FulfillWithdrawParams) -> Option<Instruction> {
let vault = pyra_accounts::get_vault(¶ms.owner);
let vault_spl =
pyra_accounts::get_associated_token_address(&vault, ¶ms.mint, ¶ms.token_program);
let drift_user = pyra_accounts::get_drift_user(¶ms.owner, 0);
let drift_user_stats = pyra_accounts::get_drift_user_stats(¶ms.owner);
let drift_state = pyra_accounts::get_drift_state();
let drift_spot_market_vault =
pyra_accounts::get_drift_spot_market_vault(params.asset_id)?;
let drift_signer = pyra_accounts::get_drift_signer();
let mut accounts = crate::pyra_program::client::accounts::FulfillWithdrawDrift {
withdraw_order: params.withdraw_order,
vault,
order_payer: params.order_payer,
admin: params.admin,
payer: params.payer,
destination: params.destination,
destination_spl: params.destination_spl,
vault_spl,
mint: params.mint,
drift_user,
drift_user_stats,
drift_state,
drift_spot_market_vault,
drift_signer,
token_program: params.token_program,
associated_token_program: pyra_accounts::ASSOCIATED_TOKEN_PROGRAM_ID,
drift_program: pyra_accounts::DRIFT_PROGRAM_ID,
system_program: SYSTEM_PROGRAM_ID,
}
.to_account_metas(None);
accounts.extend_from_slice(¶ms.remaining_accounts);
let data = crate::pyra_program::client::args::FulfillWithdrawDrift {
amount_base_units: params.amount_base_units,
}
.data();
Some(Instruction {
program_id: pyra_accounts::PYRA_PROGRAM_ID,
accounts,
data,
})
}