|
| 1 | +--- |
| 2 | +title: Subxt |
| 3 | +description: TODO |
| 4 | +--- |
| 5 | + |
| 6 | +# Subxt |
| 7 | + |
| 8 | +## Introduction |
| 9 | + |
| 10 | +Subxt is a Rust library designed for interacting with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust’s strong type system, Subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability. |
| 11 | + |
| 12 | +## Prerequisites |
| 13 | + |
| 14 | +Before using Subxt, ensure you have the following installed: |
| 15 | + |
| 16 | +- Rust and Cargo installed on your system. You can install them using [Rustup](https://rustup.rs/){target=\_blank} |
| 17 | +- A Rust project initialized. If you don’t have one, create it with: |
| 18 | + ```bash |
| 19 | + cargo new my_project && cd my_project |
| 20 | + ``` |
| 21 | + |
| 22 | +## Installation |
| 23 | + |
| 24 | +To use subxt in your project, you need to install the necessary dependencies. Each plays a specific role in enabling interaction with the blockchain: |
| 25 | + |
| 26 | +### Install subxt-cli |
| 27 | + |
| 28 | +[`subxt-cli`](https://crates.io/crates/subxt-cli){target=\_blank} is a command-line tool that provides utilities for working with Polkadot SDK metadata. In the context of subxt, it is essential for downloading chain metadata, which is required to generate type-safe Rust interfaces for interacting with the blockchain. Install it using: |
| 29 | + |
| 30 | +```bash |
| 31 | +cargo install subxt-cli |
| 32 | +``` |
| 33 | + |
| 34 | +### Add Core Dependencies |
| 35 | + |
| 36 | +These dependencies are essential for interacting with the blockchain: |
| 37 | + |
| 38 | +- **[subxt](https://crates.io/crates/subxt){target=\_blank}** - the main library for communicating with Polkadot SDK nodes. It handles RPC requests, encoding/decoding, and type generation |
| 39 | + |
| 40 | + ```bash |
| 41 | + cargo add subxt |
| 42 | + ``` |
| 43 | + |
| 44 | +- **[subxt-signer](https://crates.io/crates/subxt-signer){target=\_blank}** - provides cryptographic functionality for signing transactions. Without this, you can only read data but cannot submit transactions |
| 45 | + |
| 46 | + ```bash |
| 47 | + cargo add subxt-signer |
| 48 | + ``` |
| 49 | + |
| 50 | +- **[tokio](https://crates.io/crates/tokio){target=\_blank}** - an asynchronous runtime for Rust. Since blockchain operations are async, Tokio enables efficient handling of network requests |
| 51 | + |
| 52 | + ```bash |
| 53 | + cargo add tokio --features rt,macros |
| 54 | + ``` |
| 55 | + |
| 56 | +After adding the dependencies, your `Cargo.toml` should look like this: |
| 57 | + |
| 58 | +```toml |
| 59 | +[package] |
| 60 | +name = "my_project" |
| 61 | +version = "0.1.0" |
| 62 | +edition = "2021" |
| 63 | +
|
| 64 | +[dependencies] |
| 65 | +subxt = "0.39.0" |
| 66 | +subxt-signer = "0.39.0" |
| 67 | +tokio = { version = "1.43.0", features = ["rt", "macros"] } |
| 68 | +``` |
| 69 | +
|
| 70 | +## Get Started |
| 71 | +
|
| 72 | +This guide will walk you through the basic operations using subxt. |
| 73 | +
|
| 74 | +### Downloading Chain Metadata |
| 75 | +
|
| 76 | +Before interacting with a blockchain, you need to retrieve its metadata. This metadata defines storage structures, extrinsics, and other runtime details. Use the `subxt-cli` tool to download the metadata, replacing `INSERT_NODE_URL` with the URL of the node you want to interact with: |
| 77 | +
|
| 78 | +```bash |
| 79 | +subxt metadata --url INSERT_NODE_URL > polkadot_metadata.scale |
| 80 | +``` |
| 81 | +
|
| 82 | +### Generating Type-Safe Interfaces |
| 83 | +
|
| 84 | +Use the `#[subxt::subxt]` macro to generate a type-safe Rust interface from the downloaded metadata: |
| 85 | +
|
| 86 | +```rust |
| 87 | +// Generate an interface that we can use from the node's metadata. |
| 88 | +#[subxt::subxt(runtime_metadata_path = "./polkadot_metadata.scale")] |
| 89 | +pub mod polkadot {} |
| 90 | +``` |
| 91 | +
|
| 92 | +### Initializing the Subxt client |
| 93 | +
|
| 94 | +To interact with a blockchain node using Subxt, create an asynchronous main function and initialize the client. Replace `INSERT_NODE_URL` with the URL of your target node: |
| 95 | +
|
| 96 | +```rust |
| 97 | +use std::str::FromStr; |
| 98 | +use subxt::utils::AccountId32; |
| 99 | +use subxt::{OnlineClient, PolkadotConfig}; |
| 100 | +use subxt_signer::{bip39::Mnemonic,sr25519::Keypair}; |
| 101 | +
|
| 102 | +#[tokio::main(flavor = "current_thread")] |
| 103 | +async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 104 | + // Define the node URL. |
| 105 | + const NODE_URL: &str = "INSERT_NODE_URL"; |
| 106 | +
|
| 107 | + // Initialize the Subxt client for interacting with the blockchain. |
| 108 | + let api = OnlineClient::<PolkadotConfig>::from_url(NODE_URL).await?; |
| 109 | +
|
| 110 | + // Your code here... |
| 111 | +
|
| 112 | + Ok(()) |
| 113 | +} |
| 114 | +``` |
| 115 | +
|
| 116 | +### Reading Chain Data |
| 117 | +
|
| 118 | +Subxt provides multiple ways to access on-chain data: |
| 119 | +
|
| 120 | +- Constants - constants are predefined values in the runtime that remain unchanged unless modified by a runtime upgrade |
| 121 | +
|
| 122 | + For example, to retrieve the existential deposit, use: |
| 123 | + ```rust |
| 124 | + // A query to obtain some contant: |
| 125 | + let constant_query = polkadot::constants().balances().existential_deposit(); |
| 126 | +
|
| 127 | + // Obtain the value: |
| 128 | + let value = api.constants().at(&constant_query)?; |
| 129 | + ``` |
| 130 | +
|
| 131 | +- State - state refers to the current chain data, which updates with each block |
| 132 | +
|
| 133 | + To fetch account information, use: |
| 134 | + ```rust |
| 135 | + // Define the target account address. |
| 136 | + const ADDRESS: &str = "INSERT_ADDRESS"; |
| 137 | + let account = AccountId32::from_str(ADDRESS).unwrap(); |
| 138 | +
|
| 139 | + // Build a storage query to access account information. |
| 140 | + let storage_query = polkadot::storage().system().account(&account.into()); |
| 141 | +
|
| 142 | + // Fetch the latest state for the account. |
| 143 | + let result = api |
| 144 | + .storage() |
| 145 | + .at_latest() |
| 146 | + .await? |
| 147 | + .fetch(&storage_query) |
| 148 | + .await? |
| 149 | + .unwrap(); |
| 150 | +
|
| 151 | + println!("Account info: {:?}", result); |
| 152 | + ``` |
| 153 | +
|
| 154 | +### Submitting Transasctions |
| 155 | +
|
| 156 | +To submit a transaction, you need to construct an extrinsic, sign it with your private key, and send it to the blockchain. |
| 157 | +
|
| 158 | +For example, to transfer funds to another account: |
| 159 | +
|
| 160 | +```rust |
| 161 | +// Define the recipient address and transfer amount. |
| 162 | +const DEST_ADDRESS: &str = "INSERT_DEST_ADDRESS"; |
| 163 | +const AMOUNT: u128 = INSERT_AMOUNT; |
| 164 | +
|
| 165 | +// Convert the recipient address into an `AccountId32`. |
| 166 | +let dest = AccountId32::from_str(DEST_ADDRESS).unwrap(); |
| 167 | +
|
| 168 | +// Build the balance transfer extrinsic. |
| 169 | +let balance_transfer_tx = polkadot::tx() |
| 170 | + .balances() |
| 171 | + .transfer_allow_death(dest.into(), AMOUNT); |
| 172 | +
|
| 173 | +// Load the sender's keypair from a mnemonic phrase. |
| 174 | +const SECRET_PHRASE: &str = "INSERT_SECRET_PHRASE"; |
| 175 | +let mnemonic = Mnemonic::parse(SECRET_PHRASE).unwrap(); |
| 176 | +let sender_keypair = Keypair::from_phrase(&mnemonic, None).unwrap(); |
| 177 | +
|
| 178 | +// Sign and submit the extrinsic, then wait for it to be finalized. |
| 179 | +let events = api |
| 180 | + .tx() |
| 181 | + .sign_and_submit_then_watch_default(&balance_transfer_tx, &sender_keypair) |
| 182 | + .await? |
| 183 | + .wait_for_finalized_success() |
| 184 | + .await?; |
| 185 | +
|
| 186 | +// Check for a successful transfer event. |
| 187 | +if let Some(event) = events.find_first::<polkadot::balances::events::Transfer>()? { |
| 188 | + println!("Balance transfer successful: {:?}", event); |
| 189 | +} |
| 190 | +``` |
| 191 | +
|
| 192 | +## Where to Go Next |
| 193 | +
|
| 194 | +Now that you've covered the basics, dive into the official [Subxt documentation](https://docs.rs/subxt/latest/subxt/book/index.html){target=\_blank} for comprehensive reference materials and advanced features. |
0 commit comments