1use borsh::{BorshDeserialize, BorshSerialize};
2use bytemuck::{bytes_of, NoUninit};
3use solana_program::{instruction::{AccountMeta, Instruction}, pubkey::Pubkey};
4
5use crate::{borsh_size::BorshSize, wrapped_pod::WrappedPod};
6
7pub trait InstructionsAccount {
8 fn get_accounts_vec(&self) -> Vec<AccountMeta>;
9
10 fn get_instruction<P: BorshDeserialize + BorshSerialize + BorshSize>(
11 &self,
12 program_id: Pubkey,
13 instruction_id: u8,
14 params: P,
15 ) -> Instruction {
16 let cap = 1 + params.borsh_len();
17 let mut data = Vec::with_capacity(cap);
18 #[allow(clippy::uninit_vec)]
19 unsafe {
20 data.set_len(cap);
21 }
22 data[0] = instruction_id;
23 let mut data_pointer = &mut data[1..];
24 params.serialize(&mut data_pointer).unwrap();
25 if !data_pointer.is_empty() {
27 panic!()
28 }
29
30 let accounts_vec = self.get_accounts_vec();
31 Instruction {
32 program_id,
33 accounts: accounts_vec,
34 data,
35 }
36 }
37 fn get_instruction_cast<P: NoUninit>(
38 &self,
39 program_id: Pubkey,
40 instruction_id: u8,
41 params: P,
42 ) -> Instruction {
43 let cap = 8 + std::mem::size_of::<P>();
44 let mut data = Vec::with_capacity(cap);
45 data.push(instruction_id);
46 data.extend([0; 7].iter());
47 data.extend(bytes_of(¶ms));
48
49 Instruction {
50 program_id,
51 accounts: self.get_accounts_vec(),
52 data,
53 }
54 }
55 fn get_instruction_wrapped_pod<'a, P: WrappedPod<'a>>(
56 &self,
57 program_id: Pubkey,
58 instruction_id: u8,
59 params: P,
60 ) -> Instruction {
61 let cap = 8 + params.size();
62 let mut data = Vec::with_capacity(cap);
63 data.push(instruction_id);
64 data.extend([0; 7].iter());
65 params.export(&mut data);
66
67 Instruction {
68 program_id,
69 accounts: self.get_accounts_vec(),
70 data,
71 }
72 }
73}