1use crate::generated::types::VerificationArgs;
9use borsh::BorshDeserialize;
10use borsh::BorshSerialize;
11
12pub struct Verify {
14 pub authority: solana_program::pubkey::Pubkey,
16 pub delegate_record: Option<solana_program::pubkey::Pubkey>,
18 pub metadata: solana_program::pubkey::Pubkey,
20 pub collection_mint: Option<solana_program::pubkey::Pubkey>,
22 pub collection_metadata: Option<solana_program::pubkey::Pubkey>,
24 pub collection_master_edition: Option<solana_program::pubkey::Pubkey>,
26 pub system_program: solana_program::pubkey::Pubkey,
28 pub sysvar_instructions: solana_program::pubkey::Pubkey,
30}
31
32impl Verify {
33 pub fn instruction(
34 &self,
35 args: VerifyInstructionArgs,
36 ) -> solana_program::instruction::Instruction {
37 self.instruction_with_remaining_accounts(args, &[])
38 }
39 #[allow(clippy::vec_init_then_push)]
40 pub fn instruction_with_remaining_accounts(
41 &self,
42 args: VerifyInstructionArgs,
43 remaining_accounts: &[solana_program::instruction::AccountMeta],
44 ) -> solana_program::instruction::Instruction {
45 let mut accounts = Vec::with_capacity(8 + remaining_accounts.len());
46 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
47 self.authority,
48 true,
49 ));
50 if let Some(delegate_record) = self.delegate_record {
51 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
52 delegate_record,
53 false,
54 ));
55 } else {
56 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
57 crate::MPL_TOKEN_METADATA_ID,
58 false,
59 ));
60 }
61 accounts.push(solana_program::instruction::AccountMeta::new(
62 self.metadata,
63 false,
64 ));
65 if let Some(collection_mint) = self.collection_mint {
66 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
67 collection_mint,
68 false,
69 ));
70 } else {
71 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
72 crate::MPL_TOKEN_METADATA_ID,
73 false,
74 ));
75 }
76 if let Some(collection_metadata) = self.collection_metadata {
77 accounts.push(solana_program::instruction::AccountMeta::new(
78 collection_metadata,
79 false,
80 ));
81 } else {
82 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
83 crate::MPL_TOKEN_METADATA_ID,
84 false,
85 ));
86 }
87 if let Some(collection_master_edition) = self.collection_master_edition {
88 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
89 collection_master_edition,
90 false,
91 ));
92 } else {
93 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
94 crate::MPL_TOKEN_METADATA_ID,
95 false,
96 ));
97 }
98 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
99 self.system_program,
100 false,
101 ));
102 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
103 self.sysvar_instructions,
104 false,
105 ));
106 accounts.extend_from_slice(remaining_accounts);
107 let mut data = VerifyInstructionData::new().try_to_vec().unwrap();
108 let mut args = args.try_to_vec().unwrap();
109 data.append(&mut args);
110
111 solana_program::instruction::Instruction {
112 program_id: crate::MPL_TOKEN_METADATA_ID,
113 accounts,
114 data,
115 }
116 }
117}
118
119#[derive(BorshDeserialize, BorshSerialize)]
120struct VerifyInstructionData {
121 discriminator: u8,
122}
123
124impl VerifyInstructionData {
125 fn new() -> Self {
126 Self { discriminator: 52 }
127 }
128}
129
130#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132pub struct VerifyInstructionArgs {
133 pub verification_args: VerificationArgs,
134}
135
136#[derive(Default)]
149pub struct VerifyBuilder {
150 authority: Option<solana_program::pubkey::Pubkey>,
151 delegate_record: Option<solana_program::pubkey::Pubkey>,
152 metadata: Option<solana_program::pubkey::Pubkey>,
153 collection_mint: Option<solana_program::pubkey::Pubkey>,
154 collection_metadata: Option<solana_program::pubkey::Pubkey>,
155 collection_master_edition: Option<solana_program::pubkey::Pubkey>,
156 system_program: Option<solana_program::pubkey::Pubkey>,
157 sysvar_instructions: Option<solana_program::pubkey::Pubkey>,
158 verification_args: Option<VerificationArgs>,
159 __remaining_accounts: Vec<solana_program::instruction::AccountMeta>,
160}
161
162impl VerifyBuilder {
163 pub fn new() -> Self {
164 Self::default()
165 }
166 #[inline(always)]
168 pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self {
169 self.authority = Some(authority);
170 self
171 }
172 #[inline(always)]
175 pub fn delegate_record(
176 &mut self,
177 delegate_record: Option<solana_program::pubkey::Pubkey>,
178 ) -> &mut Self {
179 self.delegate_record = delegate_record;
180 self
181 }
182 #[inline(always)]
184 pub fn metadata(&mut self, metadata: solana_program::pubkey::Pubkey) -> &mut Self {
185 self.metadata = Some(metadata);
186 self
187 }
188 #[inline(always)]
191 pub fn collection_mint(
192 &mut self,
193 collection_mint: Option<solana_program::pubkey::Pubkey>,
194 ) -> &mut Self {
195 self.collection_mint = collection_mint;
196 self
197 }
198 #[inline(always)]
201 pub fn collection_metadata(
202 &mut self,
203 collection_metadata: Option<solana_program::pubkey::Pubkey>,
204 ) -> &mut Self {
205 self.collection_metadata = collection_metadata;
206 self
207 }
208 #[inline(always)]
211 pub fn collection_master_edition(
212 &mut self,
213 collection_master_edition: Option<solana_program::pubkey::Pubkey>,
214 ) -> &mut Self {
215 self.collection_master_edition = collection_master_edition;
216 self
217 }
218 #[inline(always)]
221 pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self {
222 self.system_program = Some(system_program);
223 self
224 }
225 #[inline(always)]
228 pub fn sysvar_instructions(
229 &mut self,
230 sysvar_instructions: solana_program::pubkey::Pubkey,
231 ) -> &mut Self {
232 self.sysvar_instructions = Some(sysvar_instructions);
233 self
234 }
235 #[inline(always)]
236 pub fn verification_args(&mut self, verification_args: VerificationArgs) -> &mut Self {
237 self.verification_args = Some(verification_args);
238 self
239 }
240 #[inline(always)]
242 pub fn add_remaining_account(
243 &mut self,
244 account: solana_program::instruction::AccountMeta,
245 ) -> &mut Self {
246 self.__remaining_accounts.push(account);
247 self
248 }
249 #[inline(always)]
251 pub fn add_remaining_accounts(
252 &mut self,
253 accounts: &[solana_program::instruction::AccountMeta],
254 ) -> &mut Self {
255 self.__remaining_accounts.extend_from_slice(accounts);
256 self
257 }
258 #[allow(clippy::clone_on_copy)]
259 pub fn instruction(&self) -> solana_program::instruction::Instruction {
260 let accounts = Verify {
261 authority: self.authority.expect("authority is not set"),
262 delegate_record: self.delegate_record,
263 metadata: self.metadata.expect("metadata is not set"),
264 collection_mint: self.collection_mint,
265 collection_metadata: self.collection_metadata,
266 collection_master_edition: self.collection_master_edition,
267 system_program: self
268 .system_program
269 .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")),
270 sysvar_instructions: self.sysvar_instructions.unwrap_or(solana_program::pubkey!(
271 "Sysvar1nstructions1111111111111111111111111"
272 )),
273 };
274 let args = VerifyInstructionArgs {
275 verification_args: self
276 .verification_args
277 .clone()
278 .expect("verification_args is not set"),
279 };
280
281 accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts)
282 }
283}
284
285pub struct VerifyCpiAccounts<'a, 'b> {
287 pub authority: &'b solana_program::account_info::AccountInfo<'a>,
289 pub delegate_record: Option<&'b solana_program::account_info::AccountInfo<'a>>,
291 pub metadata: &'b solana_program::account_info::AccountInfo<'a>,
293 pub collection_mint: Option<&'b solana_program::account_info::AccountInfo<'a>>,
295 pub collection_metadata: Option<&'b solana_program::account_info::AccountInfo<'a>>,
297 pub collection_master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
299 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
301 pub sysvar_instructions: &'b solana_program::account_info::AccountInfo<'a>,
303}
304
305pub struct VerifyCpi<'a, 'b> {
307 pub __program: &'b solana_program::account_info::AccountInfo<'a>,
309 pub authority: &'b solana_program::account_info::AccountInfo<'a>,
311 pub delegate_record: Option<&'b solana_program::account_info::AccountInfo<'a>>,
313 pub metadata: &'b solana_program::account_info::AccountInfo<'a>,
315 pub collection_mint: Option<&'b solana_program::account_info::AccountInfo<'a>>,
317 pub collection_metadata: Option<&'b solana_program::account_info::AccountInfo<'a>>,
319 pub collection_master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
321 pub system_program: &'b solana_program::account_info::AccountInfo<'a>,
323 pub sysvar_instructions: &'b solana_program::account_info::AccountInfo<'a>,
325 pub __args: VerifyInstructionArgs,
327}
328
329impl<'a, 'b> VerifyCpi<'a, 'b> {
330 pub fn new(
331 program: &'b solana_program::account_info::AccountInfo<'a>,
332 accounts: VerifyCpiAccounts<'a, 'b>,
333 args: VerifyInstructionArgs,
334 ) -> Self {
335 Self {
336 __program: program,
337 authority: accounts.authority,
338 delegate_record: accounts.delegate_record,
339 metadata: accounts.metadata,
340 collection_mint: accounts.collection_mint,
341 collection_metadata: accounts.collection_metadata,
342 collection_master_edition: accounts.collection_master_edition,
343 system_program: accounts.system_program,
344 sysvar_instructions: accounts.sysvar_instructions,
345 __args: args,
346 }
347 }
348 #[inline(always)]
349 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
350 self.invoke_signed_with_remaining_accounts(&[], &[])
351 }
352 #[inline(always)]
353 pub fn invoke_with_remaining_accounts(
354 &self,
355 remaining_accounts: &[(
356 &'b solana_program::account_info::AccountInfo<'a>,
357 bool,
358 bool,
359 )],
360 ) -> solana_program::entrypoint::ProgramResult {
361 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
362 }
363 #[inline(always)]
364 pub fn invoke_signed(
365 &self,
366 signers_seeds: &[&[&[u8]]],
367 ) -> solana_program::entrypoint::ProgramResult {
368 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
369 }
370 #[allow(clippy::clone_on_copy)]
371 #[allow(clippy::vec_init_then_push)]
372 pub fn invoke_signed_with_remaining_accounts(
373 &self,
374 signers_seeds: &[&[&[u8]]],
375 remaining_accounts: &[(
376 &'b solana_program::account_info::AccountInfo<'a>,
377 bool,
378 bool,
379 )],
380 ) -> solana_program::entrypoint::ProgramResult {
381 let mut accounts = Vec::with_capacity(8 + remaining_accounts.len());
382 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
383 *self.authority.key,
384 true,
385 ));
386 if let Some(delegate_record) = self.delegate_record {
387 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
388 *delegate_record.key,
389 false,
390 ));
391 } else {
392 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
393 crate::MPL_TOKEN_METADATA_ID,
394 false,
395 ));
396 }
397 accounts.push(solana_program::instruction::AccountMeta::new(
398 *self.metadata.key,
399 false,
400 ));
401 if let Some(collection_mint) = self.collection_mint {
402 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
403 *collection_mint.key,
404 false,
405 ));
406 } else {
407 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
408 crate::MPL_TOKEN_METADATA_ID,
409 false,
410 ));
411 }
412 if let Some(collection_metadata) = self.collection_metadata {
413 accounts.push(solana_program::instruction::AccountMeta::new(
414 *collection_metadata.key,
415 false,
416 ));
417 } else {
418 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
419 crate::MPL_TOKEN_METADATA_ID,
420 false,
421 ));
422 }
423 if let Some(collection_master_edition) = self.collection_master_edition {
424 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
425 *collection_master_edition.key,
426 false,
427 ));
428 } else {
429 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
430 crate::MPL_TOKEN_METADATA_ID,
431 false,
432 ));
433 }
434 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
435 *self.system_program.key,
436 false,
437 ));
438 accounts.push(solana_program::instruction::AccountMeta::new_readonly(
439 *self.sysvar_instructions.key,
440 false,
441 ));
442 remaining_accounts.iter().for_each(|remaining_account| {
443 accounts.push(solana_program::instruction::AccountMeta {
444 pubkey: *remaining_account.0.key,
445 is_signer: remaining_account.1,
446 is_writable: remaining_account.2,
447 })
448 });
449 let mut data = VerifyInstructionData::new().try_to_vec().unwrap();
450 let mut args = self.__args.try_to_vec().unwrap();
451 data.append(&mut args);
452
453 let instruction = solana_program::instruction::Instruction {
454 program_id: crate::MPL_TOKEN_METADATA_ID,
455 accounts,
456 data,
457 };
458 let mut account_infos = Vec::with_capacity(8 + 1 + remaining_accounts.len());
459 account_infos.push(self.__program.clone());
460 account_infos.push(self.authority.clone());
461 if let Some(delegate_record) = self.delegate_record {
462 account_infos.push(delegate_record.clone());
463 }
464 account_infos.push(self.metadata.clone());
465 if let Some(collection_mint) = self.collection_mint {
466 account_infos.push(collection_mint.clone());
467 }
468 if let Some(collection_metadata) = self.collection_metadata {
469 account_infos.push(collection_metadata.clone());
470 }
471 if let Some(collection_master_edition) = self.collection_master_edition {
472 account_infos.push(collection_master_edition.clone());
473 }
474 account_infos.push(self.system_program.clone());
475 account_infos.push(self.sysvar_instructions.clone());
476 remaining_accounts
477 .iter()
478 .for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
479
480 if signers_seeds.is_empty() {
481 solana_program::program::invoke(&instruction, &account_infos)
482 } else {
483 solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds)
484 }
485 }
486}
487
488pub struct VerifyCpiBuilder<'a, 'b> {
501 instruction: Box<VerifyCpiBuilderInstruction<'a, 'b>>,
502}
503
504impl<'a, 'b> VerifyCpiBuilder<'a, 'b> {
505 pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self {
506 let instruction = Box::new(VerifyCpiBuilderInstruction {
507 __program: program,
508 authority: None,
509 delegate_record: None,
510 metadata: None,
511 collection_mint: None,
512 collection_metadata: None,
513 collection_master_edition: None,
514 system_program: None,
515 sysvar_instructions: None,
516 verification_args: None,
517 __remaining_accounts: Vec::new(),
518 });
519 Self { instruction }
520 }
521 #[inline(always)]
523 pub fn authority(
524 &mut self,
525 authority: &'b solana_program::account_info::AccountInfo<'a>,
526 ) -> &mut Self {
527 self.instruction.authority = Some(authority);
528 self
529 }
530 #[inline(always)]
533 pub fn delegate_record(
534 &mut self,
535 delegate_record: Option<&'b solana_program::account_info::AccountInfo<'a>>,
536 ) -> &mut Self {
537 self.instruction.delegate_record = delegate_record;
538 self
539 }
540 #[inline(always)]
542 pub fn metadata(
543 &mut self,
544 metadata: &'b solana_program::account_info::AccountInfo<'a>,
545 ) -> &mut Self {
546 self.instruction.metadata = Some(metadata);
547 self
548 }
549 #[inline(always)]
552 pub fn collection_mint(
553 &mut self,
554 collection_mint: Option<&'b solana_program::account_info::AccountInfo<'a>>,
555 ) -> &mut Self {
556 self.instruction.collection_mint = collection_mint;
557 self
558 }
559 #[inline(always)]
562 pub fn collection_metadata(
563 &mut self,
564 collection_metadata: Option<&'b solana_program::account_info::AccountInfo<'a>>,
565 ) -> &mut Self {
566 self.instruction.collection_metadata = collection_metadata;
567 self
568 }
569 #[inline(always)]
572 pub fn collection_master_edition(
573 &mut self,
574 collection_master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
575 ) -> &mut Self {
576 self.instruction.collection_master_edition = collection_master_edition;
577 self
578 }
579 #[inline(always)]
581 pub fn system_program(
582 &mut self,
583 system_program: &'b solana_program::account_info::AccountInfo<'a>,
584 ) -> &mut Self {
585 self.instruction.system_program = Some(system_program);
586 self
587 }
588 #[inline(always)]
590 pub fn sysvar_instructions(
591 &mut self,
592 sysvar_instructions: &'b solana_program::account_info::AccountInfo<'a>,
593 ) -> &mut Self {
594 self.instruction.sysvar_instructions = Some(sysvar_instructions);
595 self
596 }
597 #[inline(always)]
598 pub fn verification_args(&mut self, verification_args: VerificationArgs) -> &mut Self {
599 self.instruction.verification_args = Some(verification_args);
600 self
601 }
602 #[inline(always)]
604 pub fn add_remaining_account(
605 &mut self,
606 account: &'b solana_program::account_info::AccountInfo<'a>,
607 is_writable: bool,
608 is_signer: bool,
609 ) -> &mut Self {
610 self.instruction
611 .__remaining_accounts
612 .push((account, is_writable, is_signer));
613 self
614 }
615 #[inline(always)]
620 pub fn add_remaining_accounts(
621 &mut self,
622 accounts: &[(
623 &'b solana_program::account_info::AccountInfo<'a>,
624 bool,
625 bool,
626 )],
627 ) -> &mut Self {
628 self.instruction
629 .__remaining_accounts
630 .extend_from_slice(accounts);
631 self
632 }
633 #[inline(always)]
634 pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult {
635 self.invoke_signed(&[])
636 }
637 #[allow(clippy::clone_on_copy)]
638 #[allow(clippy::vec_init_then_push)]
639 pub fn invoke_signed(
640 &self,
641 signers_seeds: &[&[&[u8]]],
642 ) -> solana_program::entrypoint::ProgramResult {
643 let args = VerifyInstructionArgs {
644 verification_args: self
645 .instruction
646 .verification_args
647 .clone()
648 .expect("verification_args is not set"),
649 };
650 let instruction = VerifyCpi {
651 __program: self.instruction.__program,
652
653 authority: self.instruction.authority.expect("authority is not set"),
654
655 delegate_record: self.instruction.delegate_record,
656
657 metadata: self.instruction.metadata.expect("metadata is not set"),
658
659 collection_mint: self.instruction.collection_mint,
660
661 collection_metadata: self.instruction.collection_metadata,
662
663 collection_master_edition: self.instruction.collection_master_edition,
664
665 system_program: self
666 .instruction
667 .system_program
668 .expect("system_program is not set"),
669
670 sysvar_instructions: self
671 .instruction
672 .sysvar_instructions
673 .expect("sysvar_instructions is not set"),
674 __args: args,
675 };
676 instruction.invoke_signed_with_remaining_accounts(
677 signers_seeds,
678 &self.instruction.__remaining_accounts,
679 )
680 }
681}
682
683struct VerifyCpiBuilderInstruction<'a, 'b> {
684 __program: &'b solana_program::account_info::AccountInfo<'a>,
685 authority: Option<&'b solana_program::account_info::AccountInfo<'a>>,
686 delegate_record: Option<&'b solana_program::account_info::AccountInfo<'a>>,
687 metadata: Option<&'b solana_program::account_info::AccountInfo<'a>>,
688 collection_mint: Option<&'b solana_program::account_info::AccountInfo<'a>>,
689 collection_metadata: Option<&'b solana_program::account_info::AccountInfo<'a>>,
690 collection_master_edition: Option<&'b solana_program::account_info::AccountInfo<'a>>,
691 system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
692 sysvar_instructions: Option<&'b solana_program::account_info::AccountInfo<'a>>,
693 verification_args: Option<VerificationArgs>,
694 __remaining_accounts: Vec<(
696 &'b solana_program::account_info::AccountInfo<'a>,
697 bool,
698 bool,
699 )>,
700}