models_ntoken/states/
admin.rs1use crate::constants::{
2 account_size::{ADMIN_ACCOUNT_SIZE, NUMBER_OF_ADMINS, USER_ADMIN_SIZE, ADMIN_ACCOUNT_PREFIX_SIZE},
3 constant::PUBKEY_SIZE,
4 account_type::TYPE_ACCOUNT_ADMIN_ACCOUNT,
5};
6use anchor_lang::prelude::{ProgramError, Pubkey};
7use arrayref::{array_mut_ref, array_ref, array_refs};
8use serde::{Deserialize, Serialize};
9use solana_program::{
10 entrypoint_deprecated::ProgramResult,
11 program_pack::{IsInitialized, Pack, Sealed},
12};
13
14const STATE_ADMIN_SIZE: usize = 1;
15const TYPE_SIZE: usize = 1;
16
17#[repr(C)]
18#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
19
20pub struct UserAdminStruct {
21 pub user_admin_account: Pubkey,
23 pub state: u8,
25}
26impl UserAdminStruct {
27 pub fn add_admin(&mut self, user_admin_account: Pubkey) -> ProgramResult {
29 self.user_admin_account = user_admin_account;
30 self.state = 1;
31 Ok(())
32 }
33 pub fn delete_admin(&mut self) -> ProgramResult {
35 self.state = 0;
36 Ok(())
37 }
38}
39
40#[repr(C)]
41#[derive(Clone, Debug, Default, PartialEq)]
42
43pub struct AdminAccount {
44 pub type_account: u8,
46 pub list_admins: Vec<UserAdminStruct>,
48}
49
50impl Sealed for AdminAccount {}
51
52impl IsInitialized for AdminAccount {
53 fn is_initialized(&self) -> bool {
54 return self.type_account == TYPE_ACCOUNT_ADMIN_ACCOUNT;
55 }
56}
57
58impl Pack for AdminAccount {
59 const LEN: usize = ADMIN_ACCOUNT_SIZE;
60 fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
61 let src = array_ref![src, 0, ADMIN_ACCOUNT_SIZE];
62 let (type_account, list_admins) =
63 array_refs![src, TYPE_SIZE, USER_ADMIN_SIZE * NUMBER_OF_ADMINS];
64
65 let mut user_admin_vec: Vec<UserAdminStruct> = Vec::with_capacity(NUMBER_OF_ADMINS);
66 let mut offset = 0;
67 for _ in 0..NUMBER_OF_ADMINS {
68 let user_data = array_ref![list_admins, offset, USER_ADMIN_SIZE];
69 #[allow(clippy::ptr_offset_with_cast)]
70 let (user_admin_account, state) = array_refs![user_data, PUBKEY_SIZE, STATE_ADMIN_SIZE];
71 user_admin_vec.push(UserAdminStruct {
72 user_admin_account: Pubkey::new_from_array(*user_admin_account),
73 state: u8::from_le_bytes(*state),
74 });
75 offset += USER_ADMIN_SIZE;
76 }
77
78 Ok(AdminAccount {
79 type_account: u8::from_le_bytes(*type_account),
80 list_admins: user_admin_vec.to_vec(),
81 })
82 }
83
84 fn pack_into_slice(&self, dst: &mut [u8]) {
85 let dst = array_mut_ref![dst, 0, ADMIN_ACCOUNT_SIZE];
86 let AdminAccount {
87 type_account,
88 list_admins,
89 } = self;
90
91 let mut buffer = [0; ADMIN_ACCOUNT_SIZE];
92 buffer[0] = *type_account;
93
94 let admin_vec_tmp = bincode::serialize(&list_admins).unwrap();
95 let mut admin_data_tmp = [0; USER_ADMIN_SIZE * NUMBER_OF_ADMINS]; admin_data_tmp[0..USER_ADMIN_SIZE * NUMBER_OF_ADMINS as usize]
97 .clone_from_slice(&admin_vec_tmp[8..(USER_ADMIN_SIZE * NUMBER_OF_ADMINS) + 8]); buffer[ADMIN_ACCOUNT_PREFIX_SIZE..ADMIN_ACCOUNT_SIZE]
99 .clone_from_slice(&admin_data_tmp[0..USER_ADMIN_SIZE * NUMBER_OF_ADMINS as usize]);
100 dst[0..ADMIN_ACCOUNT_SIZE].copy_from_slice(&buffer[0..ADMIN_ACCOUNT_SIZE]);
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use crate::constants::account_type::TYPE_ACCOUNT_ADMIN_ACCOUNT;
108 #[test]
109 fn test_pack_admin() {
110 let mut list_admins = Vec::new();
111 for _i in 0..NUMBER_OF_ADMINS {
112 let user_admin = UserAdminStruct {
113 user_admin_account: Pubkey::new_unique(),
114 state: 1,
115 };
116
117 list_admins.push(user_admin);
118 }
119
120 let admin_account = AdminAccount {
121 type_account: TYPE_ACCOUNT_ADMIN_ACCOUNT,
122 list_admins,
123 };
124
125 let mut packed = [0u8; AdminAccount::LEN];
126
127 Pack::pack_into_slice(&admin_account, &mut packed[..]);
128 let unpacked = AdminAccount::unpack_from_slice(&packed).unwrap();
129 assert_eq!(admin_account, unpacked);
130 assert_eq!(unpacked.type_account, TYPE_ACCOUNT_ADMIN_ACCOUNT);
131 }
132}