use anchor_lang::{InstructionData, ToAccountMetas};
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
};
use crate::constants::{INSTRUCTIONS_SYSVAR_ID, SYSTEM_PROGRAM_ID};
pub struct StartSwapV2Params {
pub owner: Pubkey,
pub caller: Pubkey,
pub payer: Pubkey,
pub mint_substitute: Pubkey,
pub mint_from: Pubkey,
pub mint_to: Pubkey,
pub token_program_substitute: Pubkey,
pub token_program_from: Pubkey,
pub token_program_to: Pubkey,
pub asset_id_substitute: pyra_tokens::AssetId,
pub amount_base_units_substitute: u64,
pub asset_id_from: pyra_tokens::AssetId,
pub amount_base_units_from: u64,
pub asset_id_to: pyra_tokens::AssetId,
pub reduce_only: bool,
pub remaining_accounts: Vec<AccountMeta>,
}
pub fn start_swap_v2(params: &StartSwapV2Params) -> Option<Instruction> {
let vault = pyra_accounts::get_vault(¶ms.owner);
let vault_spl_substitute = pyra_accounts::get_associated_token_address(
&vault,
¶ms.mint_substitute,
¶ms.token_program_substitute,
);
let vault_spl_from = pyra_accounts::get_associated_token_address(
&vault,
¶ms.mint_from,
¶ms.token_program_from,
);
let caller_spl_substitute = pyra_accounts::get_associated_token_address(
¶ms.caller,
¶ms.mint_substitute,
¶ms.token_program_substitute,
);
let caller_spl_from = pyra_accounts::get_associated_token_address(
¶ms.caller,
¶ms.mint_from,
¶ms.token_program_from,
);
let caller_spl_to = pyra_accounts::get_associated_token_address(
¶ms.caller,
¶ms.mint_to,
¶ms.token_program_to,
);
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_substitute =
pyra_accounts::get_drift_spot_market_vault(params.asset_id_substitute)?;
let drift_spot_market_vault_from =
pyra_accounts::get_drift_spot_market_vault(params.asset_id_from)?;
let drift_signer = pyra_accounts::get_drift_signer();
let ledger = pyra_accounts::get_swap_ledger_v2(¶ms.mint_from);
let mut accounts = crate::pyra_program::client::accounts::StartSwapDriftV2 {
vault,
vault_spl_substitute,
vault_spl_from,
caller: params.caller,
caller_spl_substitute,
caller_spl_from,
caller_spl_to,
mint_substitute: params.mint_substitute,
mint_from: params.mint_from,
drift_user,
drift_user_stats,
drift_state,
drift_spot_market_vault_substitute,
drift_spot_market_vault_from,
drift_signer,
token_program_substitute: params.token_program_substitute,
token_program_from: params.token_program_from,
associated_token_program: pyra_accounts::ASSOCIATED_TOKEN_PROGRAM_ID,
payer: params.payer,
ledger,
drift_program: pyra_accounts::DRIFT_PROGRAM_ID,
system_program: SYSTEM_PROGRAM_ID,
instructions_sysvar_account: INSTRUCTIONS_SYSVAR_ID,
}
.to_account_metas(None);
accounts.extend_from_slice(¶ms.remaining_accounts);
let data = crate::pyra_program::client::args::StartSwapDriftV2 {
drift_market_index_substitute: params.asset_id_substitute.drift_market_index()?,
amount_base_units_substitute: params.amount_base_units_substitute,
drift_market_index_from: params.asset_id_from.drift_market_index()?,
amount_base_units_from: params.amount_base_units_from,
drift_market_index_to: params.asset_id_to.drift_market_index()?,
reduce_only: params.reduce_only,
}
.data();
Some(Instruction {
program_id: pyra_accounts::PYRA_PROGRAM_ID,
accounts,
data,
})
}