Attribute Macro subxt

Source
#[subxt]
Expand description

Generate a strongly typed API for interacting with a Substrate runtime from its metadata of WASM.

§Metadata

First, you’ll need to get hold of some metadata for the node you’d like to interact with. One way to do this is by using the subxt CLI tool:

# Install the CLI tool:
cargo install subxt-cli
# Use it to download metadata (in this case, from a node running locally)
subxt metadata > polkadot_metadata.scale

Run subxt metadata --help for more options.

§Basic usage

We can generate an interface to a chain given either:

  • A locally saved SCALE encoded metadata file (see above) for that chain,
  • The Runtime WASM for that chain, or
  • A URL pointing at the JSON-RPC interface for a node on that chain.

In each case, the subxt macro will use this data to populate the annotated module with all of the methods and types required for interacting with the chain that the Runtime/metadata was loaded from.

Let’s look at each of these:

§Using a locally saved metadata file

Annotate a Rust module with the subxt attribute referencing a metadata file like so:

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
)]
mod polkadot {}

§Using a WASM runtime via runtime_path = "..."

This requires the runtime-wasm-path feature flag.

Annotate a Rust module with the subxt attribute referencing some runtime WASM like so:

#[subxt::subxt(
    runtime_path = "../artifacts/westend_runtime.wasm",
)]
mod polkadot {}

§Connecting to a node to download metadata via runtime_metadata_insecure_url = "..."

This will, at compile time, connect to the JSON-RPC interface for some node at the URL given, download the metadata from it, and use that. This can be useful in CI, but is not recommended in production code, because:

  • The compilation time is increased since we have to download metadata from a URL each time. If the node we connect to is unresponsive, this will be slow or could fail.
  • The metadata may change from what is expected without notice, causing compilation to fail if it leads to changes in the generated interfaces that are being used.
  • The node that you connect to could be malicious and provide incorrect metadata for the chain.
#[subxt::subxt(
    runtime_metadata_insecure_url = "wss://rpc.polkadot.io:443"
)]
mod polkadot {}

§Configuration

This macro supports a number of attributes to configure what is generated:

§crate = "..."

Use this attribute to specify a custom path to the subxt_core crate:

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    crate = "crate::path::to::subxt_core"
)]
mod polkadot {}

This is useful if you write a library which uses this macro, but don’t want to force users to depend on subxt at the top level too. By default the path ::subxt is used.

§substitute_type(path = "...", with = "...")

This attribute replaces any reference to the generated type at the path given by path with a reference to the path given by with.

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    substitute_type(path = "sp_arithmetic::per_things::Perbill", with = "crate::Foo")
)]
mod polkadot {}

// In reality this needs some traits implementing on
// it to allow it to be used in place of Perbill:
pub struct Foo(u32);

If the type you’re substituting contains generic parameters, you can “pattern match” on those, and make use of them in the substituted type, like so:

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    substitute_type(
        path = "sp_runtime::multiaddress::MultiAddress<A, B>",
        with = "::subxt::utils::Static<sp_runtime::MultiAddress<A, B>>"
    )
)]
mod polkadot {}

The above is also an example of using the crate::utils::Static type to wrap some type which doesn’t on it’s own implement scale_encode::EncodeAsType or scale_decode::DecodeAsType, which are required traits for any substitute type to implement by default.

§derive_for_all_types = "..."

By default, all generated types derive a small set of traits. This attribute allows you to derive additional traits on all generated types:

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    derive_for_all_types = "Eq, PartialEq"
)]
mod polkadot {}

Any substituted types (including the default substitutes) must also implement these traits in order to avoid errors here.

§derive_for_type(path = "...", derive = "...")

Unlike the above, which derives some trait on every generated type, this attribute allows you to derive traits only for specific types. Note that any types which are used inside the specified type may also need to derive the same traits.

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    derive_for_all_types = "Eq, PartialEq",
    derive_for_type(path = "frame_support::PalletId", derive = "Ord, PartialOrd"),
    derive_for_type(path = "sp_runtime::ModuleError", derive = "Hash"),
)]
mod polkadot {}

§generate_docs

By default, documentation is not generated via the macro, since IDEs do not typically make use of it. This attribute forces documentation to be generated, too.

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    generate_docs
)]
mod polkadot {}

§runtime_types_only

By default, the macro will generate various interfaces to make using Subxt simpler in addition with any types that need generating to make this possible. This attribute makes the codegen only generate the types and not the Subxt interface.

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    runtime_types_only
)]
mod polkadot {}

§no_default_derives

By default, the macro will add all derives necessary for the generated code to play nicely with Subxt. Adding this attribute removes all default derives.

#[subxt::subxt(
    runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
    runtime_types_only,
    no_default_derives,
    derive_for_all_types="codec::Encode, codec::Decode"
)]
mod polkadot {}

Note: At the moment, you must derive at least one of codec::Encode or codec::Decode or scale_encode::EncodeAsType or scale_decode::DecodeAsType (because we add #[codec(..)] attributes on some fields/types during codegen), and you must use this feature in conjunction with runtime_types_only (or manually specify a bunch of defaults to make codegen work properly when generating the subxt interfaces).

§unstable_metadata

This attribute works only in combination with runtime_metadata_insecure_url. By default, the macro will fetch the latest stable version of the metadata from the target node. This attribute makes the codegen attempt to fetch the unstable version of the metadata first. This is not recommended in production code, since the unstable metadata a node is providing is likely to be incompatible with Subxt.

#[subxt::subxt(
    runtime_metadata_insecure_url = "wss://rpc.polkadot.io:443",
    unstable_metadata
)]
mod polkadot {}