human_common/
utils.rs

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
68/// returns next expected account that is signer
69pub 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
86/// returns next expected account while checking it's address
87pub 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}