1use crate::hash::CryptoHash;
2use crate::serialize::dec_format;
3use crate::types::{Balance, Nonce, Power, StorageUsage};
4use borsh::{BorshDeserialize, BorshSerialize};
5use std::io;
6pub use unc_account_id as id;
7
8#[derive(
9 BorshSerialize,
10 BorshDeserialize,
11 PartialEq,
12 Eq,
13 Clone,
14 Copy,
15 Debug,
16 Default,
17 serde::Serialize,
18 serde::Deserialize,
19)]
20pub enum AccountVersion {
21 #[default]
22 V1,
23}
24
25#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug, Clone)]
27pub struct Account {
28 #[serde(with = "dec_format")]
30 amount: Balance,
31 #[serde(with = "dec_format")]
33 pledging: Balance,
34 #[serde(with = "dec_format")]
36 power: Power,
37 code_hash: CryptoHash,
39 storage_usage: StorageUsage,
41 #[serde(default)]
43 version: AccountVersion,
44}
45
46impl Account {
47 pub const MAX_ACCOUNT_DELETION_STORAGE_USAGE: u64 = 10_000;
50
51 pub fn new(
52 amount: Balance,
53 pledging: Balance,
54 power: Power,
55 code_hash: CryptoHash,
56 storage_usage: StorageUsage,
57 ) -> Self {
58 Account { amount, pledging, power, code_hash, storage_usage, version: AccountVersion::V1 }
59 }
60
61 #[inline]
62 pub fn amount(&self) -> Balance {
63 self.amount
64 }
65
66 #[inline]
67 pub fn pledging(&self) -> Balance {
68 self.pledging
69 }
70
71 #[inline]
72 pub fn power(&self) -> Power {
73 self.power
74 }
75
76 #[inline]
77 pub fn code_hash(&self) -> CryptoHash {
78 self.code_hash
79 }
80
81 #[inline]
82 pub fn storage_usage(&self) -> StorageUsage {
83 self.storage_usage
84 }
85
86 #[inline]
87 pub fn version(&self) -> AccountVersion {
88 self.version
89 }
90
91 #[inline]
92 pub fn set_amount(&mut self, amount: Balance) {
93 self.amount = amount;
94 }
95
96 #[inline]
97 pub fn set_power(&mut self, power: Power) {
98 self.power = power;
99 }
100
101 #[inline]
102 pub fn set_pledging(&mut self, pledging: Balance) {
103 self.pledging = pledging;
104 }
105
106 #[inline]
107 pub fn set_code_hash(&mut self, code_hash: CryptoHash) {
108 self.code_hash = code_hash;
109 }
110
111 #[inline]
112 pub fn set_storage_usage(&mut self, storage_usage: StorageUsage) {
113 self.storage_usage = storage_usage;
114 }
115
116 pub fn set_version(&mut self, version: AccountVersion) {
117 self.version = version;
118 }
119}
120
121#[derive(BorshSerialize, BorshDeserialize)]
122struct LegacyAccount {
123 amount: Balance,
124 pledging: Balance,
125 power: Power,
126 code_hash: CryptoHash,
127 storage_usage: StorageUsage,
128}
129
130impl BorshDeserialize for Account {
131 fn deserialize_reader<R: io::Read>(rd: &mut R) -> io::Result<Self> {
132 let deserialized_account = LegacyAccount::deserialize_reader(rd)?;
135 Ok(Account {
136 amount: deserialized_account.amount,
137 pledging: deserialized_account.pledging,
138 power: deserialized_account.power,
139 code_hash: deserialized_account.code_hash,
140 storage_usage: deserialized_account.storage_usage,
141 version: AccountVersion::V1,
142 })
143 }
144}
145
146impl BorshSerialize for Account {
147 fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
148 match self.version {
149 AccountVersion::V1 => LegacyAccount {
150 amount: self.amount,
151 pledging: self.pledging,
152 power: self.power,
153 code_hash: self.code_hash,
154 storage_usage: self.storage_usage,
155 }
156 .serialize(writer),
157 }
158 }
159}
160
161#[derive(
167 BorshSerialize,
168 BorshDeserialize,
169 PartialEq,
170 Eq,
171 Hash,
172 Clone,
173 Debug,
174 serde::Serialize,
175 serde::Deserialize,
176)]
177pub struct AccessKey {
178 pub nonce: Nonce,
181
182 pub permission: AccessKeyPermission,
184}
185
186impl AccessKey {
187 pub const ACCESS_KEY_NONCE_RANGE_MULTIPLIER: u64 = 1_000_000;
188
189 pub fn full_access() -> Self {
190 Self { nonce: 0, permission: AccessKeyPermission::FullAccess }
191 }
192}
193
194#[derive(
196 BorshSerialize,
197 BorshDeserialize,
198 PartialEq,
199 Eq,
200 Hash,
201 Clone,
202 Debug,
203 serde::Serialize,
204 serde::Deserialize,
205)]
206pub enum AccessKeyPermission {
207 FunctionCall(FunctionCallPermission),
208
209 FullAccess,
212}
213
214#[derive(
219 BorshSerialize,
220 BorshDeserialize,
221 serde::Serialize,
222 serde::Deserialize,
223 PartialEq,
224 Eq,
225 Hash,
226 Clone,
227 Debug,
228)]
229pub struct FunctionCallPermission {
230 #[serde(with = "dec_format")]
237 pub allowance: Option<Balance>,
238
239 pub receiver_id: String,
244
245 pub method_names: Vec<String>,
249}
250
251#[cfg(test)]
252mod tests {
253
254 use crate::hash::hash;
255
256 use super::*;
257
258 #[test]
259 fn test_account_serialization() {
260 let acc = Account::new(1_000_000, 1_000_000, 5, CryptoHash::default(), 100);
261 let bytes = borsh::to_vec(&acc).unwrap();
262 assert_eq!(hash(&bytes).to_string(), "EVk5UaxBe8LQ8r8iD5EAxVBs6TJcMDKqyH7PBuho6bBJ");
263 }
264
265 #[test]
266 fn test_account_deserialization() {
267 let old_account = LegacyAccount {
268 amount: 100,
269 pledging: 200,
270 power: 5,
271 code_hash: CryptoHash::default(),
272 storage_usage: 300,
273 };
274 let mut old_bytes = &borsh::to_vec(&old_account).unwrap()[..];
275 let new_account = <Account as BorshDeserialize>::deserialize(&mut old_bytes).unwrap();
276 assert_eq!(new_account.amount, old_account.amount);
277 assert_eq!(new_account.pledging, old_account.pledging);
278 assert_eq!(new_account.power, old_account.power);
279 assert_eq!(new_account.code_hash, old_account.code_hash);
280 assert_eq!(new_account.storage_usage, old_account.storage_usage);
281 assert_eq!(new_account.version, AccountVersion::V1);
282 let mut new_bytes = &borsh::to_vec(&new_account).unwrap()[..];
283 let deserialized_account =
284 <Account as BorshDeserialize>::deserialize(&mut new_bytes).unwrap();
285 assert_eq!(deserialized_account, new_account);
286 }
287}