near_primitives_core_v01/
account.rs1use borsh::{BorshDeserialize, BorshSerialize};
2use serde::{Deserialize, Serialize};
3use std::io;
4
5pub use near_account_id as id;
6
7use crate::hash::CryptoHash;
8use crate::serialize::{option_u128_dec_format, u128_dec_format_compatible};
9use crate::types::{Balance, Nonce, StorageUsage};
10#[derive(
11 BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy,
12)]
13pub enum AccountVersion {
14 V1,
15}
16
17impl Default for AccountVersion {
18 fn default() -> Self {
19 AccountVersion::V1
20 }
21}
22
23#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
25pub struct Account {
26 #[serde(with = "u128_dec_format_compatible")]
28 amount: Balance,
29 #[serde(with = "u128_dec_format_compatible")]
31 locked: Balance,
32 code_hash: CryptoHash,
34 storage_usage: StorageUsage,
36 #[serde(default)]
38 version: AccountVersion,
39}
40
41impl Account {
42 pub const MAX_ACCOUNT_DELETION_STORAGE_USAGE: u64 = 10_000;
45
46 pub fn new(
47 amount: Balance,
48 locked: Balance,
49 code_hash: CryptoHash,
50 storage_usage: StorageUsage,
51 ) -> Self {
52 Account { amount, locked, code_hash, storage_usage, version: AccountVersion::V1 }
53 }
54
55 #[inline]
56 pub fn amount(&self) -> Balance {
57 self.amount
58 }
59
60 #[inline]
61 pub fn locked(&self) -> Balance {
62 self.locked
63 }
64
65 #[inline]
66 pub fn code_hash(&self) -> CryptoHash {
67 self.code_hash
68 }
69
70 #[inline]
71 pub fn storage_usage(&self) -> StorageUsage {
72 self.storage_usage
73 }
74
75 #[inline]
76 pub fn version(&self) -> AccountVersion {
77 self.version
78 }
79
80 #[inline]
81 pub fn set_amount(&mut self, amount: Balance) {
82 self.amount = amount;
83 }
84
85 #[inline]
86 pub fn set_locked(&mut self, locked: Balance) {
87 self.locked = locked;
88 }
89
90 #[inline]
91 pub fn set_code_hash(&mut self, code_hash: CryptoHash) {
92 self.code_hash = code_hash;
93 }
94
95 #[inline]
96 pub fn set_storage_usage(&mut self, storage_usage: StorageUsage) {
97 self.storage_usage = storage_usage;
98 }
99
100 pub fn set_version(&mut self, version: AccountVersion) {
101 self.version = version;
102 }
103}
104
105#[derive(BorshSerialize, BorshDeserialize)]
106struct LegacyAccount {
107 amount: Balance,
108 locked: Balance,
109 code_hash: CryptoHash,
110 storage_usage: StorageUsage,
111}
112
113impl BorshDeserialize for Account {
114 fn deserialize(buf: &mut &[u8]) -> Result<Self, io::Error> {
115 if buf.len() == std::mem::size_of::<LegacyAccount>() {
116 let deserialized_account = LegacyAccount::deserialize(buf)?;
119 Ok(Account {
120 amount: deserialized_account.amount,
121 locked: deserialized_account.locked,
122 code_hash: deserialized_account.code_hash,
123 storage_usage: deserialized_account.storage_usage,
124 version: AccountVersion::V1,
125 })
126 } else {
127 unreachable!();
128 }
129 }
130}
131
132impl BorshSerialize for Account {
133 fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
134 match self.version {
135 AccountVersion::V1 => LegacyAccount {
136 amount: self.amount,
137 locked: self.locked,
138 code_hash: self.code_hash,
139 storage_usage: self.storage_usage,
140 }
141 .serialize(writer),
142 }
143 }
144}
145
146#[derive(
152 BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Debug,
153)]
154pub struct AccessKey {
155 pub nonce: Nonce,
160
161 pub permission: AccessKeyPermission,
163}
164
165impl AccessKey {
166 pub const ACCESS_KEY_NONCE_RANGE_MULTIPLIER: u64 = 1_000_000;
167
168 pub fn full_access() -> Self {
169 Self { nonce: 0, permission: AccessKeyPermission::FullAccess }
170 }
171}
172
173#[derive(
175 BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Debug,
176)]
177pub enum AccessKeyPermission {
178 FunctionCall(FunctionCallPermission),
179
180 FullAccess,
183}
184
185#[derive(
190 BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Debug,
191)]
192pub struct FunctionCallPermission {
193 #[serde(with = "option_u128_dec_format")]
200 pub allowance: Option<Balance>,
201
202 pub receiver_id: String,
207
208 pub method_names: Vec<String>,
212}
213
214#[cfg(test)]
215mod tests {
216 use borsh::BorshSerialize;
217
218 use crate::hash::hash;
219 use crate::serialize::to_base;
220
221 use super::*;
222
223 #[test]
224 fn test_account_serialization() {
225 let acc = Account::new(1_000_000, 1_000_000, CryptoHash::default(), 100);
226 let bytes = acc.try_to_vec().unwrap();
227 assert_eq!(to_base(&hash(&bytes)), "EVk5UaxBe8LQ8r8iD5EAxVBs6TJcMDKqyH7PBuho6bBJ");
228 }
229
230 #[test]
231 fn test_account_deserialization() {
232 let old_account = LegacyAccount {
233 amount: 100,
234 locked: 200,
235 code_hash: CryptoHash::default(),
236 storage_usage: 300,
237 };
238 let mut old_bytes = &old_account.try_to_vec().unwrap()[..];
239 let new_account = <Account as BorshDeserialize>::deserialize(&mut old_bytes).unwrap();
240 assert_eq!(new_account.amount, old_account.amount);
241 assert_eq!(new_account.locked, old_account.locked);
242 assert_eq!(new_account.code_hash, old_account.code_hash);
243 assert_eq!(new_account.storage_usage, old_account.storage_usage);
244 assert_eq!(new_account.version, AccountVersion::V1);
245 let mut new_bytes = &new_account.try_to_vec().unwrap()[..];
246 let deserialized_account =
247 <Account as BorshDeserialize>::deserialize(&mut new_bytes).unwrap();
248 assert_eq!(deserialized_account, new_account);
249 }
250}