use crate::ToSolanaAccountInfo;
use solana_program::account_info::AccountInfo as SolanaAccountInfo;
use solana_program::entrypoint::ProgramResult;
use solana_program::instruction::Instruction as SolanaInstruction;
use solana_program::program::{
invoke_signed as solana_invoke_signed,
invoke_signed_unchecked as solana_invoke_signed_unchecked,
};
pub trait CPI: Sized {
fn raw_invoke_signed(
self,
instruction: &SolanaInstruction,
account_infos: &[SolanaAccountInfo],
signer_seeds: &[&[&[u8]]],
) -> ProgramResult;
fn invoke<'a, AI, const N: usize>(
self,
instruction: &SolanaInstruction,
account_infos: &[&AI; N],
) -> ProgramResult
where
AI: ToSolanaAccountInfo<'a>,
{
self.invoke_signed(instruction, account_infos, &[])
}
fn invoke_signed<'a, AI, const N: usize>(
self,
instruction: &SolanaInstruction,
account_infos: &[&AI; N],
signer_seeds: &[&[&[u8]]],
) -> ProgramResult
where
AI: ToSolanaAccountInfo<'a>,
{
self.raw_invoke_signed(
instruction,
&array_init::array_init::<_, _, N>(|x| unsafe {
account_infos[x].to_solana_account_info()
}),
signer_seeds,
)
}
fn invoke_variable_size<'a, 'b, AI, I>(
self,
instruction: &SolanaInstruction,
account_infos: I,
) -> ProgramResult
where
AI: 'a + ToSolanaAccountInfo<'b>,
I: IntoIterator<Item = &'a AI>,
{
self.invoke_signed_variable_size(instruction, account_infos, &[])
}
fn invoke_signed_variable_size<'a, 'b, AI, I>(
self,
instruction: &SolanaInstruction,
account_infos: I,
signer_seeds: &[&[&[u8]]],
) -> ProgramResult
where
AI: 'a + ToSolanaAccountInfo<'b>,
I: IntoIterator<Item = &'a AI>,
{
self.raw_invoke_signed(
instruction,
&account_infos
.into_iter()
.map(|info| unsafe { info.to_solana_account_info() })
.collect::<Vec<_>>(),
signer_seeds,
)
}
}
#[derive(Copy, Clone, Debug)]
pub struct CPIChecked;
impl CPI for CPIChecked {
#[inline]
fn raw_invoke_signed(
self,
instruction: &SolanaInstruction,
account_infos: &[SolanaAccountInfo],
signer_seeds: &[&[&[u8]]],
) -> ProgramResult {
solana_invoke_signed(instruction, account_infos, signer_seeds)
}
}
#[derive(Copy, Clone, Debug)]
pub struct CPIUnchecked;
impl CPI for CPIUnchecked {
#[inline]
fn raw_invoke_signed(
self,
instruction: &SolanaInstruction,
account_infos: &[SolanaAccountInfo],
signer_seeds: &[&[&[u8]]],
) -> ProgramResult {
solana_invoke_signed_unchecked(instruction, account_infos, signer_seeds)
}
}