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