ntoken_solana_models/states/
admin.rs1use 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 pub user_admin_account: Pubkey,
24 pub state: u8,
26}
27impl UserAdminStruct {
28 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 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 pub type_account: u8,
47 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]; 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]); 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}