pub struct AccountList<'a> { /* private fields */ }Expand description
Iterator-style account accessor with inline constraint checks.
In raw pinocchio you typically write:
if accounts.len() < 4 {
return Err(ProgramError::NotEnoughAccountKeys);
}
let payer = &accounts[0];
check_signer(payer)?;
let vault = &accounts[1];
check_writable(vault)?;
let system = &accounts[2];
check_system_program(system)?;
let state = &accounts[3];
check_account(state, program_id, STATE_DISC, STATE_LEN)?;AccountList collapses that to:
let mut accs = AccountList::new(accounts);
let payer = accs.next_signer()?;
let vault = accs.next_writable()?;
let system = accs.next_system_program()?;
let state = accs.next_account(program_id, STATE_DISC, STATE_LEN)?;Same instructions generated at the end - just far less noise.
Implementations§
Source§impl<'a> AccountList<'a>
impl<'a> AccountList<'a>
pub fn new(accounts: &'a [AccountView]) -> Self
Sourcepub fn next(&mut self) -> Result<&'a AccountView, ProgramError>
pub fn next(&mut self) -> Result<&'a AccountView, ProgramError>
Consume the next account with no additional checks.
Use this for accounts where you want to do custom validation immediately after, or for accounts that only need to exist.
Sourcepub fn next_signer(&mut self) -> Result<&'a AccountView, ProgramError>
pub fn next_signer(&mut self) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify it signed the transaction.
Sourcepub fn next_writable(&mut self) -> Result<&'a AccountView, ProgramError>
pub fn next_writable(&mut self) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify it is marked writable.
Sourcepub fn next_writable_signer(&mut self) -> Result<&'a AccountView, ProgramError>
pub fn next_writable_signer(&mut self) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify it is a writable signer.
Common pattern for the fee payer or the instruction authority that is also being mutated (e.g. depositing lamports).
Sourcepub fn next_system_program(&mut self) -> Result<&'a AccountView, ProgramError>
pub fn next_system_program(&mut self) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify it is the system program.
Sourcepub fn next_with_address(
&mut self,
expected: &Address,
) -> Result<&'a AccountView, ProgramError>
pub fn next_with_address( &mut self, expected: &Address, ) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify its address matches expected.
Use this to assert any well-known program or sysvar address:
let token_prog = accs.next_with_address(&jiminy::programs::TOKEN)?;Sourcepub fn next_account(
&mut self,
program_id: &Address,
discriminator: u8,
min_len: usize,
) -> Result<&'a AccountView, ProgramError>
pub fn next_account( &mut self, program_id: &Address, discriminator: u8, min_len: usize, ) -> Result<&'a AccountView, ProgramError>
Consume the next account and run the combined ownership + size + discriminator check. This is the most common pattern for your program’s own state accounts.
Sourcepub fn next_writable_account(
&mut self,
program_id: &Address,
discriminator: u8,
min_len: usize,
) -> Result<&'a AccountView, ProgramError>
pub fn next_writable_account( &mut self, program_id: &Address, discriminator: u8, min_len: usize, ) -> Result<&'a AccountView, ProgramError>
Consume the next account as a writable state account.
Combines next_account with a writable check - the most common
pattern for accounts being modified in an instruction.
Sourcepub fn next_executable(&mut self) -> Result<&'a AccountView, ProgramError>
pub fn next_executable(&mut self) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify it is an executable program.
Use for CPI target programs passed as instruction accounts, where you want to confirm the caller didn’t pass a regular data account.
Sourcepub fn next_signer_writable_account(
&mut self,
program_id: &Address,
discriminator: u8,
min_len: usize,
) -> Result<&'a AccountView, ProgramError>
pub fn next_signer_writable_account( &mut self, program_id: &Address, discriminator: u8, min_len: usize, ) -> Result<&'a AccountView, ProgramError>
Consume the next account as a writable signer state account.
Combines signer + writable + ownership + size + discriminator checks.
The full equivalent of Anchor’s #[account(mut, signer)] for a
program-owned state account.
let state = accs.next_signer_writable_account(program_id, STATE_DISC, STATE_LEN)?;Sourcepub fn next_token_account(
&mut self,
expected_mint: &Address,
expected_owner: &Address,
) -> Result<&'a AccountView, ProgramError>
pub fn next_token_account( &mut self, expected_mint: &Address, expected_owner: &Address, ) -> Result<&'a AccountView, ProgramError>
Consume the next account as a validated token account.
Verifies: data size ≥ 165, mint matches, owner matches. This is the zero-copy equivalent of Anchor’s:
#[account(token::mint = expected_mint, token::authority = expected_owner)]let user_token = accs.next_token_account(&usdc_mint, user.address())?;Sourcepub fn next_mint(
&mut self,
expected_token_program: &Address,
) -> Result<&'a AccountView, ProgramError>
pub fn next_mint( &mut self, expected_token_program: &Address, ) -> Result<&'a AccountView, ProgramError>
Consume the next account as a validated mint.
Verifies: data size ≥ 82 and owned by the expected token program.
let mint = accs.next_mint(&programs::TOKEN)?;Sourcepub fn next_clock(&mut self) -> Result<&'a AccountView, ProgramError>
pub fn next_clock(&mut self) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify it is the Clock sysvar.
let clock = accs.next_clock()?;
let (slot, timestamp) = jiminy::sysvar::read_clock(clock)?;Sourcepub fn next_sysvar_instructions(
&mut self,
) -> Result<&'a AccountView, ProgramError>
pub fn next_sysvar_instructions( &mut self, ) -> Result<&'a AccountView, ProgramError>
Consume the next account and verify it is the Sysvar Instructions account.
Required for CPI guard checks (check_no_cpi_caller).
let sysvar_ix = accs.next_sysvar_instructions()?;
jiminy::cpi_guard::check_no_cpi_caller(sysvar_ix, program_id)?;