1use crate::generated::types::CreateArgs;
9use borsh::BorshDeserialize;
10use borsh::BorshSerialize;
11
12pub struct Create {
14 pub metadata: solana_program::pubkey::Pubkey,
16 pub master_edition: Option<solana_program::pubkey::Pubkey>,
18 pub mint: (solana_program::pubkey::Pubkey, bool),
20 pub authority: solana_program::pubkey::Pubkey,
22 pub payer: solana_program::pubkey::Pubkey,
24 pub update_authority: (solana_program::pubkey::Pubkey, bool),
26 pub system_program: solana_program::pubkey::Pubkey,
28 pub sysvar_instructions: solana_program::pubkey::Pubkey,
30 pub spl_token_program: Option<solana_program::pubkey::Pubkey>,
32}
33
34impl Create {
35 pub fn instruction(
36 &self,
37 args: CreateInstructionArgs,
38 ) -> solana_program::instruction::Instruction {
39 self.instruction_with_remaining_accounts(args, &[])
40 }
41 #[allow(clippy::vec_init_then_push)]
42 pub fn instruction_with_remaining_accounts(
43 &self,
44 args: CreateInstructionArgs,
45 remaining_accounts: &[solana_program::instruction::AccountMeta],
46 ) -> solana_program::instruction::Instruction {
47 let mut accounts = Vec::with_capacity(9 + remaining_accounts.len());
48 accounts.push(solana_program::instruction::AccountMeta::new(
49 self.metadata,
50 false,
51 ));
52 if let Some(master_edition) = self.master_edition {
53 accounts.push(solana_program::instruction::AccountMeta::new(
54 master_edition,
55 false,
56 ));
57 } else {
58 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
59 crate::MPL_TOKEN_METADATA_ID,
60 false,
61 ));
62 }
63 accounts.push(solana_program::instruction::AccountMeta::new(
64 self.mint.0,
65 self.mint.1,
66 ));
67 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
68 self.authority,
69 true,
70 ));
71 accounts.push(solana_program::instruction::AccountMeta::new(
72 self.payer, true,
73 ));
74 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
75 self.update_authority.0,
76 self.update_authority.1,
77 ));
78 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
79 self.system_program,
80 false,
81 ));
82 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
83 self.sysvar_instructions,
84 false,
85 ));
86 if let Some(spl_token_program) = self.spl_token_program {
87 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
88 spl_token_program,
89 false,
90 ));
91 } else {
92 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
93 crate::MPL_TOKEN_METADATA_ID,
94 false,
95 ));
96 }
97 accounts.extend_from_slice(remaining_accounts);
98 let mut data = CreateInstructionData::new().try_to_vec().unwrap();
99 let mut args = args.try_to_vec().unwrap();
100 data.append(&mut args);
101
102 solana_program::instruction::Instruction {
103 program_id: crate::MPL_TOKEN_METADATA_ID,
104 accounts,
105 data,
106 }
107 }
108}
109
110#[derive(BorshDeserialize, BorshSerialize)]
111struct CreateInstructionData {
112 discriminator: u8,
113}
114
115impl CreateInstructionData {
116 fn new() -> Self {
117 Self { discriminator: 42 }
118 }
119}
120
121#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123pub struct CreateInstructionArgs {
124 pub create_args: CreateArgs,
125}
126
127#[derive(Default)]
141pub struct CreateBuilder {
142 metadata: Option<solana_program::pubkey::Pubkey>,
143 master_edition: Option<solana_program::pubkey::Pubkey>,
144 mint: Option<(solana_program::pubkey::Pubkey, bool)>,
145 authority: Option<solana_program::pubkey::Pubkey>,
146 payer: Option<solana_program::pubkey::Pubkey>,
147 update_authority: Option<(solana_program::pubkey::Pubkey, bool)>,
148 system_program: Option<solana_program::pubkey::Pubkey>,
149 sysvar_instructions: Option<solana_program::pubkey::Pubkey>,
150 spl_token_program: Option<solana_program::pubkey::Pubkey>,
151 create_args: Option<CreateArgs>,
152 __remaining_accounts: Vec<solana_program::instruction::AccountMeta>,
153}
154
155impl CreateBuilder {
156 pub fn new() -> Self {
157 Self::default()
158 }
159 #[inline(always)]
161 pub fn metadata(&mut self, metadata: solana_program::pubkey::Pubkey) -> &mut Self {
162 self.metadata = Some(metadata);
163 self
164 }
165 #[inline(always)]
168 pub fn master_edition(
169 &mut self,
170 master_edition: Option<solana_program::pubkey::Pubkey>,
171 ) -> &mut Self {
172 self.master_edition = master_edition;
173 self
174 }
175 #[inline(always)]
177 pub fn mint(&mut self, mint: solana_program::pubkey::Pubkey, as_signer: bool) -> &mut Self {
178 self.mint = Some((mint, as_signer));
179 self
180 }
181 #[inline(always)]
183 pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self {
184 self.authority = Some(authority);
185 self
186 }
187 #[inline(always)]
189 pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self {
190 self.payer = Some(payer);
191 self
192 }
193 #[inline(always)]
195 pub fn update_authority(
196 &mut self,
197 update_authority: solana_program::pubkey::Pubkey,
198 as_signer: bool,
199 ) -> &mut Self {
200 self.update_authority = Some((update_authority, as_signer));
201 self
202 }
203 #[inline(always)]
206 pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self {
207 self.system_program = Some(system_program);
208 self
209 }
210 #[inline(always)]
213 pub fn sysvar_instructions(
214 &mut self,
215 sysvar_instructions: solana_program::pubkey::Pubkey,
216 ) -> &mut Self {
217 self.sysvar_instructions = Some(sysvar_instructions);
218 self
219 }
220 #[inline(always)]
223 pub fn spl_token_program(
224 &mut self,
225 spl_token_program: Option<solana_program::pubkey::Pubkey>,
226 ) -> &mut Self {
227 self.spl_token_program = spl_token_program;
228 self
229 }
230 #[inline(always)]
231 pub fn create_args(&mut self, create_args: CreateArgs) -> &mut Self {
232 self.create_args = Some(create_args);
233 self
234 }
235 #[inline(always)]
237 pub fn add_remaining_account(
238 &mut self,
239 account: solana_program::instruction::AccountMeta,
240 ) -> &mut Self {
241 self.__remaining_accounts.push(account);
242 self
243 }
244 #[inline(always)]
246 pub fn add_remaining_accounts(
247 &mut self,
248 accounts: &[solana_program::instruction::AccountMeta],
249 ) -> &mut Self {
250 self.__remaining_accounts.extend_from_slice(accounts);
251 self
252 }
253 #[allow(clippy::clone_on_copy)]
254 pub fn instruction(&self) -> solana_program::instruction::Instruction {
255 let accounts = Create {
256 metadata: self.metadata.expect("metadata is not set"),
257 master_edition: self.master_edition,
258 mint: self.mint.expect("mint is not set"),
259 authority: self.authority.expect("authority is not set"),
260 payer: self.payer.expect("payer is not set"),
261 update_authority: self.update_authority.expect("update_authority is not set"),
262 system_program: self
263 .system_program
264 .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")),
265 sysvar_instructions: self.sysvar_instructions.unwrap_or(solana_program::pubkey!(
266 "Sysvar1nstructions1111111111111111111111111"
267 )),
268 spl_token_program: self.spl_token_program,
269 };
270 let args = CreateInstructionArgs {
271 create_args: self.create_args.clone().expect("create_args is not set"),
272 };
273
274 accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts)
275 }
276}
277
278pub struct CreateCpiAccounts<'a, 'b> {
280 pub metadata: &'b solana_program::account_info::AccountInfo<'a>,
282 pub master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
284 pub mint: (&'b solana_program::account_info::AccountInfo<'a>, bool),
286 pub authority: &'b solana_program::account_info::AccountInfo<'a>,
288 pub payer: &'b solana_program::account_info::AccountInfo<'a>,
290 pub update_authority: (&'b solana_program::account_info::AccountInfo<'a>, bool),
292 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
294 pub sysvar_instructions: &'b solana_program::account_info::AccountInfo<'a>,
296 pub spl_token_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
298}
299
300pub struct CreateCpi<'a, 'b> {
302 pub __program: &'b solana_program::account_info::AccountInfo<'a>,
304 pub metadata: &'b solana_program::account_info::AccountInfo<'a>,
306 pub master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
308 pub mint: (&'b solana_program::account_info::AccountInfo<'a>, bool),
310 pub authority: &'b solana_program::account_info::AccountInfo<'a>,
312 pub payer: &'b solana_program::account_info::AccountInfo<'a>,
314 pub update_authority: (&'b solana_program::account_info::AccountInfo<'a>, bool),
316 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
318 pub sysvar_instructions: &'b solana_program::account_info::AccountInfo<'a>,
320 pub spl_token_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
322 pub __args: CreateInstructionArgs,
324}
325
326impl<'a, 'b> CreateCpi<'a, 'b> {
327 pub fn new(
328 program: &'b solana_program::account_info::AccountInfo<'a>,
329 accounts: CreateCpiAccounts<'a, 'b>,
330 args: CreateInstructionArgs,
331 ) -> Self {
332 Self {
333 __program: program,
334 metadata: accounts.metadata,
335 master_edition: accounts.master_edition,
336 mint: accounts.mint,
337 authority: accounts.authority,
338 payer: accounts.payer,
339 update_authority: accounts.update_authority,
340 system_program: accounts.system_program,
341 sysvar_instructions: accounts.sysvar_instructions,
342 spl_token_program: accounts.spl_token_program,
343 __args: args,
344 }
345 }
346 #[inline(always)]
347 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
348 self.invoke_signed_with_remaining_accounts(&[], &[])
349 }
350 #[inline(always)]
351 pub fn invoke_with_remaining_accounts(
352 &self,
353 remaining_accounts: &[(
354 &'b solana_program::account_info::AccountInfo<'a>,
355 bool,
356 bool,
357 )],
358 ) -> solana_program::entrypoint::ProgramResult {
359 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
360 }
361 #[inline(always)]
362 pub fn invoke_signed(
363 &self,
364 signers_seeds: &[&[&[u8]]],
365 ) -> solana_program::entrypoint::ProgramResult {
366 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
367 }
368 #[allow(clippy::clone_on_copy)]
369 #[allow(clippy::vec_init_then_push)]
370 pub fn invoke_signed_with_remaining_accounts(
371 &self,
372 signers_seeds: &[&[&[u8]]],
373 remaining_accounts: &[(
374 &'b solana_program::account_info::AccountInfo<'a>,
375 bool,
376 bool,
377 )],
378 ) -> solana_program::entrypoint::ProgramResult {
379 let mut accounts = Vec::with_capacity(9 + remaining_accounts.len());
380 accounts.push(solana_program::instruction::AccountMeta::new(
381 *self.metadata.key,
382 false,
383 ));
384 if let Some(master_edition) = self.master_edition {
385 accounts.push(solana_program::instruction::AccountMeta::new(
386 *master_edition.key,
387 false,
388 ));
389 } else {
390 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
391 crate::MPL_TOKEN_METADATA_ID,
392 false,
393 ));
394 }
395 accounts.push(solana_program::instruction::AccountMeta::new(
396 *self.mint.0.key,
397 self.mint.1,
398 ));
399 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
400 *self.authority.key,
401 true,
402 ));
403 accounts.push(solana_program::instruction::AccountMeta::new(
404 *self.payer.key,
405 true,
406 ));
407 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
408 *self.update_authority.0.key,
409 self.update_authority.1,
410 ));
411 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
412 *self.system_program.key,
413 false,
414 ));
415 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
416 *self.sysvar_instructions.key,
417 false,
418 ));
419 if let Some(spl_token_program) = self.spl_token_program {
420 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
421 *spl_token_program.key,
422 false,
423 ));
424 } else {
425 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
426 crate::MPL_TOKEN_METADATA_ID,
427 false,
428 ));
429 }
430 remaining_accounts.iter().for_each(|remaining_account| {
431 accounts.push(solana_program::instruction::AccountMeta {
432 pubkey: *remaining_account.0.key,
433 is_signer: remaining_account.1,
434 is_writable: remaining_account.2,
435 })
436 });
437 let mut data = CreateInstructionData::new().try_to_vec().unwrap();
438 let mut args = self.__args.try_to_vec().unwrap();
439 data.append(&mut args);
440
441 let instruction = solana_program::instruction::Instruction {
442 program_id: crate::MPL_TOKEN_METADATA_ID,
443 accounts,
444 data,
445 };
446 let mut account_infos = Vec::with_capacity(9 + 1 + remaining_accounts.len());
447 account_infos.push(self.__program.clone());
448 account_infos.push(self.metadata.clone());
449 if let Some(master_edition) = self.master_edition {
450 account_infos.push(master_edition.clone());
451 }
452 account_infos.push(self.mint.0.clone());
453 account_infos.push(self.authority.clone());
454 account_infos.push(self.payer.clone());
455 account_infos.push(self.update_authority.0.clone());
456 account_infos.push(self.system_program.clone());
457 account_infos.push(self.sysvar_instructions.clone());
458 if let Some(spl_token_program) = self.spl_token_program {
459 account_infos.push(spl_token_program.clone());
460 }
461 remaining_accounts
462 .iter()
463 .for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
464
465 if signers_seeds.is_empty() {
466 solana_program::program::invoke(&instruction, &account_infos)
467 } else {
468 solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds)
469 }
470 }
471}
472
473pub struct CreateCpiBuilder<'a, 'b> {
487 instruction: Box<CreateCpiBuilderInstruction<'a, 'b>>,
488}
489
490impl<'a, 'b> CreateCpiBuilder<'a, 'b> {
491 pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self {
492 let instruction = Box::new(CreateCpiBuilderInstruction {
493 __program: program,
494 metadata: None,
495 master_edition: None,
496 mint: None,
497 authority: None,
498 payer: None,
499 update_authority: None,
500 system_program: None,
501 sysvar_instructions: None,
502 spl_token_program: None,
503 create_args: None,
504 __remaining_accounts: Vec::new(),
505 });
506 Self { instruction }
507 }
508 #[inline(always)]
510 pub fn metadata(
511 &mut self,
512 metadata: &'b solana_program::account_info::AccountInfo<'a>,
513 ) -> &mut Self {
514 self.instruction.metadata = Some(metadata);
515 self
516 }
517 #[inline(always)]
520 pub fn master_edition(
521 &mut self,
522 master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
523 ) -> &mut Self {
524 self.instruction.master_edition = master_edition;
525 self
526 }
527 #[inline(always)]
529 pub fn mint(
530 &mut self,
531 mint: &'b solana_program::account_info::AccountInfo<'a>,
532 as_signer: bool,
533 ) -> &mut Self {
534 self.instruction.mint = Some((mint, as_signer));
535 self
536 }
537 #[inline(always)]
539 pub fn authority(
540 &mut self,
541 authority: &'b solana_program::account_info::AccountInfo<'a>,
542 ) -> &mut Self {
543 self.instruction.authority = Some(authority);
544 self
545 }
546 #[inline(always)]
548 pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self {
549 self.instruction.payer = Some(payer);
550 self
551 }
552 #[inline(always)]
554 pub fn update_authority(
555 &mut self,
556 update_authority: &'b solana_program::account_info::AccountInfo<'a>,
557 as_signer: bool,
558 ) -> &mut Self {
559 self.instruction.update_authority = Some((update_authority, as_signer));
560 self
561 }
562 #[inline(always)]
564 pub fn system_program(
565 &mut self,
566 system_program: &'b solana_program::account_info::AccountInfo<'a>,
567 ) -> &mut Self {
568 self.instruction.system_program = Some(system_program);
569 self
570 }
571 #[inline(always)]
573 pub fn sysvar_instructions(
574 &mut self,
575 sysvar_instructions: &'b solana_program::account_info::AccountInfo<'a>,
576 ) -> &mut Self {
577 self.instruction.sysvar_instructions = Some(sysvar_instructions);
578 self
579 }
580 #[inline(always)]
583 pub fn spl_token_program(
584 &mut self,
585 spl_token_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
586 ) -> &mut Self {
587 self.instruction.spl_token_program = spl_token_program;
588 self
589 }
590 #[inline(always)]
591 pub fn create_args(&mut self, create_args: CreateArgs) -> &mut Self {
592 self.instruction.create_args = Some(create_args);
593 self
594 }
595 #[inline(always)]
597 pub fn add_remaining_account(
598 &mut self,
599 account: &'b solana_program::account_info::AccountInfo<'a>,
600 is_writable: bool,
601 is_signer: bool,
602 ) -> &mut Self {
603 self.instruction
604 .__remaining_accounts
605 .push((account, is_writable, is_signer));
606 self
607 }
608 #[inline(always)]
613 pub fn add_remaining_accounts(
614 &mut self,
615 accounts: &[(
616 &'b solana_program::account_info::AccountInfo<'a>,
617 bool,
618 bool,
619 )],
620 ) -> &mut Self {
621 self.instruction
622 .__remaining_accounts
623 .extend_from_slice(accounts);
624 self
625 }
626 #[inline(always)]
627 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
628 self.invoke_signed(&[])
629 }
630 #[allow(clippy::clone_on_copy)]
631 #[allow(clippy::vec_init_then_push)]
632 pub fn invoke_signed(
633 &self,
634 signers_seeds: &[&[&[u8]]],
635 ) -> solana_program::entrypoint::ProgramResult {
636 let args = CreateInstructionArgs {
637 create_args: self
638 .instruction
639 .create_args
640 .clone()
641 .expect("create_args is not set"),
642 };
643 let instruction = CreateCpi {
644 __program: self.instruction.__program,
645
646 metadata: self.instruction.metadata.expect("metadata is not set"),
647
648 master_edition: self.instruction.master_edition,
649
650 mint: self.instruction.mint.expect("mint is not set"),
651
652 authority: self.instruction.authority.expect("authority is not set"),
653
654 payer: self.instruction.payer.expect("payer is not set"),
655
656 update_authority: self
657 .instruction
658 .update_authority
659 .expect("update_authority is not set"),
660
661 system_program: self
662 .instruction
663 .system_program
664 .expect("system_program is not set"),
665
666 sysvar_instructions: self
667 .instruction
668 .sysvar_instructions
669 .expect("sysvar_instructions is not set"),
670
671 spl_token_program: self.instruction.spl_token_program,
672 __args: args,
673 };
674 instruction.invoke_signed_with_remaining_accounts(
675 signers_seeds,
676 &self.instruction.__remaining_accounts,
677 )
678 }
679}
680
681struct CreateCpiBuilderInstruction<'a, 'b> {
682 __program: &'b solana_program::account_info::AccountInfo<'a>,
683 metadata: Option<&'b solana_program::account_info::AccountInfo<'a>>,
684 master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
685 mint: Option<(&'b solana_program::account_info::AccountInfo<'a>, bool)>,
686 authority: Option<&'b solana_program::account_info::AccountInfo<'a>>,
687 payer: Option<&'b solana_program::account_info::AccountInfo<'a>>,
688 update_authority: Option<(&'b solana_program::account_info::AccountInfo<'a>, bool)>,
689 system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
690 sysvar_instructions: Option<&'b solana_program::account_info::AccountInfo<'a>>,
691 spl_token_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
692 create_args: Option<CreateArgs>,
693 __remaining_accounts: Vec<(
695 &'b solana_program::account_info::AccountInfo<'a>,
696 bool,
697 bool,
698 )>,
699}