1pub mod delegate;
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use near_crypto::PublicKey;
5use near_primitives_core::{
6 account::AccessKey,
7 hash::CryptoHash,
8 serialize::dec_format,
9 types::{AccountId, Balance, Gas},
10};
11use near_schema_checker_lib::ProtocolSchema;
12use serde_with::base64::Base64;
13use serde_with::serde_as;
14use std::fmt;
15use std::sync::Arc;
16
17use crate::trie_key::GlobalContractCodeIdentifier;
18
19pub fn base64(s: &[u8]) -> String {
20 use base64::Engine;
21 base64::engine::general_purpose::STANDARD.encode(s)
22}
23
24#[derive(
25 BorshSerialize,
26 BorshDeserialize,
27 PartialEq,
28 Eq,
29 Clone,
30 Debug,
31 serde::Serialize,
32 serde::Deserialize,
33 ProtocolSchema,
34)]
35#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
36pub struct AddKeyAction {
37 pub public_key: PublicKey,
39 pub access_key: AccessKey,
41}
42
43#[derive(
45 BorshSerialize,
46 BorshDeserialize,
47 PartialEq,
48 Eq,
49 Clone,
50 Debug,
51 serde::Serialize,
52 serde::Deserialize,
53 ProtocolSchema,
54)]
55#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
56pub struct CreateAccountAction {}
57
58#[derive(
59 BorshSerialize,
60 BorshDeserialize,
61 PartialEq,
62 Eq,
63 Clone,
64 Debug,
65 serde::Serialize,
66 serde::Deserialize,
67 ProtocolSchema,
68)]
69#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
70pub struct DeleteAccountAction {
71 pub beneficiary_id: AccountId,
72}
73
74#[derive(
75 BorshSerialize,
76 BorshDeserialize,
77 PartialEq,
78 Eq,
79 Clone,
80 Debug,
81 serde::Serialize,
82 serde::Deserialize,
83 ProtocolSchema,
84)]
85#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
86pub struct DeleteKeyAction {
87 pub public_key: PublicKey,
89}
90
91#[serde_as]
93#[derive(
94 BorshSerialize,
95 BorshDeserialize,
96 serde::Serialize,
97 serde::Deserialize,
98 PartialEq,
99 Eq,
100 Clone,
101 ProtocolSchema,
102)]
103#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
104pub struct DeployContractAction {
105 #[serde_as(as = "Base64")]
107 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
108 pub code: Vec<u8>,
109}
110
111impl fmt::Debug for DeployContractAction {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 f.debug_struct("DeployContractAction")
114 .field("code", &format_args!("{}", base64(&self.code)))
115 .finish()
116 }
117}
118
119#[serde_as]
120#[derive(
121 BorshSerialize,
122 BorshDeserialize,
123 serde::Serialize,
124 serde::Deserialize,
125 PartialEq,
126 Eq,
127 Clone,
128 ProtocolSchema,
129 Debug,
130)]
131#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
132#[repr(u8)]
133pub enum GlobalContractDeployMode {
134 CodeHash,
138 AccountId,
142}
143
144#[serde_as]
146#[derive(
147 BorshSerialize,
148 BorshDeserialize,
149 serde::Serialize,
150 serde::Deserialize,
151 PartialEq,
152 Eq,
153 Clone,
154 ProtocolSchema,
155)]
156#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
157pub struct DeployGlobalContractAction {
158 #[serde_as(as = "Base64")]
160 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
161 pub code: Arc<[u8]>,
162
163 pub deploy_mode: GlobalContractDeployMode,
164}
165
166impl fmt::Debug for DeployGlobalContractAction {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 f.debug_struct("DeployGlobalContractAction")
169 .field("code", &format_args!("{}", base64(&self.code)))
170 .field("deploy_mode", &format_args!("{:?}", &self.deploy_mode))
171 .finish()
172 }
173}
174
175#[serde_as]
176#[derive(
177 BorshSerialize,
178 BorshDeserialize,
179 serde::Serialize,
180 serde::Deserialize,
181 Hash,
182 PartialEq,
183 Eq,
184 Clone,
185 ProtocolSchema,
186 Debug,
187)]
188#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
189pub enum GlobalContractIdentifier {
190 CodeHash(CryptoHash),
191 AccountId(AccountId),
192}
193
194impl From<GlobalContractCodeIdentifier> for GlobalContractIdentifier {
195 fn from(identifier: GlobalContractCodeIdentifier) -> Self {
196 match identifier {
197 GlobalContractCodeIdentifier::CodeHash(hash) => {
198 GlobalContractIdentifier::CodeHash(hash)
199 }
200 GlobalContractCodeIdentifier::AccountId(account_id) => {
201 GlobalContractIdentifier::AccountId(account_id)
202 }
203 }
204 }
205}
206
207impl GlobalContractIdentifier {
208 pub fn len(&self) -> usize {
209 match self {
210 GlobalContractIdentifier::CodeHash(_) => 32,
211 GlobalContractIdentifier::AccountId(account_id) => account_id.len(),
212 }
213 }
214}
215
216#[serde_as]
218#[derive(
219 BorshSerialize,
220 BorshDeserialize,
221 serde::Serialize,
222 serde::Deserialize,
223 PartialEq,
224 Eq,
225 Clone,
226 ProtocolSchema,
227 Debug,
228)]
229#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
230pub struct UseGlobalContractAction {
231 pub contract_identifier: GlobalContractIdentifier,
232}
233
234#[serde_as]
235#[derive(
236 BorshSerialize,
237 BorshDeserialize,
238 serde::Serialize,
239 serde::Deserialize,
240 PartialEq,
241 Eq,
242 Clone,
243 ProtocolSchema,
244)]
245#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
246pub struct FunctionCallAction {
247 pub method_name: String,
248 #[serde_as(as = "Base64")]
249 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
250 pub args: Vec<u8>,
251 pub gas: Gas,
252 #[serde(with = "dec_format")]
253 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
254 pub deposit: Balance,
255}
256
257impl fmt::Debug for FunctionCallAction {
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 f.debug_struct("FunctionCallAction")
260 .field("method_name", &format_args!("{}", &self.method_name))
261 .field("args", &format_args!("{}", base64(&self.args)))
262 .field("gas", &format_args!("{}", &self.gas))
263 .field("deposit", &format_args!("{}", &self.deposit))
264 .finish()
265 }
266}
267
268#[derive(
270 BorshSerialize,
271 BorshDeserialize,
272 PartialEq,
273 Eq,
274 Clone,
275 Debug,
276 serde::Serialize,
277 serde::Deserialize,
278 ProtocolSchema,
279)]
280#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
281pub struct StakeAction {
282 #[serde(with = "dec_format")]
284 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
285 pub stake: Balance,
286 pub public_key: PublicKey,
288}
289
290#[derive(
291 BorshSerialize,
292 BorshDeserialize,
293 PartialEq,
294 Eq,
295 Clone,
296 Debug,
297 serde::Serialize,
298 serde::Deserialize,
299 ProtocolSchema,
300)]
301#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
302pub struct TransferAction {
303 #[serde(with = "dec_format")]
304 #[cfg_attr(feature = "schemars", schemars(with = "String"))]
305 pub deposit: Balance,
306}
307
308#[derive(
309 BorshSerialize,
310 BorshDeserialize,
311 PartialEq,
312 Eq,
313 Debug,
314 Clone,
315 serde::Serialize,
316 serde::Deserialize,
317 strum::AsRefStr,
318 ProtocolSchema,
319)]
320#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
321pub enum Action {
322 CreateAccount(CreateAccountAction),
326 DeployContract(DeployContractAction),
328 FunctionCall(Box<FunctionCallAction>),
329 Transfer(TransferAction),
330 Stake(Box<StakeAction>),
331 AddKey(Box<AddKeyAction>),
332 DeleteKey(Box<DeleteKeyAction>),
333 DeleteAccount(DeleteAccountAction),
334 Delegate(Box<delegate::SignedDelegateAction>),
335 DeployGlobalContract(DeployGlobalContractAction),
336 UseGlobalContract(Box<UseGlobalContractAction>),
337}
338
339const _: () = assert!(
340 std::mem::size_of::<Action>() <= 32,
344 "Action <= 32 bytes for performance reasons, see #9451"
345);
346
347impl Action {
348 pub fn get_prepaid_gas(&self) -> Gas {
349 match self {
350 Action::FunctionCall(a) => a.gas,
351 _ => 0,
352 }
353 }
354 pub fn get_deposit_balance(&self) -> Balance {
355 match self {
356 Action::FunctionCall(a) => a.deposit,
357 Action::Transfer(a) => a.deposit,
358 _ => 0,
359 }
360 }
361}
362
363impl From<CreateAccountAction> for Action {
364 fn from(create_account_action: CreateAccountAction) -> Self {
365 Self::CreateAccount(create_account_action)
366 }
367}
368
369impl From<DeployContractAction> for Action {
370 fn from(deploy_contract_action: DeployContractAction) -> Self {
371 Self::DeployContract(deploy_contract_action)
372 }
373}
374
375impl From<DeployGlobalContractAction> for Action {
376 fn from(deploy_global_contract_action: DeployGlobalContractAction) -> Self {
377 Self::DeployGlobalContract(deploy_global_contract_action)
378 }
379}
380
381impl From<FunctionCallAction> for Action {
382 fn from(function_call_action: FunctionCallAction) -> Self {
383 Self::FunctionCall(Box::new(function_call_action))
384 }
385}
386
387impl From<TransferAction> for Action {
388 fn from(transfer_action: TransferAction) -> Self {
389 Self::Transfer(transfer_action)
390 }
391}
392
393impl From<StakeAction> for Action {
394 fn from(stake_action: StakeAction) -> Self {
395 Self::Stake(Box::new(stake_action))
396 }
397}
398
399impl From<AddKeyAction> for Action {
400 fn from(add_key_action: AddKeyAction) -> Self {
401 Self::AddKey(Box::new(add_key_action))
402 }
403}
404
405impl From<DeleteKeyAction> for Action {
406 fn from(delete_key_action: DeleteKeyAction) -> Self {
407 Self::DeleteKey(Box::new(delete_key_action))
408 }
409}
410
411impl From<DeleteAccountAction> for Action {
412 fn from(delete_account_action: DeleteAccountAction) -> Self {
413 Self::DeleteAccount(delete_account_action)
414 }
415}