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
+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::{