spl_token_2022/extension/group_pointer/
processor.rs1use {
2 crate::{
3 check_program_account,
4 error::TokenError,
5 extension::{
6 group_pointer::{
7 instruction::{
8 GroupPointerInstruction, InitializeInstructionData, UpdateInstructionData,
9 },
10 GroupPointer,
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 group_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 if Option::<Pubkey>::from(*authority).is_none()
39 && Option::<Pubkey>::from(*group_address).is_none()
40 {
41 msg!(
42 "The group pointer extension requires at least an authority or an address for \
43 initialization, neither was provided"
44 );
45 Err(TokenError::InvalidInstruction)?;
46 }
47
48 let extension = mint.init_extension::<GroupPointer>(true)?;
49 extension.authority = *authority;
50 extension.group_address = *group_address;
51 Ok(())
52}
53
54fn process_update(
55 program_id: &Pubkey,
56 accounts: &[AccountInfo],
57 new_group_address: &OptionalNonZeroPubkey,
58) -> ProgramResult {
59 let account_info_iter = &mut accounts.iter();
60 let mint_account_info = next_account_info(account_info_iter)?;
61 let owner_info = next_account_info(account_info_iter)?;
62 let owner_info_data_len = owner_info.data_len();
63
64 let mut mint_data = mint_account_info.data.borrow_mut();
65 let mut mint = PodStateWithExtensionsMut::<PodMint>::unpack(&mut mint_data)?;
66 let extension = mint.get_extension_mut::<GroupPointer>()?;
67 let authority =
68 Option::<Pubkey>::from(extension.authority).ok_or(TokenError::NoAuthorityExists)?;
69
70 Processor::validate_owner(
71 program_id,
72 &authority,
73 owner_info,
74 owner_info_data_len,
75 account_info_iter.as_slice(),
76 )?;
77
78 extension.group_address = *new_group_address;
79 Ok(())
80}
81
82pub(crate) fn process_instruction(
83 program_id: &Pubkey,
84 accounts: &[AccountInfo],
85 input: &[u8],
86) -> ProgramResult {
87 check_program_account(program_id)?;
88 match decode_instruction_type(input)? {
89 GroupPointerInstruction::Initialize => {
90 msg!("GroupPointerInstruction::Initialize");
91 let InitializeInstructionData {
92 authority,
93 group_address,
94 } = decode_instruction_data(input)?;
95 process_initialize(program_id, accounts, authority, group_address)
96 }
97 GroupPointerInstruction::Update => {
98 msg!("GroupPointerInstruction::Update");
99 let UpdateInstructionData { group_address } = decode_instruction_data(input)?;
100 process_update(program_id, accounts, group_address)
101 }
102 }
103}