1use borsh::BorshDeserialize;
9use borsh::BorshSerialize;
10
11pub const MINT_DISCRIMINATOR: u8 = 6;
12
13#[derive(Debug)]
15pub struct Mint {
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 mint_authority: solana_pubkey::Pubkey,
23
24 pub mint_account: solana_pubkey::Pubkey,
25
26 pub destination: solana_pubkey::Pubkey,
27
28 pub token_program: solana_pubkey::Pubkey,
29}
30
31impl Mint {
32 pub fn instruction(&self, args: MintInstructionArgs) -> 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: MintInstructionArgs,
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.mint_authority,
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.destination,
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(&MintInstructionData::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 MintInstructionData {
86 discriminator: u8,
87}
88
89impl MintInstructionData {
90 pub fn new() -> Self {
91 Self { discriminator: 6 }
92 }
93}
94
95impl Default for MintInstructionData {
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 MintInstructionArgs {
104 pub amount: u64,
105}
106
107#[derive(Clone, Debug, Default)]
119pub struct MintBuilder {
120 mint: Option<solana_pubkey::Pubkey>,
121 verification_config: Option<solana_pubkey::Pubkey>,
122 instructions_sysvar: Option<solana_pubkey::Pubkey>,
123 mint_authority: Option<solana_pubkey::Pubkey>,
124 mint_account: Option<solana_pubkey::Pubkey>,
125 destination: 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 MintBuilder {
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 mint_authority(&mut self, mint_authority: solana_pubkey::Pubkey) -> &mut Self {
153 self.mint_authority = Some(mint_authority);
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 destination(&mut self, destination: solana_pubkey::Pubkey) -> &mut Self {
163 self.destination = Some(destination);
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 = Mint {
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 mint_authority: self.mint_authority.expect("mint_authority is not set"),
203 mint_account: self.mint_account.expect("mint_account is not set"),
204 destination: self.destination.expect("destination is not set"),
205 token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!(
206 "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
207 )),
208 };
209 let args = MintInstructionArgs {
210 amount: self.amount.clone().expect("amount is not set"),
211 };
212
213 accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts)
214 }
215}
216
217pub struct MintCpiAccounts<'a, 'b> {
219 pub mint: &'b solana_account_info::AccountInfo<'a>,
220
221 pub verification_config: &'b solana_account_info::AccountInfo<'a>,
222
223 pub instructions_sysvar: &'b solana_account_info::AccountInfo<'a>,
224
225 pub mint_authority: &'b solana_account_info::AccountInfo<'a>,
226
227 pub mint_account: &'b solana_account_info::AccountInfo<'a>,
228
229 pub destination: &'b solana_account_info::AccountInfo<'a>,
230
231 pub token_program: &'b solana_account_info::AccountInfo<'a>,
232}
233
234pub struct MintCpi<'a, 'b> {
236 pub __program: &'b solana_account_info::AccountInfo<'a>,
238
239 pub mint: &'b solana_account_info::AccountInfo<'a>,
240
241 pub verification_config: &'b solana_account_info::AccountInfo<'a>,
242
243 pub instructions_sysvar: &'b solana_account_info::AccountInfo<'a>,
244
245 pub mint_authority: &'b solana_account_info::AccountInfo<'a>,
246
247 pub mint_account: &'b solana_account_info::AccountInfo<'a>,
248
249 pub destination: &'b solana_account_info::AccountInfo<'a>,
250
251 pub token_program: &'b solana_account_info::AccountInfo<'a>,
252 pub __args: MintInstructionArgs,
254}
255
256impl<'a, 'b> MintCpi<'a, 'b> {
257 pub fn new(
258 program: &'b solana_account_info::AccountInfo<'a>,
259 accounts: MintCpiAccounts<'a, 'b>,
260 args: MintInstructionArgs,
261 ) -> Self {
262 Self {
263 __program: program,
264 mint: accounts.mint,
265 verification_config: accounts.verification_config,
266 instructions_sysvar: accounts.instructions_sysvar,
267 mint_authority: accounts.mint_authority,
268 mint_account: accounts.mint_account,
269 destination: accounts.destination,
270 token_program: accounts.token_program,
271 __args: args,
272 }
273 }
274 #[inline(always)]
275 pub fn invoke(&self) -> solana_program_error::ProgramResult {
276 self.invoke_signed_with_remaining_accounts(&[], &[])
277 }
278 #[inline(always)]
279 pub fn invoke_with_remaining_accounts(
280 &self,
281 remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)],
282 ) -> solana_program_error::ProgramResult {
283 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
284 }
285 #[inline(always)]
286 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult {
287 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
288 }
289 #[allow(clippy::arithmetic_side_effects)]
290 #[allow(clippy::clone_on_copy)]
291 #[allow(clippy::vec_init_then_push)]
292 pub fn invoke_signed_with_remaining_accounts(
293 &self,
294 signers_seeds: &[&[&[u8]]],
295 remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)],
296 ) -> solana_program_error::ProgramResult {
297 let mut accounts = Vec::with_capacity(7 + remaining_accounts.len());
298 accounts.push(solana_instruction::AccountMeta::new_readonly(
299 *self.mint.key,
300 false,
301 ));
302 accounts.push(solana_instruction::AccountMeta::new_readonly(
303 *self.verification_config.key,
304 false,
305 ));
306 accounts.push(solana_instruction::AccountMeta::new_readonly(
307 *self.instructions_sysvar.key,
308 false,
309 ));
310 accounts.push(solana_instruction::AccountMeta::new_readonly(
311 *self.mint_authority.key,
312 false,
313 ));
314 accounts.push(solana_instruction::AccountMeta::new(
315 *self.mint_account.key,
316 false,
317 ));
318 accounts.push(solana_instruction::AccountMeta::new(
319 *self.destination.key,
320 false,
321 ));
322 accounts.push(solana_instruction::AccountMeta::new_readonly(
323 *self.token_program.key,
324 false,
325 ));
326 remaining_accounts.iter().for_each(|remaining_account| {
327 accounts.push(solana_instruction::AccountMeta {
328 pubkey: *remaining_account.0.key,
329 is_signer: remaining_account.1,
330 is_writable: remaining_account.2,
331 })
332 });
333 let mut data = borsh::to_vec(&MintInstructionData::new()).unwrap();
334 let mut args = borsh::to_vec(&self.__args).unwrap();
335 data.append(&mut args);
336
337 let instruction = solana_instruction::Instruction {
338 program_id: crate::SECURITY_TOKEN_PROGRAM_ID,
339 accounts,
340 data,
341 };
342 let mut account_infos = Vec::with_capacity(8 + remaining_accounts.len());
343 account_infos.push(self.__program.clone());
344 account_infos.push(self.mint.clone());
345 account_infos.push(self.verification_config.clone());
346 account_infos.push(self.instructions_sysvar.clone());
347 account_infos.push(self.mint_authority.clone());
348 account_infos.push(self.mint_account.clone());
349 account_infos.push(self.destination.clone());
350 account_infos.push(self.token_program.clone());
351 remaining_accounts
352 .iter()
353 .for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
354
355 if signers_seeds.is_empty() {
356 solana_cpi::invoke(&instruction, &account_infos)
357 } else {
358 solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds)
359 }
360 }
361}
362
363#[derive(Clone, Debug)]
375pub struct MintCpiBuilder<'a, 'b> {
376 instruction: Box<MintCpiBuilderInstruction<'a, 'b>>,
377}
378
379impl<'a, 'b> MintCpiBuilder<'a, 'b> {
380 pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self {
381 let instruction = Box::new(MintCpiBuilderInstruction {
382 __program: program,
383 mint: None,
384 verification_config: None,
385 instructions_sysvar: None,
386 mint_authority: None,
387 mint_account: None,
388 destination: None,
389 token_program: None,
390 amount: None,
391 __remaining_accounts: Vec::new(),
392 });
393 Self { instruction }
394 }
395 #[inline(always)]
396 pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
397 self.instruction.mint = Some(mint);
398 self
399 }
400 #[inline(always)]
401 pub fn verification_config(
402 &mut self,
403 verification_config: &'b solana_account_info::AccountInfo<'a>,
404 ) -> &mut Self {
405 self.instruction.verification_config = Some(verification_config);
406 self
407 }
408 #[inline(always)]
409 pub fn instructions_sysvar(
410 &mut self,
411 instructions_sysvar: &'b solana_account_info::AccountInfo<'a>,
412 ) -> &mut Self {
413 self.instruction.instructions_sysvar = Some(instructions_sysvar);
414 self
415 }
416 #[inline(always)]
417 pub fn mint_authority(
418 &mut self,
419 mint_authority: &'b solana_account_info::AccountInfo<'a>,
420 ) -> &mut Self {
421 self.instruction.mint_authority = Some(mint_authority);
422 self
423 }
424 #[inline(always)]
425 pub fn mint_account(
426 &mut self,
427 mint_account: &'b solana_account_info::AccountInfo<'a>,
428 ) -> &mut Self {
429 self.instruction.mint_account = Some(mint_account);
430 self
431 }
432 #[inline(always)]
433 pub fn destination(
434 &mut self,
435 destination: &'b solana_account_info::AccountInfo<'a>,
436 ) -> &mut Self {
437 self.instruction.destination = Some(destination);
438 self
439 }
440 #[inline(always)]
441 pub fn token_program(
442 &mut self,
443 token_program: &'b solana_account_info::AccountInfo<'a>,
444 ) -> &mut Self {
445 self.instruction.token_program = Some(token_program);
446 self
447 }
448 #[inline(always)]
449 pub fn amount(&mut self, amount: u64) -> &mut Self {
450 self.instruction.amount = Some(amount);
451 self
452 }
453 #[inline(always)]
455 pub fn add_remaining_account(
456 &mut self,
457 account: &'b solana_account_info::AccountInfo<'a>,
458 is_writable: bool,
459 is_signer: bool,
460 ) -> &mut Self {
461 self.instruction
462 .__remaining_accounts
463 .push((account, is_writable, is_signer));
464 self
465 }
466 #[inline(always)]
471 pub fn add_remaining_accounts(
472 &mut self,
473 accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)],
474 ) -> &mut Self {
475 self.instruction
476 .__remaining_accounts
477 .extend_from_slice(accounts);
478 self
479 }
480 #[inline(always)]
481 pub fn invoke(&self) -> solana_program_error::ProgramResult {
482 self.invoke_signed(&[])
483 }
484 #[allow(clippy::clone_on_copy)]
485 #[allow(clippy::vec_init_then_push)]
486 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult {
487 let args = MintInstructionArgs {
488 amount: self.instruction.amount.clone().expect("amount is not set"),
489 };
490 let instruction = MintCpi {
491 __program: self.instruction.__program,
492
493 mint: self.instruction.mint.expect("mint is not set"),
494
495 verification_config: self
496 .instruction
497 .verification_config
498 .expect("verification_config is not set"),
499
500 instructions_sysvar: self
501 .instruction
502 .instructions_sysvar
503 .expect("instructions_sysvar is not set"),
504
505 mint_authority: self
506 .instruction
507 .mint_authority
508 .expect("mint_authority is not set"),
509
510 mint_account: self
511 .instruction
512 .mint_account
513 .expect("mint_account is not set"),
514
515 destination: self
516 .instruction
517 .destination
518 .expect("destination is not set"),
519
520 token_program: self
521 .instruction
522 .token_program
523 .expect("token_program is not set"),
524 __args: args,
525 };
526 instruction.invoke_signed_with_remaining_accounts(
527 signers_seeds,
528 &self.instruction.__remaining_accounts,
529 )
530 }
531}
532
533#[derive(Clone, Debug)]
534struct MintCpiBuilderInstruction<'a, 'b> {
535 __program: &'b solana_account_info::AccountInfo<'a>,
536 mint: Option<&'b solana_account_info::AccountInfo<'a>>,
537 verification_config: Option<&'b solana_account_info::AccountInfo<'a>>,
538 instructions_sysvar: Option<&'b solana_account_info::AccountInfo<'a>>,
539 mint_authority: Option<&'b solana_account_info::AccountInfo<'a>>,
540 mint_account: Option<&'b solana_account_info::AccountInfo<'a>>,
541 destination: Option<&'b solana_account_info::AccountInfo<'a>>,
542 token_program: Option<&'b solana_account_info::AccountInfo<'a>>,
543 amount: Option<u64>,
544 __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>,
546}