spl_associated_token_account_interface/
instruction.rs1use {
3 crate::{address::get_associated_token_address_with_program_id, program::id},
4 solana_instruction::{AccountMeta, Instruction},
5 solana_pubkey::Pubkey,
6};
7
8const SYSTEM_PROGRAM_ID: Pubkey = Pubkey::from_str_const("11111111111111111111111111111111");
9
10#[cfg(feature = "borsh")]
11use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
12
13#[derive(Clone, Debug, PartialEq)]
15#[cfg_attr(
16 feature = "borsh",
17 derive(BorshDeserialize, BorshSerialize, BorshSchema)
18)]
19pub enum AssociatedTokenAccountInstruction {
20 Create,
30 CreateIdempotent,
41 RecoverNested,
61}
62
63fn build_associated_token_account_instruction(
64 funding_address: &Pubkey,
65 wallet_address: &Pubkey,
66 token_mint_address: &Pubkey,
67 token_program_id: &Pubkey,
68 instruction: u8,
69) -> Instruction {
70 let associated_account_address = get_associated_token_address_with_program_id(
71 wallet_address,
72 token_mint_address,
73 token_program_id,
74 );
75 assert!(instruction <= 1);
77 Instruction {
78 program_id: id(),
79 accounts: vec![
80 AccountMeta::new(*funding_address, true),
81 AccountMeta::new(associated_account_address, false),
82 AccountMeta::new_readonly(*wallet_address, false),
83 AccountMeta::new_readonly(*token_mint_address, false),
84 AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
85 AccountMeta::new_readonly(*token_program_id, false),
86 ],
87 data: vec![instruction],
88 }
89}
90
91pub fn create_associated_token_account(
93 funding_address: &Pubkey,
94 wallet_address: &Pubkey,
95 token_mint_address: &Pubkey,
96 token_program_id: &Pubkey,
97) -> Instruction {
98 build_associated_token_account_instruction(
99 funding_address,
100 wallet_address,
101 token_mint_address,
102 token_program_id,
103 0, )
105}
106
107pub fn create_associated_token_account_idempotent(
109 funding_address: &Pubkey,
110 wallet_address: &Pubkey,
111 token_mint_address: &Pubkey,
112 token_program_id: &Pubkey,
113) -> Instruction {
114 build_associated_token_account_instruction(
115 funding_address,
116 wallet_address,
117 token_mint_address,
118 token_program_id,
119 1, )
121}
122
123pub fn recover_nested(
125 wallet_address: &Pubkey,
126 owner_token_mint_address: &Pubkey,
127 nested_token_mint_address: &Pubkey,
128 token_program_id: &Pubkey,
129) -> Instruction {
130 let owner_associated_account_address = get_associated_token_address_with_program_id(
131 wallet_address,
132 owner_token_mint_address,
133 token_program_id,
134 );
135 let destination_associated_account_address = get_associated_token_address_with_program_id(
136 wallet_address,
137 nested_token_mint_address,
138 token_program_id,
139 );
140 let nested_associated_account_address = get_associated_token_address_with_program_id(
141 &owner_associated_account_address, nested_token_mint_address,
143 token_program_id,
144 );
145
146 Instruction {
147 program_id: id(),
148 accounts: vec![
149 AccountMeta::new(nested_associated_account_address, false),
150 AccountMeta::new_readonly(*nested_token_mint_address, false),
151 AccountMeta::new(destination_associated_account_address, false),
152 AccountMeta::new_readonly(owner_associated_account_address, false),
153 AccountMeta::new_readonly(*owner_token_mint_address, false),
154 AccountMeta::new(*wallet_address, true),
155 AccountMeta::new_readonly(*token_program_id, false),
156 ],
157 data: vec![2], }
159}
160
161#[cfg(test)]
162mod tests {
163 use {super::*, solana_sdk_ids::system_program};
164
165 #[test]
166 fn system_program_id() {
167 assert_eq!(system_program::id(), SYSTEM_PROGRAM_ID);
168 }
169}