ntoken_solana_models/states/
admin.rs

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