spherenet_program_whitelist_interface/onchain/
add_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 AddEntry<'a> {
31 pub whitelist_account: &'a AccountInfo,
33 pub whitelist_authority: &'a AccountInfo,
35 pub whitelist_entry_account: &'a AccountInfo,
37 pub payer: &'a AccountInfo,
39 pub system_program: &'a AccountInfo,
41 pub program_authority: Pubkey,
43}
44
45impl<'a> AddEntry<'a> {
46 #[inline(always)]
47 pub fn invoke(&self) -> ProgramResult {
48 self.invoke_signed(&[])
49 }
50
51 fn create_instruction_data(program_authority: &Pubkey) -> [MaybeUninit<u8>; 33] {
53 let mut instruction_data = [UNINIT_BYTE; 33];
54
55 write_bytes(&mut instruction_data, &[4]);
57 write_bytes(&mut instruction_data[1..33], program_authority.as_ref());
59
60 instruction_data
61 }
62
63 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
64 let account_metas: [AccountMeta; 5] = [
66 AccountMeta::readonly(self.whitelist_account.key()),
67 AccountMeta::readonly_signer(self.whitelist_authority.key()),
68 AccountMeta::writable(self.whitelist_entry_account.key()),
69 AccountMeta::writable_signer(self.payer.key()),
70 AccountMeta::readonly(self.system_program.key()),
71 ];
72
73 let instruction_data = Self::create_instruction_data(&self.program_authority);
75
76 let instruction = Instruction {
77 program_id: &ID,
78 accounts: &account_metas,
79 data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, 33) },
80 };
81
82 invoke_signed(
83 &instruction,
84 &[
85 self.whitelist_account,
86 self.whitelist_authority,
87 self.whitelist_entry_account,
88 self.payer,
89 self.system_program,
90 ],
91 signers,
92 )
93 }
94}
95
96pub fn add_entry(
98 whitelist_account: &AccountInfo,
99 whitelist_authority: &AccountInfo,
100 whitelist_entry_account: &AccountInfo,
101 payer: &AccountInfo,
102 system_program: &AccountInfo,
103 program_authority: Pubkey,
104) -> ProgramResult {
105 let ix = AddEntry {
106 whitelist_account,
107 whitelist_authority,
108 whitelist_entry_account,
109 payer,
110 system_program,
111 program_authority,
112 };
113 ix.invoke()
114}
115
116pub fn add_entry_with_seed(
119 whitelist_account: &AccountInfo,
120 whitelist_authority: &AccountInfo,
121 whitelist_entry_account: &AccountInfo,
122 payer: &AccountInfo,
123 system_program: &AccountInfo,
124 program_authority: Pubkey,
125 signer_seeds: &[Signer],
126) -> ProgramResult {
127 let ix = AddEntry {
128 whitelist_account,
129 whitelist_authority,
130 whitelist_entry_account,
131 payer,
132 system_program,
133 program_authority,
134 };
135 ix.invoke_signed(signer_seeds)
136}
137
138#[cfg(test)]
139mod tests {
140 use {super::*, crate::instructions::ProgramWhitelistInstruction};
141
142 #[test]
143 fn test_instruction_data_creation() {
144 let program_authority_bytes = [42u8; 32]; let program_authority = Pubkey::from(program_authority_bytes);
147
148 let instruction_data = AddEntry::create_instruction_data(&program_authority);
150
151 let instruction = Instruction {
153 program_id: &ID,
154 accounts: &[], data: unsafe { from_raw_parts(instruction_data.as_ptr() as _, 33) },
156 };
157
158 let parsed_ix = ProgramWhitelistInstruction::unpack(instruction.data).unwrap();
160
161 match parsed_ix {
163 ProgramWhitelistInstruction::AddEntry {
164 program_authority: parsed_program_authority,
165 } => {
166 assert_eq!(parsed_program_authority, program_authority);
167 }
168 _ => panic!("Parsed incorrect instruction type"),
169 }
170 }
171}