pub mod delegate;
use crate::{
deterministic_account_id::DeterministicAccountStateInit, trie_key::GlobalContractCodeIdentifier,
};
use borsh::{BorshDeserialize, BorshSerialize};
use near_crypto::PublicKey;
use near_primitives_core::account::AccessKey;
pub use near_primitives_core::global_contract::GlobalContractIdentifier;
use near_primitives_core::types::{AccountId, Balance, Gas};
use near_schema_checker_lib::ProtocolSchema;
use serde_with::base64::Base64;
use serde_with::serde_as;
use std::fmt;
use std::sync::Arc;
pub fn base64(s: &[u8]) -> String {
use base64::Engine;
base64::engine::general_purpose::STANDARD.encode(s)
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct AddKeyAction {
pub public_key: PublicKey,
pub access_key: AccessKey,
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct CreateAccountAction {}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct DeleteAccountAction {
pub beneficiary_id: AccountId,
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct DeleteKeyAction {
pub public_key: PublicKey,
}
#[serde_as]
#[derive(
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
PartialEq,
Eq,
Clone,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct DeployContractAction {
#[serde_as(as = "Base64")]
#[cfg_attr(feature = "schemars", schemars(with = "String"))]
pub code: Vec<u8>,
}
impl fmt::Debug for DeployContractAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DeployContractAction")
.field("code", &format_args!("{}", base64(&self.code)))
.finish()
}
}
#[derive(
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
PartialEq,
Eq,
Clone,
ProtocolSchema,
Debug,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[repr(u8)]
pub enum GlobalContractDeployMode {
CodeHash,
AccountId,
}
#[serde_as]
#[derive(
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
PartialEq,
Eq,
Clone,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct DeployGlobalContractAction {
#[serde_as(as = "Base64")]
#[cfg_attr(feature = "schemars", schemars(with = "String"))]
pub code: Arc<[u8]>,
pub deploy_mode: GlobalContractDeployMode,
}
impl fmt::Debug for DeployGlobalContractAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DeployGlobalContractAction")
.field("code", &format_args!("{}", base64(&self.code)))
.field("deploy_mode", &format_args!("{:?}", &self.deploy_mode))
.finish()
}
}
impl From<GlobalContractCodeIdentifier> for GlobalContractIdentifier {
fn from(identifier: GlobalContractCodeIdentifier) -> Self {
match identifier {
GlobalContractCodeIdentifier::CodeHash(hash) => {
GlobalContractIdentifier::CodeHash(hash)
}
GlobalContractCodeIdentifier::AccountId(account_id) => {
GlobalContractIdentifier::AccountId(account_id)
}
}
}
}
#[derive(
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
PartialEq,
Eq,
Clone,
ProtocolSchema,
Debug,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct UseGlobalContractAction {
pub contract_identifier: GlobalContractIdentifier,
}
#[serde_as]
#[derive(
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
PartialEq,
Eq,
Clone,
ProtocolSchema,
Debug,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct DeterministicStateInitAction {
pub state_init: DeterministicAccountStateInit,
pub deposit: Balance,
}
#[serde_as]
#[derive(
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
PartialEq,
Eq,
Clone,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct FunctionCallAction {
pub method_name: String,
#[serde_as(as = "Base64")]
#[cfg_attr(feature = "schemars", schemars(with = "String"))]
pub args: Vec<u8>,
pub gas: Gas,
pub deposit: Balance,
}
impl fmt::Debug for FunctionCallAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FunctionCallAction")
.field("method_name", &format_args!("{}", &self.method_name))
.field("args", &format_args!("{}", base64(&self.args)))
.field("gas", &format_args!("{}", &self.gas))
.field("deposit", &format_args!("{}", &self.deposit))
.finish()
}
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct StakeAction {
pub stake: Balance,
pub public_key: PublicKey,
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct TransferAction {
pub deposit: Balance,
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct TransferToGasKeyAction {
pub public_key: PublicKey,
pub deposit: Balance,
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Clone,
Debug,
serde::Serialize,
serde::Deserialize,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct WithdrawFromGasKeyAction {
pub public_key: PublicKey,
pub amount: Balance,
}
#[derive(
BorshSerialize,
BorshDeserialize,
PartialEq,
Eq,
Debug,
Clone,
serde::Serialize,
serde::Deserialize,
strum::AsRefStr,
ProtocolSchema,
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[borsh(use_discriminant = true)]
#[repr(u8)]
pub enum Action {
CreateAccount(CreateAccountAction) = 0,
DeployContract(DeployContractAction) = 1,
FunctionCall(Box<FunctionCallAction>) = 2,
Transfer(TransferAction) = 3,
Stake(Box<StakeAction>) = 4,
AddKey(Box<AddKeyAction>) = 5,
DeleteKey(Box<DeleteKeyAction>) = 6,
DeleteAccount(DeleteAccountAction) = 7,
Delegate(Box<delegate::SignedDelegateAction>) = 8,
DeployGlobalContract(DeployGlobalContractAction) = 9,
UseGlobalContract(Box<UseGlobalContractAction>) = 10,
DeterministicStateInit(Box<DeterministicStateInitAction>) = 11,
TransferToGasKey(Box<TransferToGasKeyAction>) = 12,
WithdrawFromGasKey(Box<WithdrawFromGasKeyAction>) = 13,
}
const _: () = assert!(
std::mem::size_of::<Action>() <= 32,
"Action <= 32 bytes for performance reasons, see #9451"
);
impl Action {
pub fn get_prepaid_gas(&self) -> Gas {
match self {
Action::FunctionCall(a) => a.gas,
_ => Gas::ZERO,
}
}
pub fn get_deposit_balance(&self) -> Balance {
match self {
Action::FunctionCall(a) => a.deposit,
Action::Transfer(a) => a.deposit,
Action::DeterministicStateInit(a) => a.deposit,
Action::TransferToGasKey(a) => a.deposit,
_ => Balance::ZERO,
}
}
}
impl From<CreateAccountAction> for Action {
fn from(create_account_action: CreateAccountAction) -> Self {
Self::CreateAccount(create_account_action)
}
}
impl From<DeployContractAction> for Action {
fn from(deploy_contract_action: DeployContractAction) -> Self {
Self::DeployContract(deploy_contract_action)
}
}
impl From<DeployGlobalContractAction> for Action {
fn from(deploy_global_contract_action: DeployGlobalContractAction) -> Self {
Self::DeployGlobalContract(deploy_global_contract_action)
}
}
impl From<FunctionCallAction> for Action {
fn from(function_call_action: FunctionCallAction) -> Self {
Self::FunctionCall(Box::new(function_call_action))
}
}
impl From<TransferAction> for Action {
fn from(transfer_action: TransferAction) -> Self {
Self::Transfer(transfer_action)
}
}
impl From<StakeAction> for Action {
fn from(stake_action: StakeAction) -> Self {
Self::Stake(Box::new(stake_action))
}
}
impl From<AddKeyAction> for Action {
fn from(add_key_action: AddKeyAction) -> Self {
Self::AddKey(Box::new(add_key_action))
}
}
impl From<DeleteKeyAction> for Action {
fn from(delete_key_action: DeleteKeyAction) -> Self {
Self::DeleteKey(Box::new(delete_key_action))
}
}
impl From<DeleteAccountAction> for Action {
fn from(delete_account_action: DeleteAccountAction) -> Self {
Self::DeleteAccount(delete_account_action)
}
}
impl From<TransferToGasKeyAction> for Action {
fn from(action: TransferToGasKeyAction) -> Self {
Self::TransferToGasKey(Box::new(action))
}
}
impl From<WithdrawFromGasKeyAction> for Action {
fn from(action: WithdrawFromGasKeyAction) -> Self {
Self::WithdrawFromGasKey(Box::new(action))
}
}