Skip to main content

near_primitives_core/
global_contract.rs

1use crate::account::AccountContract;
2use crate::hash::CryptoHash;
3use borsh::{BorshDeserialize, BorshSerialize};
4use near_account_id::AccountId;
5use near_schema_checker_lib::ProtocolSchema;
6use serde_with::serde_as;
7use std::fmt;
8
9#[serde_as]
10#[derive(
11    BorshSerialize,
12    BorshDeserialize,
13    serde::Serialize,
14    serde::Deserialize,
15    Hash,
16    PartialEq,
17    Eq,
18    Clone,
19    ProtocolSchema,
20    Debug,
21)]
22#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
23#[borsh(use_discriminant = true)]
24#[repr(u8)]
25pub enum GlobalContractIdentifier {
26    #[serde(rename = "hash")]
27    CodeHash(CryptoHash) = 0,
28    #[serde(rename = "account_id")]
29    AccountId(AccountId) = 1,
30}
31
32impl GlobalContractIdentifier {
33    pub fn len(&self) -> usize {
34        match self {
35            GlobalContractIdentifier::CodeHash(_) => 32,
36            GlobalContractIdentifier::AccountId(account_id) => account_id.len(),
37        }
38    }
39}
40
41/// Extract [`GlobalContractIdentifier`] out of [`AccountContract`] if it represents a global
42/// contract.
43///
44/// If conversion is not possible, the conversion error can be inspected to obtain information
45/// about the local error.
46impl TryFrom<AccountContract> for GlobalContractIdentifier {
47    type Error = ContractIsLocalError;
48    fn try_from(value: AccountContract) -> Result<Self, Self::Error> {
49        match value {
50            AccountContract::None => Err(ContractIsLocalError::NotDeployed),
51            AccountContract::Local(h) => Err(ContractIsLocalError::Deployed(h)),
52            AccountContract::Global(h) => Ok(GlobalContractIdentifier::CodeHash(h)),
53            AccountContract::GlobalByAccount(a) => Ok(GlobalContractIdentifier::AccountId(a)),
54        }
55    }
56}
57
58#[derive(Debug)]
59pub enum ContractIsLocalError {
60    NotDeployed,
61    Deployed(CryptoHash),
62}
63
64impl std::error::Error for ContractIsLocalError {}
65
66impl fmt::Display for ContractIsLocalError {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        f.write_str(match self {
69            ContractIsLocalError::NotDeployed => "contract is not deployed",
70            ContractIsLocalError::Deployed(_) => "a locally deployed contract is deployed",
71        })
72    }
73}