module_ntoken/states/
nft.rs

1use crate::constants::{
2    account_size::NFT_ACCOUNT_SIZE, constant::PUBKEY_SIZE, account_type::TYPE_ACCOUNT_NFT_ACCOUNT,
3};
4use anchor_lang::prelude::{ProgramError, Pubkey};
5use arrayref::{array_mut_ref, array_ref, array_refs, mut_array_refs};
6use serde::{Deserialize, Serialize};
7use solana_program::program_pack::{IsInitialized, Pack, Sealed};
8
9const TYPE_SIZE: usize = 1;
10const STAKE_SIZE: usize = 1;
11const NONCE_SIZE: usize = 1;
12
13/// Account data.
14#[repr(C)]
15#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
16pub struct NFTAccount {
17    /// The type of account.
18    pub type_account: u8,
19    /// The owner of this account.
20    pub owner: Pubkey,
21    /// The  user stake his nft token.
22    pub stake: u8,
23    ///  The signer used by cross program .
24    pub authority: Pubkey,
25    /// Nonce used in program address for invoke a cross-program instruction..
26    pub nonce: u8,
27    /// Create account program for cross program.
28    pub create_account_programm: Pubkey,
29}
30
31impl Sealed for NFTAccount {}
32
33impl IsInitialized for NFTAccount {
34    fn is_initialized(&self) -> bool {
35        return self.type_account == TYPE_ACCOUNT_NFT_ACCOUNT;
36    }
37}
38
39/// pack and unpack for nft account.
40impl Pack for NFTAccount {
41    const LEN: usize = NFT_ACCOUNT_SIZE;
42    // unpack nft account
43    fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError> {
44        let src = array_ref![src, 0, NFT_ACCOUNT_SIZE];
45        let (type_account, owner, stake, authority, nonce, create_account_programm) = array_refs![
46            src,
47            TYPE_SIZE,
48            PUBKEY_SIZE,
49            STAKE_SIZE,
50            PUBKEY_SIZE,
51            NONCE_SIZE,
52            PUBKEY_SIZE
53        ];
54        Ok(NFTAccount {
55            type_account: u8::from_le_bytes(*type_account),
56            owner: Pubkey::new_from_array(*owner),
57            stake: u8::from_le_bytes(*stake),
58            authority: Pubkey::new_from_array(*authority),
59            nonce: u8::from_le_bytes(*nonce),
60            create_account_programm: Pubkey::new_from_array(*create_account_programm),
61        })
62    }
63
64    // pack nft account
65    fn pack_into_slice(&self, dst: &mut [u8]) {
66        let dst = array_mut_ref![dst, 0, NFT_ACCOUNT_SIZE];
67        let (
68            type_account_dst,
69            owner_dst,
70            stake_dst,
71            authority_dst,
72            nonce_dst,
73            create_account_programm_dst,
74        ) = mut_array_refs![
75            dst,
76            TYPE_SIZE,
77            PUBKEY_SIZE,
78            STAKE_SIZE,
79            PUBKEY_SIZE,
80            NONCE_SIZE,
81            PUBKEY_SIZE
82        ];
83        let NFTAccount {
84            type_account,
85            owner,
86            stake,
87            authority,
88            nonce,
89            create_account_programm,
90        } = self;
91        *type_account_dst = type_account.to_le_bytes();
92        owner_dst.copy_from_slice(owner.as_ref());
93        *stake_dst = stake.to_le_bytes();
94        authority_dst.copy_from_slice(authority.as_ref());
95        *nonce_dst = nonce.to_le_bytes();
96        create_account_programm_dst.copy_from_slice(create_account_programm.as_ref());
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103    use crate::constants::account_type::TYPE_ACCOUNT_NFT_ACCOUNT;
104
105    #[test]
106    fn test_pack_nft() {
107        let type_account = TYPE_ACCOUNT_NFT_ACCOUNT;
108        let owner = Pubkey::new_unique();
109        let stake = 0;
110        let authority = Pubkey::new_unique();
111        let nonce = 255;
112        let create_account_programm = Pubkey::new_unique();
113
114        let nft = NFTAccount {
115            type_account,
116            owner,
117            stake,
118            authority,
119            nonce,
120            create_account_programm,
121        };
122
123        let mut packed = [0u8; NFTAccount::LEN];
124
125        Pack::pack_into_slice(&nft, &mut packed[..]);
126        let unpacked = NFTAccount::unpack_from_slice(&packed).unwrap();
127        assert_eq!(nft, unpacked);
128        assert_eq!(unpacked.type_account, TYPE_ACCOUNT_NFT_ACCOUNT);
129    }
130}