Macro lido::accounts_struct[][src]

macro_rules! accounts_struct {
    {
    $NameAccountMeta : ident, $NameAccountInfo : ident
    {
        $(pub $var_account : ident
          {
              is_signer : $is_signer : expr, is_writable : $is_writable : tt,
          }), * $(, $(const $const_account : ident = $const_value : expr), *)
        ?
        $(, pub ... $multi_account : ident
          { is_signer : false, is_writable : true, }) ?,
    }
} => { ... };
}
Expand description

Generates two structs for passing accounts by name.

Using this macro has a few advantages over accepting/parsing a list of accounts manually:

  • There is no risk of making a mistake in the ordering of accounts, or forgetting to update one place after modifying a different place.

  • It forces for every account to consider whether it should be writable or not, and it enforces this when the program is called.

  • It has a shorthand for defining accounts that have a statically known address.

The macro accepts three types of field:

  • User-specified accounts, with pub.

  • Optionally, one or more accounts with a fixed address, with const. These are not part of the Meta struct, because their address is known, so the caller does not need to provide it, but they are part of the Info struct, because the program does need to access them.

  • Optionally, a vector with a variable number of accounts, with pub ....

Example:

accounts_struct! {
    ExampleAccountsMeta, ExampleAccountsInfo {
        pub frobnicator { is_signer: true, is_writable: false, },
        const sysvar_rent = sysvar::rent::id(),
        pub ...widgets { is_signer: false, is_writable: true, },
    }
}

This generates two structs:

struct ExampleAccountsMeta {
    frobnicator: Pubkey,
    widgets: Vec<Pubkey>,
}

impl ExampleAccountsMeta {
    pub fn to_vec(&self) -> Vec<AccountMeta> {
    }
}

struct ExampleAccountsInfo<'a> {
    frobnicator: &'a AccountInfo<'a>,
    sysvar_rent: &'a AccountInfo<'a>,
    widgets: &'a [AccountInfo<'a>],
}

impl<'a> ExampleAccountsInfo<'a> {
    pub fn try_from_slice<'b: 'a>(raw: &'b [AccountInfo<'a>]) -> Result<ExampleAccountsInfo<'a>, ProgramError> {
    }
}

Such that the accounts returned by to_vec are in the same order that try_from_slice expects them. try_from_slice furthermore validates that is_signer and is_writable match the definition.