web3_utils/
accounts.rs

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        // We check that we have written to the whole buffer to ensure that no undefined bytes remain at the end of data.
26        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(&params));
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}