pinocchio_token/instructions/
initialize_account_2.rs1use {
2 crate::{
3 instructions::{account_borrow_failed_error, invalid_argument_error, CpiWriter},
4 write_bytes, UNINIT_BYTE, UNINIT_CPI_ACCOUNT, UNINIT_INSTRUCTION_ACCOUNT,
5 },
6 core::{mem::MaybeUninit, slice::from_raw_parts},
7 solana_account_view::AccountView,
8 solana_address::Address,
9 solana_instruction_view::{
10 cpi::{invoke_unchecked, CpiAccount},
11 InstructionAccount, InstructionView,
12 },
13 solana_program_error::{ProgramError, ProgramResult},
14};
15
16pub struct InitializeAccount2<'account> {
28 pub account: &'account AccountView,
30
31 pub mint: &'account AccountView,
33
34 pub rent_sysvar: &'account AccountView,
36
37 pub owner: &'account Address,
39}
40
41impl<'account> InitializeAccount2<'account> {
42 pub const DISCRIMINATOR: u8 = 16;
43
44 pub const ACCOUNTS_LEN: usize = 3;
46
47 pub const DATA_LEN: usize = 33;
51
52 #[inline(always)]
53 pub fn new(
54 account: &'account AccountView,
55 mint: &'account AccountView,
56 rent_sysvar: &'account AccountView,
57 owner: &'account Address,
58 ) -> Self {
59 Self {
60 account,
61 mint,
62 rent_sysvar,
63 owner,
64 }
65 }
66
67 #[inline(always)]
68 pub fn invoke(&self) -> ProgramResult {
69 let mut instruction_accounts =
70 [UNINIT_INSTRUCTION_ACCOUNT; InitializeAccount2::ACCOUNTS_LEN];
71 let written_instruction_accounts =
72 self.write_instruction_accounts(&mut instruction_accounts)?;
73
74 let mut accounts = [UNINIT_CPI_ACCOUNT; Self::ACCOUNTS_LEN];
75 let written_accounts = self.write_accounts(&mut accounts)?;
76
77 let mut instruction_data = [UNINIT_BYTE; Self::DATA_LEN];
78 let written_instruction_data = self.write_instruction_data(&mut instruction_data)?;
79
80 unsafe {
81 invoke_unchecked(
82 &InstructionView {
83 program_id: &crate::ID,
84 accounts: from_raw_parts(
85 instruction_accounts.as_ptr() as _,
86 written_instruction_accounts,
87 ),
88 data: from_raw_parts(instruction_data.as_ptr() as _, written_instruction_data),
89 },
90 from_raw_parts(accounts.as_ptr() as *const CpiAccount, written_accounts),
91 );
92 }
93
94 Ok(())
95 }
96}
97
98impl CpiWriter for InitializeAccount2<'_> {
99 #[inline(always)]
100 fn write_accounts<'cpi>(
101 &self,
102 accounts: &mut [MaybeUninit<CpiAccount<'cpi>>],
103 ) -> Result<usize, ProgramError>
104 where
105 Self: 'cpi,
106 {
107 write_accounts(self.account, self.mint, self.rent_sysvar, accounts)
108 }
109
110 #[inline(always)]
111 fn write_instruction_accounts<'cpi>(
112 &self,
113 accounts: &mut [MaybeUninit<InstructionAccount<'cpi>>],
114 ) -> Result<usize, ProgramError>
115 where
116 Self: 'cpi,
117 {
118 write_instruction_accounts(self.account, self.mint, self.rent_sysvar, accounts)
119 }
120
121 #[inline(always)]
122 fn write_instruction_data(&self, data: &mut [MaybeUninit<u8>]) -> Result<usize, ProgramError> {
123 write_instruction_data(self.owner, data)
124 }
125}
126
127impl super::IntoBatch for InitializeAccount2<'_> {
128 #[inline(always)]
129 fn into_batch<'account, 'state>(
130 self,
131 batch: &mut super::Batch<'account, 'state>,
132 ) -> ProgramResult
133 where
134 Self: 'account + 'state,
135 {
136 batch.push(
137 |accounts| write_accounts(self.account, self.mint, self.rent_sysvar, accounts),
138 |accounts| {
139 write_instruction_accounts(self.account, self.mint, self.rent_sysvar, accounts)
140 },
141 |data| write_instruction_data(self.owner, data),
142 )
143 }
144}
145
146#[inline(always)]
147fn write_accounts<'account, 'out>(
148 account: &'account AccountView,
149 mint: &'account AccountView,
150 rent_sysvar: &'account AccountView,
151 accounts: &mut [MaybeUninit<CpiAccount<'out>>],
152) -> Result<usize, ProgramError>
153where
154 'account: 'out,
155{
156 if accounts.len() < InitializeAccount2::ACCOUNTS_LEN {
157 return Err(invalid_argument_error());
158 }
159
160 if account.is_borrowed() {
161 return Err(account_borrow_failed_error());
162 }
163
164 CpiAccount::init_from_account_view(account, &mut accounts[0]);
165
166 CpiAccount::init_from_account_view(mint, &mut accounts[1]);
167
168 CpiAccount::init_from_account_view(rent_sysvar, &mut accounts[2]);
169
170 Ok(InitializeAccount2::ACCOUNTS_LEN)
171}
172
173#[inline(always)]
174fn write_instruction_accounts<'account, 'out>(
175 account: &'account AccountView,
176 mint: &'account AccountView,
177 rent_sysvar: &'account AccountView,
178 accounts: &mut [MaybeUninit<InstructionAccount<'out>>],
179) -> Result<usize, ProgramError>
180where
181 'account: 'out,
182{
183 if accounts.len() < InitializeAccount2::ACCOUNTS_LEN {
184 return Err(invalid_argument_error());
185 }
186
187 accounts[0].write(InstructionAccount::writable(account.address()));
188
189 accounts[1].write(InstructionAccount::readonly(mint.address()));
190
191 accounts[2].write(InstructionAccount::readonly(rent_sysvar.address()));
192
193 Ok(InitializeAccount2::ACCOUNTS_LEN)
194}
195
196#[inline(always)]
197fn write_instruction_data(
198 owner: &Address,
199 data: &mut [MaybeUninit<u8>],
200) -> Result<usize, ProgramError> {
201 if data.len() < InitializeAccount2::DATA_LEN {
202 return Err(invalid_argument_error());
203 }
204
205 data[0].write(InitializeAccount2::DISCRIMINATOR);
206
207 write_bytes(&mut data[1..InitializeAccount2::DATA_LEN], owner.as_array());
208
209 Ok(InitializeAccount2::DATA_LEN)
210}