1use crate::solana::transaction::{AccountMeta, Instruction};
28
29pub const METADATA_PROGRAM_ID: [u8; 32] = [
36 11, 112, 101, 177, 227, 209, 124, 69, 56, 157, 82, 127, 107, 4, 195, 205, 88, 184, 108, 115,
37 26, 160, 253, 181, 73, 182, 209, 188, 3, 248, 41, 70,
38];
39
40pub const BUBBLEGUM_PROGRAM_ID: [u8; 32] = [
43 0x98, 0x8B, 0x80, 0xEB, 0x79, 0x35, 0x28, 0x69, 0xB2, 0x24, 0x74, 0x5F, 0x59, 0xDD, 0xBF, 0x8A,
44 0x26, 0x58, 0xCA, 0x13, 0xDC, 0x68, 0x81, 0x21, 0x26, 0x35, 0x1C, 0xAE, 0x07, 0xC1, 0xA5, 0xA5,
45];
46
47const SYSTEM_PROGRAM_ID: [u8; 32] = [0u8; 32];
49
50const SYSVAR_RENT_ID: [u8; 32] = [
52 0x06, 0xA7, 0xD5, 0x17, 0x19, 0x2C, 0x5C, 0x51, 0x21, 0x8C, 0xC9, 0x4C, 0x3D, 0x4A, 0xF1, 0x7F,
53 0x58, 0xDA, 0xEE, 0x08, 0x9B, 0xA1, 0xFD, 0x44, 0xE3, 0xDB, 0xD9, 0x8A, 0x00, 0x00, 0x00, 0x00,
54];
55
56#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct Creator {
63 pub address: [u8; 32],
65 pub verified: bool,
67 pub share: u8,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq)]
73pub struct MetadataData {
74 pub name: String,
76 pub symbol: String,
78 pub uri: String,
80 pub seller_fee_basis_points: u16,
82 pub creators: Vec<Creator>,
84}
85
86#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct Collection {
89 pub verified: bool,
91 pub key: [u8; 32],
93}
94
95#[derive(Debug, Clone, PartialEq, Eq)]
97pub struct Uses {
98 pub use_method: UseMethod,
100 pub remaining: u64,
102 pub total: u64,
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
108#[repr(u8)]
109pub enum UseMethod {
110 Burn = 0,
112 Multiple = 1,
114 Single = 2,
116}
117
118fn borsh_string(data: &mut Vec<u8>, s: &str) {
123 data.extend_from_slice(&(s.len() as u32).to_le_bytes());
124 data.extend_from_slice(s.as_bytes());
125}
126
127fn borsh_option_pubkey(data: &mut Vec<u8>, key: Option<&[u8; 32]>) {
128 match key {
129 Some(k) => {
130 data.push(1); data.extend_from_slice(k);
132 }
133 None => data.push(0), }
135}
136
137fn borsh_creators(data: &mut Vec<u8>, creators: &[Creator]) {
138 data.push(1); data.extend_from_slice(&(creators.len() as u32).to_le_bytes());
140 for c in creators {
141 data.extend_from_slice(&c.address);
142 data.push(u8::from(c.verified));
143 data.push(c.share);
144 }
145}
146
147fn borsh_metadata_data(data: &mut Vec<u8>, md: &MetadataData) {
148 borsh_string(data, &md.name);
149 borsh_string(data, &md.symbol);
150 borsh_string(data, &md.uri);
151 data.extend_from_slice(&md.seller_fee_basis_points.to_le_bytes());
152 borsh_creators(data, &md.creators);
153}
154
155fn borsh_collection(data: &mut Vec<u8>, collection: Option<&Collection>) {
156 match collection {
157 Some(c) => {
158 data.push(1);
159 data.push(u8::from(c.verified));
160 data.extend_from_slice(&c.key);
161 }
162 None => data.push(0),
163 }
164}
165
166fn borsh_uses(data: &mut Vec<u8>, uses: Option<&Uses>) {
167 match uses {
168 Some(u) => {
169 data.push(1);
170 data.push(u.use_method as u8);
171 data.extend_from_slice(&u.remaining.to_le_bytes());
172 data.extend_from_slice(&u.total.to_le_bytes());
173 }
174 None => data.push(0),
175 }
176}
177
178#[allow(clippy::too_many_arguments)]
193pub fn create_metadata_account_v3(
194 metadata_account: &[u8; 32],
195 mint: &[u8; 32],
196 mint_authority: &[u8; 32],
197 payer: &[u8; 32],
198 update_authority: &[u8; 32],
199 metadata: &MetadataData,
200 is_mutable: bool,
201 collection: Option<&Collection>,
202) -> Instruction {
203 let mut data = Vec::with_capacity(256);
204 data.push(33); borsh_metadata_data(&mut data, metadata);
207 data.push(u8::from(is_mutable));
208 borsh_collection(&mut data, collection);
209 borsh_uses(&mut data, None); Instruction {
212 program_id: METADATA_PROGRAM_ID,
213 accounts: vec![
214 AccountMeta::new(*metadata_account, false), AccountMeta::new_readonly(*mint, false), AccountMeta::new_readonly(*mint_authority, true), AccountMeta::new(*payer, true), AccountMeta::new_readonly(*update_authority, false), AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
220 AccountMeta::new_readonly(SYSVAR_RENT_ID, false),
221 ],
222 data,
223 }
224}
225
226pub fn create_master_edition_v3(
239 edition_account: &[u8; 32],
240 mint: &[u8; 32],
241 update_authority: &[u8; 32],
242 mint_authority: &[u8; 32],
243 payer: &[u8; 32],
244 metadata_account: &[u8; 32],
245 max_supply: Option<u64>,
246) -> Instruction {
247 let mut data = Vec::with_capacity(16);
248 data.push(17); match max_supply {
251 Some(supply) => {
252 data.push(1); data.extend_from_slice(&supply.to_le_bytes());
254 }
255 None => data.push(0), }
257
258 let token_program: [u8; 32] = [
260 0x06, 0xDD, 0xF6, 0xE1, 0xD7, 0x65, 0xA1, 0x93, 0xD9, 0xCB, 0xE1, 0x46, 0xCE, 0xEB, 0x79,
261 0xAC, 0x1C, 0xB4, 0x85, 0xED, 0x5F, 0x5B, 0x37, 0x91, 0x3A, 0x8C, 0xF5, 0x85, 0x7E, 0xFF,
262 0x00, 0xA9,
263 ];
264
265 Instruction {
266 program_id: METADATA_PROGRAM_ID,
267 accounts: vec![
268 AccountMeta::new(*edition_account, false),
269 AccountMeta::new(*mint, false),
270 AccountMeta::new_readonly(*update_authority, true),
271 AccountMeta::new_readonly(*mint_authority, true),
272 AccountMeta::new(*payer, true),
273 AccountMeta::new_readonly(*metadata_account, false),
274 AccountMeta::new_readonly(token_program, false),
275 AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
276 AccountMeta::new_readonly(SYSVAR_RENT_ID, false),
277 ],
278 data,
279 }
280}
281
282pub fn verify_collection(
292 metadata_account: &[u8; 32],
293 collection_authority: &[u8; 32],
294 payer: &[u8; 32],
295 collection_mint: &[u8; 32],
296 collection_metadata: &[u8; 32],
297 collection_edition: &[u8; 32],
298) -> Instruction {
299 let data = vec![18]; Instruction {
302 program_id: METADATA_PROGRAM_ID,
303 accounts: vec![
304 AccountMeta::new(*metadata_account, false),
305 AccountMeta::new_readonly(*collection_authority, true),
306 AccountMeta::new(*payer, true),
307 AccountMeta::new_readonly(*collection_mint, false),
308 AccountMeta::new_readonly(*collection_metadata, false),
309 AccountMeta::new_readonly(*collection_edition, false),
310 ],
311 data,
312 }
313}
314
315pub fn update_metadata_account_v2(
321 metadata_account: &[u8; 32],
322 update_authority: &[u8; 32],
323 new_data: Option<&MetadataData>,
324 new_update_authority: Option<&[u8; 32]>,
325 primary_sale_happened: Option<bool>,
326 is_mutable: Option<bool>,
327) -> Instruction {
328 let mut data = Vec::with_capacity(256);
329 data.push(15); match new_data {
333 Some(md) => {
334 data.push(1);
335 borsh_metadata_data(&mut data, md);
336 }
337 None => data.push(0),
338 }
339
340 borsh_option_pubkey(&mut data, new_update_authority);
342
343 match primary_sale_happened {
345 Some(v) => {
346 data.push(1);
347 data.push(u8::from(v));
348 }
349 None => data.push(0),
350 }
351
352 match is_mutable {
354 Some(v) => {
355 data.push(1);
356 data.push(u8::from(v));
357 }
358 None => data.push(0),
359 }
360
361 Instruction {
362 program_id: METADATA_PROGRAM_ID,
363 accounts: vec![
364 AccountMeta::new(*metadata_account, false),
365 AccountMeta::new_readonly(*update_authority, true),
366 ],
367 data,
368 }
369}
370
371#[allow(clippy::too_many_arguments)]
390pub fn mint_v1(
391 tree_authority: &[u8; 32],
392 leaf_owner: &[u8; 32],
393 leaf_delegate: &[u8; 32],
394 merkle_tree: &[u8; 32],
395 payer: &[u8; 32],
396 tree_delegate: &[u8; 32],
397 log_wrapper: &[u8; 32],
398 compression_program: &[u8; 32],
399 metadata: &MetadataData,
400) -> Instruction {
401 let discriminator: [u8; 8] = [145, 98, 192, 118, 184, 147, 118, 104];
403
404 let mut data = Vec::with_capacity(256);
405 data.extend_from_slice(&discriminator);
406 borsh_metadata_data(&mut data, metadata);
407
408 Instruction {
409 program_id: BUBBLEGUM_PROGRAM_ID,
410 accounts: vec![
411 AccountMeta::new(*tree_authority, false),
412 AccountMeta::new_readonly(*leaf_owner, false),
413 AccountMeta::new_readonly(*leaf_delegate, false),
414 AccountMeta::new(*merkle_tree, false),
415 AccountMeta::new(*payer, true),
416 AccountMeta::new_readonly(*tree_delegate, true),
417 AccountMeta::new_readonly(*log_wrapper, false),
418 AccountMeta::new_readonly(*compression_program, false),
419 AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
420 ],
421 data,
422 }
423}
424
425#[allow(clippy::too_many_arguments)]
441pub fn transfer(
442 tree_authority: &[u8; 32],
443 leaf_owner: &[u8; 32],
444 leaf_delegate: &[u8; 32],
445 new_leaf_owner: &[u8; 32],
446 merkle_tree: &[u8; 32],
447 log_wrapper: &[u8; 32],
448 compression_program: &[u8; 32],
449 root: &[u8; 32],
450 data_hash: &[u8; 32],
451 creator_hash: &[u8; 32],
452 nonce: u64,
453 index: u32,
454 proof: &[[u8; 32]],
455) -> Instruction {
456 let discriminator: [u8; 8] = [163, 52, 200, 231, 140, 3, 69, 186];
458
459 let mut data = Vec::with_capacity(128);
460 data.extend_from_slice(&discriminator);
461 data.extend_from_slice(root);
462 data.extend_from_slice(data_hash);
463 data.extend_from_slice(creator_hash);
464 data.extend_from_slice(&nonce.to_le_bytes());
465 data.extend_from_slice(&index.to_le_bytes());
466
467 let mut accounts = vec![
468 AccountMeta::new(*tree_authority, false),
469 AccountMeta::new_readonly(*leaf_owner, true), AccountMeta::new_readonly(*leaf_delegate, false),
471 AccountMeta::new_readonly(*new_leaf_owner, false),
472 AccountMeta::new(*merkle_tree, false),
473 AccountMeta::new_readonly(*log_wrapper, false),
474 AccountMeta::new_readonly(*compression_program, false),
475 AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
476 ];
477
478 for node in proof {
480 accounts.push(AccountMeta::new_readonly(*node, false));
481 }
482
483 Instruction {
484 program_id: BUBBLEGUM_PROGRAM_ID,
485 accounts,
486 data,
487 }
488}
489
490#[cfg(test)]
495#[allow(clippy::unwrap_used, clippy::expect_used)]
496mod tests {
497 use super::*;
498
499 const MINT: [u8; 32] = [0xAA; 32];
500 const AUTH: [u8; 32] = [0xBB; 32];
501 const PAYER: [u8; 32] = [0xCC; 32];
502 const META_ACCT: [u8; 32] = [0xDD; 32];
503 const EDITION: [u8; 32] = [0xEE; 32];
504
505 fn sample_metadata() -> MetadataData {
506 MetadataData {
507 name: "Test NFT".into(),
508 symbol: "TNFT".into(),
509 uri: "https://example.com/nft.json".into(),
510 seller_fee_basis_points: 500,
511 creators: vec![Creator {
512 address: AUTH,
513 verified: true,
514 share: 100,
515 }],
516 }
517 }
518
519 #[test]
522 fn test_metadata_program_id_length() {
523 assert_eq!(METADATA_PROGRAM_ID.len(), 32);
524 }
525
526 #[test]
527 fn test_bubblegum_program_id_length() {
528 assert_eq!(BUBBLEGUM_PROGRAM_ID.len(), 32);
529 }
530
531 #[test]
532 fn test_program_ids_differ() {
533 assert_ne!(METADATA_PROGRAM_ID, BUBBLEGUM_PROGRAM_ID);
534 }
535
536 #[test]
539 fn test_create_metadata_v3_discriminator() {
540 let ix = create_metadata_account_v3(
541 &META_ACCT,
542 &MINT,
543 &AUTH,
544 &PAYER,
545 &AUTH,
546 &sample_metadata(),
547 true,
548 None,
549 );
550 assert_eq!(ix.data[0], 33);
551 }
552
553 #[test]
554 fn test_create_metadata_v3_program_id() {
555 let ix = create_metadata_account_v3(
556 &META_ACCT,
557 &MINT,
558 &AUTH,
559 &PAYER,
560 &AUTH,
561 &sample_metadata(),
562 true,
563 None,
564 );
565 assert_eq!(ix.program_id, METADATA_PROGRAM_ID);
566 }
567
568 #[test]
569 fn test_create_metadata_v3_accounts() {
570 let ix = create_metadata_account_v3(
571 &META_ACCT,
572 &MINT,
573 &AUTH,
574 &PAYER,
575 &AUTH,
576 &sample_metadata(),
577 true,
578 None,
579 );
580 assert_eq!(ix.accounts.len(), 7);
581 assert_eq!(ix.accounts[0].pubkey, META_ACCT);
582 assert!(ix.accounts[0].is_writable);
583 assert_eq!(ix.accounts[2].pubkey, AUTH);
584 assert!(ix.accounts[2].is_signer); assert_eq!(ix.accounts[3].pubkey, PAYER);
586 assert!(ix.accounts[3].is_signer); }
588
589 #[test]
590 fn test_create_metadata_v3_data_encoding() {
591 let md = MetadataData {
592 name: "A".into(),
593 symbol: "B".into(),
594 uri: "C".into(),
595 seller_fee_basis_points: 100,
596 creators: vec![],
597 };
598 let ix =
599 create_metadata_account_v3(&META_ACCT, &MINT, &AUTH, &PAYER, &AUTH, &md, false, None);
600 assert_eq!(ix.data[0], 33);
602 let name_len = u32::from_le_bytes(ix.data[1..5].try_into().unwrap());
604 assert_eq!(name_len, 1);
605 assert_eq!(ix.data[5], b'A');
606 }
607
608 #[test]
609 fn test_create_metadata_v3_with_collection() {
610 let col = Collection {
611 verified: false,
612 key: [0xFF; 32],
613 };
614 let ix = create_metadata_account_v3(
615 &META_ACCT,
616 &MINT,
617 &AUTH,
618 &PAYER,
619 &AUTH,
620 &sample_metadata(),
621 true,
622 Some(&col),
623 );
624 assert!(ix.data.len() > 50);
626 }
627
628 #[test]
631 fn test_create_master_edition_v3_discriminator() {
632 let ix =
633 create_master_edition_v3(&EDITION, &MINT, &AUTH, &AUTH, &PAYER, &META_ACCT, Some(1));
634 assert_eq!(ix.data[0], 17);
635 }
636
637 #[test]
638 fn test_create_master_edition_v3_max_supply() {
639 let ix =
640 create_master_edition_v3(&EDITION, &MINT, &AUTH, &AUTH, &PAYER, &META_ACCT, Some(100));
641 assert_eq!(ix.data[1], 1); let supply = u64::from_le_bytes(ix.data[2..10].try_into().unwrap());
643 assert_eq!(supply, 100);
644 }
645
646 #[test]
647 fn test_create_master_edition_v3_unlimited() {
648 let ix = create_master_edition_v3(&EDITION, &MINT, &AUTH, &AUTH, &PAYER, &META_ACCT, None);
649 assert_eq!(ix.data[1], 0); assert_eq!(ix.data.len(), 2);
651 }
652
653 #[test]
654 fn test_create_master_edition_v3_accounts() {
655 let ix = create_master_edition_v3(&EDITION, &MINT, &AUTH, &AUTH, &PAYER, &META_ACCT, None);
656 assert_eq!(ix.accounts.len(), 9);
657 assert!(ix.accounts[2].is_signer); assert!(ix.accounts[3].is_signer); assert!(ix.accounts[4].is_signer); }
661
662 #[test]
665 fn test_verify_collection_discriminator() {
666 let ix = verify_collection(&META_ACCT, &AUTH, &PAYER, &MINT, &[0x11; 32], &[0x22; 32]);
667 assert_eq!(ix.data, vec![18]);
668 }
669
670 #[test]
671 fn test_verify_collection_accounts() {
672 let ix = verify_collection(&META_ACCT, &AUTH, &PAYER, &MINT, &[0x11; 32], &[0x22; 32]);
673 assert_eq!(ix.accounts.len(), 6);
674 assert!(ix.accounts[1].is_signer); assert!(ix.accounts[2].is_signer); }
677
678 #[test]
681 fn test_update_metadata_v2_discriminator() {
682 let ix = update_metadata_account_v2(&META_ACCT, &AUTH, None, None, None, None);
683 assert_eq!(ix.data[0], 15);
684 }
685
686 #[test]
687 fn test_update_metadata_v2_no_changes() {
688 let ix = update_metadata_account_v2(&META_ACCT, &AUTH, None, None, None, None);
689 assert_eq!(ix.data, vec![15, 0, 0, 0, 0]);
691 }
692
693 #[test]
694 fn test_update_metadata_v2_with_new_authority() {
695 let new_auth = [0xFF; 32];
696 let ix = update_metadata_account_v2(&META_ACCT, &AUTH, None, Some(&new_auth), None, None);
697 assert_eq!(ix.data[0], 15);
698 assert_eq!(ix.data[1], 0); assert_eq!(ix.data[2], 1); assert_eq!(&ix.data[3..35], &new_auth);
701 }
702
703 #[test]
704 fn test_update_metadata_v2_accounts() {
705 let ix = update_metadata_account_v2(&META_ACCT, &AUTH, None, None, None, None);
706 assert_eq!(ix.accounts.len(), 2);
707 assert!(ix.accounts[1].is_signer);
708 }
709
710 #[test]
713 fn test_bubblegum_mint_v1_discriminator() {
714 let ix = mint_v1(
715 &[0x01; 32],
716 &[0x02; 32],
717 &[0x03; 32],
718 &[0x04; 32],
719 &PAYER,
720 &AUTH,
721 &[0x05; 32],
722 &[0x06; 32],
723 &sample_metadata(),
724 );
725 assert_eq!(&ix.data[0..8], &[145, 98, 192, 118, 184, 147, 118, 104]);
726 }
727
728 #[test]
729 fn test_bubblegum_mint_v1_program_id() {
730 let ix = mint_v1(
731 &[0x01; 32],
732 &[0x02; 32],
733 &[0x03; 32],
734 &[0x04; 32],
735 &PAYER,
736 &AUTH,
737 &[0x05; 32],
738 &[0x06; 32],
739 &sample_metadata(),
740 );
741 assert_eq!(ix.program_id, BUBBLEGUM_PROGRAM_ID);
742 }
743
744 #[test]
745 fn test_bubblegum_mint_v1_accounts() {
746 let ix = mint_v1(
747 &[0x01; 32],
748 &[0x02; 32],
749 &[0x03; 32],
750 &[0x04; 32],
751 &PAYER,
752 &AUTH,
753 &[0x05; 32],
754 &[0x06; 32],
755 &sample_metadata(),
756 );
757 assert_eq!(ix.accounts.len(), 9);
758 assert!(ix.accounts[4].is_signer); assert!(ix.accounts[5].is_signer); }
761
762 #[test]
765 fn test_bubblegum_transfer_discriminator() {
766 let ix = transfer(
767 &[0x01; 32],
768 &[0x02; 32],
769 &[0x03; 32],
770 &[0x04; 32],
771 &[0x05; 32],
772 &[0x06; 32],
773 &[0x07; 32],
774 &[0xAA; 32],
775 &[0xBB; 32],
776 &[0xCC; 32],
777 0,
778 0,
779 &[],
780 );
781 assert_eq!(&ix.data[0..8], &[163, 52, 200, 231, 140, 3, 69, 186]);
782 }
783
784 #[test]
785 fn test_bubblegum_transfer_data_encoding() {
786 let root = [0xAA; 32];
787 let data_hash = [0xBB; 32];
788 let creator_hash = [0xCC; 32];
789 let ix = transfer(
790 &[0x01; 32],
791 &[0x02; 32],
792 &[0x03; 32],
793 &[0x04; 32],
794 &[0x05; 32],
795 &[0x06; 32],
796 &[0x07; 32],
797 &root,
798 &data_hash,
799 &creator_hash,
800 42,
801 7,
802 &[],
803 );
804 assert_eq!(&ix.data[8..40], &root);
805 assert_eq!(&ix.data[40..72], &data_hash);
806 assert_eq!(&ix.data[72..104], &creator_hash);
807 let nonce = u64::from_le_bytes(ix.data[104..112].try_into().unwrap());
808 assert_eq!(nonce, 42);
809 let idx = u32::from_le_bytes(ix.data[112..116].try_into().unwrap());
810 assert_eq!(idx, 7);
811 }
812
813 #[test]
814 fn test_bubblegum_transfer_with_proof() {
815 let proof = vec![[0x11; 32], [0x22; 32], [0x33; 32]];
816 let ix = transfer(
817 &[0x01; 32],
818 &[0x02; 32],
819 &[0x03; 32],
820 &[0x04; 32],
821 &[0x05; 32],
822 &[0x06; 32],
823 &[0x07; 32],
824 &[0xAA; 32],
825 &[0xBB; 32],
826 &[0xCC; 32],
827 0,
828 0,
829 &proof,
830 );
831 assert_eq!(ix.accounts.len(), 8 + 3); }
833
834 #[test]
835 fn test_bubblegum_transfer_leaf_owner_is_signer() {
836 let ix = transfer(
837 &[0x01; 32],
838 &[0x02; 32],
839 &[0x03; 32],
840 &[0x04; 32],
841 &[0x05; 32],
842 &[0x06; 32],
843 &[0x07; 32],
844 &[0xAA; 32],
845 &[0xBB; 32],
846 &[0xCC; 32],
847 0,
848 0,
849 &[],
850 );
851 assert_eq!(ix.accounts[1].pubkey, [0x02; 32]);
852 assert!(ix.accounts[1].is_signer); }
854
855 #[test]
858 fn test_borsh_string() {
859 let mut buf = Vec::new();
860 borsh_string(&mut buf, "Hello");
861 assert_eq!(buf.len(), 4 + 5);
862 let len = u32::from_le_bytes(buf[0..4].try_into().unwrap());
863 assert_eq!(len, 5);
864 assert_eq!(&buf[4..], b"Hello");
865 }
866
867 #[test]
868 fn test_borsh_string_empty() {
869 let mut buf = Vec::new();
870 borsh_string(&mut buf, "");
871 assert_eq!(buf.len(), 4);
872 assert_eq!(u32::from_le_bytes(buf[..4].try_into().unwrap()), 0);
873 }
874
875 #[test]
876 fn test_borsh_creators() {
877 let mut buf = Vec::new();
878 borsh_creators(
879 &mut buf,
880 &[Creator {
881 address: [0xFF; 32],
882 verified: true,
883 share: 50,
884 }],
885 );
886 assert_eq!(buf[0], 1); let count = u32::from_le_bytes(buf[1..5].try_into().unwrap());
888 assert_eq!(count, 1);
889 assert_eq!(&buf[5..37], &[0xFF; 32]);
890 assert_eq!(buf[37], 1); assert_eq!(buf[38], 50); }
893
894 #[test]
895 fn test_borsh_collection_some() {
896 let mut buf = Vec::new();
897 let col = Collection {
898 verified: true,
899 key: [0xAA; 32],
900 };
901 borsh_collection(&mut buf, Some(&col));
902 assert_eq!(buf[0], 1); assert_eq!(buf[1], 1); assert_eq!(&buf[2..34], &[0xAA; 32]);
905 }
906
907 #[test]
908 fn test_borsh_collection_none() {
909 let mut buf = Vec::new();
910 borsh_collection(&mut buf, None);
911 assert_eq!(buf, vec![0]); }
913
914 #[test]
915 fn test_use_method_values() {
916 assert_eq!(UseMethod::Burn as u8, 0);
917 assert_eq!(UseMethod::Multiple as u8, 1);
918 assert_eq!(UseMethod::Single as u8, 2);
919 }
920}