// Copyright 2019-2025 Parity Technologies (UK) Ltd. // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. //! # Blocks //! //! The [blocks API](crate::blocks::BlocksClient) in Subxt unifies many of the other interfaces, and //! allows you to: //! //! - Access information about specific blocks (see [`crate::blocks::BlocksClient::at()`] and //! [`crate::blocks::BlocksClient::at_latest()`]). //! - Subscribe to [all](crate::blocks::BlocksClient::subscribe_all()), //! [best](crate::blocks::BlocksClient::subscribe_best()) or //! [finalized](crate::blocks::BlocksClient::subscribe_finalized()) blocks as they are produced. //! **Prefer to subscribe to finalized blocks unless you know what you're doing.** //! //! In either case, you'll end up with [`crate::blocks::Block`]'s, from which you can access various //! information about the block, such a the [header](crate::blocks::Block::header()), //! [block number](crate::blocks::Block::number()) and [body (the //! extrinsics)](crate::blocks::Block::extrinsics()). [`crate::blocks::Block`]'s also provide //! shortcuts to other Subxt APIs that will operate at the given block: //! //! - [storage](crate::blocks::Block::storage()), //! - [events](crate::blocks::Block::events()) //! - [runtime APIs](crate::blocks::Block::runtime_api()) //! //! Aside from these links to other Subxt APIs, the main thing that we can do here is iterate over //! and decode the extrinsics in a block body. //! //! ## Decoding Extrinsics //! //! Given a block, you can [download the block body](crate::blocks::Block::extrinsics()) and //! [iterate over the extrinsics](crate::blocks::Extrinsics::iter) stored within it. The extrinsics //! yielded are of type [ExtrinsicDetails](crate::blocks::ExtrinsicDetails), which is just a blob of //! bytes that also stores which pallet and call in that pallet it belongs to. It also contains //! information about signed extensions that have been used for submitting this extrinsic. //! //! To use the extrinsic, you probably want to decode it into a concrete Rust type. These Rust types //! representing extrinsics from different pallets can be generated from metadata using the subxt //! macro or the CLI tool. //! //! When decoding the extrinsic into a static type you have two options: //! //! ### Statically decode the extrinsics into [the root extrinsic type](crate::blocks::ExtrinsicDetails::as_root_extrinsic()) //! //! The root extrinsic type generated by subxt is a Rust enum with one variant for each pallet. Each //! of these variants has a field that is another enum whose variants cover all calls of the //! respective pallet. If the extrinsic bytes are valid and your metadata matches the chain's //! metadata, decoding the bytes of an extrinsic into this root extrinsic type should always //! succeed. //! //! This example shows how to subscribe to blocks and decode the extrinsics in each block into the //! root extrinsic type. Once we get hold of the //! [ExtrinsicDetails](crate::blocks::ExtrinsicDetails), we can decode it statically or dynamically. //! We can also access details about the extrinsic, including the associated events and transaction //! extensions. //! //! ```rust,ignore #![doc = include_str!("../../../examples/blocks_subscribing.rs")] //! ``` //! //! ### Statically decode the extrinsic into [a specific pallet call](crate::blocks::ExtrinsicDetails::as_extrinsic()) //! //! This is useful if you are expecting a specific extrinsic to be part of some block. If the extrinsic you try to decode //! is a different extrinsic, an `Ok(None)` value is returned from [`as_extrinsic::()`](crate::blocks::ExtrinsicDetails::as_extrinsic()); //! //! If you are only interested in finding specific extrinsics in a block, you can also [iterate over all of them](crate::blocks::Extrinsics::find), //! get only [the first one](crate::blocks::Extrinsics::find_first), or [the last one](crate::blocks::Extrinsics::find_last). //! //! The following example monitors `TransferKeepAlive` extrinsics on the Pezkuwi network. //! We statically decode them and access the [tip](crate::blocks::ExtrinsicTransactionExtensions::tip()) and //! [account nonce](crate::blocks::ExtrinsicTransactionExtensions::nonce()) transaction extensions. //! ```rust,ignore #![doc = include_str!("../../../examples/block_decoding_static.rs")] //! ``` //! //! ### Dynamically decode the extrinsic //! //! Sometimes you might use subxt with metadata that is not known at compile time. In this case, you do not //! have access to a statically generated interface module that contains the relevant Rust types. You can //! [decode ExtrinsicDetails dynamically](crate::blocks::ExtrinsicDetails::decode_as_fields()), which gives //! you access to it's fields as a [scale value composite](scale_value::Composite). The following example //! looks for signed extrinsics on the Pezkuwi network and retrieves their pallet name, variant name, data //! fields and transaction extensions dynamically. Notice how we do not need to use code generation via the //! subxt macro. The only fixed component we provide is the [PezkuwiConfig](crate::config::PezkuwiConfig). //! Other than that it works in a chain-agnostic way: //! ```rust,ignore #![doc = include_str!("../../../examples/block_decoding_dynamic.rs")] //! ``` //! //! ## Decoding transaction extensions //! //! Extrinsics can contain transaction extensions. The transaction extensions can be different across chains. //! The [Config](crate::Config) implementation for your chain defines which transaction extensions you expect. //! Once you get hold of the [ExtrinsicDetails](crate::blocks::ExtrinsicDetails) for an extrinsic you are interested in, //! you can try to [get its transaction extensions](crate::blocks::ExtrinsicDetails::transaction_extensions()). //! These are only available on V4 signed extrinsics or V5 general extrinsics. You can try to //! [find a specific transaction extension](crate::blocks::ExtrinsicTransactionExtensions::find), in the returned //! [transaction extensions](crate::blocks::ExtrinsicTransactionExtensions). //! //! Subxt also provides utility functions to get the [tip](crate::blocks::ExtrinsicTransactionExtensions::tip()) and //! the [account nonce](crate::blocks::ExtrinsicTransactionExtensions::nonce()) associated with an extrinsic, given //! its transaction extensions. If you prefer to do things dynamically you can get the data of the transaction extension //! as a [scale value](crate::blocks::ExtrinsicTransactionExtension::value()).