pub struct DynCpi<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> { /* private fields */ }Expand description
Variable-length CPI builder with compile-time stack capacity.
MAX_ACCTS is the upper bound on the number of AccountMeta
entries. MAX_DATA is the upper bound on the instruction data
byte count. Exceeding either returns an error; nothing panics.
Use when the CPI shape is not known at compile time. For
statically-shaped CPIs, prefer cpi::invoke_signed::<N> which
avoids the two bounds entirely.
Implementations§
Source§impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> DynCpi<'a, MAX_ACCTS, MAX_DATA>
impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> DynCpi<'a, MAX_ACCTS, MAX_DATA>
Sourcepub fn push_account(
&mut self,
account: &'a AccountView<'a>,
writable: bool,
signer: bool,
) -> ProgramResult
pub fn push_account( &mut self, account: &'a AccountView<'a>, writable: bool, signer: bool, ) -> ProgramResult
Append one account meta. The writable and signer flags
are carried through to the emitted CPI instruction.
Each call appends one meta. Order and duplicates are preserved because
the callee reads accounts positionally. In parallel, the builder folds
the account into a deduplicated info set keyed by pubkey: pushing
an address already present does not allocate a second info slot,
it reuses the existing one and OR-merges the writable/signer flags.
Repeated metas for the same address therefore share one account-info at
submit time. See Self::info_count.
Returns Err(ProgramError::InvalidArgument) when the builder
is already at MAX_ACCTS capacity. Users pick the capacity
at the type parameter; bumping it is a type-system edit, not
a runtime error.
Sourcepub fn push_data(&mut self, bytes: &[u8]) -> ProgramResult
pub fn push_data(&mut self, bytes: &[u8]) -> ProgramResult
Append the given bytes to the instruction data buffer.
Returns Err(ProgramError::InvalidArgument) when the buffer
does not have room for the full slice. The append is
all-or-nothing; a partial write does not happen.
Sourcepub fn push_byte(&mut self, byte: u8) -> ProgramResult
pub fn push_byte(&mut self, byte: u8) -> ProgramResult
Append one byte. Sugar for programs that build instruction data one discriminator + one argument at a time.
Sourcepub fn push_u64_le(&mut self, value: u64) -> ProgramResult
pub fn push_u64_le(&mut self, value: u64) -> ProgramResult
Append the little-endian encoding of a u64. Covers the
most common arg shape (lamports, timestamps, flags).
Sourcepub fn push_pubkey(&mut self, address: &Address) -> ProgramResult
pub fn push_pubkey(&mut self, address: &Address) -> ProgramResult
Append a 32-byte pubkey.
Sourcepub const fn account_count(&self) -> usize
pub const fn account_count(&self) -> usize
Current account (meta) count, one per push_account, including
duplicates. This is the length of the ordered meta list the callee
sees, not the deduped info count (see Self::info_count).
Sourcepub const fn info_count(&self) -> usize
pub const fn info_count(&self) -> usize
Number of unique account-infos after SIMD-0339 pubkey dedup.
This is <= account_count(), and is exactly the count of
account-infos handed to the syscall at submit time. Pushing the same
address twice leaves this unchanged.
Sourcepub fn dedup_info(&self, k: usize) -> Option<(&'a AccountView<'a>, bool, bool)>
pub fn dedup_info(&self, k: usize) -> Option<(&'a AccountView<'a>, bool, bool)>
The k-th deduplicated account-info: its view plus the OR-merged
(writable, signer) privilege across every occurrence. Returns
None for k >= info_count().
Infos are in first-occurrence (push) order, so dedup_info(0) is the
account whose first push came first.
Sourcepub const fn program_id(&self) -> &Address
pub const fn program_id(&self) -> &Address
Program id this dynamic CPI targets.
Sourcepub fn data(&self) -> &[u8]
pub fn data(&self) -> &[u8]
Borrow the finalized data buffer. Useful for tests that want to inspect the wire bytes without actually submitting the CPI.
Sourcepub fn account_views(&self) -> &[&'a AccountView<'a>]
pub fn account_views(&self) -> &[&'a AccountView<'a>]
The pushed account views, in push order.
Sourcepub fn invoke(&self) -> ProgramResult
pub fn invoke(&self) -> ProgramResult
Submit the built CPI (no PDA signers).
Equivalent to invoke_signed with an
empty signer set.
Sourcepub fn invoke_signed(&self, signers: &[Signer<'_, '_>]) -> ProgramResult
pub fn invoke_signed(&self, signers: &[Signer<'_, '_>]) -> ProgramResult
Submit the built CPI with the given PDA signer seeds.
Assembles the pushed (account, writable, signer) metas, preserving the
full ordered list and duplicates, and the data buffer into an
InstructionView, then routes it through the validated,
dedup-aware path
(cpi::invoke_signed_deduped).
The metas define what the callee sees positionally; the account-info
list handed to the syscall is the pubkey-deduplicated set (one info
per unique account, flags OR-merged). Address/flag agreement, PDA-signer
resolution, live-borrow checks, and duplicate-writable rejection all
run over the full meta list before the syscall, so deduplication does not
skip those validation steps.