1use solana_program::{
2 account_info::{next_account_info, AccountInfo},
3 msg,
4 program_error::ProgramError,
5 program_pack::Pack,
6 pubkey::Pubkey,
7};
8
9use spl_associated_token_account::get_associated_token_address;
10use spl_token::state as token_state;
11
12pub fn next_expected_token_wallet<'a, 'b: 'a, I>(
13 i: &mut I,
14 wallet_addr: &Pubkey,
15) -> Result<token_state::Account, ProgramError>
16where
17 I: Iterator<Item = &'a AccountInfo<'b>>,
18{
19 let wallet = next_account_info(i)?;
20
21 if wallet.key != wallet_addr {
22 msg!(
23 "invalid wallet: expected {} but got {}",
24 wallet_addr,
25 wallet.key
26 );
27 return Err(ProgramError::InvalidArgument);
28 }
29
30 if !spl_token::check_id(wallet.owner) {
31 return Err(ProgramError::IllegalOwner);
32 }
33
34 let account = token_state::Account::unpack(&wallet.data.borrow())?;
35
36 Ok(account)
37}
38
39pub fn next_atoken_wallet<'a, 'b: 'a, I>(
40 i: &mut I,
41 expected_user: &Pubkey,
42 exprected_mint: &Pubkey,
43) -> Result<(Pubkey, token_state::Account), ProgramError>
44where
45 I: Iterator<Item = &'a AccountInfo<'b>>,
46{
47 let wallet_acc = next_account_info(i)?;
48
49 let expected = get_associated_token_address(expected_user, exprected_mint);
50 if expected != *wallet_acc.key {
51 msg!(
52 "invalid atoken wallet: expected {} but got {}",
53 expected,
54 wallet_acc.key
55 );
56 return Err(ProgramError::InvalidArgument);
57 }
58
59 if !spl_token::check_id(wallet_acc.owner) {
60 return Err(ProgramError::IllegalOwner);
61 }
62
63 let wallet = token_state::Account::unpack(&wallet_acc.try_borrow_data()?)?;
64
65 Ok((*wallet_acc.key, wallet))
66}
67
68pub fn next_signer_account<'a, 'b, I: Iterator<Item = &'a AccountInfo<'b>>>(
70 i: &mut I,
71 expected_acc: &Pubkey,
72) -> Result<&'a AccountInfo<'b>, ProgramError> {
73 let account = next_account_info(i)?;
74
75 if account.key != expected_acc {
76 return Err(ProgramError::InvalidArgument);
77 }
78
79 if !account.is_signer {
80 return Err(ProgramError::MissingRequiredSignature);
81 }
82
83 Ok(account)
84}
85
86pub fn next_expected_account<'a, 'b: 'a, I>(
88 i: &mut I,
89 expected_key: &Pubkey,
90) -> Result<I::Item, ProgramError>
91where
92 I: Iterator<Item = &'a AccountInfo<'b>>,
93{
94 let acc = next_account_info(i)?;
95
96 if acc.key != expected_key {
97 msg!(
98 "invalid account: expected {} but got {}",
99 expected_key,
100 acc.key
101 );
102 return Err(ProgramError::InvalidArgument);
103 }
104
105 Ok(acc)
106}