1use super::transaction::{AccountMeta, Instruction};
15
16pub const TOKEN_2022_ID: [u8; 32] = [
22 0x06, 0xDD, 0xF6, 0xE1, 0xEE, 0x75, 0x8F, 0xDE, 0x18, 0x42, 0x5D, 0xBC, 0xE4, 0x6C, 0xCD, 0xDA,
23 0xB6, 0x1A, 0xFC, 0x4D, 0x83, 0xB9, 0x0D, 0x27, 0xFE, 0xBD, 0xF9, 0x28, 0xD8, 0xA1, 0x8B, 0xFC,
24];
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum AccountState {
33 Uninitialized = 0,
35 Initialized = 1,
37 Frozen = 2,
39}
40
41#[must_use]
45pub fn initialize_default_account_state(mint: &[u8; 32], state: AccountState) -> Instruction {
46 let data = vec![29, 0, state as u8];
49 Instruction {
50 program_id: TOKEN_2022_ID,
51 accounts: vec![AccountMeta::new(*mint, false)],
52 data,
53 }
54}
55
56#[must_use]
58pub fn update_default_account_state(
59 mint: &[u8; 32],
60 freeze_authority: &[u8; 32],
61 state: AccountState,
62) -> Instruction {
63 let data = vec![29, 1, state as u8];
64 Instruction {
65 program_id: TOKEN_2022_ID,
66 accounts: vec![
67 AccountMeta::new(*mint, false),
68 AccountMeta::new_readonly(*freeze_authority, true),
69 ],
70 data,
71 }
72}
73
74#[must_use]
87pub fn initialize_transfer_fee_config(
88 mint: &[u8; 32],
89 transfer_fee_config_authority: Option<&[u8; 32]>,
90 withdraw_withheld_authority: Option<&[u8; 32]>,
91 transfer_fee_basis_points: u16,
92 maximum_fee: u64,
93) -> Instruction {
94 let mut data = vec![26, 0];
97
98 match transfer_fee_config_authority {
100 Some(auth) => {
101 data.push(1);
102 data.extend_from_slice(auth);
103 }
104 None => {
105 data.push(0);
106 data.extend_from_slice(&[0u8; 32]);
107 }
108 }
109
110 match withdraw_withheld_authority {
112 Some(auth) => {
113 data.push(1);
114 data.extend_from_slice(auth);
115 }
116 None => {
117 data.push(0);
118 data.extend_from_slice(&[0u8; 32]);
119 }
120 }
121
122 data.extend_from_slice(&transfer_fee_basis_points.to_le_bytes());
123 data.extend_from_slice(&maximum_fee.to_le_bytes());
124
125 Instruction {
126 program_id: TOKEN_2022_ID,
127 accounts: vec![AccountMeta::new(*mint, false)],
128 data,
129 }
130}
131
132#[must_use]
136pub fn harvest_withheld_tokens_to_mint(
137 mint: &[u8; 32],
138 token_accounts: &[[u8; 32]],
139) -> Instruction {
140 let data = vec![26, 4]; let mut accounts = vec![AccountMeta::new(*mint, false)];
142 for acct in token_accounts {
143 accounts.push(AccountMeta::new(*acct, false));
144 }
145 Instruction {
146 program_id: TOKEN_2022_ID,
147 accounts,
148 data,
149 }
150}
151
152#[must_use]
154pub fn withdraw_withheld_tokens_from_mint(
155 mint: &[u8; 32],
156 destination: &[u8; 32],
157 withdraw_authority: &[u8; 32],
158) -> Instruction {
159 let data = vec![26, 3]; Instruction {
161 program_id: TOKEN_2022_ID,
162 accounts: vec![
163 AccountMeta::new(*mint, false),
164 AccountMeta::new(*destination, false),
165 AccountMeta::new_readonly(*withdraw_authority, true),
166 ],
167 data,
168 }
169}
170
171#[must_use]
179pub fn initialize_transfer_hook(
180 mint: &[u8; 32],
181 authority: Option<&[u8; 32]>,
182 transfer_hook_program_id: &[u8; 32],
183) -> Instruction {
184 let mut data = vec![36, 0];
187 match authority {
188 Some(auth) => {
189 data.push(1);
190 data.extend_from_slice(auth);
191 }
192 None => {
193 data.push(0);
194 data.extend_from_slice(&[0u8; 32]);
195 }
196 }
197 data.extend_from_slice(transfer_hook_program_id);
198
199 Instruction {
200 program_id: TOKEN_2022_ID,
201 accounts: vec![AccountMeta::new(*mint, false)],
202 data,
203 }
204}
205
206#[must_use]
208pub fn update_transfer_hook(
209 mint: &[u8; 32],
210 authority: &[u8; 32],
211 new_program_id: &[u8; 32],
212) -> Instruction {
213 let mut data = vec![36, 1]; data.extend_from_slice(new_program_id);
215 Instruction {
216 program_id: TOKEN_2022_ID,
217 accounts: vec![
218 AccountMeta::new(*mint, false),
219 AccountMeta::new_readonly(*authority, true),
220 ],
221 data,
222 }
223}
224
225#[must_use]
233pub fn enable_cpi_guard(account: &[u8; 32], owner: &[u8; 32]) -> Instruction {
234 let data = vec![37, 0]; Instruction {
236 program_id: TOKEN_2022_ID,
237 accounts: vec![
238 AccountMeta::new(*account, false),
239 AccountMeta::new_readonly(*owner, true),
240 ],
241 data,
242 }
243}
244
245#[must_use]
247pub fn disable_cpi_guard(account: &[u8; 32], owner: &[u8; 32]) -> Instruction {
248 let data = vec![37, 1]; Instruction {
250 program_id: TOKEN_2022_ID,
251 accounts: vec![
252 AccountMeta::new(*account, false),
253 AccountMeta::new_readonly(*owner, true),
254 ],
255 data,
256 }
257}
258
259#[must_use]
267pub fn initialize_permanent_delegate(mint: &[u8; 32], delegate: &[u8; 32]) -> Instruction {
268 let mut data = vec![35, 0]; data.extend_from_slice(delegate);
270 Instruction {
271 program_id: TOKEN_2022_ID,
272 accounts: vec![AccountMeta::new(*mint, false)],
273 data,
274 }
275}
276
277#[must_use]
283pub fn enable_required_memo_transfers(account: &[u8; 32], owner: &[u8; 32]) -> Instruction {
284 let data = vec![30, 0]; Instruction {
286 program_id: TOKEN_2022_ID,
287 accounts: vec![
288 AccountMeta::new(*account, false),
289 AccountMeta::new_readonly(*owner, true),
290 ],
291 data,
292 }
293}
294
295#[must_use]
297pub fn disable_required_memo_transfers(account: &[u8; 32], owner: &[u8; 32]) -> Instruction {
298 let data = vec![30, 1]; Instruction {
300 program_id: TOKEN_2022_ID,
301 accounts: vec![
302 AccountMeta::new(*account, false),
303 AccountMeta::new_readonly(*owner, true),
304 ],
305 data,
306 }
307}
308
309#[must_use]
319pub fn initialize_interest_bearing_config(
320 mint: &[u8; 32],
321 rate_authority: Option<&[u8; 32]>,
322 rate: i16,
323) -> Instruction {
324 let mut data = vec![33, 0]; match rate_authority {
326 Some(auth) => {
327 data.push(1);
328 data.extend_from_slice(auth);
329 }
330 None => {
331 data.push(0);
332 data.extend_from_slice(&[0u8; 32]);
333 }
334 }
335 data.extend_from_slice(&rate.to_le_bytes());
336
337 Instruction {
338 program_id: TOKEN_2022_ID,
339 accounts: vec![AccountMeta::new(*mint, false)],
340 data,
341 }
342}
343
344#[must_use]
346pub fn update_interest_rate(
347 mint: &[u8; 32],
348 rate_authority: &[u8; 32],
349 new_rate: i16,
350) -> Instruction {
351 let mut data = vec![33, 1]; data.extend_from_slice(&new_rate.to_le_bytes());
353 Instruction {
354 program_id: TOKEN_2022_ID,
355 accounts: vec![
356 AccountMeta::new(*mint, false),
357 AccountMeta::new_readonly(*rate_authority, true),
358 ],
359 data,
360 }
361}
362
363#[must_use]
371pub fn initialize_token_metadata(
372 mint: &[u8; 32],
373 update_authority: &[u8; 32],
374 mint_authority: &[u8; 32],
375 name: &str,
376 symbol: &str,
377 uri: &str,
378) -> Instruction {
379 let mut data = Vec::new();
380 data.extend_from_slice(&[210, 225, 30, 162, 88, 184, 226, 143]);
383
384 let name_bytes = name.as_bytes();
386 data.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
387 data.extend_from_slice(name_bytes);
388
389 let symbol_bytes = symbol.as_bytes();
390 data.extend_from_slice(&(symbol_bytes.len() as u32).to_le_bytes());
391 data.extend_from_slice(symbol_bytes);
392
393 let uri_bytes = uri.as_bytes();
394 data.extend_from_slice(&(uri_bytes.len() as u32).to_le_bytes());
395 data.extend_from_slice(uri_bytes);
396
397 Instruction {
398 program_id: TOKEN_2022_ID,
399 accounts: vec![
400 AccountMeta::new(*mint, false),
401 AccountMeta::new_readonly(*update_authority, false),
402 AccountMeta::new_readonly(*mint_authority, true),
403 ],
404 data,
405 }
406}
407
408#[must_use]
414pub fn update_token_metadata_field(
415 mint: &[u8; 32],
416 update_authority: &[u8; 32],
417 field: &str,
418 value: &str,
419) -> Instruction {
420 let mut data = Vec::new();
421 data.extend_from_slice(&[221, 233, 49, 45, 181, 202, 220, 200]);
423
424 let field_bytes = field.as_bytes();
425 data.extend_from_slice(&(field_bytes.len() as u32).to_le_bytes());
426 data.extend_from_slice(field_bytes);
427
428 let value_bytes = value.as_bytes();
429 data.extend_from_slice(&(value_bytes.len() as u32).to_le_bytes());
430 data.extend_from_slice(value_bytes);
431
432 Instruction {
433 program_id: TOKEN_2022_ID,
434 accounts: vec![
435 AccountMeta::new(*mint, false),
436 AccountMeta::new_readonly(*update_authority, true),
437 ],
438 data,
439 }
440}
441
442#[must_use]
448pub fn initialize_group_pointer(
449 mint: &[u8; 32],
450 authority: Option<&[u8; 32]>,
451 group_address: &[u8; 32],
452) -> Instruction {
453 let mut data = vec![40, 0]; match authority {
455 Some(auth) => {
456 data.push(1);
457 data.extend_from_slice(auth);
458 }
459 None => {
460 data.push(0);
461 data.extend_from_slice(&[0u8; 32]);
462 }
463 }
464 data.extend_from_slice(group_address);
465 Instruction {
466 program_id: TOKEN_2022_ID,
467 accounts: vec![AccountMeta::new(*mint, false)],
468 data,
469 }
470}
471
472#[must_use]
474pub fn initialize_group_member_pointer(
475 mint: &[u8; 32],
476 authority: Option<&[u8; 32]>,
477 member_address: &[u8; 32],
478) -> Instruction {
479 let mut data = vec![41, 0]; match authority {
481 Some(auth) => {
482 data.push(1);
483 data.extend_from_slice(auth);
484 }
485 None => {
486 data.push(0);
487 data.extend_from_slice(&[0u8; 32]);
488 }
489 }
490 data.extend_from_slice(member_address);
491 Instruction {
492 program_id: TOKEN_2022_ID,
493 accounts: vec![AccountMeta::new(*mint, false)],
494 data,
495 }
496}
497
498#[cfg(test)]
503#[allow(clippy::unwrap_used, clippy::expect_used)]
504mod tests {
505 use super::*;
506
507 const MINT: [u8; 32] = [0xAA; 32];
508 const AUTH: [u8; 32] = [0xBB; 32];
509 const DEST: [u8; 32] = [0xCC; 32];
510
511 #[test]
514 fn test_token_2022_program_id_length() {
515 assert_eq!(TOKEN_2022_ID.len(), 32);
516 }
517
518 #[test]
519 fn test_all_instructions_use_token_2022_id() {
520 let ix1 = initialize_default_account_state(&MINT, AccountState::Frozen);
521 let ix2 = initialize_transfer_fee_config(&MINT, None, None, 0, 0);
522 let ix3 = initialize_transfer_hook(&MINT, None, &[0; 32]);
523 let ix4 = enable_cpi_guard(&MINT, &AUTH);
524 let ix5 = initialize_permanent_delegate(&MINT, &AUTH);
525 let ix6 = enable_required_memo_transfers(&MINT, &AUTH);
526 let ix7 = initialize_interest_bearing_config(&MINT, None, 0);
527 for ix in [ix1, ix2, ix3, ix4, ix5, ix6, ix7] {
528 assert_eq!(ix.program_id, TOKEN_2022_ID);
529 }
530 }
531
532 #[test]
535 fn test_initialize_default_account_state() {
536 let ix = initialize_default_account_state(&MINT, AccountState::Frozen);
537 assert_eq!(ix.data[0], 29);
538 assert_eq!(ix.data[1], 0);
539 assert_eq!(ix.data[2], 2); }
541
542 #[test]
543 fn test_initialize_default_account_state_initialized() {
544 let ix = initialize_default_account_state(&MINT, AccountState::Initialized);
545 assert_eq!(ix.data[2], 1);
546 }
547
548 #[test]
549 fn test_initialize_default_account_state_uninitialized() {
550 let ix = initialize_default_account_state(&MINT, AccountState::Uninitialized);
551 assert_eq!(ix.data[2], 0);
552 }
553
554 #[test]
555 fn test_update_default_account_state() {
556 let ix = update_default_account_state(&MINT, &AUTH, AccountState::Initialized);
557 assert_eq!(ix.data[0], 29);
558 assert_eq!(ix.data[1], 1);
559 assert_eq!(ix.data[2], 1);
560 assert_eq!(ix.accounts.len(), 2);
561 }
562
563 #[test]
564 fn test_update_default_account_state_accounts() {
565 let ix = update_default_account_state(&MINT, &AUTH, AccountState::Frozen);
566 assert_eq!(ix.accounts[0].pubkey, MINT);
567 assert!(!ix.accounts[0].is_signer);
568 assert_eq!(ix.accounts[1].pubkey, AUTH);
569 assert!(ix.accounts[1].is_signer);
570 }
571
572 #[test]
575 fn test_initialize_transfer_fee_config() {
576 let ix = initialize_transfer_fee_config(&MINT, Some(&AUTH), Some(&DEST), 100, 1_000_000);
577 assert_eq!(ix.data[0], 26);
578 assert_eq!(ix.data[1], 0);
579 assert!(ix.data.len() > 70);
580 }
581
582 #[test]
583 fn test_initialize_transfer_fee_config_data_structure() {
584 let ix = initialize_transfer_fee_config(
585 &MINT,
586 Some(&AUTH),
587 Some(&DEST),
588 200, 5_000_000,
590 );
591 assert_eq!(ix.data[0], 26);
593 assert_eq!(ix.data[1], 0);
594 assert_eq!(ix.data[2], 1); assert_eq!(&ix.data[3..35], &AUTH);
596 assert_eq!(ix.data[35], 1); assert_eq!(&ix.data[36..68], &DEST);
598 let bps = u16::from_le_bytes([ix.data[68], ix.data[69]]);
600 assert_eq!(bps, 200);
601 let max_fee = u64::from_le_bytes(ix.data[70..78].try_into().unwrap());
603 assert_eq!(max_fee, 5_000_000);
604 }
605
606 #[test]
607 fn test_initialize_transfer_fee_config_no_authorities() {
608 let ix = initialize_transfer_fee_config(&MINT, None, None, 50, 500);
609 assert_eq!(ix.data[0], 26);
610 assert_eq!(ix.data[2], 0); assert_eq!(&ix.data[3..35], &[0u8; 32]); assert_eq!(ix.data[35], 0); }
614
615 #[test]
616 fn test_harvest_withheld_tokens() {
617 let accounts = vec![[0x11; 32], [0x22; 32]];
618 let ix = harvest_withheld_tokens_to_mint(&MINT, &accounts);
619 assert_eq!(ix.data, vec![26, 4]);
620 assert_eq!(ix.accounts.len(), 3);
621 }
622
623 #[test]
624 fn test_harvest_withheld_tokens_empty() {
625 let ix = harvest_withheld_tokens_to_mint(&MINT, &[]);
626 assert_eq!(ix.accounts.len(), 1); }
628
629 #[test]
630 fn test_harvest_withheld_tokens_many() {
631 let accounts: Vec<[u8; 32]> = (0..10).map(|i| [i; 32]).collect();
632 let ix = harvest_withheld_tokens_to_mint(&MINT, &accounts);
633 assert_eq!(ix.accounts.len(), 11); }
635
636 #[test]
637 fn test_withdraw_withheld_tokens() {
638 let ix = withdraw_withheld_tokens_from_mint(&MINT, &DEST, &AUTH);
639 assert_eq!(ix.data, vec![26, 3]);
640 assert_eq!(ix.accounts.len(), 3);
641 assert_eq!(ix.accounts[0].pubkey, MINT);
642 assert_eq!(ix.accounts[1].pubkey, DEST);
643 assert_eq!(ix.accounts[2].pubkey, AUTH);
644 assert!(ix.accounts[2].is_signer);
645 }
646
647 #[test]
650 fn test_initialize_transfer_hook() {
651 let hook_program = [0xDD; 32];
652 let ix = initialize_transfer_hook(&MINT, Some(&AUTH), &hook_program);
653 assert_eq!(ix.data[0], 36);
654 assert_eq!(ix.data[1], 0);
655 assert_eq!(ix.data[2], 1); assert_eq!(&ix.data[3..35], &AUTH);
657 assert_eq!(&ix.data[35..67], &hook_program);
658 }
659
660 #[test]
661 fn test_initialize_transfer_hook_no_authority() {
662 let hook_program = [0xDD; 32];
663 let ix = initialize_transfer_hook(&MINT, None, &hook_program);
664 assert_eq!(ix.data[2], 0); assert_eq!(&ix.data[3..35], &[0u8; 32]);
666 assert_eq!(&ix.data[35..67], &hook_program);
667 }
668
669 #[test]
670 fn test_update_transfer_hook() {
671 let new_program = [0xEE; 32];
672 let ix = update_transfer_hook(&MINT, &AUTH, &new_program);
673 assert_eq!(ix.data[0], 36);
674 assert_eq!(ix.data[1], 1);
675 assert_eq!(&ix.data[2..34], &new_program);
676 }
677
678 #[test]
679 fn test_update_transfer_hook_accounts() {
680 let ix = update_transfer_hook(&MINT, &AUTH, &[0; 32]);
681 assert_eq!(ix.accounts[0].pubkey, MINT);
682 assert!(!ix.accounts[0].is_signer);
683 assert_eq!(ix.accounts[1].pubkey, AUTH);
684 assert!(ix.accounts[1].is_signer);
685 }
686
687 #[test]
690 fn test_enable_cpi_guard() {
691 let ix = enable_cpi_guard(&MINT, &AUTH);
692 assert_eq!(ix.data, vec![37, 0]);
693 assert_eq!(ix.accounts.len(), 2);
694 }
695
696 #[test]
697 fn test_disable_cpi_guard() {
698 let ix = disable_cpi_guard(&MINT, &AUTH);
699 assert_eq!(ix.data, vec![37, 1]);
700 }
701
702 #[test]
703 fn test_cpi_guard_toggle_differ() {
704 let enable = enable_cpi_guard(&MINT, &AUTH);
705 let disable = disable_cpi_guard(&MINT, &AUTH);
706 assert_ne!(enable.data, disable.data);
707 }
708
709 #[test]
712 fn test_initialize_permanent_delegate() {
713 let ix = initialize_permanent_delegate(&MINT, &AUTH);
714 assert_eq!(ix.data[0], 35);
715 assert_eq!(ix.data[1], 0);
716 assert_eq!(&ix.data[2..34], &AUTH);
717 assert_eq!(ix.accounts.len(), 1);
718 }
719
720 #[test]
721 fn test_permanent_delegate_data_length() {
722 let ix = initialize_permanent_delegate(&MINT, &AUTH);
723 assert_eq!(ix.data.len(), 2 + 32); }
725
726 #[test]
729 fn test_enable_required_memo() {
730 let ix = enable_required_memo_transfers(&MINT, &AUTH);
731 assert_eq!(ix.data, vec![30, 0]);
732 }
733
734 #[test]
735 fn test_disable_required_memo() {
736 let ix = disable_required_memo_transfers(&MINT, &AUTH);
737 assert_eq!(ix.data, vec![30, 1]);
738 }
739
740 #[test]
741 fn test_memo_toggle_differ() {
742 let enable = enable_required_memo_transfers(&MINT, &AUTH);
743 let disable = disable_required_memo_transfers(&MINT, &AUTH);
744 assert_ne!(enable.data, disable.data);
745 }
746
747 #[test]
750 fn test_initialize_interest_bearing() {
751 let ix = initialize_interest_bearing_config(&MINT, Some(&AUTH), 500);
752 assert_eq!(ix.data[0], 33);
753 assert_eq!(ix.data[1], 0);
754 assert_eq!(ix.data[2], 1); let rate_offset = ix.data.len() - 2;
756 let rate = i16::from_le_bytes([ix.data[rate_offset], ix.data[rate_offset + 1]]);
757 assert_eq!(rate, 500);
758 }
759
760 #[test]
761 fn test_initialize_interest_bearing_no_authority() {
762 let ix = initialize_interest_bearing_config(&MINT, None, 100);
763 assert_eq!(ix.data[2], 0); assert_eq!(&ix.data[3..35], &[0u8; 32]);
765 }
766
767 #[test]
768 fn test_initialize_interest_bearing_negative_rate() {
769 let ix = initialize_interest_bearing_config(&MINT, Some(&AUTH), -500);
770 let rate_offset = ix.data.len() - 2;
771 let rate = i16::from_le_bytes([ix.data[rate_offset], ix.data[rate_offset + 1]]);
772 assert_eq!(rate, -500);
773 }
774
775 #[test]
776 fn test_update_interest_rate() {
777 let ix = update_interest_rate(&MINT, &AUTH, -100);
778 assert_eq!(ix.data[0], 33);
779 assert_eq!(ix.data[1], 1);
780 let rate = i16::from_le_bytes([ix.data[2], ix.data[3]]);
781 assert_eq!(rate, -100);
782 }
783
784 #[test]
785 fn test_update_interest_rate_positive() {
786 let ix = update_interest_rate(&MINT, &AUTH, 1000);
787 let rate = i16::from_le_bytes([ix.data[2], ix.data[3]]);
788 assert_eq!(rate, 1000);
789 }
790
791 #[test]
794 fn test_initialize_token_metadata() {
795 let ix = initialize_token_metadata(
796 &MINT,
797 &AUTH,
798 &AUTH,
799 "Test Token",
800 "TEST",
801 "https://example.com/meta.json",
802 );
803 assert_eq!(ix.program_id, TOKEN_2022_ID);
804 assert_eq!(ix.accounts.len(), 3);
805 assert_eq!(ix.data.len(), 8 + 4 + 10 + 4 + 4 + 4 + 29);
806 }
807
808 #[test]
809 fn test_initialize_token_metadata_discriminator() {
810 let ix = initialize_token_metadata(&MINT, &AUTH, &AUTH, "X", "Y", "Z");
811 assert_eq!(&ix.data[0..8], &[210, 225, 30, 162, 88, 184, 226, 143]);
813 }
814
815 #[test]
816 fn test_initialize_token_metadata_string_encoding() {
817 let ix = initialize_token_metadata(&MINT, &AUTH, &AUTH, "MyToken", "MTK", "https://uri");
818 let name_len = u32::from_le_bytes(ix.data[8..12].try_into().unwrap());
821 assert_eq!(name_len, 7);
822 assert_eq!(&ix.data[12..19], b"MyToken");
823 let sym_len = u32::from_le_bytes(ix.data[19..23].try_into().unwrap());
825 assert_eq!(sym_len, 3);
826 assert_eq!(&ix.data[23..26], b"MTK");
827 let uri_len = u32::from_le_bytes(ix.data[26..30].try_into().unwrap());
829 assert_eq!(uri_len, 11);
830 assert_eq!(&ix.data[30..41], b"https://uri");
831 }
832
833 #[test]
834 fn test_initialize_token_metadata_accounts() {
835 let mint_auth = [0xDD; 32];
836 let ix = initialize_token_metadata(&MINT, &AUTH, &mint_auth, "X", "Y", "Z");
837 assert_eq!(ix.accounts[0].pubkey, MINT);
838 assert!(!ix.accounts[0].is_signer);
839 assert_eq!(ix.accounts[1].pubkey, AUTH);
840 assert!(!ix.accounts[1].is_signer); assert_eq!(ix.accounts[2].pubkey, mint_auth);
842 assert!(ix.accounts[2].is_signer); }
844
845 #[test]
846 fn test_update_token_metadata_field() {
847 let ix = update_token_metadata_field(&MINT, &AUTH, "name", "New Name");
848 assert_eq!(ix.program_id, TOKEN_2022_ID);
849 assert_eq!(ix.accounts.len(), 2);
850 assert_eq!(ix.data.len(), 8 + 4 + 4 + 4 + 8);
851 }
852
853 #[test]
854 fn test_update_token_metadata_field_discriminator() {
855 let ix = update_token_metadata_field(&MINT, &AUTH, "x", "y");
856 assert_eq!(&ix.data[0..8], &[221, 233, 49, 45, 181, 202, 220, 200]);
857 }
858
859 #[test]
860 fn test_update_token_metadata_field_encoding() {
861 let ix = update_token_metadata_field(&MINT, &AUTH, "uri", "https://new");
862 let field_len = u32::from_le_bytes(ix.data[8..12].try_into().unwrap());
863 assert_eq!(field_len, 3);
864 assert_eq!(&ix.data[12..15], b"uri");
865 let val_len = u32::from_le_bytes(ix.data[15..19].try_into().unwrap());
866 assert_eq!(val_len, 11);
867 assert_eq!(&ix.data[19..30], b"https://new");
868 }
869
870 #[test]
873 fn test_initialize_group_pointer() {
874 let group_addr = [0xFF; 32];
875 let ix = initialize_group_pointer(&MINT, Some(&AUTH), &group_addr);
876 assert_eq!(ix.data[0], 40);
877 assert_eq!(ix.data[1], 0);
878 assert_eq!(ix.data[2], 1); assert_eq!(&ix.data[3..35], &AUTH);
880 assert_eq!(&ix.data[35..67], &group_addr);
881 }
882
883 #[test]
884 fn test_initialize_group_pointer_no_authority() {
885 let group_addr = [0xFF; 32];
886 let ix = initialize_group_pointer(&MINT, None, &group_addr);
887 assert_eq!(ix.data[2], 0); assert_eq!(&ix.data[3..35], &[0u8; 32]);
889 }
890
891 #[test]
892 fn test_initialize_group_member_pointer() {
893 let member_addr = [0xEE; 32];
894 let ix = initialize_group_member_pointer(&MINT, None, &member_addr);
895 assert_eq!(ix.data[0], 41);
896 assert_eq!(ix.data[1], 0);
897 assert_eq!(ix.data[2], 0); }
899
900 #[test]
901 fn test_initialize_group_member_pointer_with_authority() {
902 let member_addr = [0xEE; 32];
903 let ix = initialize_group_member_pointer(&MINT, Some(&AUTH), &member_addr);
904 assert_eq!(ix.data[2], 1); assert_eq!(&ix.data[3..35], &AUTH);
906 assert_eq!(&ix.data[35..67], &member_addr);
907 }
908
909 #[test]
912 fn test_account_state_values() {
913 assert_eq!(AccountState::Uninitialized as u8, 0);
914 assert_eq!(AccountState::Initialized as u8, 1);
915 assert_eq!(AccountState::Frozen as u8, 2);
916 }
917
918 #[test]
919 fn test_account_state_eq() {
920 assert_eq!(AccountState::Frozen, AccountState::Frozen);
921 assert_ne!(AccountState::Frozen, AccountState::Initialized);
922 }
923
924 #[test]
927 fn test_all_discriminator_values() {
928 let discriminators = [
930 initialize_transfer_fee_config(&MINT, None, None, 0, 0).data[0], initialize_default_account_state(&MINT, AccountState::Frozen).data[0], enable_required_memo_transfers(&MINT, &AUTH).data[0], initialize_interest_bearing_config(&MINT, None, 0).data[0], initialize_permanent_delegate(&MINT, &AUTH).data[0], initialize_transfer_hook(&MINT, None, &[0; 32]).data[0], enable_cpi_guard(&MINT, &AUTH).data[0], initialize_group_pointer(&MINT, None, &[0; 32]).data[0], initialize_group_member_pointer(&MINT, None, &[0; 32]).data[0], ];
940 assert_eq!(discriminators, [26, 29, 30, 33, 35, 36, 37, 40, 41]);
941 }
942}