mpl_testing_utils/utils/
metadata.rs

1use crate::{solana::create_associated_token_account, utils::*};
2use mpl_token_metadata::{
3    id, instruction,
4    state::{Collection, Creator, Data, DataV2, Uses, PREFIX},
5};
6use solana_program::borsh::try_from_slice_unchecked;
7use solana_program_test::*;
8use solana_sdk::{
9    pubkey::Pubkey, signature::Signer, signer::keypair::Keypair, transaction::Transaction,
10};
11
12#[derive(Debug)]
13pub struct Metadata {
14    pub mint: Keypair,
15    pub pubkey: Pubkey,
16    pub token: Keypair,
17}
18
19impl Default for Metadata {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl Metadata {
26    pub fn new() -> Self {
27        let mint = Keypair::new();
28        let mint_pubkey = mint.pubkey();
29        let program_id = id();
30
31        let metadata_seeds = &[PREFIX.as_bytes(), program_id.as_ref(), mint_pubkey.as_ref()];
32        let (pubkey, _) = Pubkey::find_program_address(metadata_seeds, &id());
33
34        Metadata {
35            mint,
36            pubkey,
37            token: Keypair::new(),
38        }
39    }
40
41    pub async fn get_data(
42        &self,
43        context: &mut ProgramTestContext,
44    ) -> mpl_token_metadata::state::Metadata {
45        let account = get_account(context, &self.pubkey).await;
46        try_from_slice_unchecked(&account.data).unwrap()
47    }
48
49    pub async fn create(
50        &self,
51        context: &mut ProgramTestContext,
52        name: String,
53        symbol: String,
54        uri: String,
55        creators: Option<Vec<Creator>>,
56        seller_fee_basis_points: u16,
57        is_mutable: bool,
58        amount: u64,
59    ) -> Result<(), BanksClientError> {
60        create_mint(context, &self.mint, &context.payer.pubkey(), None).await?;
61
62        let token = create_associated_token_account(context, &self.token, &self.mint.pubkey())
63            .await
64            .unwrap();
65        mint_tokens(
66            context,
67            &self.mint.pubkey(),
68            &token,
69            amount,
70            &context.payer.pubkey(),
71            None,
72        )
73        .await?;
74
75        let tx = Transaction::new_signed_with_payer(
76            &[instruction::create_metadata_accounts(
77                id(),
78                self.pubkey,
79                self.mint.pubkey(),
80                context.payer.pubkey(),
81                context.payer.pubkey(),
82                context.payer.pubkey(),
83                name,
84                symbol,
85                uri,
86                creators,
87                seller_fee_basis_points,
88                false,
89                is_mutable,
90            )],
91            Some(&context.payer.pubkey()),
92            &[&context.payer],
93            context.last_blockhash,
94        );
95
96        context.banks_client.process_transaction(tx).await
97    }
98
99    pub async fn create_v2(
100        &self,
101        context: &mut ProgramTestContext,
102        name: String,
103        symbol: String,
104        uri: String,
105        creators: Option<Vec<Creator>>,
106        seller_fee_basis_points: u16,
107        is_mutable: bool,
108        collection: Option<Collection>,
109        uses: Option<Uses>,
110    ) -> Result<(), BanksClientError> {
111        create_mint(context, &self.mint, &context.payer.pubkey(), None).await?;
112        create_token_account(
113            context,
114            &self.token,
115            &self.mint.pubkey(),
116            &context.payer.pubkey(),
117        )
118        .await?;
119        mint_tokens(
120            context,
121            &self.mint.pubkey(),
122            &self.token.pubkey(),
123            1,
124            &context.payer.pubkey(),
125            None,
126        )
127        .await?;
128
129        let tx = Transaction::new_signed_with_payer(
130            &[instruction::create_metadata_accounts_v2(
131                id(),
132                self.pubkey,
133                self.mint.pubkey(),
134                context.payer.pubkey(),
135                context.payer.pubkey(),
136                context.payer.pubkey(),
137                name,
138                symbol,
139                uri,
140                creators,
141                seller_fee_basis_points,
142                false,
143                is_mutable,
144                collection,
145                uses,
146            )],
147            Some(&context.payer.pubkey()),
148            &[&context.payer],
149            context.last_blockhash,
150        );
151
152        context.banks_client.process_transaction(tx).await
153    }
154
155    pub async fn update_primary_sale_happened_via_token(
156        &self,
157        context: &mut ProgramTestContext,
158    ) -> Result<(), BanksClientError> {
159        let tx = Transaction::new_signed_with_payer(
160            &[instruction::update_primary_sale_happened_via_token(
161                id(),
162                self.pubkey,
163                context.payer.pubkey(),
164                self.token.pubkey(),
165            )],
166            Some(&context.payer.pubkey()),
167            &[&context.payer],
168            context.last_blockhash,
169        );
170
171        context.banks_client.process_transaction(tx).await
172    }
173
174    pub async fn update(
175        &self,
176        context: &mut ProgramTestContext,
177        name: String,
178        symbol: String,
179        uri: String,
180        creators: Option<Vec<Creator>>,
181        seller_fee_basis_points: u16,
182    ) -> Result<(), BanksClientError> {
183        let tx = Transaction::new_signed_with_payer(
184            &[instruction::update_metadata_accounts(
185                id(),
186                self.pubkey,
187                context.payer.pubkey(),
188                None,
189                Some(Data {
190                    name,
191                    symbol,
192                    uri,
193                    creators,
194                    seller_fee_basis_points,
195                }),
196                None,
197            )],
198            Some(&context.payer.pubkey()),
199            &[&context.payer],
200            context.last_blockhash,
201        );
202
203        context.banks_client.process_transaction(tx).await
204    }
205
206    pub async fn update_v2(
207        &self,
208        context: &mut ProgramTestContext,
209        name: String,
210        symbol: String,
211        uri: String,
212        creators: Option<Vec<Creator>>,
213        seller_fee_basis_points: u16,
214        is_mutable: bool,
215        collection: Option<Collection>,
216        uses: Option<Uses>,
217    ) -> Result<(), BanksClientError> {
218        let tx = Transaction::new_signed_with_payer(
219            &[instruction::update_metadata_accounts_v2(
220                id(),
221                self.pubkey,
222                context.payer.pubkey(),
223                None,
224                Some(DataV2 {
225                    name,
226                    symbol,
227                    uri,
228                    creators,
229                    seller_fee_basis_points,
230                    collection,
231                    uses,
232                }),
233                None,
234                Some(is_mutable),
235            )],
236            Some(&context.payer.pubkey()),
237            &[&context.payer],
238            context.last_blockhash,
239        );
240
241        context.banks_client.process_transaction(tx).await
242    }
243
244    pub async fn verify_collection(
245        &self,
246        context: &mut ProgramTestContext,
247        collection: Pubkey,
248        collection_authority: Keypair,
249        collection_mint: Pubkey,
250        collection_master_edition_account: Pubkey,
251        collection_authority_record: Option<Pubkey>,
252    ) -> Result<(), BanksClientError> {
253        let tx = Transaction::new_signed_with_payer(
254            &[instruction::verify_collection(
255                id(),
256                self.pubkey,
257                collection_authority.pubkey(),
258                context.payer.pubkey(),
259                collection_mint,
260                collection,
261                collection_master_edition_account,
262                collection_authority_record,
263            )],
264            Some(&context.payer.pubkey()),
265            &[&context.payer, &collection_authority],
266            context.last_blockhash,
267        );
268
269        context.banks_client.process_transaction(tx).await
270    }
271
272    pub async fn unverify_collection(
273        &self,
274        context: &mut ProgramTestContext,
275        collection: Pubkey,
276        collection_authority: Keypair,
277        collection_mint: Pubkey,
278        collection_master_edition_account: Pubkey,
279        collection_authority_record: Option<Pubkey>,
280    ) -> Result<(), BanksClientError> {
281        let tx = Transaction::new_signed_with_payer(
282            &[instruction::unverify_collection(
283                id(),
284                self.pubkey,
285                collection_authority.pubkey(),
286                collection_mint,
287                collection,
288                collection_master_edition_account,
289                collection_authority_record,
290            )],
291            Some(&context.payer.pubkey()),
292            &[&context.payer, &collection_authority],
293            context.last_blockhash,
294        );
295
296        context.banks_client.process_transaction(tx).await
297    }
298}