Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[0.32.0] - 2023-09-27
This is a big release that adds quite a lot, and also introduces some slightly larger breaking changes. Let's look at the main changes:
The
Backend
trait and theUnstableBackend
andLegacyBackend
impls.See #1126, #1137 and #1161 for more information.
The overarching idea here is that we want Subxt to be able to continue to support talking to nodes/light-clients using the "legacy" RPC APIs that are currently available, but we also want to be able to support using only the new RPC APIs once they are stabilized.
Until now, the higher level APIs in Subxt all had access to the RPCs and could call whatever they needed. Now, we've abstracted away which RPCs are called (or even that RPCs are used at all) behind a
subxt::backend::Backend
trait. Higher level APIs no longer have access to RPC methods and instead have access to the currentBackend
implementation. We then added twoBackend
implementations:subxt::backend::legacy::LegacyBackend
: This uses the "legacy" RPCs, as we've done to date, to obtain the information we need. This is still the default backend that Subxt will use.subxt::backend::unstable::UnstableBackend
: This backend relies on the new (and currently still unstable)chainHead
based RPC APIs to obtain the information we need. This could break at any time as the RPC methods update, until they are fully stabilized. One day, this will be the default backend.One of the significant differences between backends is that the
UnstableBackend
can only fetch further information about blocks that are "pinned", ie that we have signalled are still in use. To that end, the backend now hands backBlockRef
s instead of plain block hashes. As long as aBlockRef
exists for some block, the backend (and node) will attempt to keep it available. Thus, Subxt will keep hold of these internally as needed, and also allows you to obtain them from aBlock
withblock.reference()
, in case you need to try and hold on to any blocks for longer.One of the main breaking changes here is in how you can access and call RPC methods.
Previously, you could access them directly from the Subxt client, since it exposed the RPC methods itself, eg:
Now, the client only knows about a
Backend
(ie it has a.backend()
method instead of.rpc()
), and doesn't know about RPCs, but you can still manually create anRpcClient
to call RPC methods like so:If you'd like to share a single client for RPCs and Subxt usage, you can clone this RPC client and run
OnlineClient::<SubstrateConfig>::from_rpc_client(rpc_client)
to create a Subxt client using it.Another side effect of this change is that RPC related things have moved from
subxt::rpc::*
tosubxt::backend::rpc::*
and some renaming has happened along the way.A number of smaller breaking changes have also been made in order to expose details that are compatible with both sets of RPCs, and to generally move Subxt towards working well with the new APIs and exposing things in a consistent way:
fetch_keys
is renamed tofetch_raw_keys
(this just for consistency withfetch_raw
).iter
no longer accepts apage_size
argument, and each item returned is now anOption<Result<(key, val)>>
instead of aResult<Option<(key, val)>>
(we now return a validStream
implementation for storage entry iteration). See this example.next_item
=>next
. If you rely on higher level calls likesign_and_submit_then_watch
, nothing has changed..at_latest()
in various places would mean that calls would run against the latest best block. Now, all such calls will run against the latest finalized block. The latest best block is subject to changing or being pruned entirely, and can differ between nodes..at(block_hash)
should continue to work as-is, but can now also accept aBlockRef
, to keep the relevant block around while you're using the associated APIs.block.body().await?.extrinsics()
. This has now been simplified toblock.extrinsics().await?
.Making
ExtrinsicParams
more flexible withSignedExtension
s.See #1107 for more information.
When configuring Subxt to work against a given chain, you needed to configure the
ExtrinsicParams
associated type to encode exactly what was required by the chain when submitting transactions. This could be difficult to get right.Now, we have "upgraded" the
ExtrinsicParams
trait to give it access to metadata, so that it can be smarter about how to encode the correct values. We've also added asubxt::config::SignedExtension
trait, and provided implementations of it for all of the "standard" signed extensions (though we have a little work to do still).How can you use
SignedExtension
s? Well,subxt::config::signed_extensions::AnyOf<T, Params>
is a type which can accept any tuple ofSignedExtension
s, and itself implementsExtrinsicParams
. It's smart, and will use the metadata to know which of the signed extensions that you provided to actually use on a given chain. So,AnyOf
makes it easy to compose whicheverSignedExtension
s you need to work with a chain.Finally, we expose
subxt::config::{ DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder }
; the former just usesAnyOf
to automatically use any of the "standard" signed extensions as needed, and the latter provided a nice builder interface to configure any parameters for them. This is now the default type used inSubstrateConfig
andPolkadotConfig
, so long story short: those configurations (and particularly theirExtrinsicParams
) are more likely to Just Work now across default chains.See this example for how to create and use custom signed extensions, or this example for how to implement custom
ExtrinsicParams
if you'd prefer to ignoreSignedExtension
s entirely.As a result of using the new
DefaultExtrinsicParams
inSubstrateConfig
andPolkadotConfig
, the interface to configure transactions has changed (and in fact been generally simplified). Configuring a mortal transaction with a small tip ƒor instance used to look like:And now it will look like this:
Check the docs for
PolkadotExtrinsicParamsBuilder
and theExtrinsicParams
trait for more information.Storage: Allow iterating storage entries at different depths
See (#1079) for more information.
Previously, we could statically iterate over the root of some storage map using something like:
Now, the suffix
_root
has been renamed to_iter
, and if the storage entry is for instance a double map (or greater depth), we'll also now generate_iter2
,iter3
and so on, each accepting the keys needed to access the map at that depth to iterate the remainder. The above example now becomes:Note also that the pagination size no longer needs to be provided; that's handled internally by the relevant
Backend
.Custom values
This is not a breaking change, but just a noteworthy addition; see #1106, #1117 and #1147 for more information.
V15 metadata allows chains to insert arbitrary information into a new "custom values" hashmap (see this). Subxt has now added APIs to allow accessing these custom values a little like how constants can be accessed.
Dynamically accessing custom values looks a bit like this:
We can also use codegen to statically access values, which makes use of validation and returns a known type whenever possible, for the added compile time safety this brings:
That sums up the most significant changes. All of the key commits in this release can be found here:
Added
UnstableBackend
: Add a chainHead based backend implementation (#1161)UnstableBackend
: Expose the chainHead RPCs (#1137)storage_version()
andruntime_wasm_code()
to storage (#1111)Changed
subxt-codegen
: Add "web" feature for WASM compilation that works withjsonrpsee
(#1175)subxt-codegen
: support compiling to WASM (#1154)Debug
impl forDispatchError
to avoid huge metadata output (#1153)Fixed
sp-arithmetic
to help substrate compat. (#1155)chainHead_follow
(#1116)