mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 05:51:02 +00:00
Fix documentation examples (#568)
* Fix documentation examples Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * CI: Add `cargo test --doc` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update .github/workflows/rust.yml Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> * Remove docs/subxt.md and move documentation to subxt/lib.rs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Hide polkadot interface for `events/mod.rs` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * docs: Use `#` for headers Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
This commit is contained in:
@@ -99,6 +99,12 @@ jobs:
|
|||||||
- name: Check internal documentation links
|
- name: Check internal documentation links
|
||||||
run: RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc -vv --workspace --no-deps --document-private-items
|
run: RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc -vv --workspace --no-deps --document-private-items
|
||||||
|
|
||||||
|
- name: Run cargo test on documentation
|
||||||
|
uses: actions-rs/cargo@v1.0.3
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --doc
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
name: Cargo test
|
name: Cargo test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ a different node then the `metadata` command accepts a `--url` argument.
|
|||||||
|
|
||||||
## Subxt Documentation
|
## Subxt Documentation
|
||||||
|
|
||||||
For more details regarding utilizing subxt, please visit the [documentation](docs/subxt.md).
|
For more details regarding utilizing subxt, please visit the [documentation](https://docs.rs/subxt/latest/subxt/).
|
||||||
|
|
||||||
## Integration Testing
|
## Integration Testing
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -29,13 +29,16 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Example
|
//! ## Example
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
|
//! use std::fs;
|
||||||
//! use codec::Decode;
|
//! use codec::Decode;
|
||||||
//! use frame_metadata::RuntimeMetadataPrefixed;
|
//! use frame_metadata::RuntimeMetadataPrefixed;
|
||||||
//! use subxt_codegen::DerivesRegistry;
|
//! use subxt_codegen::DerivesRegistry;
|
||||||
//!
|
//!
|
||||||
|
//! let encoded = fs::read("../artifacts/polkadot_metadata.scale").unwrap();
|
||||||
|
//!
|
||||||
//! // Runtime metadata obtained from a node.
|
//! // Runtime metadata obtained from a node.
|
||||||
//! let metadata = <RuntimeMetadataPrefixed as Decode>::decode(encoded)?;
|
//! let metadata = <RuntimeMetadataPrefixed as Decode>::decode(&mut &*encoded).unwrap();
|
||||||
//! // Module under which the API is generated.
|
//! // Module under which the API is generated.
|
||||||
//! let item_mod = syn::parse_quote!(
|
//! let item_mod = syn::parse_quote!(
|
||||||
//! pub mod api {}
|
//! pub mod api {}
|
||||||
|
|||||||
-144
@@ -1,144 +0,0 @@
|
|||||||
Subxt is a library to **sub**mit e**xt**rinsics to a [substrate](https://github.com/paritytech/substrate) node via RPC.
|
|
||||||
|
|
||||||
The generated Subxt API exposes the ability to:
|
|
||||||
- [Submit extrinsics](https://docs.substrate.io/v3/concepts/extrinsics/) (Calls)
|
|
||||||
- [Query storage](https://docs.substrate.io/v3/runtime/storage/) (Storage)
|
|
||||||
- [Query constants](https://docs.substrate.io/how-to-guides/v3/basics/configurable-constants/) (Constants)
|
|
||||||
- [Subscribe to events](https://docs.substrate.io/v3/runtime/events-and-errors/) (Events)
|
|
||||||
|
|
||||||
|
|
||||||
### Generate the runtime API
|
|
||||||
|
|
||||||
Subxt generates a runtime API from downloaded static metadata. The metadata can be downloaded using the
|
|
||||||
[subxt-cli](https://crates.io/crates/subxt-cli) tool.
|
|
||||||
|
|
||||||
To generate the runtime API, use the `subxt` attribute which points at downloaded static metadata.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#[subxt::subxt(runtime_metadata_path = "metadata.scale")]
|
|
||||||
pub mod node_runtime { }
|
|
||||||
```
|
|
||||||
|
|
||||||
The `node_runtime` has the following hierarchy:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub mod node_runtime {
|
|
||||||
pub mod PalletName {
|
|
||||||
pub mod calls { }
|
|
||||||
pub mod storage { }
|
|
||||||
pub mod constants { }
|
|
||||||
pub mod events { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information regarding the `node_runtime` hierarchy, please visit the
|
|
||||||
[subxt-codegen](https://docs.rs/subxt-codegen/latest/subxt_codegen/) documentation.
|
|
||||||
|
|
||||||
|
|
||||||
### Initializing the API client
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
|
|
||||||
|
|
||||||
let api = ClientBuilder::new()
|
|
||||||
.set_url("wss://rpc.polkadot.io:443")
|
|
||||||
.build()
|
|
||||||
.await?
|
|
||||||
.to_runtime_api::<node_runtime::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](../examples/examples/balance_transfer.rs) 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](../examples/examples/fetch_staking_details.rs) 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](../examples/examples/fetch_constants.rs) 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](../examples/examples/subscribe_all_events.rs): Subscribe to events emitted from blocks.
|
|
||||||
- [subscribe_one_event](../examples/examples/subscribe_one_event.rs): Subscribe and filter by one event.
|
|
||||||
- [subscribe_some_events](../examples/examples/subscribe_some_events.rs): 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:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// To make sure that all of our statically generated pallets are compatible with the
|
|
||||||
// runtime node, we can run this check:
|
|
||||||
api.validate_metadata()?;
|
|
||||||
```
|
|
||||||
|
|
||||||
Call level validation:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
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)?;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 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](../examples/examples/subscribe_runtime_updates.rs) example for more details.
|
|
||||||
+27
-9
@@ -97,17 +97,23 @@ impl ClientBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new Client.
|
/// Builder for [Client].
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```no_run
|
||||||
/// use subxt::{ClientBuilder, DefaultConfig};
|
/// use subxt::{ClientBuilder, DefaultConfig};
|
||||||
///
|
///
|
||||||
/// let client = ClientBuilder::new()
|
/// #[tokio::main]
|
||||||
/// .set_url("wss://rpc.polkadot.io:443")
|
/// async fn main() {
|
||||||
/// .build::<DefaultConfig>()
|
/// // Build the client.
|
||||||
/// .await?;
|
/// let client = ClientBuilder::new()
|
||||||
|
/// .set_url("wss://rpc.polkadot.io:443")
|
||||||
|
/// .build::<DefaultConfig>()
|
||||||
|
/// .await
|
||||||
|
/// .unwrap();
|
||||||
|
/// // Use the client...
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn build<T: Config>(self) -> Result<Client<T>, BasicError> {
|
pub async fn build<T: Config>(self) -> Result<Client<T>, BasicError> {
|
||||||
let client = if let Some(client) = self.client {
|
let client = if let Some(client) = self.client {
|
||||||
@@ -208,14 +214,26 @@ impl<T: Config> Client<T> {
|
|||||||
/// performing runtime updates, while the API is still in use.
|
/// performing runtime updates, while the API is still in use.
|
||||||
/// Without performing runtime updates the submitted extrinsics may fail.
|
/// Without performing runtime updates the submitted extrinsics may fail.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```no_run
|
||||||
|
/// # use subxt::{ClientBuilder, DefaultConfig};
|
||||||
|
/// #
|
||||||
|
/// # #[tokio::main]
|
||||||
|
/// # async fn main() {
|
||||||
|
/// # let client = ClientBuilder::new()
|
||||||
|
/// # .set_url("wss://rpc.polkadot.io:443")
|
||||||
|
/// # .build::<DefaultConfig>()
|
||||||
|
/// # .await
|
||||||
|
/// # .unwrap();
|
||||||
|
/// #
|
||||||
/// let update_client = client.updates();
|
/// let update_client = client.updates();
|
||||||
|
/// // Spawn a new background task to handle runtime updates.
|
||||||
/// tokio::spawn(async move {
|
/// tokio::spawn(async move {
|
||||||
/// let result = update_client.perform_runtime_updates().await;
|
/// let result = update_client.perform_runtime_updates().await;
|
||||||
/// println!("Runtime update finished with result={:?}", result);
|
/// println!("Runtime update finished with result={:?}", result);
|
||||||
/// });
|
/// });
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn updates(&self) -> UpdateClient<T> {
|
pub fn updates(&self) -> UpdateClient<T> {
|
||||||
UpdateClient::new(
|
UpdateClient::new(
|
||||||
|
|||||||
+35
-7
@@ -21,7 +21,7 @@
|
|||||||
//!
|
//!
|
||||||
//! This module is wrapped by the generated API in `RuntimeAPI::EventsApi`.
|
//! This module is wrapped by the generated API in `RuntimeAPI::EventsApi`.
|
||||||
//!
|
//!
|
||||||
//! # Example
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! ## Subscribe to all events
|
//! ## Subscribe to all events
|
||||||
//!
|
//!
|
||||||
@@ -31,12 +31,23 @@
|
|||||||
//!
|
//!
|
||||||
//! To obtain the events from a given block use `at()`.
|
//! To obtain the events from a given block use `at()`.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
//! let mut events = api.events().subscribe().await?;
|
//! # use futures::StreamExt;
|
||||||
|
//! # 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>>>();
|
||||||
|
//! let mut events = api.events().subscribe().await.unwrap();
|
||||||
//!
|
//!
|
||||||
//! while let Some(ev) = events.next().await {
|
//! while let Some(ev) = events.next().await {
|
||||||
//! // Obtain all events from this block.
|
//! // Obtain all events from this block.
|
||||||
//! let ev: subxt::Events<_, _> = ev?;
|
//! let ev: subxt::Events<_, _> = ev.unwrap();
|
||||||
//! // Print block hash.
|
//! // Print block hash.
|
||||||
//! println!("Event at block hash {:?}", ev.block_hash());
|
//! println!("Event at block hash {:?}", ev.block_hash());
|
||||||
//! // Iterate over all events.
|
//! // Iterate over all events.
|
||||||
@@ -45,6 +56,7 @@
|
|||||||
//! println!("Event details {:?}", event_details);
|
//! println!("Event details {:?}", event_details);
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Filter events
|
//! ## Filter events
|
||||||
@@ -55,16 +67,32 @@
|
|||||||
//! returned directly. Otherwise, we'll be given a corresponding tuple of `Option`'s, with exactly
|
//! returned directly. Otherwise, we'll be given a corresponding tuple of `Option`'s, with exactly
|
||||||
//! one variant populated each time.
|
//! one variant populated each time.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
//! let mut events = api
|
//! # use futures::StreamExt;
|
||||||
|
//! # 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>>>();
|
||||||
|
//!
|
||||||
|
//! let mut transfer_events = api
|
||||||
//! .events()
|
//! .events()
|
||||||
//! .subscribe()
|
//! .subscribe()
|
||||||
//! .await?
|
//! .await
|
||||||
|
//! .unwrap()
|
||||||
//! .filter_events::<(polkadot::balances::events::Transfer,)>();
|
//! .filter_events::<(polkadot::balances::events::Transfer,)>();
|
||||||
//!
|
//!
|
||||||
//! while let Some(transfer_event) = transfer_events.next().await {
|
//! while let Some(transfer_event) = transfer_events.next().await {
|
||||||
//! println!("Balance transfer event: {transfer_event:?}");
|
//! println!("Balance transfer event: {transfer_event:?}");
|
||||||
//! }
|
//! }
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
mod decoding;
|
mod decoding;
|
||||||
|
|||||||
+178
-1
@@ -14,7 +14,184 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#![doc = include_str!("../../docs/subxt.md")]
|
//! Subxt is a library to **sub**mit e**xt**rinsics to a [substrate](https://github.com/paritytech/substrate) node via RPC.
|
||||||
|
//!
|
||||||
|
//! The generated Subxt API exposes the ability to:
|
||||||
|
//! - [Submit extrinsics](https://docs.substrate.io/v3/concepts/extrinsics/) (Calls)
|
||||||
|
//! - [Query storage](https://docs.substrate.io/v3/runtime/storage/) (Storage)
|
||||||
|
//! - [Query constants](https://docs.substrate.io/how-to-guides/v3/basics/configurable-constants/) (Constants)
|
||||||
|
//! - [Subscribe to events](https://docs.substrate.io/v3/runtime/events-and-errors/) (Events)
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! # Generate the runtime API
|
||||||
|
//!
|
||||||
|
//! Subxt generates a runtime API from downloaded static metadata. The metadata can be downloaded using the
|
||||||
|
//! [subxt-cli](https://crates.io/crates/subxt-cli) tool.
|
||||||
|
//!
|
||||||
|
//! To generate the runtime API, use the `subxt` attribute which points at downloaded static metadata.
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! #[subxt::subxt(runtime_metadata_path = "metadata.scale")]
|
||||||
|
//! pub mod node_runtime { }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! The `node_runtime` has the following hierarchy:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! pub mod node_runtime {
|
||||||
|
//! pub mod PalletName {
|
||||||
|
//! pub mod calls { }
|
||||||
|
//! pub mod storage { }
|
||||||
|
//! pub mod constants { }
|
||||||
|
//! pub mod events { }
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! For more information regarding the `node_runtime` hierarchy, please visit the
|
||||||
|
//! [subxt-codegen](https://docs.rs/subxt-codegen/latest/subxt_codegen/) documentation.
|
||||||
|
//!
|
||||||
|
//!
|
||||||
|
//! # Initializing the API client
|
||||||
|
//!
|
||||||
|
//! ```no_run
|
||||||
|
//! 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](../examples/examples/balance_transfer.rs) 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](../examples/examples/fetch_staking_details.rs) 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](../examples/examples/fetch_constants.rs) 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](../examples/examples/subscribe_all_events.rs): Subscribe to events emitted from blocks.
|
||||||
|
//! - [subscribe_one_event](../examples/examples/subscribe_one_event.rs): Subscribe and filter by one event.
|
||||||
|
//! - [subscribe_some_events](../examples/examples/subscribe_some_events.rs): 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:
|
||||||
|
//!
|
||||||
|
//! ```no_run
|
||||||
|
//! # 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:
|
||||||
|
//!
|
||||||
|
//! ```ignore
|
||||||
|
//! # 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](../examples/examples/subscribe_runtime_updates.rs) example for more details.
|
||||||
|
|
||||||
#![deny(
|
#![deny(
|
||||||
bad_style,
|
bad_style,
|
||||||
const_err,
|
const_err,
|
||||||
|
|||||||
+40
-10
@@ -23,12 +23,23 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Fetch Storage
|
//! ## Fetch Storage
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
//! use subxt::rpc::Rpc;
|
//! # use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
|
||||||
//! use subxt::storage::StorageKeyPrefix;
|
//! # use subxt::storage::StorageKeyPrefix;
|
||||||
|
//! # use subxt::rpc::Rpc;
|
||||||
//!
|
//!
|
||||||
|
//! #[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>>>();
|
||||||
//! // Storage prefix is `twox_128("System") ++ twox_128("ExtrinsicCount")`.
|
//! // Storage prefix is `twox_128("System") ++ twox_128("ExtrinsicCount")`.
|
||||||
//! let key = StorageKeyPrefix::new::<node_runtime::system::storage::ExtrinsicCount>()
|
//! let key = StorageKeyPrefix::new::<polkadot::system::storage::ExtrinsicCount>()
|
||||||
//! .to_storage_key();
|
//! .to_storage_key();
|
||||||
//!
|
//!
|
||||||
//! // Obtain the RPC from a generated API
|
//! // Obtain the RPC from a generated API
|
||||||
@@ -36,27 +47,46 @@
|
|||||||
//! .client
|
//! .client
|
||||||
//! .rpc();
|
//! .rpc();
|
||||||
//!
|
//!
|
||||||
//! let result = rpc.storage(&key, None)?;
|
//! let result = rpc.storage(&key, None).await.unwrap();
|
||||||
//! println!("Storage result: {:?}", result);
|
//! println!("Storage result: {:?}", result);
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Fetch Keys
|
//! ## Fetch Keys
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
//! use subxt::rpc::Rpc;
|
//! # use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
|
||||||
//! use subxt::storage::StorageKeyPrefix;
|
//! # use subxt::storage::StorageKeyPrefix;
|
||||||
//! let key = StorageKeyPrefix::new::<polkadot::xcm_pallet::storage::VersionNotifiers>();
|
//! # use subxt::rpc::Rpc;
|
||||||
|
//!
|
||||||
|
//! #[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>>>();
|
||||||
|
//! let key = StorageKeyPrefix::new::<polkadot::xcm_pallet::storage::VersionNotifiers>()
|
||||||
|
//! .to_storage_key();
|
||||||
//!
|
//!
|
||||||
//! // Obtain the RPC from a generated API
|
//! // Obtain the RPC from a generated API
|
||||||
//! let rpc: &Rpc<_> = api
|
//! let rpc: &Rpc<_> = api
|
||||||
//! .client
|
//! .client
|
||||||
//! .rpc();
|
//! .rpc();
|
||||||
|
//!
|
||||||
//! // Fetch up to 10 keys.
|
//! // Fetch up to 10 keys.
|
||||||
//! let keys = rpc
|
//! let keys = rpc
|
||||||
//! .storage_keys_paged(Some(key), 10, None, None);
|
//! .storage_keys_paged(Some(key), 10, None, None)
|
||||||
|
//! .await
|
||||||
|
//! .unwrap();
|
||||||
|
//!
|
||||||
//! for key in keys.iter() {
|
//! for key in keys.iter() {
|
||||||
//! println!("Key: 0x{}", hex::encode(&key));
|
//! println!("Key: 0x{}", hex::encode(&key));
|
||||||
//! }
|
//! }
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
// jsonrpsee subscriptions are interminable.
|
// jsonrpsee subscriptions are interminable.
|
||||||
|
|||||||
+40
-6
@@ -32,28 +32,62 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Fetch Storage Keys
|
//! ## Fetch Storage Keys
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
|
//! # use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
|
||||||
|
//! # use subxt::storage::StorageClient;
|
||||||
|
//!
|
||||||
|
//! #[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>>>();
|
||||||
|
//! # // Obtain the storage client wrapper from the API.
|
||||||
|
//! # let storage: StorageClient<_> = api.client.storage();
|
||||||
//! // Fetch just the keys, returning up to 10 keys.
|
//! // Fetch just the keys, returning up to 10 keys.
|
||||||
//! let keys = storage
|
//! let keys = storage
|
||||||
//! .fetch_keys::<node_runtime::xcm_pallet::storage::VersionNotifiers>(10, None, None)
|
//! .fetch_keys::<polkadot::xcm_pallet::storage::VersionNotifiers>(10, None, None)
|
||||||
//! .await?;
|
//! .await
|
||||||
|
//! .unwrap();
|
||||||
//! // Iterate over each key
|
//! // Iterate over each key
|
||||||
//! for key in keys.iter() {
|
//! for key in keys.iter() {
|
||||||
//! println!("Key: 0x{}", hex::encode(&key));
|
//! println!("Key: 0x{}", hex::encode(&key));
|
||||||
//! }
|
//! }
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! ## Iterate over Storage
|
//! ## Iterate over Storage
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
|
//! # use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
|
||||||
|
//! # use subxt::storage::StorageClient;
|
||||||
|
//!
|
||||||
|
//! #[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>>>();
|
||||||
|
//! # // Obtain the storage client wrapper from the API.
|
||||||
|
//! # let storage: StorageClient<_> = api.client.storage();
|
||||||
//! // Iterate over keys and values.
|
//! // Iterate over keys and values.
|
||||||
//! let mut iter = storage
|
//! let mut iter = storage
|
||||||
//! .iter::<polkadot::xcm_pallet::storage::VersionNotifiers>(None)
|
//! .iter::<polkadot::xcm_pallet::storage::VersionNotifiers>(None)
|
||||||
//! .await?;
|
//! .await
|
||||||
//! while let Some((key, value)) = iter.next().await? {
|
//! .unwrap();
|
||||||
|
//! while let Some((key, value)) = iter.next().await.unwrap() {
|
||||||
//! println!("Key: 0x{}", hex::encode(&key));
|
//! println!("Key: 0x{}", hex::encode(&key));
|
||||||
//! println!("Value: {}", value);
|
//! println!("Value: {}", value);
|
||||||
//! }
|
//! }
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use codec::{
|
use codec::{
|
||||||
|
|||||||
+13
-1
@@ -28,12 +28,24 @@
|
|||||||
//!
|
//!
|
||||||
//! Here we use tokio to check for updates in the background, but any runtime can be used.
|
//! Here we use tokio to check for updates in the background, but any runtime can be used.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```no_run
|
||||||
|
//! # use subxt::{ClientBuilder, DefaultConfig};
|
||||||
|
//! #
|
||||||
|
//! # #[tokio::main]
|
||||||
|
//! # async fn main() {
|
||||||
|
//! # let client = ClientBuilder::new()
|
||||||
|
//! # .set_url("wss://rpc.polkadot.io:443")
|
||||||
|
//! # .build::<DefaultConfig>()
|
||||||
|
//! # .await
|
||||||
|
//! # .unwrap();
|
||||||
|
//! #
|
||||||
//! let update_client = client.updates();
|
//! let update_client = client.updates();
|
||||||
|
//! // Spawn a new background task to handle runtime updates.
|
||||||
//! tokio::spawn(async move {
|
//! tokio::spawn(async move {
|
||||||
//! let result = update_client.perform_runtime_updates().await;
|
//! let result = update_client.perform_runtime_updates().await;
|
||||||
//! println!("Runtime update finished with result={:?}", result);
|
//! println!("Runtime update finished with result={:?}", result);
|
||||||
//! });
|
//! });
|
||||||
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
Reference in New Issue
Block a user