light_token/instruction/
mint_to_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 MintToChecked {
27 pub mint: Pubkey,
29 pub destination: Pubkey,
31 pub amount: u64,
33 pub decimals: u8,
35 pub authority: Pubkey,
37 pub max_top_up: Option<u16>,
40 pub fee_payer: Option<Pubkey>,
42}
43
44pub struct MintToCheckedCpi<'info> {
66 pub mint: AccountInfo<'info>,
67 pub destination: AccountInfo<'info>,
68 pub amount: u64,
69 pub decimals: u8,
70 pub authority: AccountInfo<'info>,
71 pub system_program: AccountInfo<'info>,
72 pub max_top_up: Option<u16>,
74 pub fee_payer: Option<AccountInfo<'info>>,
76}
77
78impl<'info> MintToCheckedCpi<'info> {
79 pub fn instruction(&self) -> Result<Instruction, ProgramError> {
80 MintToChecked::from(self).instruction()
81 }
82
83 pub fn invoke(self) -> Result<(), ProgramError> {
84 let instruction = MintToChecked::from(&self).instruction()?;
85 if let Some(fee_payer) = self.fee_payer {
86 let account_infos = [
87 self.mint,
88 self.destination,
89 self.authority,
90 self.system_program,
91 fee_payer,
92 ];
93 invoke(&instruction, &account_infos)
94 } else {
95 let account_infos = [
96 self.mint,
97 self.destination,
98 self.authority,
99 self.system_program,
100 ];
101 invoke(&instruction, &account_infos)
102 }
103 }
104
105 pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
106 let instruction = MintToChecked::from(&self).instruction()?;
107 if let Some(fee_payer) = self.fee_payer {
108 let account_infos = [
109 self.mint,
110 self.destination,
111 self.authority,
112 self.system_program,
113 fee_payer,
114 ];
115 invoke_signed(&instruction, &account_infos, signer_seeds)
116 } else {
117 let account_infos = [
118 self.mint,
119 self.destination,
120 self.authority,
121 self.system_program,
122 ];
123 invoke_signed(&instruction, &account_infos, signer_seeds)
124 }
125 }
126}
127
128impl<'info> From<&MintToCheckedCpi<'info>> for MintToChecked {
129 fn from(cpi: &MintToCheckedCpi<'info>) -> Self {
130 Self {
131 mint: *cpi.mint.key,
132 destination: *cpi.destination.key,
133 amount: cpi.amount,
134 decimals: cpi.decimals,
135 authority: *cpi.authority.key,
136 max_top_up: cpi.max_top_up,
137 fee_payer: cpi.fee_payer.as_ref().map(|a| *a.key),
138 }
139 }
140}
141
142impl MintToChecked {
143 pub fn instruction(self) -> Result<Instruction, ProgramError> {
144 let authority_meta = if self.max_top_up.is_some() && self.fee_payer.is_none() {
147 AccountMeta::new(self.authority, true)
148 } else {
149 AccountMeta::new_readonly(self.authority, true)
150 };
151
152 let mut accounts = vec![
153 AccountMeta::new(self.mint, false),
154 AccountMeta::new(self.destination, false),
155 authority_meta,
156 AccountMeta::new_readonly(Pubkey::default(), false),
158 ];
159
160 if let Some(fee_payer) = self.fee_payer {
162 accounts.push(AccountMeta::new(fee_payer, true));
163 }
164
165 Ok(Instruction {
166 program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
167 accounts,
168 data: {
169 let mut data = vec![14u8]; data.extend_from_slice(&self.amount.to_le_bytes());
171 data.push(self.decimals);
172 if let Some(max_top_up) = self.max_top_up {
174 data.extend_from_slice(&max_top_up.to_le_bytes());
175 }
176 data
177 },
178 })
179 }
180}