Skip to main content

anchor_spl/
metadata.rs

1pub use mpl_token_metadata::{self, ID};
2use {
3    anchor_lang::{
4        context::CpiContext,
5        error::ErrorCode,
6        solana_program::{account_info::AccountInfo, pubkey::Pubkey},
7        system_program, Accounts, Result, ToAccountInfos,
8    },
9    std::ops::Deref,
10};
11
12pub fn approve_collection_authority<'info>(
13    ctx: CpiContext<'_, '_, '_, 'info, ApproveCollectionAuthority<'info>>,
14) -> Result<()> {
15    let ix = mpl_token_metadata::instructions::ApproveCollectionAuthority {
16        collection_authority_record: *ctx.accounts.collection_authority_record.key,
17        metadata: *ctx.accounts.metadata.key,
18        mint: *ctx.accounts.mint.key,
19        new_collection_authority: *ctx.accounts.new_collection_authority.key,
20        payer: *ctx.accounts.payer.key,
21        rent: None,
22        system_program: system_program::ID,
23        update_authority: *ctx.accounts.update_authority.key,
24    }
25    .instruction();
26    anchor_lang::solana_program::program::invoke_signed(
27        &ix,
28        &ToAccountInfos::to_account_infos(&ctx),
29        ctx.signer_seeds,
30    )
31    .map_err(Into::into)
32}
33
34pub fn bubblegum_set_collection_size<'info>(
35    ctx: CpiContext<'_, '_, '_, 'info, BubblegumSetCollectionSize<'info>>,
36    collection_authority_record: Option<Pubkey>,
37    size: u64,
38) -> Result<()> {
39    let ix = mpl_token_metadata::instructions::BubblegumSetCollectionSize {
40        collection_metadata: *ctx.accounts.metadata_account.key,
41        collection_authority: *ctx.accounts.update_authority.key,
42        collection_mint: *ctx.accounts.mint.key,
43        bubblegum_signer: *ctx.accounts.bubblegum_signer.key,
44        collection_authority_record,
45    }
46    .instruction(
47        mpl_token_metadata::instructions::BubblegumSetCollectionSizeInstructionArgs {
48            set_collection_size_args: mpl_token_metadata::types::SetCollectionSizeArgs { size },
49        },
50    );
51    anchor_lang::solana_program::program::invoke_signed(
52        &ix,
53        &ToAccountInfos::to_account_infos(&ctx),
54        ctx.signer_seeds,
55    )
56    .map_err(Into::into)
57}
58
59pub fn burn_edition_nft<'info>(
60    ctx: CpiContext<'_, '_, '_, 'info, BurnEditionNft<'info>>,
61) -> Result<()> {
62    let ix = mpl_token_metadata::instructions::BurnEditionNft {
63        edition_marker_account: *ctx.accounts.edition_marker.key,
64        master_edition_account: *ctx.accounts.master_edition.key,
65        master_edition_mint: *ctx.accounts.master_edition_mint.key,
66        master_edition_token_account: *ctx.accounts.master_edition_token.key,
67        metadata: *ctx.accounts.metadata.key,
68        owner: *ctx.accounts.owner.key,
69        print_edition_account: *ctx.accounts.print_edition.key,
70        print_edition_mint: *ctx.accounts.print_edition_mint.key,
71        print_edition_token_account: *ctx.accounts.print_edition_token.key,
72        spl_token_program: *ctx.accounts.spl_token.key,
73    }
74    .instruction();
75    anchor_lang::solana_program::program::invoke_signed(
76        &ix,
77        &ToAccountInfos::to_account_infos(&ctx),
78        ctx.signer_seeds,
79    )
80    .map_err(Into::into)
81}
82
83/// Burn an NFT by closing its token, metadata and edition accounts.
84///
85/// The lamports of the closed accounts will be transferred to the owner.
86///
87/// # Note
88///
89/// This instruction takes an optional `collection_metadata` argument, if this argument is
90/// `Some`, the `ctx` argument should also include the `collection_metadata` account in its
91/// remaining accounts, otherwise the CPI will fail because [`BurnNft`] only includes required
92/// accounts.
93///
94/// ```ignore
95/// CpiContext::new(program, BurnNft { .. })
96///     .with_remaining_accounts(vec![ctx.accounts.collection_metadata]);
97/// ```
98pub fn burn_nft<'info>(
99    ctx: CpiContext<'_, '_, '_, 'info, BurnNft<'info>>,
100    collection_metadata: Option<Pubkey>,
101) -> Result<()> {
102    let ix = mpl_token_metadata::instructions::BurnNft {
103        collection_metadata,
104        master_edition_account: *ctx.accounts.edition.key,
105        metadata: *ctx.accounts.metadata.key,
106        mint: *ctx.accounts.mint.key,
107        owner: *ctx.accounts.owner.key,
108        spl_token_program: *ctx.accounts.spl_token.key,
109        token_account: *ctx.accounts.token.key,
110    }
111    .instruction();
112    anchor_lang::solana_program::program::invoke_signed(
113        &ix,
114        &ToAccountInfos::to_account_infos(&ctx),
115        ctx.signer_seeds,
116    )
117    .map_err(Into::into)
118}
119
120pub fn create_metadata_accounts_v3<'info>(
121    ctx: CpiContext<'_, '_, '_, 'info, CreateMetadataAccountsV3<'info>>,
122    data: mpl_token_metadata::types::DataV2,
123    is_mutable: bool,
124    update_authority_is_signer: bool,
125    collection_details: Option<mpl_token_metadata::types::CollectionDetails>,
126) -> Result<()> {
127    let ix = mpl_token_metadata::instructions::CreateMetadataAccountV3 {
128        metadata: *ctx.accounts.metadata.key,
129        mint: *ctx.accounts.mint.key,
130        mint_authority: *ctx.accounts.mint_authority.key,
131        payer: *ctx.accounts.payer.key,
132        rent: None,
133        system_program: system_program::ID,
134        update_authority: (
135            *ctx.accounts.update_authority.key,
136            update_authority_is_signer,
137        ),
138    }
139    .instruction(
140        mpl_token_metadata::instructions::CreateMetadataAccountV3InstructionArgs {
141            collection_details,
142            data,
143            is_mutable,
144        },
145    );
146    anchor_lang::solana_program::program::invoke_signed(
147        &ix,
148        &ToAccountInfos::to_account_infos(&ctx),
149        ctx.signer_seeds,
150    )
151    .map_err(Into::into)
152}
153
154pub fn update_metadata_accounts_v2<'info>(
155    ctx: CpiContext<'_, '_, '_, 'info, UpdateMetadataAccountsV2<'info>>,
156    new_update_authority: Option<Pubkey>,
157    data: Option<mpl_token_metadata::types::DataV2>,
158    primary_sale_happened: Option<bool>,
159    is_mutable: Option<bool>,
160) -> Result<()> {
161    let ix = mpl_token_metadata::instructions::UpdateMetadataAccountV2 {
162        metadata: *ctx.accounts.metadata.key,
163        update_authority: *ctx.accounts.update_authority.key,
164    }
165    .instruction(
166        mpl_token_metadata::instructions::UpdateMetadataAccountV2InstructionArgs {
167            new_update_authority,
168            data,
169            primary_sale_happened,
170            is_mutable,
171        },
172    );
173    anchor_lang::solana_program::program::invoke_signed(
174        &ix,
175        &ToAccountInfos::to_account_infos(&ctx),
176        ctx.signer_seeds,
177    )
178    .map_err(Into::into)
179}
180
181pub fn create_master_edition_v3<'info>(
182    ctx: CpiContext<'_, '_, '_, 'info, CreateMasterEditionV3<'info>>,
183    max_supply: Option<u64>,
184) -> Result<()> {
185    let ix = mpl_token_metadata::instructions::CreateMasterEditionV3 {
186        edition: *ctx.accounts.edition.key,
187        metadata: *ctx.accounts.metadata.key,
188        mint: *ctx.accounts.mint.key,
189        mint_authority: *ctx.accounts.mint_authority.key,
190        payer: *ctx.accounts.payer.key,
191        rent: None,
192        system_program: system_program::ID,
193        token_program: spl_token_interface::ID,
194        update_authority: *ctx.accounts.update_authority.key,
195    }
196    .instruction(
197        mpl_token_metadata::instructions::CreateMasterEditionV3InstructionArgs { max_supply },
198    );
199    anchor_lang::solana_program::program::invoke_signed(
200        &ix,
201        &ToAccountInfos::to_account_infos(&ctx),
202        ctx.signer_seeds,
203    )
204    .map_err(Into::into)
205}
206
207pub fn mint_new_edition_from_master_edition_via_token<'info>(
208    ctx: CpiContext<'_, '_, '_, 'info, MintNewEditionFromMasterEditionViaToken<'info>>,
209    edition: u64,
210) -> Result<()> {
211    let ix = mpl_token_metadata::instructions::MintNewEditionFromMasterEditionViaToken {
212        edition_mark_pda: *ctx.accounts.edition_mark_pda.key,
213        master_edition: *ctx.accounts.master_edition.key,
214        metadata: *ctx.accounts.metadata.key,
215        new_edition: *ctx.accounts.new_edition.key,
216        new_metadata: *ctx.accounts.new_metadata.key,
217        new_metadata_update_authority: *ctx.accounts.new_metadata_update_authority.key,
218        new_mint: *ctx.accounts.new_mint.key,
219        new_mint_authority: *ctx.accounts.new_mint_authority.key,
220        payer: *ctx.accounts.payer.key,
221        rent: None,
222        system_program: system_program::ID,
223        token_account: *ctx.accounts.token_account.key,
224        token_account_owner: *ctx.accounts.token_account_owner.key,
225        token_program: spl_token_interface::ID,
226    }
227    .instruction(
228        mpl_token_metadata::instructions::MintNewEditionFromMasterEditionViaTokenInstructionArgs {
229            mint_new_edition_from_master_edition_via_token_args:
230                mpl_token_metadata::types::MintNewEditionFromMasterEditionViaTokenArgs { edition },
231        },
232    );
233    anchor_lang::solana_program::program::invoke_signed(
234        &ix,
235        &ToAccountInfos::to_account_infos(&ctx),
236        ctx.signer_seeds,
237    )
238    .map_err(Into::into)
239}
240
241pub fn revoke_collection_authority<'info>(
242    ctx: CpiContext<'_, '_, '_, 'info, RevokeCollectionAuthority<'info>>,
243) -> Result<()> {
244    let ix = mpl_token_metadata::instructions::RevokeCollectionAuthority {
245        collection_authority_record: *ctx.accounts.collection_authority_record.key,
246        delegate_authority: *ctx.accounts.delegate_authority.key,
247        metadata: *ctx.accounts.metadata.key,
248        mint: *ctx.accounts.mint.key,
249        revoke_authority: *ctx.accounts.revoke_authority.key,
250    }
251    .instruction();
252    anchor_lang::solana_program::program::invoke_signed(
253        &ix,
254        &ToAccountInfos::to_account_infos(&ctx),
255        ctx.signer_seeds,
256    )
257    .map_err(Into::into)
258}
259
260pub fn set_collection_size<'info>(
261    ctx: CpiContext<'_, '_, '_, 'info, SetCollectionSize<'info>>,
262    collection_authority_record: Option<Pubkey>,
263    size: u64,
264) -> Result<()> {
265    let ix = mpl_token_metadata::instructions::SetCollectionSize {
266        collection_authority: *ctx.accounts.update_authority.key,
267        collection_authority_record,
268        collection_metadata: *ctx.accounts.metadata.key,
269        collection_mint: *ctx.accounts.mint.key,
270    }
271    .instruction(
272        mpl_token_metadata::instructions::SetCollectionSizeInstructionArgs {
273            set_collection_size_args: mpl_token_metadata::types::SetCollectionSizeArgs { size },
274        },
275    );
276    anchor_lang::solana_program::program::invoke_signed(
277        &ix,
278        &ToAccountInfos::to_account_infos(&ctx),
279        ctx.signer_seeds,
280    )
281    .map_err(Into::into)
282}
283
284pub fn verify_collection<'info>(
285    ctx: CpiContext<'_, '_, '_, 'info, VerifyCollection<'info>>,
286    collection_authority_record: Option<Pubkey>,
287) -> Result<()> {
288    let ix = mpl_token_metadata::instructions::VerifyCollection {
289        collection: *ctx.accounts.collection_metadata.key,
290        collection_authority: *ctx.accounts.collection_authority.key,
291        collection_authority_record,
292        collection_master_edition_account: *ctx.accounts.collection_master_edition.key,
293        collection_mint: *ctx.accounts.collection_mint.key,
294        metadata: *ctx.accounts.metadata.key,
295        payer: *ctx.accounts.payer.key,
296    }
297    .instruction();
298    anchor_lang::solana_program::program::invoke_signed(
299        &ix,
300        &ToAccountInfos::to_account_infos(&ctx),
301        ctx.signer_seeds,
302    )
303    .map_err(Into::into)
304}
305
306pub fn verify_sized_collection_item<'info>(
307    ctx: CpiContext<'_, '_, '_, 'info, VerifySizedCollectionItem<'info>>,
308    collection_authority_record: Option<Pubkey>,
309) -> Result<()> {
310    let ix = mpl_token_metadata::instructions::VerifySizedCollectionItem {
311        collection: *ctx.accounts.collection_metadata.key,
312        collection_authority: *ctx.accounts.collection_authority.key,
313        collection_authority_record,
314        collection_master_edition_account: *ctx.accounts.collection_master_edition.key,
315        collection_mint: *ctx.accounts.collection_mint.key,
316        metadata: *ctx.accounts.metadata.key,
317        payer: *ctx.accounts.payer.key,
318    }
319    .instruction();
320    anchor_lang::solana_program::program::invoke_signed(
321        &ix,
322        &ToAccountInfos::to_account_infos(&ctx),
323        ctx.signer_seeds,
324    )
325    .map_err(Into::into)
326}
327
328pub fn set_and_verify_collection<'info>(
329    ctx: CpiContext<'_, '_, '_, 'info, SetAndVerifyCollection<'info>>,
330    collection_authority_record: Option<Pubkey>,
331) -> Result<()> {
332    let ix = mpl_token_metadata::instructions::SetAndVerifyCollection {
333        collection: *ctx.accounts.collection_metadata.key,
334        collection_authority: *ctx.accounts.collection_authority.key,
335        collection_authority_record,
336        collection_master_edition_account: *ctx.accounts.collection_master_edition.key,
337        collection_mint: *ctx.accounts.collection_mint.key,
338        metadata: *ctx.accounts.metadata.key,
339        payer: *ctx.accounts.payer.key,
340        update_authority: *ctx.accounts.update_authority.key,
341    }
342    .instruction();
343    anchor_lang::solana_program::program::invoke_signed(
344        &ix,
345        &ToAccountInfos::to_account_infos(&ctx),
346        ctx.signer_seeds,
347    )
348    .map_err(Into::into)
349}
350
351pub fn set_and_verify_sized_collection_item<'info>(
352    ctx: CpiContext<'_, '_, '_, 'info, SetAndVerifySizedCollectionItem<'info>>,
353    collection_authority_record: Option<Pubkey>,
354) -> Result<()> {
355    let ix = mpl_token_metadata::instructions::SetAndVerifySizedCollectionItem {
356        collection: *ctx.accounts.collection_metadata.key,
357        collection_authority: *ctx.accounts.collection_authority.key,
358        collection_authority_record,
359        collection_master_edition_account: *ctx.accounts.collection_master_edition.key,
360        collection_mint: *ctx.accounts.collection_mint.key,
361        metadata: *ctx.accounts.metadata.key,
362        payer: *ctx.accounts.payer.key,
363        update_authority: *ctx.accounts.update_authority.key,
364    }
365    .instruction();
366    anchor_lang::solana_program::program::invoke_signed(
367        &ix,
368        &ToAccountInfos::to_account_infos(&ctx),
369        ctx.signer_seeds,
370    )
371    .map_err(Into::into)
372}
373
374pub fn freeze_delegated_account<'info>(
375    ctx: CpiContext<'_, '_, '_, 'info, FreezeDelegatedAccount<'info>>,
376) -> Result<()> {
377    let ix = mpl_token_metadata::instructions::FreezeDelegatedAccount {
378        delegate: *ctx.accounts.delegate.key,
379        edition: *ctx.accounts.edition.key,
380        mint: *ctx.accounts.mint.key,
381        token_account: *ctx.accounts.token_account.key,
382        token_program: *ctx.accounts.token_program.key,
383    }
384    .instruction();
385    anchor_lang::solana_program::program::invoke_signed(
386        &ix,
387        &ToAccountInfos::to_account_infos(&ctx),
388        ctx.signer_seeds,
389    )
390    .map_err(Into::into)
391}
392
393pub fn thaw_delegated_account<'info>(
394    ctx: CpiContext<'_, '_, '_, 'info, ThawDelegatedAccount<'info>>,
395) -> Result<()> {
396    let ix = mpl_token_metadata::instructions::ThawDelegatedAccount {
397        delegate: *ctx.accounts.delegate.key,
398        edition: *ctx.accounts.edition.key,
399        mint: *ctx.accounts.mint.key,
400        token_account: *ctx.accounts.token_account.key,
401        token_program: *ctx.accounts.token_program.key,
402    }
403    .instruction();
404    anchor_lang::solana_program::program::invoke_signed(
405        &ix,
406        &ToAccountInfos::to_account_infos(&ctx),
407        ctx.signer_seeds,
408    )
409    .map_err(Into::into)
410}
411
412pub fn update_primary_sale_happened_via_token<'info>(
413    ctx: CpiContext<'_, '_, '_, 'info, UpdatePrimarySaleHappenedViaToken<'info>>,
414) -> Result<()> {
415    let ix = mpl_token_metadata::instructions::UpdatePrimarySaleHappenedViaToken {
416        metadata: *ctx.accounts.metadata.key,
417        owner: *ctx.accounts.owner.key,
418        token: *ctx.accounts.token.key,
419    }
420    .instruction();
421    anchor_lang::solana_program::program::invoke_signed(
422        &ix,
423        &ToAccountInfos::to_account_infos(&ctx),
424        ctx.signer_seeds,
425    )?;
426    Ok(())
427}
428
429pub fn set_token_standard<'info>(
430    ctx: CpiContext<'_, '_, '_, 'info, SetTokenStandard<'info>>,
431    edition_account: Option<Pubkey>,
432) -> Result<()> {
433    let ix = mpl_token_metadata::instructions::SetTokenStandard {
434        edition: edition_account,
435        metadata: *ctx.accounts.metadata_account.key,
436        mint: *ctx.accounts.mint_account.key,
437        update_authority: *ctx.accounts.update_authority.key,
438    }
439    .instruction();
440    anchor_lang::solana_program::program::invoke_signed(
441        &ix,
442        &ToAccountInfos::to_account_infos(&ctx),
443        ctx.signer_seeds,
444    )
445    .map_err(Into::into)
446}
447
448pub fn sign_metadata<'info>(ctx: CpiContext<'_, '_, '_, 'info, SignMetadata<'info>>) -> Result<()> {
449    let ix = mpl_token_metadata::instructions::SignMetadata {
450        creator: *ctx.accounts.creator.key,
451        metadata: *ctx.accounts.metadata.key,
452    }
453    .instruction();
454    anchor_lang::solana_program::program::invoke_signed(
455        &ix,
456        &ToAccountInfos::to_account_infos(&ctx),
457        ctx.signer_seeds,
458    )?;
459    Ok(())
460}
461
462pub fn remove_creator_verification<'info>(
463    ctx: CpiContext<'_, '_, '_, 'info, RemoveCreatorVerification<'info>>,
464) -> Result<()> {
465    let ix = mpl_token_metadata::instructions::RemoveCreatorVerification {
466        creator: *ctx.accounts.creator.key,
467        metadata: *ctx.accounts.metadata.key,
468    }
469    .instruction();
470    anchor_lang::solana_program::program::invoke_signed(
471        &ix,
472        &ToAccountInfos::to_account_infos(&ctx),
473        ctx.signer_seeds,
474    )?;
475    Ok(())
476}
477
478pub fn utilize<'info>(
479    ctx: CpiContext<'_, '_, '_, 'info, Utilize<'info>>,
480    use_authority_record: Option<Pubkey>,
481    burner: Option<Pubkey>,
482    number_of_uses: u64,
483) -> Result<()> {
484    let ix = mpl_token_metadata::instructions::Utilize {
485        ata_program: spl_associated_token_account_interface::program::ID,
486        burner,
487        metadata: *ctx.accounts.metadata.key,
488        mint: *ctx.accounts.mint.key,
489        owner: *ctx.accounts.owner.key,
490        rent: solana_sysvar::rent::ID,
491        system_program: system_program::ID,
492        token_account: *ctx.accounts.token_account.key,
493        token_program: spl_token_interface::ID,
494        use_authority: *ctx.accounts.use_authority.key,
495        use_authority_record,
496    }
497    .instruction(mpl_token_metadata::instructions::UtilizeInstructionArgs { number_of_uses });
498    anchor_lang::solana_program::program::invoke_signed(
499        &ix,
500        &ToAccountInfos::to_account_infos(&ctx),
501        ctx.signer_seeds,
502    )
503    .map_err(Into::into)
504}
505
506pub fn unverify_collection<'info>(
507    ctx: CpiContext<'_, '_, '_, 'info, UnverifyCollection<'info>>,
508    collection_authority_record: Option<Pubkey>,
509) -> Result<()> {
510    let ix = mpl_token_metadata::instructions::UnverifyCollection {
511        collection: *ctx.accounts.metadata.key,
512        collection_authority: *ctx.accounts.collection_authority.key,
513        collection_authority_record,
514        collection_master_edition_account: *ctx.accounts.collection_master_edition_account.key,
515        collection_mint: *ctx.accounts.collection_mint.key,
516        metadata: *ctx.accounts.metadata.key,
517    }
518    .instruction();
519    anchor_lang::solana_program::program::invoke_signed(
520        &ix,
521        &ToAccountInfos::to_account_infos(&ctx),
522        ctx.signer_seeds,
523    )
524    .map_err(Into::into)
525}
526
527pub fn unverify_sized_collection_item<'info>(
528    ctx: CpiContext<'_, '_, '_, 'info, UnverifySizedCollectionItem<'info>>,
529    collection_authority_record: Option<Pubkey>,
530) -> Result<()> {
531    let ix = mpl_token_metadata::instructions::UnverifySizedCollectionItem {
532        collection: *ctx.accounts.metadata.key,
533        collection_authority: *ctx.accounts.collection_authority.key,
534        collection_authority_record,
535        collection_master_edition_account: *ctx.accounts.collection_master_edition_account.key,
536        collection_mint: *ctx.accounts.collection_mint.key,
537        metadata: *ctx.accounts.metadata.key,
538        payer: *ctx.accounts.payer.key,
539    }
540    .instruction();
541    anchor_lang::solana_program::program::invoke_signed(
542        &ix,
543        &ToAccountInfos::to_account_infos(&ctx),
544        ctx.signer_seeds,
545    )
546    .map_err(Into::into)
547}
548
549#[derive(Accounts)]
550pub struct ApproveCollectionAuthority<'info> {
551    pub collection_authority_record: AccountInfo<'info>,
552    pub new_collection_authority: AccountInfo<'info>,
553    pub update_authority: AccountInfo<'info>,
554    pub payer: AccountInfo<'info>,
555    pub metadata: AccountInfo<'info>,
556    pub mint: AccountInfo<'info>,
557}
558
559#[derive(Accounts)]
560pub struct BubblegumSetCollectionSize<'info> {
561    pub metadata_account: AccountInfo<'info>,
562    pub update_authority: AccountInfo<'info>,
563    pub mint: AccountInfo<'info>,
564    pub bubblegum_signer: AccountInfo<'info>,
565}
566
567#[derive(Accounts)]
568pub struct BurnEditionNft<'info> {
569    pub metadata: AccountInfo<'info>,
570    pub owner: AccountInfo<'info>,
571    pub print_edition_mint: AccountInfo<'info>,
572    pub master_edition_mint: AccountInfo<'info>,
573    pub print_edition_token: AccountInfo<'info>,
574    pub master_edition_token: AccountInfo<'info>,
575    pub master_edition: AccountInfo<'info>,
576    pub print_edition: AccountInfo<'info>,
577    pub edition_marker: AccountInfo<'info>,
578    pub spl_token: AccountInfo<'info>,
579}
580
581#[derive(Accounts)]
582pub struct BurnNft<'info> {
583    pub metadata: AccountInfo<'info>,
584    pub owner: AccountInfo<'info>,
585    pub mint: AccountInfo<'info>,
586    pub token: AccountInfo<'info>,
587    pub edition: AccountInfo<'info>,
588    pub spl_token: AccountInfo<'info>,
589}
590
591#[derive(Accounts)]
592pub struct CreateMetadataAccountsV3<'info> {
593    pub metadata: AccountInfo<'info>,
594    pub mint: AccountInfo<'info>,
595    pub mint_authority: AccountInfo<'info>,
596    pub payer: AccountInfo<'info>,
597    pub update_authority: AccountInfo<'info>,
598    pub system_program: AccountInfo<'info>,
599    pub rent: AccountInfo<'info>,
600}
601
602#[derive(Accounts)]
603pub struct UpdateMetadataAccountsV2<'info> {
604    pub metadata: AccountInfo<'info>,
605    pub update_authority: AccountInfo<'info>,
606}
607
608#[derive(Accounts)]
609pub struct CreateMasterEditionV3<'info> {
610    pub edition: AccountInfo<'info>,
611    pub mint: AccountInfo<'info>,
612    pub update_authority: AccountInfo<'info>,
613    pub mint_authority: AccountInfo<'info>,
614    pub payer: AccountInfo<'info>,
615    pub metadata: AccountInfo<'info>,
616    pub token_program: AccountInfo<'info>,
617    pub system_program: AccountInfo<'info>,
618    pub rent: AccountInfo<'info>,
619}
620
621#[derive(Accounts)]
622pub struct MintNewEditionFromMasterEditionViaToken<'info> {
623    pub new_metadata: AccountInfo<'info>,
624    pub new_edition: AccountInfo<'info>,
625    pub master_edition: AccountInfo<'info>,
626    pub new_mint: AccountInfo<'info>,
627    pub edition_mark_pda: AccountInfo<'info>,
628    pub new_mint_authority: AccountInfo<'info>,
629    pub payer: AccountInfo<'info>,
630    pub token_account_owner: AccountInfo<'info>,
631    pub token_account: AccountInfo<'info>,
632    pub new_metadata_update_authority: AccountInfo<'info>,
633    pub metadata: AccountInfo<'info>,
634    pub token_program: AccountInfo<'info>,
635    pub system_program: AccountInfo<'info>,
636    pub rent: AccountInfo<'info>,
637    //
638    // Not actually used by the program but still needed because it's needed
639    // for the pda calculation in the helper. :/
640    //
641    // The better thing to do would be to remove this and have the instruction
642    // helper pass in the `edition_mark_pda` directly.
643    //
644    pub metadata_mint: AccountInfo<'info>,
645}
646
647#[derive(Accounts)]
648pub struct RevokeCollectionAuthority<'info> {
649    pub collection_authority_record: AccountInfo<'info>,
650    pub delegate_authority: AccountInfo<'info>,
651    pub revoke_authority: AccountInfo<'info>,
652    pub metadata: AccountInfo<'info>,
653    pub mint: AccountInfo<'info>,
654}
655
656#[derive(Accounts)]
657pub struct SetCollectionSize<'info> {
658    pub metadata: AccountInfo<'info>,
659    pub mint: AccountInfo<'info>,
660    pub update_authority: AccountInfo<'info>,
661    pub system_program: AccountInfo<'info>,
662}
663
664#[derive(Accounts)]
665pub struct SetTokenStandard<'info> {
666    pub metadata_account: AccountInfo<'info>,
667    pub update_authority: AccountInfo<'info>,
668    pub mint_account: AccountInfo<'info>,
669}
670
671#[derive(Accounts)]
672pub struct VerifyCollection<'info> {
673    pub payer: AccountInfo<'info>,
674    pub metadata: AccountInfo<'info>,
675    pub collection_authority: AccountInfo<'info>,
676    pub collection_mint: AccountInfo<'info>,
677    pub collection_metadata: AccountInfo<'info>,
678    pub collection_master_edition: AccountInfo<'info>,
679}
680
681#[derive(Accounts)]
682pub struct VerifySizedCollectionItem<'info> {
683    pub payer: AccountInfo<'info>,
684    pub metadata: AccountInfo<'info>,
685    pub collection_authority: AccountInfo<'info>,
686    pub collection_mint: AccountInfo<'info>,
687    pub collection_metadata: AccountInfo<'info>,
688    pub collection_master_edition: AccountInfo<'info>,
689}
690
691#[derive(Accounts)]
692pub struct SetAndVerifyCollection<'info> {
693    pub metadata: AccountInfo<'info>,
694    pub collection_authority: AccountInfo<'info>,
695    pub payer: AccountInfo<'info>,
696    pub update_authority: AccountInfo<'info>,
697    pub collection_mint: AccountInfo<'info>,
698    pub collection_metadata: AccountInfo<'info>,
699    pub collection_master_edition: AccountInfo<'info>,
700}
701
702#[derive(Accounts)]
703pub struct SetAndVerifySizedCollectionItem<'info> {
704    pub metadata: AccountInfo<'info>,
705    pub collection_authority: AccountInfo<'info>,
706    pub payer: AccountInfo<'info>,
707    pub update_authority: AccountInfo<'info>,
708    pub collection_mint: AccountInfo<'info>,
709    pub collection_metadata: AccountInfo<'info>,
710    pub collection_master_edition: AccountInfo<'info>,
711}
712
713#[derive(Accounts)]
714pub struct FreezeDelegatedAccount<'info> {
715    pub metadata: AccountInfo<'info>,
716    pub delegate: AccountInfo<'info>,
717    pub token_account: AccountInfo<'info>,
718    pub edition: AccountInfo<'info>,
719    pub mint: AccountInfo<'info>,
720    pub token_program: AccountInfo<'info>,
721}
722
723#[derive(Accounts)]
724pub struct ThawDelegatedAccount<'info> {
725    pub metadata: AccountInfo<'info>,
726    pub delegate: AccountInfo<'info>,
727    pub token_account: AccountInfo<'info>,
728    pub edition: AccountInfo<'info>,
729    pub mint: AccountInfo<'info>,
730    pub token_program: AccountInfo<'info>,
731}
732
733#[derive(Accounts)]
734pub struct UpdatePrimarySaleHappenedViaToken<'info> {
735    pub metadata: AccountInfo<'info>,
736    pub owner: AccountInfo<'info>,
737    pub token: AccountInfo<'info>,
738}
739
740#[derive(Accounts)]
741pub struct SignMetadata<'info> {
742    pub creator: AccountInfo<'info>,
743    pub metadata: AccountInfo<'info>,
744}
745
746#[derive(Accounts)]
747pub struct RemoveCreatorVerification<'info> {
748    pub creator: AccountInfo<'info>,
749    pub metadata: AccountInfo<'info>,
750}
751
752#[derive(Accounts)]
753pub struct Utilize<'info> {
754    pub metadata: AccountInfo<'info>,
755    pub token_account: AccountInfo<'info>,
756    pub mint: AccountInfo<'info>,
757    pub use_authority: AccountInfo<'info>,
758    pub owner: AccountInfo<'info>,
759}
760
761#[derive(Accounts)]
762pub struct UnverifyCollection<'info> {
763    pub metadata: AccountInfo<'info>,
764    pub collection_authority: AccountInfo<'info>,
765    pub collection_mint: AccountInfo<'info>,
766    pub collection: AccountInfo<'info>,
767    pub collection_master_edition_account: AccountInfo<'info>,
768}
769
770#[derive(Accounts)]
771pub struct UnverifySizedCollectionItem<'info> {
772    pub metadata: AccountInfo<'info>,
773    pub collection_authority: AccountInfo<'info>,
774    pub payer: AccountInfo<'info>,
775    pub collection_mint: AccountInfo<'info>,
776    pub collection: AccountInfo<'info>,
777    pub collection_master_edition_account: AccountInfo<'info>,
778}
779
780#[derive(Clone, Debug, PartialEq)]
781pub struct MetadataAccount(mpl_token_metadata::accounts::Metadata);
782
783impl anchor_lang::AccountDeserialize for MetadataAccount {
784    fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
785        let md = Self::try_deserialize_unchecked(buf)?;
786        if md.key != mpl_token_metadata::types::Key::MetadataV1 {
787            return Err(ErrorCode::AccountNotInitialized.into());
788        }
789        Ok(md)
790    }
791
792    fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
793        let md = mpl_token_metadata::accounts::Metadata::safe_deserialize(buf)?;
794        Ok(Self(md))
795    }
796}
797
798impl anchor_lang::AccountSerialize for MetadataAccount {}
799
800impl anchor_lang::Owner for MetadataAccount {
801    fn owner() -> Pubkey {
802        ID
803    }
804}
805
806impl Deref for MetadataAccount {
807    type Target = mpl_token_metadata::accounts::Metadata;
808    fn deref(&self) -> &Self::Target {
809        &self.0
810    }
811}
812
813#[derive(Clone, Debug, PartialEq)]
814pub struct MasterEditionAccount(mpl_token_metadata::accounts::MasterEdition);
815
816impl anchor_lang::AccountDeserialize for MasterEditionAccount {
817    fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
818        let me = Self::try_deserialize_unchecked(buf)?;
819        if me.key != mpl_token_metadata::types::Key::MasterEditionV2 {
820            return Err(ErrorCode::AccountNotInitialized.into());
821        }
822        Ok(me)
823    }
824
825    fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
826        let result = mpl_token_metadata::accounts::MasterEdition::safe_deserialize(buf)?;
827        Ok(Self(result))
828    }
829}
830
831impl Deref for MasterEditionAccount {
832    type Target = mpl_token_metadata::accounts::MasterEdition;
833    fn deref(&self) -> &Self::Target {
834        &self.0
835    }
836}
837
838impl anchor_lang::AccountSerialize for MasterEditionAccount {}
839
840impl anchor_lang::Owner for MasterEditionAccount {
841    fn owner() -> Pubkey {
842        ID
843    }
844}
845
846#[derive(Clone, Debug, PartialEq)]
847pub struct TokenRecordAccount(mpl_token_metadata::accounts::TokenRecord);
848
849impl TokenRecordAccount {
850    pub const LEN: usize = mpl_token_metadata::accounts::TokenRecord::LEN;
851}
852impl anchor_lang::AccountDeserialize for TokenRecordAccount {
853    fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
854        let tr = Self::try_deserialize_unchecked(buf)?;
855        if tr.key != mpl_token_metadata::types::Key::TokenRecord {
856            return Err(ErrorCode::AccountNotInitialized.into());
857        }
858        Ok(tr)
859    }
860
861    fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
862        let tr = mpl_token_metadata::accounts::TokenRecord::safe_deserialize(buf)?;
863        Ok(Self(tr))
864    }
865}
866
867impl anchor_lang::AccountSerialize for TokenRecordAccount {}
868
869impl anchor_lang::Owner for TokenRecordAccount {
870    fn owner() -> Pubkey {
871        ID
872    }
873}
874
875impl Deref for TokenRecordAccount {
876    type Target = mpl_token_metadata::accounts::TokenRecord;
877    fn deref(&self) -> &Self::Target {
878        &self.0
879    }
880}
881
882#[derive(Clone)]
883pub struct Metadata;
884
885impl anchor_lang::Id for Metadata {
886    fn id() -> Pubkey {
887        ID
888    }
889}