Skip to main content

solana_nft_token_metadata/
instruction.rs

1use crate::{
2    deprecated_instruction::{MintPrintingTokensViaTokenArgs, SetReservationListArgs},
3    state::{Collection, Creator, Data, DataV2, Uses, EDITION, EDITION_MARKER_BIT_SIZE, PREFIX},
4};
5use borsh::{BorshDeserialize, BorshSerialize};
6use solana_program::{
7    instruction::{AccountMeta, Instruction},
8    pubkey::Pubkey,
9    sysvar,
10};
11
12#[repr(C)]
13#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
14/// Args for update call
15pub struct UpdateMetadataAccountArgs {
16    pub data: Option<Data>,
17    pub update_authority: Option<Pubkey>,
18    pub primary_sale_happened: Option<bool>,
19}
20
21#[repr(C)]
22#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
23/// Args for update call
24pub struct UpdateMetadataAccountArgsV2 {
25    pub data: Option<DataV2>,
26    pub update_authority: Option<Pubkey>,
27    pub primary_sale_happened: Option<bool>,
28    pub is_mutable: Option<bool>,
29}
30
31#[repr(C)]
32#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
33/// Args for create call
34pub struct CreateMetadataAccountArgs {
35    /// Note that unique metadatas are disabled for now.
36    pub data: Data,
37    /// Whether you want your metadata to be updateable in the future.
38    pub is_mutable: bool,
39}
40
41#[repr(C)]
42#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
43/// Args for create call
44pub struct CreateMetadataAccountArgsV2 {
45    /// Note that unique metadatas are disabled for now.
46    pub data: DataV2,
47    /// Whether you want your metadata to be updateable in the future.
48    pub is_mutable: bool,
49}
50
51#[repr(C)]
52#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
53pub struct CreateMasterEditionArgs {
54    /// If set, means that no more than this number of editions can ever be minted. This is immutable.
55    pub max_supply: Option<u64>,
56}
57
58#[repr(C)]
59#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
60pub struct MintNewEditionFromMasterEditionViaTokenArgs {
61    pub edition: u64,
62}
63
64#[repr(C)]
65#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
66pub struct ApproveUseAuthorityArgs {
67    pub number_of_uses: u64,
68}
69
70#[repr(C)]
71#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
72pub struct UtilizeArgs {
73    pub number_of_uses: u64,
74}
75
76/// Instructions supported by the Metadata program.
77#[derive(BorshSerialize, BorshDeserialize, Clone)]
78pub enum MetadataInstruction {
79    /// Create Metadata object.
80    ///   0. `[writable]`  Metadata key (pda of ['metadata', program id, mint id])
81    ///   1. `[]` Mint of token asset
82    ///   2. `[signer]` Mint authority
83    ///   3. `[signer]` payer
84    ///   4. `[]` update authority info
85    ///   5. `[]` System program
86    ///   6. `[]` Rent info
87    CreateMetadataAccount(CreateMetadataAccountArgs),
88
89    /// Update a Metadata
90    ///   0. `[writable]` Metadata account
91    ///   1. `[signer]` Update authority key
92    UpdateMetadataAccount(UpdateMetadataAccountArgs),
93
94    /// Register a Metadata as a Master Edition V1, which means Editions can be minted.
95    /// Henceforth, no further tokens will be mintable from this primary mint. Will throw an error if more than one
96    /// token exists, and will throw an error if less than one token exists in this primary mint.
97    ///   0. `[writable]` Unallocated edition V1 account with address as pda of ['metadata', program id, mint, 'edition']
98    ///   1. `[writable]` Metadata mint
99    ///   2. `[writable]` Printing mint - A mint you control that can mint tokens that can be exchanged for limited editions of your
100    ///       master edition via the MintNewEditionFromMasterEditionViaToken endpoint
101    ///   3. `[writable]` One time authorization printing mint - A mint you control that prints tokens that gives the bearer permission to mint any
102    ///                  number of tokens from the printing mint one time via an endpoint with the token-metadata program for your metadata. Also burns the token.
103    ///   4. `[signer]` Current Update authority key
104    ///   5. `[signer]`   Printing mint authority - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY.
105    ///   6. `[signer]` Mint authority on the metadata's mint - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY
106    ///   7. `[]` Metadata account
107    ///   8. `[signer]` payer
108    ///   9. `[]` Token program
109    ///   10. `[]` System program
110    ///   11. `[]` Rent info
111    ///   13. `[signer]`   One time authorization printing mint authority - must be provided if using max supply. THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY.
112    DeprecatedCreateMasterEdition(CreateMasterEditionArgs),
113
114    /// Given an authority token minted by the Printing mint of a master edition, and a brand new non-metadata-ed mint with one token
115    /// make a new Metadata + Edition that is a child of the master edition denoted by this authority token.
116    ///   0. `[writable]` New Metadata key (pda of ['metadata', program id, mint id])
117    ///   1. `[writable]` New Edition V1 (pda of ['metadata', program id, mint id, 'edition'])
118    ///   2. `[writable]` Master Record Edition V1 (pda of ['metadata', program id, master metadata mint id, 'edition'])
119    ///   3. `[writable]` Mint of new token - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY
120    ///   4. `[signer]` Mint authority of new mint
121    ///   5. `[writable]` Printing Mint of master record edition
122    ///   6. `[writable]` Token account containing Printing mint token to be transferred
123    ///   7. `[writable]` Edition pda to mark creation - will be checked for pre-existence. (pda of ['metadata', program id, master mint id, edition_number])
124    ///   8. `[signer]` Burn authority for this token
125    ///   9. `[signer]` payer
126    ///   10. `[]` update authority info for new metadata account
127    ///   11. `[]` Master record metadata account
128    ///   12. `[]` Token program
129    ///   13. `[]` System program
130    ///   14. `[]` Rent info
131    ///   15. `[optional/writable]` Reservation List - If present, and you are on this list, you can get
132    ///        an edition number given by your position on the list.
133    DeprecatedMintNewEditionFromMasterEditionViaPrintingToken,
134
135    /// Allows updating the primary sale boolean on Metadata solely through owning an account
136    /// containing a token from the metadata's mint and being a signer on this transaction.
137    /// A sort of limited authority for limited update capability that is required for things like
138    /// Metaplex to work without needing full authority passing.
139    ///
140    ///   0. `[writable]` Metadata key (pda of ['metadata', program id, mint id])
141    ///   1. `[signer]` Owner on the token account
142    ///   2. `[]` Account containing tokens from the metadata's mint
143    UpdatePrimarySaleHappenedViaToken,
144
145    /// Reserve up to 200 editions in sequence for up to 200 addresses in an existing reservation PDA, which can then be used later by
146    /// redeemers who have printing tokens as a reservation to get a specific edition number
147    /// as opposed to whatever one is currently listed on the master edition. Used by Auction Manager
148    /// to guarantee printing order on bid redemption. AM will call whenever the first person redeems a
149    /// printing bid to reserve the whole block
150    /// of winners in order and then each winner when they get their token submits their mint and account
151    /// with the pda that was created by that first bidder - the token metadata can then cross reference
152    /// these people with the list and see that bidder A gets edition #2, so on and so forth.
153    ///
154    /// NOTE: If you have more than 20 addresses in a reservation list, this may be called multiple times to build up the list,
155    /// otherwise, it simply wont fit in one transaction. Only provide a total_reservation argument on the first call, which will
156    /// allocate the edition space, and in follow up calls this will specifically be unnecessary (and indeed will error.)
157    ///
158    ///   0. `[writable]` Master Edition V1 key (pda of ['metadata', program id, mint id, 'edition'])
159    ///   1. `[writable]` PDA for ReservationList of ['metadata', program id, master edition key, 'reservation', resource-key]
160    ///   2. `[signer]` The resource you tied the reservation list too
161    DeprecatedSetReservationList(SetReservationListArgs),
162
163    /// Create an empty reservation list for a resource who can come back later as a signer and fill the reservation list
164    /// with reservations to ensure that people who come to get editions get the number they expect. See SetReservationList for more.
165    ///
166    ///   0. `[writable]` PDA for ReservationList of ['metadata', program id, master edition key, 'reservation', resource-key]
167    ///   1. `[signer]` Payer
168    ///   2. `[signer]` Update authority
169    ///   3. `[]` Master Edition V1 key (pda of ['metadata', program id, mint id, 'edition'])
170    ///   4. `[]` A resource you wish to tie the reservation list to. This is so your later visitors who come to
171    ///       redeem can derive your reservation list PDA with something they can easily get at. You choose what this should be.
172    ///   5. `[]` Metadata key (pda of ['metadata', program id, mint id])
173    ///   6. `[]` System program
174    ///   7. `[]` Rent info
175    DeprecatedCreateReservationList,
176
177    /// Sign a piece of metadata that has you as an unverified creator so that it is now verified.
178    ///   0. `[writable]` Metadata (pda of ['metadata', program id, mint id])
179    ///   1. `[signer]` Creator
180    SignMetadata,
181
182    /// Using a one time authorization token from a master edition v1, print any number of printing tokens from the printing_mint
183    /// one time, burning the one time authorization token.
184    ///
185    ///   0. `[writable]` Destination account
186    ///   1. `[writable]` Token account containing one time authorization token
187    ///   2. `[writable]` One time authorization mint
188    ///   3. `[writable]` Printing mint
189    ///   4. `[signer]` Burn authority
190    ///   5. `[]` Metadata key (pda of ['metadata', program id, mint id])
191    ///   6. `[]` Master Edition V1 key (pda of ['metadata', program id, mint id, 'edition'])
192    ///   7. `[]` Token program
193    ///   8. `[]` Rent
194    DeprecatedMintPrintingTokensViaToken(MintPrintingTokensViaTokenArgs),
195
196    /// Using your update authority, mint printing tokens for your master edition.
197    ///
198    ///   0. `[writable]` Destination account
199    ///   1. `[writable]` Printing mint
200    ///   2. `[signer]` Update authority
201    ///   3. `[]` Metadata key (pda of ['metadata', program id, mint id])
202    ///   4. `[]` Master Edition V1 key (pda of ['metadata', program id, mint id, 'edition'])
203    ///   5. `[]` Token program
204    ///   6. `[]` Rent
205    DeprecatedMintPrintingTokens(MintPrintingTokensViaTokenArgs),
206
207    /// Register a Metadata as a Master Edition V2, which means Edition V2s can be minted.
208    /// Henceforth, no further tokens will be mintable from this primary mint. Will throw an error if more than one
209    /// token exists, and will throw an error if less than one token exists in this primary mint.
210    ///   0. `[writable]` Unallocated edition V2 account with address as pda of ['metadata', program id, mint, 'edition']
211    ///   1. `[writable]` Metadata mint
212    ///   2. `[signer]` Update authority
213    ///   3. `[signer]` Mint authority on the metadata's mint - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY
214    ///   4. `[signer]` payer
215    ///   5. `[]` Metadata account
216    ///   6. `[]` Token program
217    ///   7. `[]` System program
218    ///   8. `[]` Rent info
219    CreateMasterEdition(CreateMasterEditionArgs),
220
221    /// Given a token account containing the master edition token to prove authority, and a brand new non-metadata-ed mint with one token
222    /// make a new Metadata + Edition that is a child of the master edition denoted by this authority token.
223    ///   0. `[writable]` New Metadata key (pda of ['metadata', program id, mint id])
224    ///   1. `[writable]` New Edition (pda of ['metadata', program id, mint id, 'edition'])
225    ///   2. `[writable]` Master Record Edition V2 (pda of ['metadata', program id, master metadata mint id, 'edition'])
226    ///   3. `[writable]` Mint of new token - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY
227    ///   4. `[writable]` Edition pda to mark creation - will be checked for pre-existence. (pda of ['metadata', program id, master metadata mint id, 'edition', edition_number])
228    ///   where edition_number is NOT the edition number you pass in args but actually edition_number = floor(edition/EDITION_MARKER_BIT_SIZE).
229    ///   5. `[signer]` Mint authority of new mint
230    ///   6. `[signer]` payer
231    ///   7. `[signer]` owner of token account containing master token (#8)
232    ///   8. `[]` token account containing token from master metadata mint
233    ///   9. `[]` Update authority info for new metadata
234    ///   10. `[]` Master record metadata account
235    ///   11. `[]` Token program
236    ///   12. `[]` System program
237    ///   13. `[]` Rent info
238    MintNewEditionFromMasterEditionViaToken(MintNewEditionFromMasterEditionViaTokenArgs),
239
240    /// Converts the Master Edition V1 to a Master Edition V2, draining lamports from the two printing mints
241    /// to the owner of the token account holding the master edition token. Permissionless.
242    /// Can only be called if there are currenly no printing tokens or one time authorization tokens in circulation.
243    ///
244    ///   0. `[writable]` Master Record Edition V1 (pda of ['metadata', program id, master metadata mint id, 'edition'])
245    ///   1. `[writable]` One time authorization mint
246    ///   2. `[writable]` Printing mint
247    ConvertMasterEditionV1ToV2,
248
249    /// Proxy Call to Mint Edition using a Store Token Account as a Vault Authority.
250    ///
251    ///   0. `[writable]` New Metadata key (pda of ['metadata', program id, mint id])
252    ///   1. `[writable]` New Edition (pda of ['metadata', program id, mint id, 'edition'])
253    ///   2. `[writable]` Master Record Edition V2 (pda of ['metadata', program id, master metadata mint id, 'edition']
254    ///   3. `[writable]` Mint of new token - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY
255    ///   4. `[writable]` Edition pda to mark creation - will be checked for pre-existence. (pda of ['metadata', program id, master metadata mint id, 'edition', edition_number])
256    ///   where edition_number is NOT the edition number you pass in args but actually edition_number = floor(edition/EDITION_MARKER_BIT_SIZE).
257    ///   5. `[signer]` Mint authority of new mint
258    ///   6. `[signer]` payer
259    ///   7. `[signer]` Vault authority
260    ///   8. `[]` Safety deposit token store account
261    ///   9. `[]` Safety deposit box
262    ///   10. `[]` Vault
263    ///   11. `[]` Update authority info for new metadata
264    ///   12. `[]` Master record metadata account
265    ///   13. `[]` Token program
266    ///   14. `[]` Token vault program
267    ///   15. `[]` System program
268    ///   16. `[]` Rent info
269    MintNewEditionFromMasterEditionViaVaultProxy(MintNewEditionFromMasterEditionViaTokenArgs),
270
271    /// Puff a Metadata - make all of it's variable length fields (name/uri/symbol) a fixed length using a null character
272    /// so that it can be found using offset searches by the RPC to make client lookups cheaper.
273    ///   0. `[writable]` Metadata account
274    PuffMetadata,
275
276    /// Update a Metadata with is_mutable as a parameter
277    ///   0. `[writable]` Metadata account
278    ///   1. `[signer]` Update authority key
279    UpdateMetadataAccountV2(UpdateMetadataAccountArgsV2),
280
281    /// Create Metadata object.
282    ///   0. `[writable]`  Metadata key (pda of ['metadata', program id, mint id])
283    ///   1. `[]` Mint of token asset
284    ///   2. `[signer]` Mint authority
285    ///   3. `[signer]` payer
286    ///   4. `[]` update authority info
287    ///   5. `[]` System program
288    ///   6. `[]` Rent info
289    CreateMetadataAccountV2(CreateMetadataAccountArgsV2),
290    /// Register a Metadata as a Master Edition V2, which means Edition V2s can be minted.
291    /// Henceforth, no further tokens will be mintable from this primary mint. Will throw an error if more than one
292    /// token exists, and will throw an error if less than one token exists in this primary mint.
293    ///   0. `[writable]` Unallocated edition V2 account with address as pda of ['metadata', program id, mint, 'edition']
294    ///   1. `[writable]` Metadata mint
295    ///   2. `[signer]` Update authority
296    ///   3. `[signer]` Mint authority on the metadata's mint - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY
297    ///   4. `[signer]` payer
298    ///   5.  [writable] Metadata account
299    ///   6. `[]` Token program
300    ///   7. `[]` System program
301    ///   8. `[]` Rent info
302    CreateMasterEditionV3(CreateMasterEditionArgs),
303    ///See [verify_collection] for Doc
304    VerifyCollection,
305    ///See [utilize] for Doc
306    Utilize(UtilizeArgs),
307
308    ///See [approve_use_authority] for Doc
309    ApproveUseAuthority(ApproveUseAuthorityArgs),
310    ///See [revoke_use_authority] for Doc
311    RevokeUseAuthority,
312
313    ///See [revoke_use_authority] for Doc
314    UnverifyCollection,
315
316    ///See [approve_collection_authority] for Doc
317    ApproveCollectionAuthority,
318    ///See [revoke_collection_authority] for Doc
319    RevokeCollectionAuthority,
320}
321
322/// Creates an CreateMetadataAccounts instruction
323/// #[deprecated(since="1.1.0", note="please use `create_metadata_accounts_v2` instead")]
324#[allow(clippy::too_many_arguments)]
325pub fn create_metadata_accounts(
326    program_id: Pubkey,
327    metadata_account: Pubkey,
328    mint: Pubkey,
329    mint_authority: Pubkey,
330    payer: Pubkey,
331    update_authority: Pubkey,
332    name: String,
333    symbol: String,
334    uri: String,
335    creators: Option<Vec<Creator>>,
336    seller_fee_basis_points: u16,
337    update_authority_is_signer: bool,
338    is_mutable: bool,
339) -> Instruction {
340    Instruction {
341        program_id,
342        accounts: vec![
343            AccountMeta::new(metadata_account, false),
344            AccountMeta::new_readonly(mint, false),
345            AccountMeta::new_readonly(mint_authority, true),
346            AccountMeta::new(payer, true),
347            AccountMeta::new_readonly(update_authority, update_authority_is_signer),
348            AccountMeta::new_readonly(solana_program::system_program::id(), false),
349            AccountMeta::new_readonly(sysvar::rent::id(), false),
350        ],
351        data: MetadataInstruction::CreateMetadataAccount(CreateMetadataAccountArgs {
352            data: Data {
353                name,
354                symbol,
355                uri,
356                seller_fee_basis_points,
357                creators,
358            },
359            is_mutable,
360        })
361        .try_to_vec()
362        .unwrap(),
363    }
364}
365
366/// Creates an CreateMetadataAccounts instruction
367#[allow(clippy::too_many_arguments)]
368pub fn create_metadata_accounts_v2(
369    program_id: Pubkey,
370    metadata_account: Pubkey,
371    mint: Pubkey,
372    mint_authority: Pubkey,
373    payer: Pubkey,
374    update_authority: Pubkey,
375    name: String,
376    symbol: String,
377    uri: String,
378    creators: Option<Vec<Creator>>,
379    seller_fee_basis_points: u16,
380    update_authority_is_signer: bool,
381    is_mutable: bool,
382    collection: Option<Collection>,
383    uses: Option<Uses>,
384) -> Instruction {
385    Instruction {
386        program_id,
387        accounts: vec![
388            AccountMeta::new(metadata_account, false),
389            AccountMeta::new_readonly(mint, false),
390            AccountMeta::new_readonly(mint_authority, true),
391            AccountMeta::new(payer, true),
392            AccountMeta::new_readonly(update_authority, update_authority_is_signer),
393            AccountMeta::new_readonly(solana_program::system_program::id(), false),
394            AccountMeta::new_readonly(sysvar::rent::id(), false),
395        ],
396        data: MetadataInstruction::CreateMetadataAccountV2(CreateMetadataAccountArgsV2 {
397            data: DataV2 {
398                name,
399                symbol,
400                uri,
401                seller_fee_basis_points,
402                creators,
403                collection,
404                uses,
405            },
406            is_mutable,
407        })
408        .try_to_vec()
409        .unwrap(),
410    }
411}
412
413/// update metadata account instruction
414/// #[deprecated(since="1.1.0", note="please use `update_metadata_accounts_v2` instead")]
415pub fn update_metadata_accounts(
416    program_id: Pubkey,
417    metadata_account: Pubkey,
418    update_authority: Pubkey,
419    new_update_authority: Option<Pubkey>,
420    data: Option<Data>,
421    primary_sale_happened: Option<bool>,
422) -> Instruction {
423    Instruction {
424        program_id,
425        accounts: vec![
426            AccountMeta::new(metadata_account, false),
427            AccountMeta::new_readonly(update_authority, true),
428        ],
429        data: MetadataInstruction::UpdateMetadataAccount(UpdateMetadataAccountArgs {
430            data,
431            update_authority: new_update_authority,
432            primary_sale_happened,
433        })
434        .try_to_vec()
435        .unwrap(),
436    }
437}
438
439// update metadata account v2 instruction
440pub fn update_metadata_accounts_v2(
441    program_id: Pubkey,
442    metadata_account: Pubkey,
443    update_authority: Pubkey,
444    new_update_authority: Option<Pubkey>,
445    data: Option<DataV2>,
446    primary_sale_happened: Option<bool>,
447    is_mutable: Option<bool>,
448) -> Instruction {
449    Instruction {
450        program_id,
451        accounts: vec![
452            AccountMeta::new(metadata_account, false),
453            AccountMeta::new_readonly(update_authority, true),
454        ],
455        data: MetadataInstruction::UpdateMetadataAccountV2(UpdateMetadataAccountArgsV2 {
456            data,
457            update_authority: new_update_authority,
458            primary_sale_happened,
459            is_mutable,
460        })
461        .try_to_vec()
462        .unwrap(),
463    }
464}
465
466/// puff metadata account instruction
467pub fn puff_metadata_account(program_id: Pubkey, metadata_account: Pubkey) -> Instruction {
468    Instruction {
469        program_id,
470        accounts: vec![AccountMeta::new(metadata_account, false)],
471        data: MetadataInstruction::PuffMetadata.try_to_vec().unwrap(),
472    }
473}
474
475/// creates a update_primary_sale_happened_via_token instruction
476#[allow(clippy::too_many_arguments)]
477pub fn update_primary_sale_happened_via_token(
478    program_id: Pubkey,
479    metadata: Pubkey,
480    owner: Pubkey,
481    token: Pubkey,
482) -> Instruction {
483    Instruction {
484        program_id,
485        accounts: vec![
486            AccountMeta::new(metadata, false),
487            AccountMeta::new_readonly(owner, true),
488            AccountMeta::new_readonly(token, false),
489        ],
490        data: MetadataInstruction::UpdatePrimarySaleHappenedViaToken
491            .try_to_vec()
492            .unwrap(),
493    }
494}
495
496/// creates a create_master_edition instruction
497#[allow(clippy::too_many_arguments)]
498/// [deprecated(since="1.1.0", note="please use `create_master_edition_v3` instead")]
499pub fn create_master_edition(
500    program_id: Pubkey,
501    edition: Pubkey,
502    mint: Pubkey,
503    update_authority: Pubkey,
504    mint_authority: Pubkey,
505    metadata: Pubkey,
506    payer: Pubkey,
507    max_supply: Option<u64>,
508) -> Instruction {
509    let accounts = vec![
510        AccountMeta::new(edition, false),
511        AccountMeta::new(mint, false),
512        AccountMeta::new_readonly(update_authority, true),
513        AccountMeta::new_readonly(mint_authority, true),
514        AccountMeta::new(payer, true),
515        AccountMeta::new_readonly(metadata, false),
516        AccountMeta::new_readonly(spl_token::id(), false),
517        AccountMeta::new_readonly(solana_program::system_program::id(), false),
518        AccountMeta::new_readonly(sysvar::rent::id(), false),
519    ];
520
521    Instruction {
522        program_id,
523        accounts,
524        data: MetadataInstruction::CreateMasterEdition(CreateMasterEditionArgs { max_supply })
525            .try_to_vec()
526            .unwrap(),
527    }
528}
529
530/// creates a create_master_edition instruction
531#[allow(clippy::too_many_arguments)]
532pub fn create_master_edition_v3(
533    program_id: Pubkey,
534    edition: Pubkey,
535    mint: Pubkey,
536    update_authority: Pubkey,
537    mint_authority: Pubkey,
538    metadata: Pubkey,
539    payer: Pubkey,
540    max_supply: Option<u64>,
541) -> Instruction {
542    let accounts = vec![
543        AccountMeta::new(edition, false),
544        AccountMeta::new(mint, false),
545        AccountMeta::new_readonly(update_authority, true),
546        AccountMeta::new_readonly(mint_authority, true),
547        AccountMeta::new(payer, true),
548        AccountMeta::new(metadata, false),
549        AccountMeta::new_readonly(spl_token::id(), false),
550        AccountMeta::new_readonly(solana_program::system_program::id(), false),
551        AccountMeta::new_readonly(sysvar::rent::id(), false),
552    ];
553
554    Instruction {
555        program_id,
556        accounts,
557        data: MetadataInstruction::CreateMasterEditionV3(CreateMasterEditionArgs { max_supply })
558            .try_to_vec()
559            .unwrap(),
560    }
561}
562
563/// creates a mint_new_edition_from_master_edition instruction
564#[allow(clippy::too_many_arguments)]
565pub fn mint_new_edition_from_master_edition_via_token(
566    program_id: Pubkey,
567    new_metadata: Pubkey,
568    new_edition: Pubkey,
569    master_edition: Pubkey,
570    new_mint: Pubkey,
571    new_mint_authority: Pubkey,
572    payer: Pubkey,
573    token_account_owner: Pubkey,
574    token_account: Pubkey,
575    new_metadata_update_authority: Pubkey,
576    metadata: Pubkey,
577    metadata_mint: Pubkey,
578    edition: u64,
579) -> Instruction {
580    let edition_number = edition.checked_div(EDITION_MARKER_BIT_SIZE).unwrap();
581    let as_string = edition_number.to_string();
582    let (edition_mark_pda, _) = Pubkey::find_program_address(
583        &[
584            PREFIX.as_bytes(),
585            program_id.as_ref(),
586            metadata_mint.as_ref(),
587            EDITION.as_bytes(),
588            as_string.as_bytes(),
589        ],
590        &program_id,
591    );
592
593    let accounts = vec![
594        AccountMeta::new(new_metadata, false),
595        AccountMeta::new(new_edition, false),
596        AccountMeta::new(master_edition, false),
597        AccountMeta::new(new_mint, false),
598        AccountMeta::new(edition_mark_pda, false),
599        AccountMeta::new_readonly(new_mint_authority, true),
600        AccountMeta::new(payer, true),
601        AccountMeta::new_readonly(token_account_owner, true),
602        AccountMeta::new_readonly(token_account, false),
603        AccountMeta::new_readonly(new_metadata_update_authority, false),
604        AccountMeta::new_readonly(metadata, false),
605        AccountMeta::new_readonly(spl_token::id(), false),
606        AccountMeta::new_readonly(solana_program::system_program::id(), false),
607        AccountMeta::new_readonly(sysvar::rent::id(), false),
608    ];
609
610    Instruction {
611        program_id,
612        accounts,
613        data: MetadataInstruction::MintNewEditionFromMasterEditionViaToken(
614            MintNewEditionFromMasterEditionViaTokenArgs { edition },
615        )
616        .try_to_vec()
617        .unwrap(),
618    }
619}
620
621/// Sign Metadata
622#[allow(clippy::too_many_arguments)]
623pub fn sign_metadata(program_id: Pubkey, metadata: Pubkey, creator: Pubkey) -> Instruction {
624    Instruction {
625        program_id,
626        accounts: vec![
627            AccountMeta::new(metadata, false),
628            AccountMeta::new_readonly(creator, true),
629        ],
630        data: MetadataInstruction::SignMetadata.try_to_vec().unwrap(),
631    }
632}
633
634/// Converts a master edition v1 to v2
635#[allow(clippy::too_many_arguments)]
636pub fn convert_master_edition_v1_to_v2(
637    program_id: Pubkey,
638    master_edition: Pubkey,
639    one_time_auth: Pubkey,
640    printing_mint: Pubkey,
641) -> Instruction {
642    Instruction {
643        program_id,
644        accounts: vec![
645            AccountMeta::new(master_edition, false),
646            AccountMeta::new(one_time_auth, false),
647            AccountMeta::new(printing_mint, false),
648        ],
649        data: MetadataInstruction::ConvertMasterEditionV1ToV2
650            .try_to_vec()
651            .unwrap(),
652    }
653}
654
655/// creates a mint_edition_proxy instruction
656#[allow(clippy::too_many_arguments)]
657pub fn mint_edition_from_master_edition_via_vault_proxy(
658    program_id: Pubkey,
659    new_metadata: Pubkey,
660    new_edition: Pubkey,
661    master_edition: Pubkey,
662    new_mint: Pubkey,
663    edition_mark_pda: Pubkey,
664    new_mint_authority: Pubkey,
665    payer: Pubkey,
666    vault_authority: Pubkey,
667    safety_deposit_store: Pubkey,
668    safety_deposit_box: Pubkey,
669    vault: Pubkey,
670    new_metadata_update_authority: Pubkey,
671    metadata: Pubkey,
672    token_program: Pubkey,
673    token_vault_program_info: Pubkey,
674    edition: u64,
675) -> Instruction {
676    let accounts = vec![
677        AccountMeta::new(new_metadata, false),
678        AccountMeta::new(new_edition, false),
679        AccountMeta::new(master_edition, false),
680        AccountMeta::new(new_mint, false),
681        AccountMeta::new(edition_mark_pda, false),
682        AccountMeta::new_readonly(new_mint_authority, true),
683        AccountMeta::new(payer, true),
684        AccountMeta::new_readonly(vault_authority, true),
685        AccountMeta::new_readonly(safety_deposit_store, false),
686        AccountMeta::new_readonly(safety_deposit_box, false),
687        AccountMeta::new_readonly(vault, false),
688        AccountMeta::new_readonly(new_metadata_update_authority, false),
689        AccountMeta::new_readonly(metadata, false),
690        AccountMeta::new_readonly(token_program, false),
691        AccountMeta::new_readonly(token_vault_program_info, false),
692        AccountMeta::new_readonly(solana_program::system_program::id(), false),
693        AccountMeta::new_readonly(sysvar::rent::id(), false),
694    ];
695
696    Instruction {
697        program_id,
698        accounts,
699        data: MetadataInstruction::MintNewEditionFromMasterEditionViaVaultProxy(
700            MintNewEditionFromMasterEditionViaTokenArgs { edition },
701        )
702        .try_to_vec()
703        .unwrap(),
704    }
705}
706
707/// # Verify Collection
708///
709/// If a MetadataAccount Has a Collection allow the UpdateAuthority of the Collection to Verify the NFT Belongs in the Collection
710///
711/// ### Accounts:
712///
713///   0. `[writable]` Metadata account
714///   1. `[signer]` Collection Update authority
715///   2. `[signer]` payer
716///   3. `[]` Mint of the Collection
717///   4. `[]` Metadata Account of the Collection
718///   5. `[]` MasterEdition2 Account of the Collection Token
719#[allow(clippy::too_many_arguments)]
720pub fn verify_collection(
721    program_id: Pubkey,
722    metadata: Pubkey,
723    collection_authority: Pubkey,
724    payer: Pubkey,
725    collection_mint: Pubkey,
726    collection: Pubkey,
727    collection_master_edition_account: Pubkey,
728    collection_authority_record: Option<Pubkey>,
729) -> Instruction {
730    let mut accounts = vec![
731        AccountMeta::new(metadata, false),
732        AccountMeta::new(collection_authority, true),
733        AccountMeta::new(payer, true),
734        AccountMeta::new_readonly(collection_mint, false),
735        AccountMeta::new_readonly(collection, false),
736        AccountMeta::new_readonly(collection_master_edition_account, false),
737    ];
738
739    if collection_authority_record.is_some() {
740        accounts.push(AccountMeta::new_readonly(
741            collection_authority_record.unwrap(),
742            false,
743        ));
744    }
745    Instruction {
746        program_id,
747        accounts: accounts,
748        data: MetadataInstruction::VerifyCollection.try_to_vec().unwrap(),
749    }
750}
751
752/// # Unverify Collection
753///
754/// If a MetadataAccount Has a Collection allow an Authority of the Collection to unverify an NFT in a Collection
755///
756/// ### Accounts:
757///
758///   0. `[writable]` Metadata account
759///   1. `[signer]` Collection Authority
760///   2. `[signer]` payer
761///   3. `[]` Mint of the Collection
762///   4. `[]` Metadata Account of the Collection
763///   5. `[]` MasterEdition2 Account of the Collection Token
764#[allow(clippy::too_many_arguments)]
765pub fn unverify_collection(
766    program_id: Pubkey,
767    metadata: Pubkey,
768    collection_authority: Pubkey,
769    collection_mint: Pubkey,
770    collection: Pubkey,
771    collection_master_edition_account: Pubkey,
772    collection_authority_record: Option<Pubkey>,
773) -> Instruction {
774    let mut accounts = vec![
775        AccountMeta::new(metadata, false),
776        AccountMeta::new(collection_authority, true),
777        AccountMeta::new_readonly(collection_mint, false),
778        AccountMeta::new_readonly(collection, false),
779        AccountMeta::new_readonly(collection_master_edition_account, false),
780    ];
781
782    if collection_authority_record.is_some() {
783        accounts.push(AccountMeta::new_readonly(
784            collection_authority_record.unwrap(),
785            false,
786        ));
787    }
788    Instruction {
789        program_id,
790        accounts: accounts,
791        data: MetadataInstruction::UnverifyCollection
792            .try_to_vec()
793            .unwrap(),
794    }
795}
796
797///# Utilize
798///
799///Utilize or Use an NFT , burns the NFT and returns the lamports to the update authority if the use method is burn and its out of uses.
800///Use Authority can be the Holder of the NFT, or a Delegated Use Authority.
801///
802///### Accounts:
803///
804///   0. `[writable]` Metadata account
805///   1. `[writable]` Token Account Of NFT
806///   2. `[writable]` Mint of the Metadata
807///   2. `[signer]` A Use Authority / Can be the current Owner of the NFT
808///   3. `[signer]` Payer
809///   4. `[]` Owner
810///   5. `[]` Token program
811///   6. `[]` Associated Token program
812///   7. `[]` System program
813///   8. `[]` Rent info
814///   9. Optional `[writable]` Use Authority Record PDA If present the program Assumes a delegated use authority
815
816#[allow(clippy::too_many_arguments)]
817pub fn utilize(
818    program_id: Pubkey,
819    metadata: Pubkey,
820    token_account: Pubkey,
821    mint: Pubkey,
822    use_authority_record_pda: Option<Pubkey>,
823    use_authority: Pubkey,
824    owner: Pubkey,
825    burner: Option<Pubkey>,
826    number_of_uses: u64,
827) -> Instruction {
828    let mut accounts = vec![
829        AccountMeta::new(metadata, false),
830        AccountMeta::new(token_account, false),
831        AccountMeta::new(mint, false),
832        AccountMeta::new(use_authority, true),
833        AccountMeta::new_readonly(owner, false),
834        AccountMeta::new_readonly(spl_token::id(), false),
835        AccountMeta::new_readonly(spl_associated_token_account::id(), false),
836        AccountMeta::new_readonly(solana_program::system_program::id(), false),
837        AccountMeta::new_readonly(sysvar::rent::id(), false),
838    ];
839    if use_authority_record_pda.is_some() {
840        accounts.push(AccountMeta::new(use_authority_record_pda.unwrap(), false));
841    }
842    if burner.is_some() {
843        accounts.push(AccountMeta::new_readonly(burner.unwrap(), false));
844    }
845
846    Instruction {
847        program_id,
848        accounts,
849        data: MetadataInstruction::Utilize(UtilizeArgs { number_of_uses })
850            .try_to_vec()
851            .unwrap(),
852    }
853}
854
855///# Approve Use Authority
856///
857///Approve another account to call [utilize] on this NFT
858///
859///### Args:
860///
861///See: [ApproveUseAuthorityArgs]
862///
863///### Accounts:
864///
865///   0. `[writable]` Use Authority Record PDA
866///   1. `[writable]` Owned Token Account Of Mint
867///   2. `[signer]` Owner
868///   3. `[signer]` Payer
869///   4. `[]` A Use Authority
870///   5. `[]` Metadata account
871///   6. `[]` Mint of Metadata
872///   7. `[]` Program As Signer (Burner)
873///   8. `[]` Token program
874///   9. `[]` System program
875///   10. `[]` Rent info
876#[allow(clippy::too_many_arguments)]
877pub fn approve_use_authority(
878    program_id: Pubkey,
879    use_authority_record: Pubkey,
880    user: Pubkey,
881    owner: Pubkey,
882    payer: Pubkey,
883    owner_token_account: Pubkey,
884    metadata: Pubkey,
885    mint: Pubkey,
886    burner: Pubkey,
887    number_of_uses: u64,
888) -> Instruction {
889    Instruction {
890        program_id,
891        accounts: vec![
892            AccountMeta::new(use_authority_record, false),
893            AccountMeta::new(owner, true),
894            AccountMeta::new(payer, true),
895            AccountMeta::new_readonly(user, false),
896            AccountMeta::new(owner_token_account, false),
897            AccountMeta::new_readonly(metadata, false),
898            AccountMeta::new_readonly(mint, false),
899            AccountMeta::new_readonly(burner, false),
900            AccountMeta::new_readonly(spl_token::id(), false),
901            AccountMeta::new_readonly(solana_program::system_program::id(), false),
902            AccountMeta::new_readonly(sysvar::rent::id(), false),
903        ],
904        data: MetadataInstruction::ApproveUseAuthority(ApproveUseAuthorityArgs { number_of_uses })
905            .try_to_vec()
906            .unwrap(),
907    }
908}
909
910//# Revoke Use Authority
911///
912///Revoke account to call [utilize] on this NFT
913///
914///### Accounts:
915///
916///   0. `[writable]` Use Authority Record PDA
917///   1. `[writable]` Owned Token Account Of Mint
918///   2. `[signer]` Owner
919///   3. `[signer]` Payer
920///   4. `[]` A Use Authority
921///   5. `[]` Metadata account
922///   6. `[]` Mint of Metadata
923///   7. `[]` Token program
924///   8. `[]` System program
925///   9. `[]` Rent info
926#[allow(clippy::too_many_arguments)]
927pub fn revoke_use_authority(
928    program_id: Pubkey,
929    use_authority_record: Pubkey,
930    user: Pubkey,
931    owner: Pubkey,
932    owner_token_account: Pubkey,
933    metadata: Pubkey,
934    mint: Pubkey,
935) -> Instruction {
936    Instruction {
937        program_id,
938        accounts: vec![
939            AccountMeta::new(use_authority_record, false),
940            AccountMeta::new(owner, true),
941            AccountMeta::new_readonly(user, false),
942            AccountMeta::new(owner_token_account, false),
943            AccountMeta::new_readonly(mint, false),
944            AccountMeta::new_readonly(metadata, false),
945            AccountMeta::new_readonly(spl_token::id(), false),
946            AccountMeta::new_readonly(solana_program::system_program::id(), false),
947            AccountMeta::new_readonly(sysvar::rent::id(), false),
948        ],
949        data: MetadataInstruction::RevokeUseAuthority
950            .try_to_vec()
951            .unwrap(),
952    }
953}
954
955///# Approve Collection Authority
956///
957///Approve another account to verify nfts beloging to a collection, [verify_collection] on the collection NFT
958///
959///### Accounts:
960///   0. `[writable]` Collection Authority Record PDA
961///   1. `[signer]` Update Authority of Collection NFT
962///   2. `[signer]` Payer
963///   3. `[]` A Collection Authority
964///   4. `[]` Collection Metadata account
965///   5. `[]` Mint of Collection Metadata
966///   6. `[]` Token program
967///   7. `[]` System program
968///   8. `[]` Rent info
969#[allow(clippy::too_many_arguments)]
970pub fn approve_collection_authority(
971    program_id: Pubkey,
972    collection_authority_record: Pubkey,
973    new_collection_authority: Pubkey,
974    update_authority: Pubkey,
975    payer: Pubkey,
976    metadata: Pubkey,
977    mint: Pubkey,
978) -> Instruction {
979    Instruction {
980        program_id,
981        accounts: vec![
982            AccountMeta::new(collection_authority_record, false),
983            AccountMeta::new_readonly(new_collection_authority, false),
984            AccountMeta::new(update_authority, true),
985            AccountMeta::new(payer, true),
986            AccountMeta::new_readonly(metadata, false),
987            AccountMeta::new_readonly(mint, false),
988            AccountMeta::new_readonly(solana_program::system_program::id(), false),
989            AccountMeta::new_readonly(sysvar::rent::id(), false),
990        ],
991        data: MetadataInstruction::ApproveCollectionAuthority
992            .try_to_vec()
993            .unwrap(),
994    }
995}
996
997//# Revoke Collection Authority
998///
999///Revoke account to call [verify_collection] on this NFT
1000///
1001///### Accounts:
1002///
1003///   0. `[writable]` Use Authority Record PDA
1004///   1. `[writable]` Owned Token Account Of Mint
1005///   2. `[]` Metadata account
1006///   3. `[]` Mint of Metadata
1007#[allow(clippy::too_many_arguments)]
1008pub fn revoke_collection_authority(
1009    program_id: Pubkey,
1010    collection_authority_record: Pubkey,
1011    update_authority: Pubkey,
1012    metadata: Pubkey,
1013    mint: Pubkey,
1014) -> Instruction {
1015    Instruction {
1016        program_id,
1017        accounts: vec![
1018            AccountMeta::new(collection_authority_record, false),
1019            AccountMeta::new(update_authority, true),
1020            AccountMeta::new_readonly(metadata, false),
1021            AccountMeta::new_readonly(mint, false),
1022        ],
1023        data: MetadataInstruction::RevokeCollectionAuthority
1024            .try_to_vec()
1025            .unwrap(),
1026    }
1027}