light_token/instruction/
burn.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 Burn {
26 pub source: Pubkey,
28 pub mint: 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 BurnCpi<'info> {
62 pub source: AccountInfo<'info>,
63 pub mint: 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> BurnCpi<'info> {
74 pub fn instruction(&self) -> Result<Instruction, ProgramError> {
75 Burn::from(self).instruction()
76 }
77
78 pub fn invoke(self) -> Result<(), ProgramError> {
79 let instruction = Burn::from(&self).instruction()?;
80 if let Some(fee_payer) = self.fee_payer {
81 let account_infos = [
82 self.source,
83 self.mint,
84 self.authority,
85 self.system_program,
86 fee_payer,
87 ];
88 invoke(&instruction, &account_infos)
89 } else {
90 let account_infos = [self.source, self.mint, self.authority, self.system_program];
91 invoke(&instruction, &account_infos)
92 }
93 }
94
95 pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
96 let instruction = Burn::from(&self).instruction()?;
97 if let Some(fee_payer) = self.fee_payer {
98 let account_infos = [
99 self.source,
100 self.mint,
101 self.authority,
102 self.system_program,
103 fee_payer,
104 ];
105 invoke_signed(&instruction, &account_infos, signer_seeds)
106 } else {
107 let account_infos = [self.source, self.mint, self.authority, self.system_program];
108 invoke_signed(&instruction, &account_infos, signer_seeds)
109 }
110 }
111}
112
113impl<'info> From<&BurnCpi<'info>> for Burn {
114 fn from(cpi: &BurnCpi<'info>) -> Self {
115 Self {
116 source: *cpi.source.key,
117 mint: *cpi.mint.key,
118 amount: cpi.amount,
119 authority: *cpi.authority.key,
120 max_top_up: cpi.max_top_up,
121 fee_payer: cpi.fee_payer.as_ref().map(|a| *a.key),
122 }
123 }
124}
125
126impl Burn {
127 pub fn instruction(self) -> Result<Instruction, ProgramError> {
128 let authority_meta = if self.max_top_up.is_some() && self.fee_payer.is_none() {
131 AccountMeta::new(self.authority, true)
132 } else {
133 AccountMeta::new_readonly(self.authority, true)
134 };
135
136 let mut accounts = vec![
137 AccountMeta::new(self.source, false),
138 AccountMeta::new(self.mint, false),
139 authority_meta,
140 AccountMeta::new_readonly(Pubkey::default(), false),
142 ];
143
144 if let Some(fee_payer) = self.fee_payer {
146 accounts.push(AccountMeta::new(fee_payer, true));
147 }
148
149 Ok(Instruction {
150 program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
151 accounts,
152 data: {
153 let mut data = vec![8u8]; data.extend_from_slice(&self.amount.to_le_bytes());
155 if let Some(max_top_up) = self.max_top_up {
157 data.extend_from_slice(&max_top_up.to_le_bytes());
158 }
159 data
160 },
161 })
162 }
163}