Skip to content

Commit 378b7e7

Browse files
committed
Add more docs, pass over README, logo
1 parent d9b1df4 commit 378b7e7

File tree

9 files changed

+325
-81
lines changed

9 files changed

+325
-81
lines changed

README.md

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,73 @@
1-
# subxt · [![build](https://github.com/paritytech/subxt/actions/workflows/rust.yml/badge.svg)](https://github.com/paritytech/subxt/actions/workflows/rust.yml) [![Latest Version](https://img.shields.io/crates/v/subxt.svg)](https://crates.io/crates/subxt) [![Documentation](https://docs.rs/subxt/badge.svg)](https://docs.rs/subxt)
1+
<p align="center">
2+
<img src="./logo.svg" alt="subxt logo" width="420" />
3+
</p>
24

3-
Subxt is a library for interacting with [Substrate](https://github.com/paritytech/polkadot-sdk) based nodes in Rust and WebAssembly. It can:
5+
<p align="center">
6+
<a href="https://github.com/paritytech/subxt/actions/workflows/rust.yml"><img src="https://github.com/paritytech/subxt/actions/workflows/rust.yml/badge.svg" alt="build"></a>
7+
<a href="https://crates.io/crates/subxt"><img src="https://img.shields.io/crates/v/subxt.svg" alt="Latest Version"></a>
8+
<a href="https://docs.rs/subxt"><img src="https://docs.rs/subxt/badge.svg" alt="Documentation"></a>
9+
</p>
10+
11+
Subxt is a library for interacting with chains in the [Polkadot](https://github.com/paritytech/polkadot-sdk) network. It can:
412

513
- Submit Extrinsics (this is where the name comes from).
6-
- Subscribe to blocks, reading the extrinsics and associated events from them.
7-
- Read and iterate over storage values.
8-
- Read constants and custom values from the metadata.
9-
- Call runtime APIs, returning the results.
10-
- Do all of the above via a safe, statically typed interface or via a dynamic one when you need the flexibility.
11-
- Compile to WASM and run entirely in the browser.
12-
- Do a bunch of things in a `#[no_std]` environment via the `subxt-core` crate.
13-
- Use a built-in light client (`smoldot`) to interact with chains.
14+
- Access information at any block (eg storage values, constants, Runtime APIs, View Functions).
15+
- Subscribe to new blocks (and then do the above at them).
16+
- Do all of the above via a safe, statically typed interface or via a flexible dynamic interface.
17+
- Do most of the above via a built-in light client to interact with chains trustlessly.
18+
- Compile to WASM and run [entirely in the browser](./examples/wasm-example), or be [called via FFI](./examples/ffi-example) in many other languages.
1419

1520
## Usage
1621

17-
Take a look in the [examples](./subxt/examples) folder or the [examples](./examples) folder for various smaller or
18-
larger `subxt` usage examples, or [read the guide](https://docs.rs/subxt/latest/subxt/book/index.html) to learn more.
19-
20-
### Downloading metadata from a Substrate node
21-
22-
Use the [`subxt-cli`](./cli) tool to download the metadata for your target runtime from a node.
23-
24-
1. Install:
25-
26-
```bash
27-
cargo install subxt-cli
28-
```
29-
30-
2. Save the encoded metadata to a file:
31-
32-
```bash
33-
subxt metadata -f bytes > metadata.scale
34-
```
35-
36-
This defaults to querying the metadata of a locally running node on the default `http://localhost:9933/`. If querying
37-
a different node then the `metadata` command accepts a `--url` argument.
38-
39-
## Subxt Documentation
40-
41-
For more details regarding utilizing subxt, please visit the [documentation](https://docs.rs/subxt/latest/subxt/).
42-
43-
## Integration Testing
44-
45-
Most tests require a running substrate node to communicate with. This is done by spawning an instance of the
46-
substrate node per test. It requires an up-to-date `substrate` executable on your path.
47-
48-
This can be installed from source via cargo:
49-
50-
```bash
51-
cargo install --git https://github.com/paritytech/polkadot-sdk staging-node-cli --force
22+
Take a look at the [single-file examples](./subxt/examples) folder or the [project based examples](./examples) folder for various smaller or
23+
larger `subxt` usage examples, or [read the docs](https://docs.rs/subxt/latest/subxt) to learn more.
24+
25+
## Example
26+
27+
The "hello world" example of Subxt is submitting a transaction. This is what it looks like:
28+
29+
```rust
30+
use subxt::{Error, OnlineClient, PolkadotConfig};
31+
use subxt_signer::sr25519::dev;
32+
33+
// Generate an interface that we can use from the node's metadata.
34+
#[subxt::subxt(runtime_metadata_path = "/path/to/polkadot_rc_metadata.scale")]
35+
mod polkadot {}
36+
37+
#[tokio::main]
38+
async fn main() -> Result<(), Error> {
39+
// Create a new API client, configured to talk to Polkadot nodes.
40+
let api = OnlineClient::<PolkadotConfig>::new().await?;
41+
42+
// Almost all actions are performed at an explicit block. Here we use
43+
// the current block at the time of running this.
44+
let at_block = api.at_current_block().await?;
45+
46+
// Build a balance transfer extrinsic.
47+
let dest = dev::bob().public_key().into();
48+
let balance_transfer_tx = polkadot::transactions()
49+
.balances()
50+
.transfer_allow_death(dest, 10_000);
51+
52+
// Submit the balance transfer extrinsic from Alice, and wait for it
53+
// to be successful and in a finalized block. We get back the extrinsic
54+
// events if all is well.
55+
let from = dev::alice();
56+
let events = at_block
57+
.transactions()
58+
.sign_and_submit_then_watch_default(&balance_transfer_tx, &from)
59+
.await?
60+
.wait_for_finalized_success()
61+
.await?;
62+
63+
// (Optional) we can look for a specific event to learn more about
64+
// the submission.
65+
if let Some(event) = events.find_first::<polkadot::balances::events::Transfer>() {
66+
println!("Balance transfer success: {event:?}");
67+
}
68+
69+
Ok(())
70+
}
5271
```
5372

5473
## Real world usage
@@ -68,9 +87,9 @@ Please add your project to this list via a PR.
6887
- [Hyperbridge](https://github.com/polytope-labs/hyperbridge) A hyperscalable coprocessor for verifiable cross-chain interoperability.
6988
- [pop CLI](https://github.com/r0gue-io/pop-cli) The all-in-one tool for Polkadot development.
7089

71-
**Alternatives**
90+
## Alternatives
7291

73-
[substrate-api-client](https://github.com/scs/substrate-api-client) provides similar functionality.
92+
If you're working in TypeScript / JavaScript, [polkadot-api](https://github.com/polkadot-api/polkadot-api) is an excellent and actively developed alternative.
7493

7594
#### License
7695

422 KB
Binary file not shown.

logo.svg

Lines changed: 44 additions & 0 deletions
Loading

subxt/examples/config_assethub.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! Configuring Subxt to talk to AssetHub.
2+
use subxt::Error;
3+
use subxt::config::{
4+
Config, DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder, PolkadotConfig, SubstrateConfig,
5+
};
6+
use subxt_signer::sr25519::dev;
7+
8+
#[subxt::subxt(
9+
runtime_metadata_path = "../artifacts/polkadot_assethub_metadata_small.scale",
10+
derive_for_type(
11+
path = "staging_xcm::v5::location::Location",
12+
derive = "Clone, codec::Encode",
13+
recursive
14+
)
15+
)]
16+
pub mod assethub {}
17+
use assethub::runtime_types::staging_xcm::v5::junctions::Junctions;
18+
use assethub::runtime_types::staging_xcm::v5::location::Location;
19+
20+
/// Our AssetHub configuration wraps SubstrateConfig and
21+
/// tweaks it in a couple of places.
22+
#[derive(Debug, Clone, Default)]
23+
pub struct AssetHubConfig(SubstrateConfig);
24+
25+
impl Config for AssetHubConfig {
26+
// AssetHub, like Polkadot, has no account index on its address type:
27+
type Address = <PolkadotConfig as Config>::Address;
28+
29+
// Configure the asset location to be our generated Location type.
30+
type AssetId = Location;
31+
32+
// Just copy the default SubstrateConfig for these:
33+
type AccountId = <SubstrateConfig as Config>::AccountId;
34+
type Signature = <SubstrateConfig as Config>::Signature;
35+
type Hasher = <SubstrateConfig as Config>::Hasher;
36+
type Header = <SubstrateConfig as Config>::Header;
37+
type ExtrinsicParams = DefaultExtrinsicParams<AssetHubConfig>;
38+
39+
// Forward these methods to the default SubstrateConfig:
40+
fn genesis_hash(&self) -> Option<subxt::config::HashFor<Self>> {
41+
self.0.genesis_hash()
42+
}
43+
fn legacy_types_for_spec_version<'this>(
44+
&'this self,
45+
spec_version: u32,
46+
) -> Option<scale_info_legacy::TypeRegistrySet<'this>> {
47+
self.0.legacy_types_for_spec_version(spec_version)
48+
}
49+
fn metadata_for_spec_version(&self, spec_version: u32) -> Option<subxt::ArcMetadata> {
50+
self.0.metadata_for_spec_version(spec_version)
51+
}
52+
fn set_metadata_for_spec_version(&self, spec_version: u32, metadata: subxt::ArcMetadata) {
53+
self.0.set_metadata_for_spec_version(spec_version, metadata);
54+
}
55+
fn spec_and_transaction_version_for_block_number(
56+
&self,
57+
block_number: u64,
58+
) -> Option<(u32, u32)> {
59+
self.0
60+
.spec_and_transaction_version_for_block_number(block_number)
61+
}
62+
}
63+
64+
#[tokio::main]
65+
async fn main() -> Result<(), Error> {
66+
// With the config defined, we can create a Subxt client using it:
67+
let client = subxt::OnlineClient::<AssetHubConfig>::new().await?;
68+
69+
// Build some extrinsic to submit:
70+
let tx_payload = assethub::tx().system().remark(b"Hello".to_vec());
71+
72+
// Build extrinsic params using an asset at some location as a tip:
73+
let location = Location {
74+
parents: 3,
75+
interior: Junctions::Here,
76+
};
77+
let tx_config = DefaultExtrinsicParamsBuilder::<AssetHubConfig>::new()
78+
.tip_of(1234, location)
79+
.build();
80+
81+
// And provide the extrinsic params including the tip when submitting a transaction:
82+
let _ = client
83+
.tx()
84+
.await?
85+
.sign_and_submit_then_watch(&tx_payload, &dev::alice(), tx_config)
86+
.await;
87+
88+
Ok(())
89+
}

subxt/examples/config_eth.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Configuring Subxt to talk to AssetHub.
2+
use subxt::Error;
3+
use subxt::config::{Config, DefaultExtrinsicParams, SubstrateConfig};
4+
5+
/// Our EthConfig wraps SubstrateConfig and configures the
6+
/// account ID / address / signature to be based on 20 byte IDs.
7+
#[derive(Debug, Clone, Default)]
8+
pub struct EthConfig(SubstrateConfig);
9+
10+
impl Config for EthConfig {
11+
// AssetHub, like Polkadot, has no account index on its address type:
12+
type Address = subxt::utils::AccountId20;
13+
type AccountId = subxt::utils::AccountId20;
14+
type Signature = subxt_signer::eth::Signature;
15+
16+
// Just copy the default SubstrateConfig for these:
17+
type AssetId = <SubstrateConfig as Config>::AssetId;
18+
type Hasher = <SubstrateConfig as Config>::Hasher;
19+
type Header = <SubstrateConfig as Config>::Header;
20+
type ExtrinsicParams = DefaultExtrinsicParams<EthConfig>;
21+
22+
// Forward these methods to the default SubstrateConfig:
23+
fn genesis_hash(&self) -> Option<subxt::config::HashFor<Self>> {
24+
self.0.genesis_hash()
25+
}
26+
fn legacy_types_for_spec_version<'this>(
27+
&'this self,
28+
spec_version: u32,
29+
) -> Option<scale_info_legacy::TypeRegistrySet<'this>> {
30+
self.0.legacy_types_for_spec_version(spec_version)
31+
}
32+
fn metadata_for_spec_version(&self, spec_version: u32) -> Option<subxt::ArcMetadata> {
33+
self.0.metadata_for_spec_version(spec_version)
34+
}
35+
fn set_metadata_for_spec_version(&self, spec_version: u32, metadata: subxt::ArcMetadata) {
36+
self.0.set_metadata_for_spec_version(spec_version, metadata);
37+
}
38+
fn spec_and_transaction_version_for_block_number(
39+
&self,
40+
block_number: u64,
41+
) -> Option<(u32, u32)> {
42+
self.0
43+
.spec_and_transaction_version_for_block_number(block_number)
44+
}
45+
}
46+
47+
#[tokio::main]
48+
async fn main() -> Result<(), Error> {
49+
// With the eth config defined, we can create a Subxt client using it:
50+
let _client = subxt::OnlineClient::<EthConfig>::new().await?;
51+
52+
Ok(())
53+
}

subxt/src/client.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//! via something like [`OnlineClient::at_block`] or [`OfflineClient::at_block`].
1010
//! These hand back [`OnlineClientAtBlock`] or [`OfflineClientAtBlock`], which expose
1111
//! various methods available online or offline at the given block.
12+
//!
13+
//! See the docs for [`ClientAtBlock`] to see what it's possible to do at a given block.
1214
1315
mod offline_client;
1416
mod online_client;

subxt/src/config.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,39 @@
1111
//! - A [`PolkadotConfig`] implementation is provided which is specialized towards the Polkadot
1212
//! Relay Chain, and comes pre-configured to work against historic Polkadot RC blocks.
1313
//!
14+
//! # Creating custom configuration
15+
//!
16+
//! Some chains require this configuration to be customized. In many cases, you can perform most
17+
//! interactions on these chains using the default [`SubstrateConfig`], but may need small
18+
//! customizations to enable all interactions to work properly.
19+
//!
20+
//! ## Asset Hub
21+
//!
22+
//! One chain that needs custom configuration to completely work is Asset Hub. For the most part
23+
//! you can just use [`SubstrateConfig`], but if you want to add a tip to a transaction in anything
24+
//! other than DOT, you'll need to change the [`Config::AssetId`] property to allow for this.
25+
//! This involves creating a new [`Config`] instance for Asset Hub, which looks like this:
26+
//!
27+
//! ```rust,no_run
28+
#![doc = include_str ! ("../examples/config_assethub.rs")]
29+
//! ```
30+
//!
31+
//! ## Ethereum based chains
32+
//!
33+
//! If you're interacting with an Ethereum based chain, you'll need to configure Subxt to work with
34+
//! 20 byte account IDs instead of the default 32 byte ones, and a corresponding `Signature` type.
35+
//! This would look something like this:
36+
//!
37+
//! ```rust,no_run
38+
#![doc = include_str ! ("../examples/config_eth.rs")]
39+
//! ```
40+
//!
41+
//! # Other chains
42+
//!
43+
//! If you find that [`SubstrateConfig`] doesn't work, and neither of the above is applicable, then
44+
//! the next step is to look at how the runtime for the chain you'd like to interact with is
45+
//! configured. Please open an issue in the Subxt repository and we can help to narrow down what
46+
//! the problem might be.
1447
1548
mod default_extrinsic_params;
1649

@@ -56,7 +89,7 @@ pub trait Config: Clone + Debug + Sized + Send + Sync + 'static {
5689
type ExtrinsicParams: ExtrinsicParams<Self>;
5790

5891
/// This is used to identify an asset in the `ChargeAssetTxPayment` signed extension.
59-
type AssetId: Debug + Clone + Encode + DecodeAsType + EncodeAsType + Send;
92+
type AssetId: AssetId;
6093

6194
/// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
6295
/// This is created on demand with the relevant metadata for a given block, and
@@ -129,7 +162,11 @@ pub type HashFor<T> = <<T as Config>::Hasher as Hasher>::Hash;
129162
/// given some [`Config`], this return the other params needed for its `ExtrinsicParams`.
130163
pub type ParamsFor<T> = <<T as Config>::ExtrinsicParams as ExtrinsicParams<T>>::Params;
131164

132-
/// Block hashes must conform to a bunch of things to be used in Subxt.
165+
/// AssetId types must conform to this trait.
166+
pub trait AssetId: Debug + Clone + Encode + DecodeAsType + EncodeAsType + Send {}
167+
impl<T> AssetId for T where T: Debug + Clone + Encode + DecodeAsType + EncodeAsType + Send {}
168+
169+
/// Block hash types must conform to this trait.
133170
pub trait Hash:
134171
Debug
135172
+ Display

0 commit comments

Comments
 (0)