Skip to main content

DynCpi

Struct DynCpi 

Source
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>

Source

pub fn new(program_id: &'a Address) -> Self

Start a new dynamic CPI against the given program.

Source

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.

Source

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.

Source

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.

Source

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).

Source

pub fn push_pubkey(&mut self, address: &Address) -> ProgramResult

Append a 32-byte pubkey.

Source

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).

Source

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.

Source

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.

Source

pub const fn program_id(&self) -> &Address

Program id this dynamic CPI targets.

Source

pub const fn data_len(&self) -> usize

Current data length.

Source

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.

Source

pub fn account_views(&self) -> &[&'a AccountView<'a>]

The pushed account views, in push order.

Source

pub fn invoke(&self) -> ProgramResult

Submit the built CPI (no PDA signers).

Equivalent to invoke_signed with an empty signer set.

Source

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.

Auto Trait Implementations§

§

impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> !Send for DynCpi<'a, MAX_ACCTS, MAX_DATA>

§

impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> !Sync for DynCpi<'a, MAX_ACCTS, MAX_DATA>

§

impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> Freeze for DynCpi<'a, MAX_ACCTS, MAX_DATA>

§

impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> RefUnwindSafe for DynCpi<'a, MAX_ACCTS, MAX_DATA>

§

impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> Unpin for DynCpi<'a, MAX_ACCTS, MAX_DATA>

§

impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> UnsafeUnpin for DynCpi<'a, MAX_ACCTS, MAX_DATA>

§

impl<'a, const MAX_ACCTS: usize, const MAX_DATA: usize> UnwindSafe for DynCpi<'a, MAX_ACCTS, MAX_DATA>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.