anchor_lang/accounts/
option.rs1use std::collections::BTreeSet;
12
13use solana_program::account_info::AccountInfo;
14use solana_program::instruction::AccountMeta;
15use solana_program::pubkey::Pubkey;
16
17use crate::{
18 error::ErrorCode, Accounts, AccountsClose, AccountsExit, Result, ToAccountInfos, ToAccountMetas,
19};
20
21impl<'info, B, T: Accounts<'info, B>> Accounts<'info, B> for Option<T> {
22 fn try_accounts(
23 program_id: &Pubkey,
24 accounts: &mut &'info [AccountInfo<'info>],
25 ix_data: &[u8],
26 bumps: &mut B,
27 reallocs: &mut BTreeSet<Pubkey>,
28 ) -> Result<Self> {
29 if accounts.is_empty() {
30 return if cfg!(feature = "allow-missing-optionals") {
31 Ok(None)
37 } else {
38 Err(ErrorCode::AccountNotEnoughKeys.into())
41 };
42 }
43
44 if accounts[0].key == program_id {
47 *accounts = &accounts[1..];
48 Ok(None)
49 } else {
50 T::try_accounts(program_id, accounts, ix_data, bumps, reallocs).map(Some)
54 }
55 }
56}
57
58impl<'info, T: ToAccountInfos<'info>> ToAccountInfos<'info> for Option<T> {
59 fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
60 self.as_ref()
61 .map_or_else(Vec::new, |account| account.to_account_infos())
62 }
63}
64
65impl<T: ToAccountMetas> ToAccountMetas for Option<T> {
66 fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
67 self.as_ref()
68 .expect("Cannot run `to_account_metas` on None")
69 .to_account_metas(is_signer)
70 }
71}
72
73impl<'info, T: AccountsClose<'info>> AccountsClose<'info> for Option<T> {
74 fn close(&self, sol_destination: AccountInfo<'info>) -> Result<()> {
75 self.as_ref()
76 .map_or(Ok(()), |t| T::close(t, sol_destination))
77 }
78}
79
80impl<'info, T: AccountsExit<'info>> AccountsExit<'info> for Option<T> {
81 fn exit(&self, program_id: &Pubkey) -> Result<()> {
82 self.as_ref().map_or(Ok(()), |t| t.exit(program_id))
83 }
84}