light_token/instruction/
approve_checked.rs1use light_sdk_types::LIGHT_TOKEN_PROGRAM_ID;
2use solana_account_info::AccountInfo;
3use solana_cpi::{invoke, invoke_signed};
4use solana_instruction::{AccountMeta, Instruction};
5use solana_program_error::ProgramError;
6use solana_pubkey::Pubkey;
7
8pub struct ApproveChecked {
28 pub token_account: Pubkey,
30 pub mint: Pubkey,
32 pub delegate: Pubkey,
34 pub owner: Pubkey,
36 pub amount: u64,
38 pub decimals: u8,
40 pub max_top_up: Option<u16>,
42}
43
44pub struct ApproveCheckedCpi<'info> {
67 pub token_account: AccountInfo<'info>,
68 pub mint: AccountInfo<'info>,
69 pub delegate: AccountInfo<'info>,
70 pub owner: AccountInfo<'info>,
71 pub system_program: AccountInfo<'info>,
72 pub amount: u64,
73 pub decimals: u8,
74 pub max_top_up: Option<u16>,
76}
77
78impl<'info> ApproveCheckedCpi<'info> {
79 pub fn instruction(&self) -> Result<Instruction, ProgramError> {
80 ApproveChecked::from(self).instruction()
81 }
82
83 pub fn invoke(self) -> Result<(), ProgramError> {
84 let instruction = ApproveChecked::from(&self).instruction()?;
85 let account_infos = [
86 self.token_account,
87 self.mint,
88 self.delegate,
89 self.owner,
90 self.system_program,
91 ];
92 invoke(&instruction, &account_infos)
93 }
94
95 pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
96 let instruction = ApproveChecked::from(&self).instruction()?;
97 let account_infos = [
98 self.token_account,
99 self.mint,
100 self.delegate,
101 self.owner,
102 self.system_program,
103 ];
104 invoke_signed(&instruction, &account_infos, signer_seeds)
105 }
106}
107
108impl<'info> From<&ApproveCheckedCpi<'info>> for ApproveChecked {
109 fn from(cpi: &ApproveCheckedCpi<'info>) -> Self {
110 Self {
111 token_account: *cpi.token_account.key,
112 mint: *cpi.mint.key,
113 delegate: *cpi.delegate.key,
114 owner: *cpi.owner.key,
115 amount: cpi.amount,
116 decimals: cpi.decimals,
117 max_top_up: cpi.max_top_up,
118 }
119 }
120}
121
122impl ApproveChecked {
123 pub fn instruction(self) -> Result<Instruction, ProgramError> {
124 let mut data = vec![13u8]; data.extend_from_slice(&self.amount.to_le_bytes());
126 data.push(self.decimals);
127 if let Some(max_top_up) = self.max_top_up {
129 data.extend_from_slice(&max_top_up.to_le_bytes());
130 }
131
132 Ok(Instruction {
133 program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
134 accounts: vec![
135 AccountMeta::new(self.token_account, false),
136 AccountMeta::new_readonly(self.mint, false),
137 AccountMeta::new_readonly(self.delegate, false),
138 AccountMeta::new(self.owner, true),
139 AccountMeta::new_readonly(Pubkey::default(), false),
140 ],
141 data,
142 })
143 }
144}