spl_token_2022/extension/metadata_pointer/
processor.rs1use {
2 crate::{
3 check_program_account,
4 error::TokenError,
5 extension::{
6 metadata_pointer::{
7 instruction::{
8 InitializeInstructionData, MetadataPointerInstruction, UpdateInstructionData,
9 },
10 MetadataPointer,
11 },
12 BaseStateWithExtensionsMut, PodStateWithExtensionsMut,
13 },
14 instruction::{decode_instruction_data, decode_instruction_type},
15 pod::PodMint,
16 processor::Processor,
17 },
18 solana_program::{
19 account_info::{next_account_info, AccountInfo},
20 entrypoint::ProgramResult,
21 msg,
22 pubkey::Pubkey,
23 },
24 spl_pod::optional_keys::OptionalNonZeroPubkey,
25};
26
27fn process_initialize(
28 _program_id: &Pubkey,
29 accounts: &[AccountInfo],
30 authority: &OptionalNonZeroPubkey,
31 metadata_address: &OptionalNonZeroPubkey,
32) -> ProgramResult {
33 let account_info_iter = &mut accounts.iter();
34 let mint_account_info = next_account_info(account_info_iter)?;
35 let mut mint_data = mint_account_info.data.borrow_mut();
36 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack_uninitialized(&mut mint_data)?;
37
38 let extension = mint.init_extension::<MetadataPointer>(true)?;
39 extension.authority = *authority;
40
41 if Option::<Pubkey>::from(*authority).is_none()
42 && Option::<Pubkey>::from(*metadata_address).is_none()
43 {
44 msg!("The metadata pointer extension requires at least an authority or an address for initialization, neither was provided");
45 Err(TokenError::InvalidInstruction)?;
46 }
47 extension.metadata_address = *metadata_address;
48 Ok(())
49}
50
51fn process_update(
52 program_id: &Pubkey,
53 accounts: &[AccountInfo],
54 new_metadata_address: &OptionalNonZeroPubkey,
55) -> ProgramResult {
56 let account_info_iter = &mut accounts.iter();
57 let mint_account_info = next_account_info(account_info_iter)?;
58 let owner_info = next_account_info(account_info_iter)?;
59 let owner_info_data_len = owner_info.data_len();
60
61 let mut mint_data = mint_account_info.data.borrow_mut();
62 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
63 let extension = mint.get_extension_mut::<MetadataPointer>()?;
64 let authority =
65 Option::<Pubkey>::from(extension.authority).ok_or(TokenError::NoAuthorityExists)?;
66
67 Processor::validate_owner(
68 program_id,
69 &authority,
70 owner_info,
71 owner_info_data_len,
72 account_info_iter.as_slice(),
73 )?;
74
75 extension.metadata_address = *new_metadata_address;
76 Ok(())
77}
78
79pub(crate) fn process_instruction(
80 program_id: &Pubkey,
81 accounts: &[AccountInfo],
82 input: &[u8],
83) -> ProgramResult {
84 check_program_account(program_id)?;
85 match decode_instruction_type(input)? {
86 MetadataPointerInstruction::Initialize => {
87 msg!("MetadataPointerInstruction::Initialize");
88 let InitializeInstructionData {
89 authority,
90 metadata_address,
91 } = decode_instruction_data(input)?;
92 process_initialize(program_id, accounts, authority, metadata_address)
93 }
94 MetadataPointerInstruction::Update => {
95 msg!("MetadataPointerInstruction::Update");
96 let UpdateInstructionData { metadata_address } = decode_instruction_data(input)?;
97 process_update(program_id, accounts, metadata_address)
98 }
99 }
100}