1use borsh::BorshDeserialize;
9use borsh::BorshSerialize;
10
11pub const BURN_DISCRIMINATOR: u8 = 7;
12
13#[derive(Debug)]
15pub struct Burn {
16 pub mint: solana_pubkey::Pubkey,
17
18 pub verification_config: solana_pubkey::Pubkey,
19
20 pub instructions_sysvar: solana_pubkey::Pubkey,
21
22 pub permanent_delegate: solana_pubkey::Pubkey,
23
24 pub mint_account: solana_pubkey::Pubkey,
25
26 pub token_account: solana_pubkey::Pubkey,
27
28 pub token_program: solana_pubkey::Pubkey,
29}
30
31impl Burn {
32 pub fn instruction(&self, args: BurnInstructionArgs) -> solana_instruction::Instruction {
33 self.instruction_with_remaining_accounts(args, &[])
34 }
35 #[allow(clippy::arithmetic_side_effects)]
36 #[allow(clippy::vec_init_then_push)]
37 pub fn instruction_with_remaining_accounts(
38 &self,
39 args: BurnInstructionArgs,
40 remaining_accounts: &[solana_instruction::AccountMeta],
41 ) -> solana_instruction::Instruction {
42 let mut accounts = Vec::with_capacity(7 + remaining_accounts.len());
43 accounts.push(solana_instruction::AccountMeta::new_readonly(
44 self.mint, false,
45 ));
46 accounts.push(solana_instruction::AccountMeta::new_readonly(
47 self.verification_config,
48 false,
49 ));
50 accounts.push(solana_instruction::AccountMeta::new_readonly(
51 self.instructions_sysvar,
52 false,
53 ));
54 accounts.push(solana_instruction::AccountMeta::new_readonly(
55 self.permanent_delegate,
56 false,
57 ));
58 accounts.push(solana_instruction::AccountMeta::new(
59 self.mint_account,
60 false,
61 ));
62 accounts.push(solana_instruction::AccountMeta::new(
63 self.token_account,
64 false,
65 ));
66 accounts.push(solana_instruction::AccountMeta::new_readonly(
67 self.token_program,
68 false,
69 ));
70 accounts.extend_from_slice(remaining_accounts);
71 let mut data = borsh::to_vec(&BurnInstructionData::new()).unwrap();
72 let mut args = borsh::to_vec(&args).unwrap();
73 data.append(&mut args);
74
75 solana_instruction::Instruction {
76 program_id: crate::SECURITY_TOKEN_PROGRAM_ID,
77 accounts,
78 data,
79 }
80 }
81}
82
83#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
84#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
85pub struct BurnInstructionData {
86 discriminator: u8,
87}
88
89impl BurnInstructionData {
90 pub fn new() -> Self {
91 Self { discriminator: 7 }
92 }
93}
94
95impl Default for BurnInstructionData {
96 fn default() -> Self {
97 Self::new()
98 }
99}
100
101#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
102#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
103pub struct BurnInstructionArgs {
104 pub amount: u64,
105}
106
107#[derive(Clone, Debug, Default)]
119pub struct BurnBuilder {
120 mint: Option<solana_pubkey::Pubkey>,
121 verification_config: Option<solana_pubkey::Pubkey>,
122 instructions_sysvar: Option<solana_pubkey::Pubkey>,
123 permanent_delegate: Option<solana_pubkey::Pubkey>,
124 mint_account: Option<solana_pubkey::Pubkey>,
125 token_account: Option<solana_pubkey::Pubkey>,
126 token_program: Option<solana_pubkey::Pubkey>,
127 amount: Option<u64>,
128 __remaining_accounts: Vec<solana_instruction::AccountMeta>,
129}
130
131impl BurnBuilder {
132 pub fn new() -> Self {
133 Self::default()
134 }
135 #[inline(always)]
136 pub fn mint(&mut self, mint: solana_pubkey::Pubkey) -> &mut Self {
137 self.mint = Some(mint);
138 self
139 }
140 #[inline(always)]
141 pub fn verification_config(&mut self, verification_config: solana_pubkey::Pubkey) -> &mut Self {
142 self.verification_config = Some(verification_config);
143 self
144 }
145 #[inline(always)]
147 pub fn instructions_sysvar(&mut self, instructions_sysvar: solana_pubkey::Pubkey) -> &mut Self {
148 self.instructions_sysvar = Some(instructions_sysvar);
149 self
150 }
151 #[inline(always)]
152 pub fn permanent_delegate(&mut self, permanent_delegate: solana_pubkey::Pubkey) -> &mut Self {
153 self.permanent_delegate = Some(permanent_delegate);
154 self
155 }
156 #[inline(always)]
157 pub fn mint_account(&mut self, mint_account: solana_pubkey::Pubkey) -> &mut Self {
158 self.mint_account = Some(mint_account);
159 self
160 }
161 #[inline(always)]
162 pub fn token_account(&mut self, token_account: solana_pubkey::Pubkey) -> &mut Self {
163 self.token_account = Some(token_account);
164 self
165 }
166 #[inline(always)]
168 pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self {
169 self.token_program = Some(token_program);
170 self
171 }
172 #[inline(always)]
173 pub fn amount(&mut self, amount: u64) -> &mut Self {
174 self.amount = Some(amount);
175 self
176 }
177 #[inline(always)]
179 pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self {
180 self.__remaining_accounts.push(account);
181 self
182 }
183 #[inline(always)]
185 pub fn add_remaining_accounts(
186 &mut self,
187 accounts: &[solana_instruction::AccountMeta],
188 ) -> &mut Self {
189 self.__remaining_accounts.extend_from_slice(accounts);
190 self
191 }
192 #[allow(clippy::clone_on_copy)]
193 pub fn instruction(&self) -> solana_instruction::Instruction {
194 let accounts = Burn {
195 mint: self.mint.expect("mint is not set"),
196 verification_config: self
197 .verification_config
198 .expect("verification_config is not set"),
199 instructions_sysvar: self.instructions_sysvar.unwrap_or(solana_pubkey::pubkey!(
200 "Sysvar1nstructions1111111111111111111111111"
201 )),
202 permanent_delegate: self
203 .permanent_delegate
204 .expect("permanent_delegate is not set"),
205 mint_account: self.mint_account.expect("mint_account is not set"),
206 token_account: self.token_account.expect("token_account is not set"),
207 token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!(
208 "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
209 )),
210 };
211 let args = BurnInstructionArgs {
212 amount: self.amount.clone().expect("amount is not set"),
213 };
214
215 accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts)
216 }
217}
218
219pub struct BurnCpiAccounts<'a, 'b> {
221 pub mint: &'b solana_account_info::AccountInfo<'a>,
222
223 pub verification_config: &'b solana_account_info::AccountInfo<'a>,
224
225 pub instructions_sysvar: &'b solana_account_info::AccountInfo<'a>,
226
227 pub permanent_delegate: &'b solana_account_info::AccountInfo<'a>,
228
229 pub mint_account: &'b solana_account_info::AccountInfo<'a>,
230
231 pub token_account: &'b solana_account_info::AccountInfo<'a>,
232
233 pub token_program: &'b solana_account_info::AccountInfo<'a>,
234}
235
236pub struct BurnCpi<'a, 'b> {
238 pub __program: &'b solana_account_info::AccountInfo<'a>,
240
241 pub mint: &'b solana_account_info::AccountInfo<'a>,
242
243 pub verification_config: &'b solana_account_info::AccountInfo<'a>,
244
245 pub instructions_sysvar: &'b solana_account_info::AccountInfo<'a>,
246
247 pub permanent_delegate: &'b solana_account_info::AccountInfo<'a>,
248
249 pub mint_account: &'b solana_account_info::AccountInfo<'a>,
250
251 pub token_account: &'b solana_account_info::AccountInfo<'a>,
252
253 pub token_program: &'b solana_account_info::AccountInfo<'a>,
254 pub __args: BurnInstructionArgs,
256}
257
258impl<'a, 'b> BurnCpi<'a, 'b> {
259 pub fn new(
260 program: &'b solana_account_info::AccountInfo<'a>,
261 accounts: BurnCpiAccounts<'a, 'b>,
262 args: BurnInstructionArgs,
263 ) -> Self {
264 Self {
265 __program: program,
266 mint: accounts.mint,
267 verification_config: accounts.verification_config,
268 instructions_sysvar: accounts.instructions_sysvar,
269 permanent_delegate: accounts.permanent_delegate,
270 mint_account: accounts.mint_account,
271 token_account: accounts.token_account,
272 token_program: accounts.token_program,
273 __args: args,
274 }
275 }
276 #[inline(always)]
277 pub fn invoke(&self) -> solana_program_error::ProgramResult {
278 self.invoke_signed_with_remaining_accounts(&[], &[])
279 }
280 #[inline(always)]
281 pub fn invoke_with_remaining_accounts(
282 &self,
283 remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)],
284 ) -> solana_program_error::ProgramResult {
285 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
286 }
287 #[inline(always)]
288 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult {
289 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
290 }
291 #[allow(clippy::arithmetic_side_effects)]
292 #[allow(clippy::clone_on_copy)]
293 #[allow(clippy::vec_init_then_push)]
294 pub fn invoke_signed_with_remaining_accounts(
295 &self,
296 signers_seeds: &[&[&[u8]]],
297 remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)],
298 ) -> solana_program_error::ProgramResult {
299 let mut accounts = Vec::with_capacity(7 + remaining_accounts.len());
300 accounts.push(solana_instruction::AccountMeta::new_readonly(
301 *self.mint.key,
302 false,
303 ));
304 accounts.push(solana_instruction::AccountMeta::new_readonly(
305 *self.verification_config.key,
306 false,
307 ));
308 accounts.push(solana_instruction::AccountMeta::new_readonly(
309 *self.instructions_sysvar.key,
310 false,
311 ));
312 accounts.push(solana_instruction::AccountMeta::new_readonly(
313 *self.permanent_delegate.key,
314 false,
315 ));
316 accounts.push(solana_instruction::AccountMeta::new(
317 *self.mint_account.key,
318 false,
319 ));
320 accounts.push(solana_instruction::AccountMeta::new(
321 *self.token_account.key,
322 false,
323 ));
324 accounts.push(solana_instruction::AccountMeta::new_readonly(
325 *self.token_program.key,
326 false,
327 ));
328 remaining_accounts.iter().for_each(|remaining_account| {
329 accounts.push(solana_instruction::AccountMeta {
330 pubkey: *remaining_account.0.key,
331 is_signer: remaining_account.1,
332 is_writable: remaining_account.2,
333 })
334 });
335 let mut data = borsh::to_vec(&BurnInstructionData::new()).unwrap();
336 let mut args = borsh::to_vec(&self.__args).unwrap();
337 data.append(&mut args);
338
339 let instruction = solana_instruction::Instruction {
340 program_id: crate::SECURITY_TOKEN_PROGRAM_ID,
341 accounts,
342 data,
343 };
344 let mut account_infos = Vec::with_capacity(8 + remaining_accounts.len());
345 account_infos.push(self.__program.clone());
346 account_infos.push(self.mint.clone());
347 account_infos.push(self.verification_config.clone());
348 account_infos.push(self.instructions_sysvar.clone());
349 account_infos.push(self.permanent_delegate.clone());
350 account_infos.push(self.mint_account.clone());
351 account_infos.push(self.token_account.clone());
352 account_infos.push(self.token_program.clone());
353 remaining_accounts
354 .iter()
355 .for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
356
357 if signers_seeds.is_empty() {
358 solana_cpi::invoke(&instruction, &account_infos)
359 } else {
360 solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds)
361 }
362 }
363}
364
365#[derive(Clone, Debug)]
377pub struct BurnCpiBuilder<'a, 'b> {
378 instruction: Box<BurnCpiBuilderInstruction<'a, 'b>>,
379}
380
381impl<'a, 'b> BurnCpiBuilder<'a, 'b> {
382 pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self {
383 let instruction = Box::new(BurnCpiBuilderInstruction {
384 __program: program,
385 mint: None,
386 verification_config: None,
387 instructions_sysvar: None,
388 permanent_delegate: None,
389 mint_account: None,
390 token_account: None,
391 token_program: None,
392 amount: None,
393 __remaining_accounts: Vec::new(),
394 });
395 Self { instruction }
396 }
397 #[inline(always)]
398 pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
399 self.instruction.mint = Some(mint);
400 self
401 }
402 #[inline(always)]
403 pub fn verification_config(
404 &mut self,
405 verification_config: &'b solana_account_info::AccountInfo<'a>,
406 ) -> &mut Self {
407 self.instruction.verification_config = Some(verification_config);
408 self
409 }
410 #[inline(always)]
411 pub fn instructions_sysvar(
412 &mut self,
413 instructions_sysvar: &'b solana_account_info::AccountInfo<'a>,
414 ) -> &mut Self {
415 self.instruction.instructions_sysvar = Some(instructions_sysvar);
416 self
417 }
418 #[inline(always)]
419 pub fn permanent_delegate(
420 &mut self,
421 permanent_delegate: &'b solana_account_info::AccountInfo<'a>,
422 ) -> &mut Self {
423 self.instruction.permanent_delegate = Some(permanent_delegate);
424 self
425 }
426 #[inline(always)]
427 pub fn mint_account(
428 &mut self,
429 mint_account: &'b solana_account_info::AccountInfo<'a>,
430 ) -> &mut Self {
431 self.instruction.mint_account = Some(mint_account);
432 self
433 }
434 #[inline(always)]
435 pub fn token_account(
436 &mut self,
437 token_account: &'b solana_account_info::AccountInfo<'a>,
438 ) -> &mut Self {
439 self.instruction.token_account = Some(token_account);
440 self
441 }
442 #[inline(always)]
443 pub fn token_program(
444 &mut self,
445 token_program: &'b solana_account_info::AccountInfo<'a>,
446 ) -> &mut Self {
447 self.instruction.token_program = Some(token_program);
448 self
449 }
450 #[inline(always)]
451 pub fn amount(&mut self, amount: u64) -> &mut Self {
452 self.instruction.amount = Some(amount);
453 self
454 }
455 #[inline(always)]
457 pub fn add_remaining_account(
458 &mut self,
459 account: &'b solana_account_info::AccountInfo<'a>,
460 is_writable: bool,
461 is_signer: bool,
462 ) -> &mut Self {
463 self.instruction
464 .__remaining_accounts
465 .push((account, is_writable, is_signer));
466 self
467 }
468 #[inline(always)]
473 pub fn add_remaining_accounts(
474 &mut self,
475 accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)],
476 ) -> &mut Self {
477 self.instruction
478 .__remaining_accounts
479 .extend_from_slice(accounts);
480 self
481 }
482 #[inline(always)]
483 pub fn invoke(&self) -> solana_program_error::ProgramResult {
484 self.invoke_signed(&[])
485 }
486 #[allow(clippy::clone_on_copy)]
487 #[allow(clippy::vec_init_then_push)]
488 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult {
489 let args = BurnInstructionArgs {
490 amount: self.instruction.amount.clone().expect("amount is not set"),
491 };
492 let instruction = BurnCpi {
493 __program: self.instruction.__program,
494
495 mint: self.instruction.mint.expect("mint is not set"),
496
497 verification_config: self
498 .instruction
499 .verification_config
500 .expect("verification_config is not set"),
501
502 instructions_sysvar: self
503 .instruction
504 .instructions_sysvar
505 .expect("instructions_sysvar is not set"),
506
507 permanent_delegate: self
508 .instruction
509 .permanent_delegate
510 .expect("permanent_delegate is not set"),
511
512 mint_account: self
513 .instruction
514 .mint_account
515 .expect("mint_account is not set"),
516
517 token_account: self
518 .instruction
519 .token_account
520 .expect("token_account is not set"),
521
522 token_program: self
523 .instruction
524 .token_program
525 .expect("token_program is not set"),
526 __args: args,
527 };
528 instruction.invoke_signed_with_remaining_accounts(
529 signers_seeds,
530 &self.instruction.__remaining_accounts,
531 )
532 }
533}
534
535#[derive(Clone, Debug)]
536struct BurnCpiBuilderInstruction<'a, 'b> {
537 __program: &'b solana_account_info::AccountInfo<'a>,
538 mint: Option<&'b solana_account_info::AccountInfo<'a>>,
539 verification_config: Option<&'b solana_account_info::AccountInfo<'a>>,
540 instructions_sysvar: Option<&'b solana_account_info::AccountInfo<'a>>,
541 permanent_delegate: Option<&'b solana_account_info::AccountInfo<'a>>,
542 mint_account: Option<&'b solana_account_info::AccountInfo<'a>>,
543 token_account: Option<&'b solana_account_info::AccountInfo<'a>>,
544 token_program: Option<&'b solana_account_info::AccountInfo<'a>>,
545 amount: Option<u64>,
546 __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>,
548}