Module subxt::book

source ·
Expand description

§The Subxt Guide

Subxt is a library for interacting with Substrate based nodes. It has a focus on submitting extrinsics, hence the name, however it’s also capable of reading blocks, storage, events and constants from a node. The aim of this guide is to explain key concepts and get you started with using Subxt.

  1. Features
  2. Limitations
  3. Quick start
  4. Usage

§Features at a glance

Here’s a quick overview of the features that Subxt has to offer:

  • Subxt allows you to generate a static, type safe interface to a node given some metadata; this allows you to catch many errors at compile time rather than runtime.
  • Subxt also makes heavy use of node metadata to encode/decode the data sent to/from it. This allows it to target almost any node which can output the correct metadata, and allows it some flexibility in encoding and decoding things to account for cross-node differences.
  • Subxt has a pallet-oriented interface, meaning that code you write to talk to some pallet on one node will often “Just Work” when pointed at different nodes that use the same pallet.
  • Subxt can work offline; you can generate and sign transactions, access constants from node metadata and more, without a network connection. This is all checked at compile time, so you can be certain it won’t try to establish a network connection if you don’t want it to.
  • Subxt can forego the statically generated interface and build transactions, storage queries and constant queries using data provided at runtime, rather than queries constructed statically.
  • Subxt can be compiled to WASM to run in the browser, allowing it to back Rust based browser apps, or even bind to JS apps.

§Limitations

In various places, you can provide a block hash to access data at a particular block, for instance:

However, Subxt is (by default) only capable of properly working with blocks that were produced after the most recent runtime update. This is because it uses the most recent metadata given back by a node to encode and decode things. It’s possible to decode older blocks produced by a runtime that emits compatible (currently, V14) metadata by manually setting the metadata used by the client using crate::client::OnlineClient::set_metadata().

Subxt does not support working with blocks produced prior to the runtime update that introduces V14 metadata. It may have some success decoding older blocks using newer metadata, but may also completely fail to do so.

§Quick start

Here is a simple but complete example of using Subxt to transfer some tokens from the example accounts, Alice to Bob:

#![allow(missing_docs)]
use subxt::{OnlineClient, PolkadotConfig};
use subxt_signer::sr25519::dev;

// Generate an interface that we can use from the node's metadata.
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")]
pub mod polkadot {}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a new API client, configured to talk to Polkadot nodes.
    let api = OnlineClient::<PolkadotConfig>::new().await?;

    // Build a balance transfer extrinsic.
    let dest = dev::bob().public_key().into();
    let balance_transfer_tx = polkadot::tx().balances().transfer_allow_death(dest, 10_000);

    // Submit the balance transfer extrinsic from Alice, and wait for it to be successful
    // and in a finalized block. We get back the extrinsic events if all is well.
    let from = dev::alice();
    let events = api
        .tx()
        .sign_and_submit_then_watch_default(&balance_transfer_tx, &from)
        .await?
        .wait_for_finalized_success()
        .await?;

    // Find a Transfer event and print it.
    let transfer_event = events.find_first::<polkadot::balances::events::Transfer>()?;
    if let Some(event) = transfer_event {
        println!("Balance transfer success: {event:?}");
    }

    Ok(())
}

This example assumes that a Polkadot node is running locally (Subxt endeavors to support all recent releases). Typically, to use Subxt to talk to some custom Substrate node (for example a parachain node), you’ll want to:

  1. Generate an interface
  2. Create a config
  3. Use the config to instantiate the client

Follow the above links to learn more about each step.

§Usage

Once Subxt is configured, the next step is interacting with a node. Follow the links below to learn more about how to use Subxt for each of the following things:

  • Transactions: Subxt can build and submit transactions, wait until they are in blocks, and retrieve the associated events.
  • Storage: Subxt can query the node storage.
  • Events: Subxt can read the events emitted for recent blocks.
  • Constants: Subxt can access the constant values stored in a node, which remain the same for a given runtime version.
  • Blocks: Subxt can load recent blocks or subscribe to new/finalized blocks, reading the extrinsics, events and storage at these blocks.
  • Runtime APIs: Subxt can make calls into pallet runtime APIs to retrieve data.
  • Custom values: Subxt can access “custom values” stored in the metadata.
  • Raw RPC calls: Subxt can be used to make raw RPC requests to compatible nodes.

§Examples

Some complete, self contained examples which are not a part of this guide:

  • parachain-example is an example which uses Zombienet to spawn a parachain locally, and then connects to it using Subxt.
  • wasm-example is an example of writing a Rust app that contains a Yew based UI, uses Subxt to interact with a chain, and compiles to WASM in order to run entirely in the browser.

Modules§

  • This modules contains details on setting up Subxt:
  • This modules contains examples of using Subxt; follow the links for more: