use hopper_runtime::error::ProgramError;
use hopper_runtime::{AccountView, Address};
use super::context::{HopperAccounts, HopperCtx};
pub trait HopperIx<'a>: Sized {
type Accounts: HopperAccounts<'a>;
type Args;
fn parse_args(data: &'a [u8]) -> Result<Self::Args, ProgramError>;
}
#[inline]
pub fn hopper_entry<'a, I, F>(
program_id: &'a Address,
accounts: &'a [AccountView],
instruction_data: &'a [u8],
handler: F,
) -> Result<(), ProgramError>
where
I: HopperIx<'a>,
F: FnOnce(HopperCtx<'a, I::Accounts>, I::Args) -> Result<(), ProgramError>,
{
let args = I::parse_args(instruction_data)?;
let (accts, bumps) = I::Accounts::try_from_accounts(program_id, accounts, instruction_data)?;
let consumed = I::Accounts::ACCOUNT_COUNT;
let remaining = if consumed < accounts.len() {
&accounts[consumed..]
} else {
&[]
};
let ctx = HopperCtx::new(accts, bumps, program_id, instruction_data, remaining);
handler(ctx, args)
}