From 8bceda2b39172b07e89e8de9835d40846266e545 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Thu, 16 Jun 2022 16:25:18 +0300 Subject: [PATCH] Fix documentation examples (#568) * Fix documentation examples Signed-off-by: Alexandru Vasile * CI: Add `cargo test --doc` Signed-off-by: Alexandru Vasile * Update .github/workflows/rust.yml Co-authored-by: Niklas Adolfsson * Remove docs/subxt.md and move documentation to subxt/lib.rs Signed-off-by: Alexandru Vasile * Hide polkadot interface for `events/mod.rs` Signed-off-by: Alexandru Vasile * docs: Use `#` for headers Signed-off-by: Alexandru Vasile Co-authored-by: Niklas Adolfsson --- .github/workflows/rust.yml | 6 ++ README.md | 2 +- codegen/src/lib.rs | 7 +- docs/subxt.md | 144 ----------------------------- subxt/src/client.rs | 36 ++++++-- subxt/src/events/mod.rs | 42 +++++++-- subxt/src/lib.rs | 179 ++++++++++++++++++++++++++++++++++++- subxt/src/rpc.rs | 50 ++++++++--- subxt/src/storage.rs | 46 ++++++++-- subxt/src/updates.rs | 14 ++- 10 files changed, 345 insertions(+), 181 deletions(-) delete mode 100644 docs/subxt.md diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dca7235f4a..a75ab618ed 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -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 diff --git a/README.md b/README.md index 1758b1f2dc..22c385e794 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 8f4cd9e023..497269ab15 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -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 = ::decode(encoded)?; +//! let metadata = ::decode(&mut &*encoded).unwrap(); //! // Module under which the API is generated. //! let item_mod = syn::parse_quote!( //! pub mod api {} diff --git a/docs/subxt.md b/docs/subxt.md deleted file mode 100644 index 66c825609c..0000000000 --- a/docs/subxt.md +++ /dev/null @@ -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::>>(); -``` - -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. diff --git a/subxt/src/client.rs b/subxt/src/client.rs index cf847de601..9ef8591f24 100644 --- a/subxt/src/client.rs +++ b/subxt/src/client.rs @@ -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::() - /// .await?; + /// #[tokio::main] + /// async fn main() { + /// // Build the client. + /// let client = ClientBuilder::new() + /// .set_url("wss://rpc.polkadot.io:443") + /// .build::() + /// .await + /// .unwrap(); + /// // Use the client... + /// } /// ``` pub async fn build(self) -> Result, BasicError> { let client = if let Some(client) = self.client { @@ -208,14 +214,26 @@ impl Client { /// 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::() + /// # .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 { UpdateClient::new( diff --git a/subxt/src/events/mod.rs b/subxt/src/events/mod.rs index c327e51230..62680608d7 100644 --- a/subxt/src/events/mod.rs +++ b/subxt/src/events/mod.rs @@ -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::>>(); +//! 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::>>(); +//! +//! 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; diff --git a/subxt/src/lib.rs b/subxt/src/lib.rs index 747a783f31..95f13fc69a 100644 --- a/subxt/src/lib.rs +++ b/subxt/src/lib.rs @@ -14,7 +14,184 @@ // You should have received a copy of the GNU General Public License // along with subxt. If not, see . -#![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::>>(); +//! # } +//! ``` +//! +//! 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::>>(); +//! // 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::>>(); +//! // 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, diff --git a/subxt/src/rpc.rs b/subxt/src/rpc.rs index bd78824f4c..b18e65ae88 100644 --- a/subxt/src/rpc.rs +++ b/subxt/src/rpc.rs @@ -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::>>(); //! // Storage prefix is `twox_128("System") ++ twox_128("ExtrinsicCount")`. -//! let key = StorageKeyPrefix::new::() +//! let key = StorageKeyPrefix::new::() //! .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::(); +//! ```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::>>(); +//! let key = StorageKeyPrefix::new::() +//! .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. diff --git a/subxt/src/storage.rs b/subxt/src/storage.rs index c0682f4aa1..2edbf60d10 100644 --- a/subxt/src/storage.rs +++ b/subxt/src/storage.rs @@ -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::>>(); +//! # // 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::(10, None, None) -//! .await?; +//! .fetch_keys::(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::>>(); +//! # // Obtain the storage client wrapper from the API. +//! # let storage: StorageClient<_> = api.client.storage(); //! // Iterate over keys and values. //! let mut iter = storage //! .iter::(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::{ diff --git a/subxt/src/updates.rs b/subxt/src/updates.rs index ea606e05fb..8aa212f9f0 100644 --- a/subxt/src/updates.rs +++ b/subxt/src/updates.rs @@ -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::() +//! # .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::{