token_metadata_descriptor/instructions/
initialize_with_data.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// todo: does this mismatch work?
12#[instruction(encoding: Encoding, bump: u8, data: Vec<u8>)]
13pub struct InitializeWithData<'info> {
14    /// entity that funds transaction
15    #[account(mut)]
16    pub payer: Signer<'info>,
17
18    /// descriptor authority, same as metadata update authority
19    pub authority: Signer<'info>,
20
21    /// CHECK: descriptor account to initialize
22    #[account(mut)]
23    pub descriptor: UncheckedAccount<'info>,
24
25    /// mint associated with the descriptor
26    pub mint: Account<'info, Mint>,
27
28    /// CHECK: metadata associated with the mint
29    #[account(
30        constraint = token_metadata.owner == token_metadata_program.key &&
31        token_metadata.to_account_info().data_len() > 0
32    )]
33    pub token_metadata: UncheckedAccount<'info>,
34
35    /// CHECK: mpl token metadata
36    #[account(address = mpl_token_metadata::id())]
37    pub token_metadata_program: UncheckedAccount<'info>,
38
39    pub system_program: Program<'info, System>,
40}
41
42pub fn initialize_with_data_handler(
43    ctx: Context<InitializeWithData>,
44    encoding: Encoding,
45    bump: u8,
46    data: &Vec<u8>,
47) -> Result<()> {
48    let payer_account_info = &ctx.accounts.payer.to_account_info();
49    let authority_account_info = &ctx.accounts.authority.to_account_info();
50    let descriptor_account_info = &ctx.accounts.descriptor.to_account_info();
51    let mint_account_info = &ctx.accounts.mint.to_account_info();
52    let token_metadata_account_info = &ctx.accounts.token_metadata.to_account_info();
53    let system_program_info = &ctx.accounts.system_program.to_account_info();
54
55    let rent = Rent::get()?;
56    let mint_key = mint_account_info.key();
57
58    let metadata = Metadata::from_account_info(&token_metadata_account_info)?;
59
60    verify_metadata(&metadata, &authority_account_info.key(), &mint_key)?;
61    verify_empty_account(&descriptor_account_info)?;
62
63    let data_len = data.len();
64    let descriptor = initialize_descriptor_helper(
65        &payer_account_info,
66        &descriptor_account_info,
67        &system_program_info,
68        &rent,
69        bump,
70        &mint_key,
71        encoding,
72        data_len as u32,
73    )?;
74
75    let descriptor_bytes = descriptor.try_to_vec().unwrap();
76    let descriptor_attributes_len = descriptor_bytes.len();
77
78    let descriptor_account_data = &mut descriptor_account_info.data.borrow_mut();
79    descriptor_account_data[0..descriptor_attributes_len].copy_from_slice(&descriptor_bytes);
80
81    let descriptor_range_end = descriptor_bytes.len() + data_len;
82    descriptor_account_data[descriptor_attributes_len..descriptor_range_end]
83        .copy_from_slice(&data[..]);
84
85    Ok(())
86}