light_token_interface/
token_2022_extensions.rs1use light_zero_copy::errors::ZeroCopyError;
2use spl_token_2022::extension::ExtensionType;
3
4use crate::state::ExtensionStructConfig;
5
6pub const RESTRICTED_EXTENSION_TYPES: [ExtensionType; 5] = [
10 ExtensionType::Pausable,
11 ExtensionType::PermanentDelegate,
12 ExtensionType::TransferFeeConfig,
13 ExtensionType::TransferHook,
14 ExtensionType::DefaultAccountState,
15];
16
17pub const ALLOWED_EXTENSION_TYPES: [ExtensionType; 16] = [
25 ExtensionType::MetadataPointer,
27 ExtensionType::TokenMetadata,
28 ExtensionType::InterestBearingConfig,
30 ExtensionType::GroupPointer,
31 ExtensionType::GroupMemberPointer,
32 ExtensionType::TokenGroup,
33 ExtensionType::TokenGroupMember,
34 ExtensionType::MintCloseAuthority,
36 ExtensionType::TransferFeeConfig,
37 ExtensionType::DefaultAccountState,
38 ExtensionType::PermanentDelegate,
39 ExtensionType::TransferHook,
40 ExtensionType::Pausable,
41 ExtensionType::ConfidentialTransferMint,
42 ExtensionType::ConfidentialTransferFeeConfig,
43 ExtensionType::ConfidentialMintBurn,
44];
45
46#[inline(always)]
48pub const fn is_restricted_extension(ext: &ExtensionType) -> bool {
49 matches!(
50 ext,
51 ExtensionType::Pausable
52 | ExtensionType::PermanentDelegate
53 | ExtensionType::TransferFeeConfig
54 | ExtensionType::TransferHook
55 | ExtensionType::DefaultAccountState
56 )
57}
58
59#[derive(Debug, Default, Clone, Copy)]
61pub struct MintExtensionFlags {
62 pub has_pausable: bool,
64 pub has_permanent_delegate: bool,
66 pub has_default_account_state: bool,
68 pub default_state_frozen: bool,
70 pub has_transfer_fee: bool,
72 pub has_transfer_hook: bool,
74}
75
76impl MintExtensionFlags {
77 pub fn num_token_account_extensions(&self) -> usize {
78 let mut count = 0;
79 if self.has_pausable {
80 count += 1;
81 }
82 if self.has_permanent_delegate {
83 count += 1;
84 }
85 if self.has_transfer_fee {
86 count += 1;
87 }
88 if self.has_transfer_hook {
89 count += 1;
90 }
91 count
92 }
93
94 pub fn calculate_account_size(&self, compressible: bool) -> Result<u64, ZeroCopyError> {
103 let mut extensions: [ExtensionStructConfig; 5] = [
106 ExtensionStructConfig::Placeholder0,
107 ExtensionStructConfig::Placeholder0,
108 ExtensionStructConfig::Placeholder0,
109 ExtensionStructConfig::Placeholder0,
110 ExtensionStructConfig::Placeholder0,
111 ];
112 let mut count = 0;
113
114 if self.has_pausable {
115 extensions[count] = ExtensionStructConfig::PausableAccount(());
116 count += 1;
117 }
118 if self.has_permanent_delegate {
119 extensions[count] = ExtensionStructConfig::PermanentDelegateAccount(());
120 count += 1;
121 }
122 if self.has_transfer_fee {
123 extensions[count] = ExtensionStructConfig::TransferFeeAccount(());
124 count += 1;
125 }
126 if self.has_transfer_hook {
127 extensions[count] = ExtensionStructConfig::TransferHookAccount(());
128 count += 1;
129 }
130 if compressible {
131 extensions[count] =
132 ExtensionStructConfig::Compressible(crate::state::CompressibleExtensionConfig {
133 info: crate::state::CompressionInfoConfig { rent_config: () },
134 });
135 count += 1;
136 }
137
138 let exts = if count == 0 {
139 None
140 } else {
141 Some(&extensions[..count])
142 };
143 crate::state::calculate_token_account_size(exts).map(|size| size as u64)
144 }
145
146 pub const fn has_restricted_extensions(&self) -> bool {
150 self.has_pausable
151 || self.has_permanent_delegate
152 || self.has_transfer_fee
153 || self.has_transfer_hook
154 || self.has_default_account_state
155 }
156}