use borsh::BorshDeserialize;
use solana_program::{
account_info::AccountInfo,
entrypoint::ProgramResult,
instruction::{AccountMeta, Instruction},
program::invoke_signed,
program_error::ProgramError,
pubkey::Pubkey,
system_program,
};
use crate::{
args::CallHandlerArgs,
ephemeral_balance_seeds_from_payer,
error::{INVALID_ESCROW_OWNER, INVALID_ESCROW_PDA},
processor::utils::loaders::{
load_initialized_validator_fees_vault, load_owned_pda, load_pda,
load_signer,
},
};
pub fn process_call_handler_v2(
_program_id: &Pubkey,
accounts: &[AccountInfo],
data: &[u8],
) -> ProgramResult {
const OTHER_ACCOUNTS_OFFSET: usize = 6;
let (
[validator, validator_fees_vault, destination_program, source_program, escrow_authority_account, escrow_account],
other_accounts,
) = accounts.split_at(OTHER_ACCOUNTS_OFFSET)
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
let args = CallHandlerArgs::try_from_slice(data)?;
load_signer(validator, "validator")?;
load_initialized_validator_fees_vault(
validator,
validator_fees_vault,
true,
)?;
let escrow_seeds: &[&[u8]] = ephemeral_balance_seeds_from_payer!(
escrow_authority_account.key,
args.escrow_index
);
let escrow_bump = load_pda(
escrow_account,
escrow_seeds,
&crate::id(),
true,
INVALID_ESCROW_PDA,
)?;
load_owned_pda(
escrow_account,
&system_program::id(),
INVALID_ESCROW_OWNER,
)?;
let (accounts_meta, handler_accounts): (
Vec<AccountMeta>,
Vec<AccountInfo>,
) = other_accounts
.iter()
.chain([source_program, escrow_authority_account, escrow_account])
.filter(|account| account.key != validator.key)
.map(|account| {
(
AccountMeta {
pubkey: *account.key,
is_writable: account.is_writable,
is_signer: account.key == escrow_account.key,
},
account.clone(),
)
})
.collect();
let handler_instruction = Instruction {
program_id: *destination_program.key,
data: args.data,
accounts: accounts_meta,
};
let bump_slice = &[escrow_bump];
let escrow_signer_seeds = [escrow_seeds, &[bump_slice]].concat();
invoke_signed(
&handler_instruction,
&handler_accounts,
&[&escrow_signer_seeds],
)
}