token_metadata_descriptor/instructions/
initialize_with_buffer.rs1use anchor_lang::prelude::*;
2use anchor_spl::token::Mint;
3use mpl_token_metadata::state::{Metadata, TokenMetadataAccount};
4
5use crate::{
6 state::{Encoding, Range},
7 utils::{initialize_descriptor_helper, verify_empty_account, verify_metadata},
8};
9
10#[derive(Accounts)]
11#[instruction(range: Option<Range>, encoding: Encoding, bump: u8)]
12pub struct InitializeWithBuffer<'info> {
13 #[account(mut)]
15 pub payer: Signer<'info>,
16
17 pub authority: Signer<'info>,
19
20 #[account(mut)]
22 pub descriptor: UncheckedAccount<'info>,
23
24 pub mint: Account<'info, Mint>,
26
27 pub buffer: UncheckedAccount<'info>,
29
30 #[account(
32 constraint = token_metadata.owner == token_metadata_program.key &&
33 token_metadata.to_account_info().data_len() > 0
34 )]
35 pub token_metadata: UncheckedAccount<'info>,
36
37 #[account(address = mpl_token_metadata::id())]
39 pub token_metadata_program: UncheckedAccount<'info>,
40
41 pub system_program: Program<'info, System>,
42}
43
44pub fn initialize_with_buffer_handler(
45 ctx: Context<InitializeWithBuffer>,
46 range: Option<Range>,
47 encoding: Encoding,
48 bump: u8,
49) -> Result<()> {
50 let payer_account_info = &ctx.accounts.payer.to_account_info();
51 let authority_account_info = &ctx.accounts.authority.to_account_info();
52 let descriptor_account_info = &ctx.accounts.descriptor.to_account_info();
53 let mint_account_info = &ctx.accounts.mint.to_account_info();
54 let token_metadata_account_info = &ctx.accounts.token_metadata.to_account_info();
55 let system_program_info = &ctx.accounts.system_program.to_account_info();
56 let buffer_account_info = &ctx.accounts.buffer.to_account_info();
57
58 let rent = Rent::get()?;
59 let mint_key = mint_account_info.key();
60
61 let metadata = Metadata::from_account_info(&token_metadata_account_info.to_account_info())?;
62
63 verify_metadata(
64 &metadata,
65 &authority_account_info.key(),
66 &mint_account_info.key(),
67 )?;
68 verify_empty_account(&descriptor_account_info)?;
69
70 let (buffer_start, buffer_end) = match range {
71 Some(r) => (r.start as usize, r.end as usize),
72 None => (0, buffer_account_info.data_len()),
73 };
74
75 let buffer_range_length = buffer_end - buffer_start;
76
77 let descriptor = initialize_descriptor_helper(
78 &payer_account_info,
79 &descriptor_account_info,
80 &system_program_info,
81 &rent,
82 bump,
83 &mint_key,
84 encoding,
85 buffer_range_length as u32,
86 )?;
87
88 let descriptor_bytes = descriptor.try_to_vec().unwrap();
89 let descriptor_attributes_len = descriptor_bytes.len();
90
91 let descriptor_account_data = &mut descriptor_account_info.data.borrow_mut();
92 descriptor_account_data[0..descriptor_attributes_len].copy_from_slice(&descriptor_bytes);
93
94 let descriptor_range_end = descriptor_bytes.len() + buffer_range_length;
95 descriptor_account_data[descriptor_attributes_len..descriptor_range_end]
96 .copy_from_slice(&buffer_account_info.data.borrow()[buffer_start..buffer_end]);
97
98 Ok(())
99}