token_metadata_descriptor/instructions/
initialize.rs

1use anchor_lang::prelude::*;
2use anchor_spl::token::Mint;
3use mpl_token_metadata::state::{Metadata, TokenMetadataAccount};
4
5use crate::{
6    state::Encoding,
7    utils::{initialize_descriptor_helper, verify_empty_account, verify_metadata},
8};
9
10#[derive(Accounts)]
11#[instruction(data_size: u64, encoding: Encoding, bump: u8)]
12pub struct Initialize<'info> {
13    /// entity that funds transaction
14    #[account(mut)]
15    pub payer: Signer<'info>,
16
17    /// descriptor authority, same as metadata update authority
18    pub authority: Signer<'info>,
19
20    /// CHECK: descriptor to initialize, decoded and verified inline.
21    #[account(mut)]
22    pub descriptor: UncheckedAccount<'info>,
23
24    /// mint associated with the descriptor
25    pub mint: Account<'info, Mint>,
26
27    /// CHECK: metadata associated with the mint
28    #[account(
29        constraint = token_metadata.owner == token_metadata_program.key &&
30        token_metadata.to_account_info().data_len() > 0
31    )]
32    pub token_metadata: UncheckedAccount<'info>,
33
34    /// CHECK: mpl token metadata
35    #[account(address = mpl_token_metadata::id())]
36    pub token_metadata_program: UncheckedAccount<'info>,
37
38    pub system_program: Program<'info, System>,
39}
40
41pub fn initialize_handler(
42    ctx: Context<Initialize>,
43    data_size: u64,
44    encoding: Encoding,
45    bump: u8,
46) -> Result<()> {
47    let payer_account_info = &ctx.accounts.payer.to_account_info();
48    let authority_account_info = &ctx.accounts.authority.to_account_info();
49    let descriptor_account_info = &ctx.accounts.descriptor.to_account_info();
50    let mint_account_info = &ctx.accounts.mint.to_account_info();
51    let token_metadata_account_info = &ctx.accounts.token_metadata.to_account_info();
52    let system_program_info = &ctx.accounts.system_program.to_account_info();
53
54    let rent = Rent::get()?;
55    let mint_key = mint_account_info.key();
56
57    let metadata = Metadata::from_account_info(&token_metadata_account_info)?;
58
59    verify_metadata(&metadata, &authority_account_info.key(), &mint_key)?;
60    verify_empty_account(&descriptor_account_info)?;
61
62    let descriptor = initialize_descriptor_helper(
63        &payer_account_info,
64        &descriptor_account_info,
65        &system_program_info,
66        &rent,
67        bump,
68        &mint_key,
69        encoding,
70        data_size as u32,
71    )?;
72
73    let descriptor_bytes = descriptor.try_to_vec().unwrap();
74    let descriptor_len = descriptor_bytes.len();
75    let descriptor_account_data = &mut descriptor_account_info.data.borrow_mut();
76    descriptor_account_data[0..descriptor_len].copy_from_slice(&descriptor_bytes);
77
78    Ok(())
79}