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:
Alexandru Vasile
2022-06-16 16:25:18 +03:00
committed by GitHub
parent c902548341
commit 8bceda2b39
10 changed files with 345 additions and 181 deletions
+6
View File
@@ -99,6 +99,12 @@ jobs:
- name: Check internal documentation links
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:
name: Cargo test
runs-on: ubuntu-latest
+1 -1
View File
@@ -24,7 +24,7 @@ a different node then the `metadata` command accepts a `--url` argument.
## 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
+5 -2
View File
@@ -29,13 +29,16 @@
//!
//! ## Example
//!
//! ```rust
//! ```no_run
//! use std::fs;
//! use codec::Decode;
//! use frame_metadata::RuntimeMetadataPrefixed;
//! use subxt_codegen::DerivesRegistry;
//!
//! let encoded = fs::read("../artifacts/polkadot_metadata.scale").unwrap();
//!
//! // 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.
//! let item_mod = syn::parse_quote!(
//! pub mod api {}
-144
View File
@@ -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
View File
@@ -97,17 +97,23 @@ impl ClientBuilder {
self
}
/// Creates a new Client.
/// Builder for [Client].
///
/// # Example
/// # Examples
///
/// ```rust
/// ```no_run
/// use subxt::{ClientBuilder, DefaultConfig};
///
/// let client = ClientBuilder::new()
/// .set_url("wss://rpc.polkadot.io:443")
/// .build::<DefaultConfig>()
/// .await?;
/// #[tokio::main]
/// async fn main() {
/// // Build the client.
/// 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> {
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.
/// 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();
/// // Spawn a new background task to handle runtime updates.
/// tokio::spawn(async move {
/// let result = update_client.perform_runtime_updates().await;
/// println!("Runtime update finished with result={:?}", result);
/// });
/// # }
/// ```
pub fn updates(&self) -> UpdateClient<T> {
UpdateClient::new(
+35 -7
View File
@@ -21,7 +21,7 @@
//!
//! This module is wrapped by the generated API in `RuntimeAPI::EventsApi`.
//!
//! # Example
//! # Examples
//!
//! ## Subscribe to all events
//!
@@ -31,12 +31,23 @@
//!
//! To obtain the events from a given block use `at()`.
//!
//! ```rust
//! let mut events = api.events().subscribe().await?;
//! ```no_run
//! # 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 {
//! // Obtain all events from this block.
//! let ev: subxt::Events<_, _> = ev?;
//! let ev: subxt::Events<_, _> = ev.unwrap();
//! // Print block hash.
//! println!("Event at block hash {:?}", ev.block_hash());
//! // Iterate over all events.
@@ -45,6 +56,7 @@
//! println!("Event details {:?}", event_details);
//! }
//! }
//! # }
//! ```
//!
//! ## Filter events
@@ -55,16 +67,32 @@
//! returned directly. Otherwise, we'll be given a corresponding tuple of `Option`'s, with exactly
//! one variant populated each time.
//!
//! ```rust
//! let mut events = api
//! ```no_run
//! # 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()
//! .subscribe()
//! .await?
//! .await
//! .unwrap()
//! .filter_events::<(polkadot::balances::events::Transfer,)>();
//!
//! while let Some(transfer_event) = transfer_events.next().await {
//! println!("Balance transfer event: {transfer_event:?}");
//! }
//! # }
//! ```
mod decoding;
+178 -1
View File
@@ -14,7 +14,184 @@
// You should have received a copy of the GNU General Public License
// 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(
bad_style,
const_err,
+40 -10
View File
@@ -23,12 +23,23 @@
//!
//! ## Fetch Storage
//!
//! ```rust
//! use subxt::rpc::Rpc;
//! use subxt::storage::StorageKeyPrefix;
//! ```no_run
//! # use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
//! # 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")`.
//! let key = StorageKeyPrefix::new::<node_runtime::system::storage::ExtrinsicCount>()
//! let key = StorageKeyPrefix::new::<polkadot::system::storage::ExtrinsicCount>()
//! .to_storage_key();
//!
//! // Obtain the RPC from a generated API
@@ -36,27 +47,46 @@
//! .client
//! .rpc();
//!
//! let result = rpc.storage(&key, None)?;
//! let result = rpc.storage(&key, None).await.unwrap();
//! println!("Storage result: {:?}", result);
//! # }
//! ```
//!
//! ## Fetch Keys
//!
//! ```rust
//! use subxt::rpc::Rpc;
//! use subxt::storage::StorageKeyPrefix;
//! let key = StorageKeyPrefix::new::<polkadot::xcm_pallet::storage::VersionNotifiers>();
//! ```no_run
//! # use subxt::{ClientBuilder, DefaultConfig, PolkadotExtrinsicParams};
//! # 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>>>();
//! let key = StorageKeyPrefix::new::<polkadot::xcm_pallet::storage::VersionNotifiers>()
//! .to_storage_key();
//!
//! // Obtain the RPC from a generated API
//! let rpc: &Rpc<_> = api
//! .client
//! .rpc();
//!
//! // Fetch up to 10 keys.
//! 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() {
//! println!("Key: 0x{}", hex::encode(&key));
//! }
//! # }
//! ```
// jsonrpsee subscriptions are interminable.
+40 -6
View File
@@ -32,28 +32,62 @@
//!
//! ## 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.
//! let keys = storage
//! .fetch_keys::<node_runtime::xcm_pallet::storage::VersionNotifiers>(10, None, None)
//! .await?;
//! .fetch_keys::<polkadot::xcm_pallet::storage::VersionNotifiers>(10, None, None)
//! .await
//! .unwrap();
//! // Iterate over each key
//! for key in keys.iter() {
//! println!("Key: 0x{}", hex::encode(&key));
//! }
//! # }
//! ```
//!
//! ## 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.
//! let mut iter = storage
//! .iter::<polkadot::xcm_pallet::storage::VersionNotifiers>(None)
//! .await?;
//! while let Some((key, value)) = iter.next().await? {
//! .await
//! .unwrap();
//! while let Some((key, value)) = iter.next().await.unwrap() {
//! println!("Key: 0x{}", hex::encode(&key));
//! println!("Value: {}", value);
//! }
//! # }
//! ```
use codec::{
+13 -1
View File
@@ -28,12 +28,24 @@
//!
//! 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();
//! // Spawn a new background task to handle runtime updates.
//! tokio::spawn(async move {
//! let result = update_client.perform_runtime_updates().await;
//! println!("Runtime update finished with result={:?}", result);
//! });
//! # }
//! ```
use crate::{