mpl_testing_utils/utils/
vault.rs

1use super::{create_mint, create_token_account, ExternalPrice, Metadata};
2use mpl_token_vault::{instruction, state::PREFIX};
3use solana_program::{pubkey::Pubkey, system_instruction};
4use solana_program_test::*;
5use solana_sdk::{
6    signature::{Keypair, Signer},
7    transaction::Transaction,
8    transport,
9};
10
11pub struct Vault {
12    pub keypair: Keypair,
13    pub mint: Keypair,
14    pub redeem_treasury: Keypair,
15    pub fraction_treasury: Keypair,
16}
17
18impl Default for Vault {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl Vault {
25    pub fn new() -> Self {
26        Vault {
27            keypair: Keypair::new(),
28            mint: Keypair::new(),
29            redeem_treasury: Keypair::new(),
30            fraction_treasury: Keypair::new(),
31        }
32    }
33
34    pub async fn add_token_to_inactive_vault(
35        &self,
36        context: &mut ProgramTestContext,
37        amount: u64,
38        metadata: &Metadata,
39    ) -> transport::Result<(Pubkey, Pubkey)> {
40        let vault_pubkey = self.keypair.pubkey();
41        let metaplex_token_vault_id = mpl_token_vault::id();
42
43        let store = Keypair::new();
44        let token_mint_pubkey = metadata.mint.pubkey();
45
46        let seeds = &[
47            PREFIX.as_bytes(),
48            vault_pubkey.as_ref(),
49            token_mint_pubkey.as_ref(),
50        ];
51        let (safety_deposit_box, _) = Pubkey::find_program_address(seeds, &metaplex_token_vault_id);
52        let seeds = &[
53            PREFIX.as_bytes(),
54            metaplex_token_vault_id.as_ref(),
55            vault_pubkey.as_ref(),
56        ];
57        let (authority, _) = Pubkey::find_program_address(seeds, &metaplex_token_vault_id);
58        create_token_account(context, &store, &token_mint_pubkey, &authority).await?;
59
60        let tx = Transaction::new_signed_with_payer(
61            &[instruction::create_add_token_to_inactive_vault_instruction(
62                mpl_token_vault::id(),
63                safety_deposit_box,
64                metadata.token.pubkey(),
65                store.pubkey(),
66                self.keypair.pubkey(),
67                context.payer.pubkey(),
68                context.payer.pubkey(),
69                context.payer.pubkey(),
70                amount,
71            )],
72            Some(&context.payer.pubkey()),
73            &[&context.payer, &context.payer, &context.payer],
74            context.last_blockhash,
75        );
76        context.banks_client.process_transaction(tx).await?;
77
78        Ok((safety_deposit_box, store.pubkey()))
79    }
80
81    pub async fn activate(
82        &self,
83        context: &mut ProgramTestContext,
84        number_of_shares: u64,
85    ) -> Result<(), BanksClientError> {
86        let metaplex_token_vault_id = mpl_token_vault::id();
87        let vault_pubkey = self.keypair.pubkey();
88
89        let seeds = &[
90            PREFIX.as_bytes(),
91            metaplex_token_vault_id.as_ref(),
92            vault_pubkey.as_ref(),
93        ];
94        let (authority, _) = Pubkey::find_program_address(seeds, &metaplex_token_vault_id);
95
96        let tx = Transaction::new_signed_with_payer(
97            &[instruction::create_activate_vault_instruction(
98                mpl_token_vault::id(),
99                self.keypair.pubkey(),
100                self.mint.pubkey(),
101                self.fraction_treasury.pubkey(),
102                authority,
103                context.payer.pubkey(),
104                number_of_shares,
105            )],
106            Some(&context.payer.pubkey()),
107            &[&context.payer],
108            context.last_blockhash,
109        );
110
111        context.banks_client.process_transaction(tx).await
112    }
113
114    pub async fn combine(
115        &self,
116        context: &mut ProgramTestContext,
117        external_price: &ExternalPrice,
118    ) -> Result<(), BanksClientError> {
119        let outstanding_token_account = Keypair::new();
120        let paying_token_account = Keypair::new();
121
122        let metaplex_token_vault_id = mpl_token_vault::id();
123        let vault_pubkey = self.keypair.pubkey();
124
125        create_token_account(
126            context,
127            &outstanding_token_account,
128            &self.mint.pubkey(),
129            &context.payer.pubkey(),
130        )
131        .await?;
132        create_token_account(
133            context,
134            &paying_token_account,
135            &external_price.price_mint.pubkey(),
136            &context.payer.pubkey(),
137        )
138        .await?;
139
140        let seeds = &[
141            PREFIX.as_bytes(),
142            metaplex_token_vault_id.as_ref(),
143            vault_pubkey.as_ref(),
144        ];
145        let (authority, _) = Pubkey::find_program_address(seeds, &metaplex_token_vault_id);
146
147        let tx = Transaction::new_signed_with_payer(
148            &[instruction::create_combine_vault_instruction(
149                mpl_token_vault::id(),
150                self.keypair.pubkey(),
151                outstanding_token_account.pubkey(),
152                paying_token_account.pubkey(),
153                self.mint.pubkey(),
154                self.fraction_treasury.pubkey(),
155                self.redeem_treasury.pubkey(),
156                context.payer.pubkey(),
157                context.payer.pubkey(),
158                context.payer.pubkey(),
159                authority,
160                external_price.keypair.pubkey(),
161            )],
162            Some(&context.payer.pubkey()),
163            &[&context.payer, &context.payer, &context.payer],
164            context.last_blockhash,
165        );
166
167        context.banks_client.process_transaction(tx).await
168    }
169
170    pub async fn create(
171        &self,
172        context: &mut ProgramTestContext,
173        external_price: &ExternalPrice,
174    ) -> Result<(), BanksClientError> {
175        let metaplex_token_vault_id = mpl_token_vault::id();
176        let vault_pubkey = self.keypair.pubkey();
177
178        let seeds = &[
179            PREFIX.as_bytes(),
180            metaplex_token_vault_id.as_ref(),
181            vault_pubkey.as_ref(),
182        ];
183        let (authority, _) = Pubkey::find_program_address(seeds, &metaplex_token_vault_id);
184
185        create_mint(context, &self.mint, &authority, Some(&authority)).await?;
186        create_token_account(
187            context,
188            &self.redeem_treasury,
189            &external_price.price_mint.pubkey(),
190            &authority,
191        )
192        .await?;
193        create_token_account(
194            context,
195            &self.fraction_treasury,
196            &self.mint.pubkey(),
197            &authority,
198        )
199        .await?;
200
201        let rent = context.banks_client.get_rent().await.unwrap();
202        let tx = Transaction::new_signed_with_payer(
203            &[
204                system_instruction::create_account(
205                    &context.payer.pubkey(),
206                    &self.keypair.pubkey(),
207                    rent.minimum_balance(mpl_token_vault::state::MAX_VAULT_SIZE),
208                    mpl_token_vault::state::MAX_VAULT_SIZE as u64,
209                    &mpl_token_vault::id(),
210                ),
211                instruction::create_init_vault_instruction(
212                    mpl_token_vault::id(),
213                    self.mint.pubkey(),
214                    self.redeem_treasury.pubkey(),
215                    self.fraction_treasury.pubkey(),
216                    self.keypair.pubkey(),
217                    context.payer.pubkey(),
218                    external_price.keypair.pubkey(),
219                    false,
220                ),
221            ],
222            Some(&context.payer.pubkey()),
223            &[&context.payer, &context.payer, &self.keypair],
224            context.last_blockhash,
225        );
226
227        context.banks_client.process_transaction(tx).await
228    }
229}