Skip to content
Library for connecting to substrate API over WebSockets
Rust Shell
Branch: master
Clone or download
Latest commit 5a825ff Nov 28, 2019

README.md

substrate-api-client

is a library written in Rust for connecting to the substrate's RPC interface via WebSockets allowing to

  • Compose extrinsics, send them and subscribe to updates.
  • supports composing extrinsics for no_std builds
  • Watch events and execute code upon events.
  • Parse and print the node metadata.

Prerequisites

In order to build the substrate-api-client and the examples, Rust and the wasm target are needed. For Linux:

curl https://sh.rustup.rs -sSf | sh

rustup default nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
cargo install --git https://github.com/alexcrichton/wasm-gc

For more information, please refer to the substrate repository.

Substrate node

To execute the examples, a running substrate node is needed. The examples have been tested with revision f17d023 of substrate. Alternatively, a dedicated test node can be found at https://github.com/scs/substrate-test-nodes.

To build the test node, execute the following steps:

git clone https://github.com/scs/substrate-test-nodes
cd substrate-test-nodes/
git checkout api-M1.1
cargo build --release

Run the node:

./target/release/substrate-test-node --dev

Tutorial

There is a detailed tutorial in the tutorials folder.

Examples

To run an example, clone the substrate-api-client repository and run the desired example directly with the cargo command:

    git clone https://github.com/scs/substrate-api-client.git
    cd substrate-api-client
    cargo run --example example_get_storage

Set the output verbosity by prepending RUST_LOG=info or RUST_LOG=debug.

The following examples can be found in the examples folder:

ink! contract

Shows how to setup an ink! contract with the predefined contract extrinsics:

  • put_code: Stores a contract wasm blob on the chain
  • create: Creates an instance of the contract
  • call: Calls a contract.

Note: This example only works with the substrate-test-node found in https://github.com/scs/substrate-test-nodes as the contract module is not included by default in a substrate node.

Read custom storage struct

Shows how to fetch and decode a custom storage struct.

// The custom struct that is to be decoded. The user must know the structure for this to work, which can fortunately
// be looked up from the node metadata and printed with the `example_print_metadata`.
#[derive(Encode, Decode, Debug)]
struct Kitty {
    id: H256,
    price: u128,
}

...

// Get the Kitty
let res_str = api.get_storage("Kitty",
                              "Kitties",
                              Some(index.encode())).unwrap();

let res_vec = hexstr_to_vec(res_str);

// Type annotations are needed here to know that to decode into.
let kitty: Kitty = Decode::decode(&mut res_vec.as_slice()).unwrap();
println!("[+] Cute decoded Kitty: {:?}\n", kitty);

Note: This example only works with the substrate-test-node found in https://github.com/scs/substrate-test-nodes for obvious reasons.

Sending generic extrinsics

Shows how to use the compose_extrinsic! macro that is able to create an extrinsic for any kind of call, even for custom runtime modules.

// Exchange "Balance" and "transfer" with the names of your custom runtime module. They are only
// used here to be able to run the examples against a generic substrate node with standard modules.
let xt: UncheckedExtrinsicV3<_, sr25519::Pair>  = compose_extrinsic!(
    api.clone(),
    "Balances",
    "transfer",
    GenericAddress::from(to.0.clone()),
    Compact(42 as u128)
);

Reading storage

Shows how to read some storage values.

// get some plain storage value
let result_str = api.get_storage("Balances", "TotalIssuance", None).unwrap();
let result = hexstr_to_u256(result_str).unwrap();
println!("[+] TotalIssuance is {}", result);

// get Alice's AccountNonce
let accountid = AccountId::from(AccountKeyring::Alice);
let result_str = api
    .get_storage("System", "AccountNonce", Some(accountid.encode()))
    .unwrap();
let result = hexstr_to_u256(result_str).unwrap();
println!("[+] Alice's Account Nonce is {}", result.low_u32());

// get Alice's AccountNonce with the AccountKey
let signer = AccountKeyring::Alice.pair();
let result_str = api
    .get_storage("System", "AccountNonce", Some(signer.public().encode()))
    .unwrap();
let result = hexstr_to_u256(result_str).unwrap();
println!("[+] Alice's Account Nonce is {}", result.low_u32());

// get Alice's AccountNonce with api.get_nonce()
api.signer = Some(signer);
println!("[+] Alice's Account Nonce is {}", api.get_nonce().unwrap());

Alternatives

Parity offers a Rust client with similar functionality: https://github.com/paritytech/substrate-subxt

Acknowledgements

The development of substrate-api-client is financed by web3 foundation's grant programme.

We also thank the teams at

You can’t perform that action at this time.