pinocchio_token/state/
token.rs1use super::AccountState;
2use pinocchio::{
3 account_info::{AccountInfo, Ref},
4 program_error::ProgramError,
5 pubkey::Pubkey,
6};
7
8use crate::ID;
9
10#[repr(C)]
12pub struct TokenAccount {
13 mint: Pubkey,
15
16 owner: Pubkey,
18
19 amount: [u8; 8],
21
22 delegate_flag: [u8; 4],
24
25 delegate: Pubkey,
28
29 state: u8,
31
32 is_native: [u8; 4],
34
35 native_amount: [u8; 8],
40
41 delegated_amount: [u8; 8],
43
44 close_authority_flag: [u8; 4],
46
47 close_authority: Pubkey,
49}
50
51impl TokenAccount {
52 pub const LEN: usize = core::mem::size_of::<TokenAccount>();
53
54 #[inline]
59 pub fn from_account_info(
60 account_info: &AccountInfo,
61 ) -> Result<Ref<TokenAccount>, ProgramError> {
62 if account_info.data_len() != Self::LEN {
63 return Err(ProgramError::InvalidAccountData);
64 }
65 if !account_info.is_owned_by(&ID) {
66 return Err(ProgramError::InvalidAccountData);
67 }
68 Ok(Ref::map(account_info.try_borrow_data()?, |data| unsafe {
69 Self::from_bytes(data)
70 }))
71 }
72
73 #[inline]
83 pub unsafe fn from_account_info_unchecked(
84 account_info: &AccountInfo,
85 ) -> Result<&TokenAccount, ProgramError> {
86 if account_info.data_len() != Self::LEN {
87 return Err(ProgramError::InvalidAccountData);
88 }
89 if account_info.owner() != &ID {
90 return Err(ProgramError::InvalidAccountData);
91 }
92 Ok(Self::from_bytes(account_info.borrow_data_unchecked()))
93 }
94
95 #[inline(always)]
101 pub unsafe fn from_bytes(bytes: &[u8]) -> &Self {
102 &*(bytes.as_ptr() as *const TokenAccount)
103 }
104
105 pub fn mint(&self) -> &Pubkey {
106 &self.mint
107 }
108
109 pub fn owner(&self) -> &Pubkey {
110 &self.owner
111 }
112
113 pub fn amount(&self) -> u64 {
114 unsafe { core::ptr::read_unaligned(self.amount.as_ptr() as *const u64) }
115 }
116
117 #[inline(always)]
118 pub fn has_delegate(&self) -> bool {
119 self.delegate_flag[0] == 1
120 }
121
122 pub fn delegate(&self) -> Option<&Pubkey> {
123 if self.has_delegate() {
124 Some(self.delegate_unchecked())
125 } else {
126 None
127 }
128 }
129
130 #[inline(always)]
132 pub fn delegate_unchecked(&self) -> &Pubkey {
133 &self.delegate
134 }
135
136 #[inline(always)]
137 pub fn state(&self) -> AccountState {
138 self.state.into()
139 }
140
141 #[inline(always)]
142 pub fn is_native(&self) -> bool {
143 self.is_native[0] == 1
144 }
145
146 pub fn native_amount(&self) -> Option<u64> {
147 if self.is_native() {
148 Some(self.native_amount_unchecked())
149 } else {
150 None
151 }
152 }
153
154 #[inline(always)]
159 pub fn native_amount_unchecked(&self) -> u64 {
160 unsafe { core::ptr::read_unaligned(self.native_amount.as_ptr() as *const u64) }
161 }
162
163 pub fn delegated_amount(&self) -> u64 {
164 unsafe { core::ptr::read_unaligned(self.delegated_amount.as_ptr() as *const u64) }
165 }
166
167 #[inline(always)]
168 pub fn has_close_authority(&self) -> bool {
169 self.close_authority_flag[0] == 1
170 }
171
172 pub fn close_authority(&self) -> Option<&Pubkey> {
173 if self.has_close_authority() {
174 Some(self.close_authority_unchecked())
175 } else {
176 None
177 }
178 }
179
180 #[inline(always)]
185 pub fn close_authority_unchecked(&self) -> &Pubkey {
186 &self.close_authority
187 }
188
189 #[inline(always)]
190 pub fn is_initialized(&self) -> bool {
191 self.state != AccountState::Uninitialized as u8
192 }
193
194 #[inline(always)]
195 pub fn is_frozen(&self) -> bool {
196 self.state == AccountState::Frozen as u8
197 }
198}