Skip to main content

gor22_token/extension/group_member_pointer/
processor.rs

1use {
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_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    member_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(*member_address).is_none()
40    {
41        msg!(
42            "The group member 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::<GroupMemberPointer>(true)?;
49    extension.authority = *authority;
50    extension.member_address = *member_address;
51    Ok(())
52}
53
54fn process_update(
55    program_id: &Pubkey,
56    accounts: &[AccountInfo],
57    new_member_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::<GroupMemberPointer>()?;
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.member_address = *new_member_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        GroupMemberPointerInstruction::Initialize => {
90            msg!("GroupMemberPointerInstruction::Initialize");
91            let InitializeInstructionData {
92                authority,
93                member_address,
94            } = decode_instruction_data(input)?;
95            process_initialize(program_id, accounts, authority, member_address)
96        }
97        GroupMemberPointerInstruction::Update => {
98            msg!("GroupMemberPointerInstruction::Update");
99            let UpdateInstructionData { member_address } = decode_instruction_data(input)?;
100            process_update(program_id, accounts, member_address)
101        }
102    }
103}