light_token/instruction/
mint_to.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 MintTo {
26 pub mint: Pubkey,
28 pub destination: Pubkey,
30 pub amount: u64,
32 pub authority: Pubkey,
34 pub max_top_up: Option<u16>,
37 pub fee_payer: Option<Pubkey>,
39}
40
41pub struct MintToCpi<'info> {
62 pub mint: AccountInfo<'info>,
63 pub destination: AccountInfo<'info>,
64 pub amount: u64,
65 pub authority: AccountInfo<'info>,
66 pub system_program: AccountInfo<'info>,
67 pub max_top_up: Option<u16>,
69 pub fee_payer: Option<AccountInfo<'info>>,
71}
72
73impl<'info> MintToCpi<'info> {
74 pub fn instruction(&self) -> Result<Instruction, ProgramError> {
75 MintTo::from(self).instruction()
76 }
77
78 pub fn invoke(self) -> Result<(), ProgramError> {
79 let instruction = MintTo::from(&self).instruction()?;
80 if let Some(fee_payer) = self.fee_payer {
81 let account_infos = [
82 self.mint,
83 self.destination,
84 self.authority,
85 self.system_program,
86 fee_payer,
87 ];
88 invoke(&instruction, &account_infos)
89 } else {
90 let account_infos = [
91 self.mint,
92 self.destination,
93 self.authority,
94 self.system_program,
95 ];
96 invoke(&instruction, &account_infos)
97 }
98 }
99
100 pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
101 let instruction = MintTo::from(&self).instruction()?;
102 if let Some(fee_payer) = self.fee_payer {
103 let account_infos = [
104 self.mint,
105 self.destination,
106 self.authority,
107 self.system_program,
108 fee_payer,
109 ];
110 invoke_signed(&instruction, &account_infos, signer_seeds)
111 } else {
112 let account_infos = [
113 self.mint,
114 self.destination,
115 self.authority,
116 self.system_program,
117 ];
118 invoke_signed(&instruction, &account_infos, signer_seeds)
119 }
120 }
121}
122
123impl<'info> From<&MintToCpi<'info>> for MintTo {
124 fn from(cpi: &MintToCpi<'info>) -> Self {
125 Self {
126 mint: *cpi.mint.key,
127 destination: *cpi.destination.key,
128 amount: cpi.amount,
129 authority: *cpi.authority.key,
130 max_top_up: cpi.max_top_up,
131 fee_payer: cpi.fee_payer.as_ref().map(|a| *a.key),
132 }
133 }
134}
135
136impl MintTo {
137 pub fn instruction(self) -> Result<Instruction, ProgramError> {
138 let authority_meta = if self.max_top_up.is_some() && self.fee_payer.is_none() {
141 AccountMeta::new(self.authority, true)
142 } else {
143 AccountMeta::new_readonly(self.authority, true)
144 };
145
146 let mut accounts = vec![
147 AccountMeta::new(self.mint, false),
148 AccountMeta::new(self.destination, false),
149 authority_meta,
150 AccountMeta::new_readonly(Pubkey::default(), false),
152 ];
153
154 if let Some(fee_payer) = self.fee_payer {
156 accounts.push(AccountMeta::new(fee_payer, true));
157 }
158
159 Ok(Instruction {
160 program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
161 accounts,
162 data: {
163 let mut data = vec![7u8]; data.extend_from_slice(&self.amount.to_le_bytes());
165 if let Some(max_top_up) = self.max_top_up {
167 data.extend_from_slice(&max_top_up.to_le_bytes());
168 }
169 data
170 },
171 })
172 }
173}