spherenet_program_whitelist_interface/onchain/
remove_entry.rs1use {
4 crate::{
5 onchain::{write_bytes, UNINIT_BYTE},
6 program::ID,
7 },
8 core::{mem::MaybeUninit, slice::from_raw_parts},
9 pinocchio::{
10 account_info::AccountInfo,
11 instruction::{AccountMeta, Instruction, Signer},
12 program::invoke_signed,
13 pubkey::Pubkey,
14 ProgramResult,
15 },
16};
17
18pub struct RemoveEntry<'a> {
28 pub whitelist_account: &'a AccountInfo,
30 pub whitelist_authority: &'a AccountInfo,
32 pub whitelist_entry_account: &'a AccountInfo,
34 pub destination_account: &'a AccountInfo,
36 pub system_program: &'a AccountInfo,
38 pub program_authority: Pubkey,
40}
41
42impl<'a> RemoveEntry<'a> {
43 #[inline(always)]
44 pub fn invoke(&self) -> ProgramResult {
45 self.invoke_signed(&[])
46 }
47
48 fn create_instruction_data(program_authority: &Pubkey) -> [MaybeUninit<u8>; 33] {
50 let mut instruction_data = [UNINIT_BYTE; 33];
51
52 write_bytes(&mut instruction_data, &[5]);
54 write_bytes(&mut instruction_data[1..33], program_authority.as_ref());
56
57 instruction_data
58 }
59
60 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
61 let account_metas: [AccountMeta; 5] = [
63 AccountMeta::readonly(self.whitelist_account.key()),
64 AccountMeta::readonly_signer(self.whitelist_authority.key()),
65 AccountMeta::writable(self.whitelist_entry_account.key()),
66 AccountMeta::writable(self.destination_account.key()),
67 AccountMeta::readonly(self.system_program.key()),
68 ];
69
70 let instruction_data = Self::create_instruction_data(&self.program_authority);
72
73 let instruction = Instruction {
74 program_id: &ID,
75 accounts: &account_metas,
76 data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, 33) },
77 };
78
79 invoke_signed(
80 &instruction,
81 &[
82 self.whitelist_account,
83 self.whitelist_authority,
84 self.whitelist_entry_account,
85 self.destination_account,
86 self.system_program,
87 ],
88 signers,
89 )
90 }
91}
92
93pub fn remove_entry(
95 whitelist_account: &AccountInfo,
96 whitelist_authority: &AccountInfo,
97 whitelist_entry_account: &AccountInfo,
98 destination_account: &AccountInfo,
99 system_program: &AccountInfo,
100 program_authority: Pubkey,
101) -> ProgramResult {
102 let ix = RemoveEntry {
103 whitelist_account,
104 whitelist_authority,
105 whitelist_entry_account,
106 destination_account,
107 system_program,
108 program_authority,
109 };
110 ix.invoke()
111}
112
113pub fn remove_entry_with_seed(
116 whitelist_account: &AccountInfo,
117 whitelist_authority: &AccountInfo,
118 whitelist_entry_account: &AccountInfo,
119 destination_account: &AccountInfo,
120 system_program: &AccountInfo,
121 program_authority: Pubkey,
122 signer_seeds: &[Signer],
123) -> ProgramResult {
124 let ix = RemoveEntry {
125 whitelist_account,
126 whitelist_authority,
127 whitelist_entry_account,
128 destination_account,
129 system_program,
130 program_authority,
131 };
132 ix.invoke_signed(signer_seeds)
133}
134
135#[cfg(test)]
136mod tests {
137 use {super::*, crate::instructions::ProgramWhitelistInstruction};
138
139 #[test]
140 fn test_instruction_data_creation() {
141 let program_authority_bytes = [42u8; 32]; let program_authority = Pubkey::from(program_authority_bytes);
144
145 let instruction_data = RemoveEntry::create_instruction_data(&program_authority);
147
148 let instruction = Instruction {
150 program_id: &ID,
151 accounts: &[], data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, 33) },
153 };
154
155 let parsed_ix = ProgramWhitelistInstruction::unpack(instruction.data).unwrap();
157
158 match parsed_ix {
160 ProgramWhitelistInstruction::RemoveEntry {
161 program_authority: parsed_program_authority,
162 } => {
163 assert_eq!(parsed_program_authority, program_authority);
164 }
165 _ => panic!("Parsed incorrect instruction type"),
166 }
167 }
168}