gmsol_utils/
instruction.rs1use anchor_lang::{
2 prelude::{zero_copy, AccountMeta, Pubkey},
3 solana_program::instruction::Instruction,
4};
5
6const MAX_IX_ACCOUNT_FLAGS: usize = 8;
7
8pub const MAX_IX_FLAGS: usize = 8;
10
11#[derive(Debug, thiserror::Error)]
13pub enum InstructionError {
14 #[error("failed to get wallet")]
16 FailedToGetWallet,
17}
18
19#[zero_copy]
21pub struct InstructionAccount {
22 pub flags: InstructionAccountFlagContainer,
24 pub pubkey: Pubkey,
26}
27
28impl crate::InitSpace for InstructionAccount {
29 const INIT_SPACE: usize = std::mem::size_of::<Self>();
30}
31
32#[derive(num_enum::IntoPrimitive)]
34#[repr(u8)]
35pub enum InstructionAccountFlag {
36 Signer,
38 Writable,
40 }
42
43crate::flags!(InstructionAccountFlag, MAX_IX_ACCOUNT_FLAGS, u8);
44
45impl<'a> From<&'a InstructionAccount> for AccountMeta {
46 fn from(a: &'a InstructionAccount) -> Self {
47 Self {
48 pubkey: a.pubkey,
49 is_signer: a.flags.get_flag(InstructionAccountFlag::Signer),
50 is_writable: a.flags.get_flag(InstructionAccountFlag::Writable),
51 }
52 }
53}
54
55pub trait InstructionAccess {
57 fn wallet(&self) -> Result<Pubkey, InstructionError>;
59
60 fn program_id(&self) -> &Pubkey;
62
63 fn data(&self) -> &[u8];
65
66 fn num_accounts(&self) -> usize;
68
69 fn accounts(&self) -> impl Iterator<Item = &InstructionAccount>;
71
72 fn to_instruction(
74 &self,
75 mark_executor_wallet_as_signer: bool,
76 ) -> Result<Instruction, InstructionError> {
77 let mut accounts = self
78 .accounts()
79 .map(From::from)
80 .collect::<Vec<AccountMeta>>();
81
82 if mark_executor_wallet_as_signer {
85 let executor_wallet = self.wallet()?;
86 accounts
87 .iter_mut()
88 .filter(|a| a.pubkey == executor_wallet)
89 .for_each(|a| a.is_signer = true);
90 }
91
92 Ok(Instruction {
93 program_id: *self.program_id(),
94 accounts,
95 data: self.data().to_vec(),
96 })
97 }
98}
99
100#[derive(num_enum::IntoPrimitive)]
102#[repr(u8)]
103pub enum InstructionFlag {
104 Approved,
106 }