Skip to content

Commit

Permalink
Add some system helper functions (#402)
Browse files Browse the repository at this point in the history
* add system api fns

* fix build
  • Loading branch information
haerdib committed Jan 3, 2023
1 parent 09bfa81 commit 5cfedac
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 2 deletions.
43 changes: 43 additions & 0 deletions primitives/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//! Re-defintion of substrate primitives.
//! Needed because substrate pallets compile to wasm in no_std.

use alloc::string::String;
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -215,3 +216,45 @@ impl<AccountId> Default for RewardDestination<AccountId> {
RewardDestination::Staked
}
}

/// Health struct returned by the RPC
// https://github.com/paritytech/substrate/blob/c172d0f683fab3792b90d876fd6ca27056af9fe9/client/rpc-api/src/system/helpers.rs#L40-L58
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Health {
/// Number of connected peers
pub peers: usize,
/// Is the node syncing
pub is_syncing: bool,
/// Should this node have any peers
///
/// Might be false for local chains or when running without discovery.
pub should_have_peers: bool,
}

impl core::fmt::Display for Health {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { "syncing" } else { "idle" })
}
}

/// The type of a chain.
///
/// This can be used by tools to determine the type of a chain for displaying
/// additional information or enabling additional features.
// https://github.com/paritytech/substrate/blob/c172d0f683fab3792b90d876fd6ca27056af9fe9/client/chain-spec/src/lib.rs#L193-L207
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub enum ChainType {
/// A development chain that runs mainly on one node.
Development,
/// A local chain that runs locally on multiple nodes for testing purposes.
Local,
/// A live chain.
Live,
/// Some custom chain type.
Custom(String),
}

/// Arbitrary properties defined in chain spec as a JSON object
// https://github.com/paritytech/substrate/blob/c172d0f683fab3792b90d876fd6ca27056af9fe9/client/chain-spec/src/lib.rs#L215-L216
pub type Properties = serde_json::map::Map<String, serde_json::Value>;
91 changes: 90 additions & 1 deletion src/api/rpc_api/frame_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use ac_compose_macros::rpc_params;
use ac_primitives::{
AccountInfo, ExtrinsicParams, FrameSystemConfig, StorageChangeSet, StorageKey,
};
use alloc::vec;
use alloc::{string::String, vec, vec::Vec};
use log::*;
use serde::de::DeserializeOwned;
use sp_core::Pair;
Expand Down Expand Up @@ -74,6 +74,95 @@ where
}
}

/// Helper functions for some common SystemApi function.
pub trait SystemApi {
type ChainType;
type Properties;
type Health;

/// Get the node's implementation name.
fn get_system_name(&self) -> Result<String>;

/// Get the node implementation's version. Should be a semver string.
fn get_system_version(&self) -> Result<String>;

/// Get the chain's name. Given as a string identifier.
fn get_system_chain(&self) -> Result<String>;

/// Get the chain's type.
fn get_system_chain_type(&self) -> Result<Self::ChainType>;

/// Get a custom set of properties as a JSON object, defined in the chain spec.
fn get_system_properties(&self) -> Result<Self::Properties>;

/// Return health status of the node.
///
/// Node is considered healthy if it is:
/// - connected to some peers (unless running in dev mode)
/// - not performing a major sync
fn get_system_health(&self) -> Result<Self::Health>;

/// Get the base58-encoded PeerId of the node.
fn get_system_local_peer_id(&self) -> Result<String>;

/// Returns the multi-addresses that the local node is listening on
///
/// The addresses include a trailing `/p2p/` with the local PeerId, and are thus suitable to
/// be passed to `addReservedPeer` or as a bootnode address for example.
fn get_system_local_listen_addresses(&self) -> Result<Vec<String>>;
}

impl<Signer, Client, Params, Runtime> SystemApi for Api<Signer, Client, Params, Runtime>
where
Client: Request,
Runtime: FrameSystemConfig,
Params: ExtrinsicParams<Runtime::Index, Runtime::Hash>,
{
type ChainType = ac_primitives::ChainType;
type Properties = ac_primitives::Properties;
type Health = ac_primitives::Health;

fn get_system_name(&self) -> Result<String> {
let res = self.client().request("system_name", rpc_params![])?;
Ok(res)
}

fn get_system_version(&self) -> Result<String> {
let res = self.client().request("system_version", rpc_params![])?;
Ok(res)
}

fn get_system_chain(&self) -> Result<String> {
let res = self.client().request("system_chain", rpc_params![])?;
Ok(res)
}

fn get_system_chain_type(&self) -> Result<Self::ChainType> {
let res = self.client().request("system_chainType", rpc_params![])?;
Ok(res)
}

fn get_system_properties(&self) -> Result<Self::Properties> {
let res = self.client().request("system_properties", rpc_params![])?;
Ok(res)
}

fn get_system_health(&self) -> Result<Self::Health> {
let res = self.client().request("system_health", rpc_params![])?;
Ok(res)
}

fn get_system_local_peer_id(&self) -> Result<String> {
let res = self.client().request("system_localPeerId", rpc_params![])?;
Ok(res)
}

fn get_system_local_listen_addresses(&self) -> Result<Vec<String>> {
let res = self.client().request("system_localListenAddresses", rpc_params![])?;
Ok(res)
}
}

pub trait SubscribeFrameSystem<Client, Hash>
where
Client: Subscribe,
Expand Down
27 changes: 26 additions & 1 deletion testing/examples/frame_system_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use kitchensink_runtime::Runtime;
use sp_keyring::AccountKeyring;
use substrate_api_client::{
rpc::JsonrpseeClient, Api, AssetTipExtrinsicParams, GetAccountInformation, StaticEvent,
SubscribeEvents, SubscribeFrameSystem,
SubscribeEvents, SubscribeFrameSystem, SystemApi,
};

/// Check out frame_system::Event::ExtrinsicSuccess:
Expand Down Expand Up @@ -49,6 +49,31 @@ async fn main() {
let _account_info = api.get_account_info(&alice).unwrap().unwrap();
let _account_data = api.get_account_data(&alice).unwrap().unwrap();

// System Api
let system_name = api.get_system_name().unwrap();
println!("System name: {}", system_name);

let system_version = api.get_system_version().unwrap();
println!("System version: {}", system_version);

let system_chain = api.get_system_chain().unwrap();
println!("System chain: {}", system_chain);

let system_chain_type = api.get_system_chain_type().unwrap();
println!("System chain type: {:?}", system_chain_type);

let system_properties = api.get_system_properties().unwrap();
println!("System properties: {:?}", system_properties);

let system_health = api.get_system_health().unwrap();
println!("System health: {}", system_health);

let system_local_peer_id = api.get_system_local_peer_id().unwrap();
println!("System local peer id: {:?}", system_local_peer_id);

let system_local_listen_addresses = api.get_system_local_listen_addresses().unwrap();
println!("System local listen addresses: {:?}", system_local_listen_addresses);

// Subscribe
let mut event_subscription = api.subscribe_system_events().unwrap();
let _event: ExtrinsicSuccess = api.wait_for_event(&mut event_subscription).unwrap();
Expand Down

0 comments on commit 5cfedac

Please sign in to comment.