1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use {
crate::ID,
solana_account_view::{AccountView, Ref},
solana_address::Address,
solana_program_error::ProgramError,
};
/// Mint data.
#[repr(C)]
pub struct Mint {
/// Indicates whether the mint authority is present or not.
mint_authority_flag: [u8; 4],
/// Optional authority used to mint new tokens. The mint authority may only
/// be provided during mint creation. If no mint authority is present
/// then the mint has a fixed supply and no further tokens may be
/// minted.
mint_authority: Address,
/// Total supply of tokens.
supply: [u8; 8],
/// Number of base 10 digits to the right of the decimal place.
decimals: u8,
/// Is `true` if this structure has been initialized.
is_initialized: u8,
/// Indicates whether the freeze authority is present or not.
freeze_authority_flag: [u8; 4],
/// Optional authority to freeze token accounts.
freeze_authority: Address,
}
impl Mint {
/// The length of the `Mint` account data.
pub const LEN: usize = core::mem::size_of::<Mint>();
/// Return a `Mint` from the given account view.
///
/// This method performs owner and length validation on `AccountView`, safe
/// borrowing the account data.
#[inline]
pub fn from_account_view(account_view: &AccountView) -> Result<Ref<'_, Mint>, ProgramError> {
if account_view.data_len() != Self::LEN {
return Err(ProgramError::InvalidAccountData);
}
if !account_view.owned_by(&ID) {
return Err(ProgramError::InvalidAccountOwner);
}
Ok(Ref::map(account_view.try_borrow()?, |data| unsafe {
Self::from_bytes_unchecked(data)
}))
}
/// Return a `Mint` from the given account view.
///
/// This method performs owner and length validation on `AccountView`, but
/// does not perform the borrow check.
///
/// # Safety
///
/// The caller must ensure that it is safe to borrow the account data (e.g.,
/// there are no mutable borrows of the account data).
#[inline]
pub unsafe fn from_account_view_unchecked(
account_view: &AccountView,
) -> Result<&Self, ProgramError> {
if account_view.data_len() != Self::LEN {
return Err(ProgramError::InvalidAccountData);
}
if account_view.owner() != &ID {
return Err(ProgramError::InvalidAccountOwner);
}
Ok(Self::from_bytes_unchecked(account_view.borrow_unchecked()))
}
/// Return a `Mint` from the given bytes.
///
/// # Safety
///
/// The caller must ensure that `bytes` contains a valid representation of
/// `Mint`, and it is properly aligned to be interpreted as an instance
/// of `Mint`. At the moment `Mint` has an alignment of 1 byte.
/// This method does not perform a length validation.
#[inline(always)]
pub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
&*(bytes.as_ptr() as *const Mint)
}
#[inline(always)]
pub fn has_mint_authority(&self) -> bool {
self.mint_authority_flag[0] == 1
}
pub fn mint_authority(&self) -> Option<&Address> {
if self.has_mint_authority() {
Some(self.mint_authority_unchecked())
} else {
None
}
}
/// Return the mint authority.
///
/// This method should be used when the caller knows that the mint will have
/// a mint authority set since it skips the `Option` check.
#[inline(always)]
pub fn mint_authority_unchecked(&self) -> &Address {
&self.mint_authority
}
pub fn supply(&self) -> u64 {
u64::from_le_bytes(self.supply)
}
pub fn decimals(&self) -> u8 {
self.decimals
}
pub fn is_initialized(&self) -> bool {
self.is_initialized == 1
}
#[inline(always)]
pub fn has_freeze_authority(&self) -> bool {
self.freeze_authority_flag[0] == 1
}
pub fn freeze_authority(&self) -> Option<&Address> {
if self.has_freeze_authority() {
Some(self.freeze_authority_unchecked())
} else {
None
}
}
/// Return the freeze authority.
///
/// This method should be used when the caller knows that the mint will have
/// a freeze authority set since it skips the `Option` check.
#[inline(always)]
pub fn freeze_authority_unchecked(&self) -> &Address {
&self.freeze_authority
}
}