models_ntoken/states/
admin.rs

1use 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    ///The account of admin.
22    pub user_admin_account: Pubkey,
23    /// true if the use  is admin and false the use is deleted .
24    pub state: u8,
25}
26impl UserAdminStruct {
27    /// add new user admin
28    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    /// delete an admin from the list
34    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    /// The type of account.
45    pub type_account: u8,
46    /// list_admins: : list of [`UserAdminStruct`].
47    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]; // maximum 10 admins
96        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]); // 0..8 : 8 bytes contain length of struct
98        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}