1use solana_program_test::{BanksClientError, ProgramTestContext};
2use solana_sdk::pubkey::Pubkey;
3use solana_sdk::signature::Keypair;
4use solana_sdk::signer::Signer;
5use solana_sdk::system_instruction;
6use solana_sdk::transaction::Transaction;
7use solana_sdk::{account::Account, program_pack::Pack};
8use spl_token::state::Mint;
9pub async fn transfer_lamports(
11 client: &mut ProgramTestContext,
12 wallet: &Keypair,
13 to: &Pubkey,
14 amount: u64,
15) -> Result<(), BanksClientError> {
16 let tx = Transaction::new_signed_with_payer(
17 &[system_instruction::transfer(&wallet.pubkey(), to, amount)],
18 Some(&wallet.pubkey()),
19 &[wallet],
20 client.last_blockhash,
21 );
22
23 client.banks_client.process_transaction(tx).await?;
24
25 Ok(())
26}
27
28pub async fn get_token_account(
29 client: &mut ProgramTestContext,
30 token_account: &Pubkey,
31) -> Result<spl_token::state::Account, BanksClientError> {
32 let account = client.banks_client.get_account(*token_account).await?;
33 Ok(spl_token::state::Account::unpack(&account.unwrap().data).unwrap())
34}
35
36pub async fn airdrop(
37 context: &mut ProgramTestContext,
38 receiver: &Pubkey,
39 amount: u64,
40) -> Result<(), BanksClientError> {
41 let tx = Transaction::new_signed_with_payer(
42 &[system_instruction::transfer(
43 &context.payer.pubkey(),
44 receiver,
45 amount,
46 )],
47 Some(&context.payer.pubkey()),
48 &[&context.payer],
49 context.last_blockhash,
50 );
51
52 context.banks_client.process_transaction(tx).await.unwrap();
53 Ok(())
54}
55
56pub async fn create_associated_token_account(
57 context: &mut ProgramTestContext,
58 wallet: &Keypair,
59 token_mint: &Pubkey,
60) -> Result<Pubkey, BanksClientError> {
61 let recent_blockhash = context.last_blockhash;
62
63 let tx = Transaction::new_signed_with_payer(
64 &[
65 spl_associated_token_account::instruction::create_associated_token_account(
66 &context.payer.pubkey(),
67 &wallet.pubkey(),
68 token_mint,
69 ),
70 ],
71 Some(&context.payer.pubkey()),
72 &[&context.payer],
73 recent_blockhash,
74 );
75
76 context.banks_client.process_transaction(tx).await.unwrap();
78
79 Ok(spl_associated_token_account::get_associated_token_address(
80 &wallet.pubkey(),
81 token_mint,
82 ))
83}
84
85pub fn clone_keypair(keypair: &Keypair) -> Keypair {
86 Keypair::from_bytes(&keypair.to_bytes()).unwrap()
87}
88
89pub async fn get_account(context: &mut ProgramTestContext, pubkey: &Pubkey) -> Account {
90 context
91 .banks_client
92 .get_account(*pubkey)
93 .await
94 .expect("account not found")
95 .expect("account empty")
96}
97
98pub async fn get_mint(context: &mut ProgramTestContext, pubkey: &Pubkey) -> Mint {
99 let account = get_account(context, pubkey).await;
100 Mint::unpack(&account.data).unwrap()
101}
102
103pub async fn mint_tokens(
104 context: &mut ProgramTestContext,
105 mint: &Pubkey,
106 account: &Pubkey,
107 amount: u64,
108 owner: &Pubkey,
109 additional_signer: Option<&Keypair>,
110) -> Result<(), BanksClientError> {
111 let mut signing_keypairs = vec![&context.payer];
112 if let Some(signer) = additional_signer {
113 signing_keypairs.push(signer);
114 }
115
116 let tx = Transaction::new_signed_with_payer(
117 &[
118 spl_token::instruction::mint_to(&spl_token::id(), mint, account, owner, &[], amount)
119 .unwrap(),
120 ],
121 Some(&context.payer.pubkey()),
122 &signing_keypairs,
123 context.last_blockhash,
124 );
125
126 context.banks_client.process_transaction(tx).await
127}
128
129pub async fn create_token_account(
130 context: &mut ProgramTestContext,
131 account: &Keypair,
132 mint: &Pubkey,
133 manager: &Pubkey,
134) -> Result<(), BanksClientError> {
135 let rent = context.banks_client.get_rent().await.unwrap();
136
137 let tx = Transaction::new_signed_with_payer(
138 &[
139 system_instruction::create_account(
140 &context.payer.pubkey(),
141 &account.pubkey(),
142 rent.minimum_balance(spl_token::state::Account::LEN),
143 spl_token::state::Account::LEN as u64,
144 &spl_token::id(),
145 ),
146 spl_token::instruction::initialize_account(
147 &spl_token::id(),
148 &account.pubkey(),
149 mint,
150 manager,
151 )
152 .unwrap(),
153 ],
154 Some(&context.payer.pubkey()),
155 &[&context.payer, account],
156 context.last_blockhash,
157 );
158
159 context.banks_client.process_transaction(tx).await
160}
161
162pub async fn create_mint(
163 context: &mut ProgramTestContext,
164 mint: &Keypair,
165 manager: &Pubkey,
166 freeze_authority: Option<&Pubkey>,
167) -> Result<(), BanksClientError> {
168 let rent = context.banks_client.get_rent().await.unwrap();
169
170 let tx = Transaction::new_signed_with_payer(
171 &[
172 system_instruction::create_account(
173 &context.payer.pubkey(),
174 &mint.pubkey(),
175 rent.minimum_balance(spl_token::state::Mint::LEN),
176 spl_token::state::Mint::LEN as u64,
177 &spl_token::id(),
178 ),
179 spl_token::instruction::initialize_mint(
180 &spl_token::id(),
181 &mint.pubkey(),
182 manager,
183 freeze_authority,
184 0,
185 )
186 .unwrap(),
187 ],
188 Some(&context.payer.pubkey()),
189 &[&context.payer, mint],
190 context.last_blockhash,
191 );
192
193 context.banks_client.process_transaction(tx).await
194}
195
196pub async fn transfer(
197 context: &mut ProgramTestContext,
198 mint: &Pubkey,
199 from: &Keypair,
200 to: &Keypair,
201) -> Result<(), BanksClientError> {
202 let to_token_account = create_associated_token_account(context, to, mint).await?;
203
204 let from_token_account =
205 spl_associated_token_account::get_associated_token_address(&from.pubkey(), mint);
206
207 let tx = Transaction::new_signed_with_payer(
208 &[spl_token::instruction::transfer(
209 &spl_token::id(),
210 &from_token_account,
211 &to_token_account,
212 &from.pubkey(),
213 &[&from.pubkey()],
214 1,
215 )
216 .unwrap()],
217 Some(&from.pubkey()),
218 &[from],
219 context.last_blockhash,
220 );
221
222 context.banks_client.process_transaction(tx).await
223}