From 186da59bc2337d8d41ea978f28d3e182b1f2aa42 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Tue, 1 Mar 2022 23:05:34 +0000 Subject: [PATCH 1/8] Added worker.view_account and {account, contract}.details --- workspaces/src/lib.rs | 2 +- workspaces/src/network/account.rs | 34 ++++++++++++++++++++++++++++++- workspaces/src/network/mod.rs | 2 +- workspaces/src/worker/impls.rs | 9 +++++++- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/workspaces/src/lib.rs b/workspaces/src/lib.rs index 8fd58b99..40e5f7af 100644 --- a/workspaces/src/lib.rs +++ b/workspaces/src/lib.rs @@ -5,7 +5,7 @@ mod worker; pub mod prelude; -pub use network::{Account, Contract, DevNetwork, Network}; +pub use network::{Account, AccountDetails, Contract, DevNetwork, Network}; pub use types::{AccountId, BlockHeight, CryptoHash, InMemorySigner}; pub use worker::{ mainnet, mainnet_archival, sandbox, testnet, with_mainnet, with_sandbox, with_testnet, Worker, diff --git a/workspaces/src/network/account.rs b/workspaces/src/network/account.rs index f0c89ae6..0b7d8007 100644 --- a/workspaces/src/network/account.rs +++ b/workspaces/src/network/account.rs @@ -1,10 +1,11 @@ use std::convert::TryInto; use near_crypto::KeyType; +use near_primitives::views::AccountView; use crate::rpc::client::{DEFAULT_CALL_DEPOSIT, DEFAULT_CALL_FN_GAS}; use crate::types::{AccountId, Balance, Gas, InMemorySigner, SecretKey}; -use crate::{Network, Worker}; +use crate::{CryptoHash, Network, Worker}; use super::{CallExecution, CallExecutionDetails, ViewResultDetails}; @@ -75,6 +76,11 @@ impl Account { .await } + /// Views the current account's details such as balance and storage usage. + pub async fn details(&self, worker: &Worker) -> anyhow::Result { + worker.view_account(&self.id).await + } + /// Create a new sub account. Returns a CreateAccountBuilder object that /// we can make use of to fill out the rest of the details. The sub account /// id will be in the form of: "{new_account_id}.{parent_account_id}" @@ -165,6 +171,11 @@ impl Contract { worker.view(self.id(), function, args).await } + /// Views the current contract's details such as balance and storage usage. + pub async fn details(&self, worker: &Worker) -> anyhow::Result { + worker.view_account(self.id()).await + } + /// Deletes the current contract, and returns the execution details of this /// transaction. The beneciary will receive the funds of the account deleted pub async fn delete_contract( @@ -314,3 +325,24 @@ where }) } } + +/// Details of an Account or Contract. This is an non-exhaustive list of items +/// that the account stores in the blockchain state. +#[non_exhaustive] +pub struct AccountDetails { + pub amount: Balance, + pub locked: Balance, + pub code_hash: CryptoHash, + pub storage_usage: u64, +} + +impl From for AccountDetails { + fn from(account: AccountView) -> Self { + Self { + amount: account.amount, + locked: account.locked, + code_hash: CryptoHash(account.code_hash.0), + storage_usage: account.storage_usage, + } + } +} diff --git a/workspaces/src/network/mod.rs b/workspaces/src/network/mod.rs index 985ec0f0..0456d8d8 100644 --- a/workspaces/src/network/mod.rs +++ b/workspaces/src/network/mod.rs @@ -17,7 +17,7 @@ use crate::rpc::patch::ImportContractBuilder; use crate::types::{AccountId, KeyType, SecretKey}; use crate::Worker; -pub use crate::network::account::{Account, Contract}; +pub use crate::network::account::{Account, AccountDetails, Contract}; pub use crate::network::mainnet::Mainnet; pub use crate::network::result::{CallExecution, CallExecutionDetails, ViewResultDetails}; pub use crate::network::sandbox::Sandbox; diff --git a/workspaces/src/worker/impls.rs b/workspaces/src/worker/impls.rs index 50167bd8..a614b6be 100644 --- a/workspaces/src/worker/impls.rs +++ b/workspaces/src/worker/impls.rs @@ -12,7 +12,7 @@ use crate::rpc::client::{Client, DEFAULT_CALL_DEPOSIT, DEFAULT_CALL_FN_GAS}; use crate::rpc::patch::ImportContractBuilder; use crate::types::{AccountId, Gas, InMemorySigner, SecretKey}; use crate::worker::Worker; -use crate::Network; +use crate::{Network, AccountDetails}; impl Clone for Worker { fn clone(&self) -> Self { @@ -150,6 +150,13 @@ where .await .map(Into::into) } + + pub async fn view_account(&self, account_id: &AccountId) -> anyhow::Result { + self.client() + .view_account(account_id.clone(), None) + .await + .map(Into::into) + } } impl Worker { From f13e4183ee1046b7d553f22ea069d46aade46823 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 2 Mar 2022 00:00:01 +0000 Subject: [PATCH 2/8] Added view_code convenient function --- workspaces/src/network/account.rs | 5 +++++ workspaces/src/worker/impls.rs | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/workspaces/src/network/account.rs b/workspaces/src/network/account.rs index 0b7d8007..b3f9adc8 100644 --- a/workspaces/src/network/account.rs +++ b/workspaces/src/network/account.rs @@ -171,6 +171,11 @@ impl Contract { worker.view(self.id(), function, args).await } + /// View the WASM code bytes of this contract. + pub async fn view_code(&self, worker: &Worker) -> anyhow::Result> { + worker.view_code(self.id()).await + } + /// Views the current contract's details such as balance and storage usage. pub async fn details(&self, worker: &Worker) -> anyhow::Result { worker.view_account(self.id()).await diff --git a/workspaces/src/worker/impls.rs b/workspaces/src/worker/impls.rs index a614b6be..1eb15103 100644 --- a/workspaces/src/worker/impls.rs +++ b/workspaces/src/worker/impls.rs @@ -12,7 +12,7 @@ use crate::rpc::client::{Client, DEFAULT_CALL_DEPOSIT, DEFAULT_CALL_FN_GAS}; use crate::rpc::patch::ImportContractBuilder; use crate::types::{AccountId, Gas, InMemorySigner, SecretKey}; use crate::worker::Worker; -use crate::{Network, AccountDetails}; +use crate::{AccountDetails, Network}; impl Clone for Worker { fn clone(&self) -> Self { @@ -119,6 +119,12 @@ where .await } + /// View the WASM code bytes of a contract on the network. + pub async fn view_code(&self, contract_id: &AccountId) -> anyhow::Result> { + let code_view = self.client().view_code(contract_id.clone(), None).await?; + Ok(code_view.code) + } + pub async fn view_state( &self, contract_id: &AccountId, From 41a741b3e05204773b762b52e0c6d19e14d723e2 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 2 Mar 2022 00:55:57 +0000 Subject: [PATCH 3/8] Added ability to query currently Block --- workspaces/src/lib.rs | 2 +- workspaces/src/network/block.rs | 57 +++++++++++++++++++++++++++++++++ workspaces/src/network/mod.rs | 2 ++ workspaces/src/rpc/client.rs | 15 ++++++++- workspaces/src/worker/impls.rs | 8 +++-- 5 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 workspaces/src/network/block.rs diff --git a/workspaces/src/lib.rs b/workspaces/src/lib.rs index 40e5f7af..fc4032e3 100644 --- a/workspaces/src/lib.rs +++ b/workspaces/src/lib.rs @@ -5,7 +5,7 @@ mod worker; pub mod prelude; -pub use network::{Account, AccountDetails, Contract, DevNetwork, Network}; +pub use network::{Account, AccountDetails, Block, Contract, DevNetwork, Network}; pub use types::{AccountId, BlockHeight, CryptoHash, InMemorySigner}; pub use worker::{ mainnet, mainnet_archival, sandbox, testnet, with_mainnet, with_sandbox, with_testnet, Worker, diff --git a/workspaces/src/network/block.rs b/workspaces/src/network/block.rs new file mode 100644 index 00000000..a4cb88ba --- /dev/null +++ b/workspaces/src/network/block.rs @@ -0,0 +1,57 @@ +use near_primitives::views::{BlockHeaderView, BlockView}; + +use crate::{BlockHeight, CryptoHash}; + +/// Struct containing information on block coming from the network +pub struct Block { + header: BlockHeader, +} + +impl Block { + /// The block timestamp in nanoseconds. + fn timestamp(&self) -> u64 { + self.header.timestamp_nanosec + } + + /// Current height of this block. + fn height(&self) -> BlockHeight { + self.header.height + } + + fn hash(&self) -> &CryptoHash { + &self.header.hash + } + + fn epoch_id(&self) -> &CryptoHash { + &self.header.epoch_id + } +} + +/// The block header info. This is a non-exhaustive list of items that +/// could be present in a block header. More can be added in the future. +#[non_exhaustive] +struct BlockHeader { + height: BlockHeight, + epoch_id: CryptoHash, + hash: CryptoHash, + timestamp_nanosec: u64, +} + +impl From for Block { + fn from(block_view: BlockView) -> Self { + Self { + header: block_view.header.into(), + } + } +} + +impl From for BlockHeader { + fn from(header_view: BlockHeaderView) -> Self { + Self { + height: header_view.height, + epoch_id: CryptoHash(header_view.epoch_id.0), + hash: CryptoHash(header_view.hash.0), + timestamp_nanosec: header_view.timestamp_nanosec, + } + } +} diff --git a/workspaces/src/network/mod.rs b/workspaces/src/network/mod.rs index 0456d8d8..2156585f 100644 --- a/workspaces/src/network/mod.rs +++ b/workspaces/src/network/mod.rs @@ -1,4 +1,5 @@ mod account; +mod block; mod info; mod mainnet; mod result; @@ -18,6 +19,7 @@ use crate::types::{AccountId, KeyType, SecretKey}; use crate::Worker; pub use crate::network::account::{Account, AccountDetails, Contract}; +pub use crate::network::block::Block; pub use crate::network::mainnet::Mainnet; pub use crate::network::result::{CallExecution, CallExecutionDetails, ViewResultDetails}; pub use crate::network::sandbox::Sandbox; diff --git a/workspaces/src/rpc/client.rs b/workspaces/src/rpc/client.rs index 14594c61..65c1d229 100644 --- a/workspaces/src/rpc/client.rs +++ b/workspaces/src/rpc/client.rs @@ -15,7 +15,8 @@ use near_primitives::transaction::{ }; use near_primitives::types::{Balance, BlockId, Finality, Gas, StoreKey}; use near_primitives::views::{ - AccessKeyView, AccountView, ContractCodeView, FinalExecutionOutcomeView, QueryRequest, + AccessKeyView, AccountView, BlockView, ContractCodeView, FinalExecutionOutcomeView, + QueryRequest, }; use crate::network::ViewResultDetails; @@ -238,6 +239,18 @@ impl Client { } } + pub(crate) async fn view_block(&self, block_id: Option) -> anyhow::Result { + let block_reference = block_id + .map(Into::into) + .unwrap_or_else(|| Finality::None.into()); + + let block_view = self + .query(&methods::block::RpcBlockRequest { block_reference }) + .await?; + + Ok(block_view) + } + pub(crate) async fn deploy( &self, signer: &InMemorySigner, diff --git a/workspaces/src/worker/impls.rs b/workspaces/src/worker/impls.rs index 1eb15103..754056cf 100644 --- a/workspaces/src/worker/impls.rs +++ b/workspaces/src/worker/impls.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use near_primitives::types::{Balance, StoreKey}; use crate::network::{ - Account, AllowDevAccountCreation, CallExecution, CallExecutionDetails, Contract, NetworkClient, - NetworkInfo, StatePatcher, TopLevelAccountCreator, ViewResultDetails, + Account, AllowDevAccountCreation, Block, CallExecution, CallExecutionDetails, Contract, + NetworkClient, NetworkInfo, StatePatcher, TopLevelAccountCreator, ViewResultDetails, }; use crate::network::{Info, Sandbox}; use crate::rpc::client::{Client, DEFAULT_CALL_DEPOSIT, DEFAULT_CALL_FN_GAS}; @@ -133,6 +133,10 @@ where self.client().view_state(contract_id.clone(), prefix).await } + pub async fn view_latest_block(&self) -> anyhow::Result { + self.client().view_block(None).await.map(Into::into) + } + pub async fn transfer_near( &self, signer: &InMemorySigner, From 6d13a94418b9a35e5b5c52c75191c54f7593a8c3 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 2 Mar 2022 01:56:31 +0000 Subject: [PATCH 4/8] Rename details to view_account --- workspaces/src/network/account.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/workspaces/src/network/account.rs b/workspaces/src/network/account.rs index b3f9adc8..44d65379 100644 --- a/workspaces/src/network/account.rs +++ b/workspaces/src/network/account.rs @@ -77,7 +77,10 @@ impl Account { } /// Views the current account's details such as balance and storage usage. - pub async fn details(&self, worker: &Worker) -> anyhow::Result { + pub async fn viwe_account( + &self, + worker: &Worker, + ) -> anyhow::Result { worker.view_account(&self.id).await } @@ -177,7 +180,10 @@ impl Contract { } /// Views the current contract's details such as balance and storage usage. - pub async fn details(&self, worker: &Worker) -> anyhow::Result { + pub async fn view_account( + &self, + worker: &Worker, + ) -> anyhow::Result { worker.view_account(self.id()).await } From 7e7a4bc1849d62f91aff97d5274f513a0ed14cf0 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 2 Mar 2022 02:06:56 +0000 Subject: [PATCH 5/8] Fix typo and added more docs --- workspaces/src/network/account.rs | 2 +- workspaces/src/network/block.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/workspaces/src/network/account.rs b/workspaces/src/network/account.rs index 44d65379..350a4b9b 100644 --- a/workspaces/src/network/account.rs +++ b/workspaces/src/network/account.rs @@ -77,7 +77,7 @@ impl Account { } /// Views the current account's details such as balance and storage usage. - pub async fn viwe_account( + pub async fn view_account( &self, worker: &Worker, ) -> anyhow::Result { diff --git a/workspaces/src/network/block.rs b/workspaces/src/network/block.rs index a4cb88ba..10f34876 100644 --- a/workspaces/src/network/block.rs +++ b/workspaces/src/network/block.rs @@ -9,20 +9,22 @@ pub struct Block { impl Block { /// The block timestamp in nanoseconds. - fn timestamp(&self) -> u64 { + pub fn timestamp(&self) -> u64 { self.header.timestamp_nanosec } /// Current height of this block. - fn height(&self) -> BlockHeight { + pub fn height(&self) -> BlockHeight { self.header.height } - fn hash(&self) -> &CryptoHash { + /// The hash of the block itself. + pub fn hash(&self) -> &CryptoHash { &self.header.hash } - fn epoch_id(&self) -> &CryptoHash { + /// The id of an epoch this block belongs to. + pub fn epoch_id(&self) -> &CryptoHash { &self.header.epoch_id } } From acef9f612833d64b4f9e16ab5648235e1a9163a5 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 2 Mar 2022 19:59:39 +0000 Subject: [PATCH 6/8] Added more docs --- workspaces/src/worker/impls.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/workspaces/src/worker/impls.rs b/workspaces/src/worker/impls.rs index 754056cf..9c7f088d 100644 --- a/workspaces/src/worker/impls.rs +++ b/workspaces/src/worker/impls.rs @@ -87,6 +87,7 @@ where self.workspace.client() } + /// Call into a contract's change function. pub async fn call( &self, contract: &Contract, @@ -108,6 +109,7 @@ where .map(Into::into) } + /// Call into a contract's view function. pub async fn view( &self, contract_id: &AccountId, @@ -125,6 +127,9 @@ where Ok(code_view.code) } + /// View the state of a account/contract on the network. This will return the internal + /// state of the account in the form of a map of key-value pairs; where STATE contains + /// info on a contract's internal data. pub async fn view_state( &self, contract_id: &AccountId, @@ -133,10 +138,13 @@ where self.client().view_state(contract_id.clone(), prefix).await } + /// View the latest block from the network pub async fn view_latest_block(&self) -> anyhow::Result { self.client().view_block(None).await.map(Into::into) } + /// Transfer tokens from one account to another. The signer is the account + /// that will be used to to send from. pub async fn transfer_near( &self, signer: &InMemorySigner, @@ -149,6 +157,8 @@ where .map(Into::into) } + /// Deletes an account from the network. The beneficiary will receive the balance + /// of the account deleted. pub async fn delete_account( &self, account_id: &AccountId, @@ -161,6 +171,7 @@ where .map(Into::into) } + /// View account details of a specific account on the network. pub async fn view_account(&self, account_id: &AccountId) -> anyhow::Result { self.client() .view_account(account_id.clone(), None) From 287b9a790ad71a92ca4eb8dd99a2ccbfa36ed0e8 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Thu, 3 Mar 2022 22:41:00 +0000 Subject: [PATCH 7/8] Addressed comments --- workspaces/src/network/account.rs | 5 +++-- workspaces/src/network/block.rs | 3 ++- workspaces/src/types.rs | 17 ++++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/workspaces/src/network/account.rs b/workspaces/src/network/account.rs index 350a4b9b..a9db7ab5 100644 --- a/workspaces/src/network/account.rs +++ b/workspaces/src/network/account.rs @@ -339,9 +339,10 @@ where /// Details of an Account or Contract. This is an non-exhaustive list of items /// that the account stores in the blockchain state. +#[derive(Debug, PartialEq)] #[non_exhaustive] pub struct AccountDetails { - pub amount: Balance, + pub balance: Balance, pub locked: Balance, pub code_hash: CryptoHash, pub storage_usage: u64, @@ -350,7 +351,7 @@ pub struct AccountDetails { impl From for AccountDetails { fn from(account: AccountView) -> Self { Self { - amount: account.amount, + balance: account.amount, locked: account.locked, code_hash: CryptoHash(account.code_hash.0), storage_usage: account.storage_usage, diff --git a/workspaces/src/network/block.rs b/workspaces/src/network/block.rs index 10f34876..d619a107 100644 --- a/workspaces/src/network/block.rs +++ b/workspaces/src/network/block.rs @@ -3,6 +3,7 @@ use near_primitives::views::{BlockHeaderView, BlockView}; use crate::{BlockHeight, CryptoHash}; /// Struct containing information on block coming from the network +#[derive(Debug, PartialEq)] pub struct Block { header: BlockHeader, } @@ -31,7 +32,7 @@ impl Block { /// The block header info. This is a non-exhaustive list of items that /// could be present in a block header. More can be added in the future. -#[non_exhaustive] +#[derive(Debug, PartialEq)] struct BlockHeader { height: BlockHeight, epoch_id: CryptoHash, diff --git a/workspaces/src/types.rs b/workspaces/src/types.rs index bfbec6b5..f7004193 100644 --- a/workspaces/src/types.rs +++ b/workspaces/src/types.rs @@ -2,11 +2,13 @@ /// and internal libraries like near-jsonrpc-client requires specific versions /// of these types which shouldn't be exposed either. use std::convert::TryFrom; +use std::fmt; use std::path::Path; pub use near_account_id::AccountId; pub(crate) use near_crypto::{KeyType, Signer}; -use near_primitives::serialize::from_base; +use near_primitives::logging::pretty_hash; +use near_primitives::serialize::{from_base, to_base}; use serde::{Deserialize, Serialize}; pub type Gas = u64; @@ -62,6 +64,7 @@ impl InMemorySigner { // type taken from near_primitives::hash::CryptoHash. /// CryptoHash is type for storing the hash of a specific block. +#[derive(PartialEq)] pub struct CryptoHash(pub [u8; 32]); impl std::str::FromStr for CryptoHash { @@ -93,3 +96,15 @@ impl TryFrom> for CryptoHash { >::try_from(v.as_ref()) } } + +impl fmt::Debug for CryptoHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", pretty_hash(&self.to_string())) + } +} + +impl fmt::Display for CryptoHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&to_base(&self.0), f) + } +} From 316988f9ce4cdd3ca78e84a49bfe35e7f106f442 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Fri, 4 Mar 2022 02:14:37 +0000 Subject: [PATCH 8/8] Added derive Hash to CryptoHash --- workspaces/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspaces/src/types.rs b/workspaces/src/types.rs index f7004193..e5a98dcd 100644 --- a/workspaces/src/types.rs +++ b/workspaces/src/types.rs @@ -64,7 +64,7 @@ impl InMemorySigner { // type taken from near_primitives::hash::CryptoHash. /// CryptoHash is type for storing the hash of a specific block. -#[derive(PartialEq)] +#[derive(Hash, PartialEq)] pub struct CryptoHash(pub [u8; 32]); impl std::str::FromStr for CryptoHash {