Subxt is a library to submit extrinsics to a substrate node via RPC.
The generated Subxt API exposes the ability to:
- Submit extrinsics (Calls)
- Query storage (Storage)
- Query constants (Constants)
- Subscribe to events (Events)
Generate the runtime API
Subxt generates a runtime API from downloaded static metadata. The metadata can be downloaded using the subxt-cli tool.
To generate the runtime API, use the subxt attribute which points at downloaded static metadata.
#[subxt::subxt(runtime_metadata_path = "metadata.scale")]
pub mod node_runtime { }
The node_runtime has the following hierarchy:
For more information regarding the node_runtime hierarchy, please visit the
subxt-codegen documentation.
Initializing the API client
use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
pub mod polkadot {}
# #[tokio::main]
# async fn main() {
let api = ClientBuilder::new()
.set_url("wss://rpc.polkadot.io:443")
.build()
.await
.unwrap()
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();
# }
The RuntimeApi type is generated by the subxt macro from the supplied metadata. This can be parameterized with user
supplied implementations for the Config and Extra types, if the default implementation differs from the target
chain.
To ensure that extrinsics are properly submitted, during the build phase of the Client the
runtime metadata of the node is downloaded. If the URL is not specified (set_url), the local host is used instead.
Submit Extrinsics
Extrinsics are obtained using the API's RuntimeApi::tx() method, followed by pallet_name() and then the
call_item_name().
Submit an extrinsic, returning success once the transaction is validated and accepted into the pool:
Please visit the balance_transfer example for more details.
Querying Storage
The runtime storage is queried via the generated RuntimeApi::storage() method, followed by the pallet_name() and
then the storage_item_name().
Please visit the fetch_staking_details example for more details.
Query Constants
Constants are embedded into the node's metadata.
The subxt offers the ability to query constants from the runtime metadata (metadata downloaded when constructing the client, not the one provided for API generation).
To query constants use the generated RuntimeApi::constants() method, followed by the pallet_name() and then the
constant_item_name().
Please visit the fetch_constants example for more details.
Subscribe to Events
To subscribe to events, use the generated RuntimeApi::events() method which exposes:
subscribe()- Subscribe to events emitted from blocks. These blocks haven't necessarily been finalised.subscribe_finalized()- Subscribe to events from finalized blocks.at()- Obtain events at a given block hash.
Examples
- subscribe_all_events: Subscribe to events emitted from blocks.
- subscribe_one_event: Subscribe and filter by one event.
- subscribe_some_events: Subscribe and filter event.
Static Metadata Validation
There are two types of metadata that the subxt is aware of:
- static metadata: Metadata used for generating the API.
- runtime metadata: Metadata downloaded from the target node when a subxt client is created.
There are cases when the static metadata is different from the runtime metadata of a node. Such is the case when the node performs a runtime update.
To ensure that subxt can properly communicate with the target node the static metadata is validated against the runtime metadata of the node.
This validation is performed at the Call, Constant, and Storage levels, as well for the entire metadata. The level of granularity ensures that the users can still submit a given call, even if another call suffered changes.
Full metadata validation:
# use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
# #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
# pub mod polkadot {}
# #[tokio::main]
# async fn main() {
# let api = ClientBuilder::new()
# .build()
# .await
# .unwrap()
# .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();
// To make sure that all of our statically generated pallets are compatible with the
// runtime node, we can run this check:
api.validate_metadata().unwrap();
# }
Call level validation:
# use sp_keyring::AccountKeyring;
# use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
# #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
# pub mod polkadot {}
# #[tokio::main]
# async fn main() {
# let api = ClientBuilder::new()
# .build()
# .await
# .unwrap()
# .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();
// Submit the `transfer` extrinsic from Alice's account to Bob's.
let dest = AccountKeyring::Bob.to_account_id().into();
let extrinsic = api
.tx()
.balances()
// Constructing an extrinsic will fail if the metadata
// is not in sync with the generated API.
.transfer(dest, 123_456_789_012_345)
.unwrap();
# }
Runtime Updates
There are cases when the node would perform a runtime update, and the runtime node's metadata would be out of sync with the subxt's metadata.
The UpdateClient API keeps the RuntimeVersion and Metadata of the client synced with the target node.
Please visit the subscribe_runtime_updates example for more details.