mpl_testing_utils/
solana.rs

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;
9/// Perform native lamports transfer.
10pub 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    // connection.send_and_confirm_transaction(&tx)?;
77    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}