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