v0.28.0
[0.28.0] - 2022-04-11
This is a fairly significant change; what follows is a description of the main changes to be aware of:
Unify how we encode and decode static and dynamic types (#842)
Prior to this, static types generated by codegen (ie subxt macro) would implement Encode
and Decode
from the parity-scale-codec
library. This meant that they woule be encoded-to and decoded-from based on their shape. Dynamic types (eg the subxt::dynamic::Value
type) would be encoded and decoded based on the node metadata instead.
This change makes use of the new scale-encode
and scale-decode
crates to auto-implement EncodeAsType
and DecodeAsType
on all of our static types. These traits allow types to take the node metadata into account when working out how best to encode and decode into them. By using metadata, we can be much more flexible/robust about how to encode/decode various types (as an example, nested transactions will now be portable across runtimes). Additionally, we can merge our codepaths for static and dynamic encoding/decoding, since both static and dynamic types can implement these traits. Read the PR description for more info.
A notable impact of this is that any types you wish to substitute when performing codegen (via the CLI tool or #[subxt]
macro) must also implement EncodeAsType
and DecodeAsType
too. Substrate types, for instance, generally do not. To work around this, #886 introduces a Static
type and enhances the type substitution logic so that you're able to wrap any types which only implement Encode
and Decode
to work (note that you lose out on the improvements from EncodeAsType
and DecodeAsType
when you do this):
#[subxt::subxt(
runtime_metadata_path = "/path/to/metadata.scale",
substitute_type(
type = "sp_runtime::multiaddress::MultiAddress<A, B>",
with = "::subxt::utils::Static<::sp_runtime::multiaddress::MultiAddress<A, B>>"
)
)]
pub mod node_runtime {}
So, if you want to substitute in Substrate types, wrap them in ::subxt::utils::Static
in the type substitution, as above. #886 also generally improves type substitution so that you can substitute the generic params in nested types, since it's required in the above.
Several types have been renamed as a result of this unification (though they aren't commonly made explicit use of). Additionally, to obtain the bytes from a storage address, instead of doing:
let addr_bytes = storage_address.to_bytes()
You must now do:
let addr_bytes = cxt.client().storage().address_bytes(&storage_address).unwrap();
This is because the address on it's own no longer requires as much static information, and relies more heavily now on the node metadata to encode it to bytes.
Expose Signer payload (#861)
This is not a breaking change, but notable in that is adds create_partial_signed_with_nonce
and create_partial_signed
to the TxClient
to allow you to break extrinsic creation into two steps:
- building a payload, and then
- when a signature is provided, getting back an extrinsic ready to be submitted.
This allows a signer payload to be obtained from Subxt, handed off to some external application, and then once a signature has been obtained, that can be passed back to Subxt to complete the creation of an extrinsic. This opens the door to using browser wallet extensions, for instance, to sign Subxt payloads.
Stripping unneeded pallets from metadata (#879)
This is not a breaking change, but adds the ability to use the Subxt CLI tool to strip out all but some named list of pallets from a metadata bundle. Aside from allowing you to store a significantly smaller metadata bundle with only the APIs you need in it, it will also lead to faster codegen, since there's much less of it to do.
Use a command like subxt metadata --pallets Balances,System
to select specific pallets. You can provide an existing metadata file to take that and strip it, outputting a smaller bundle. Alternately it will grab the metadata from a local node and strip that before outputting.
Dispatch error changes (#878)
The DispatchError
returned from either attempting to submit an extrinsic, or from calling .dry_run()
has changed. It's now far more complete with respect to the information it returns in each case, and the interface has been tidied up. Changes include:
- For
ModuleError
's, instead oferr.pallet
anderr.error
, you can obtain error details usinglet details = err.details()?
and thendetails.pallet()
anddetails.error()
. DryRunResult
is now a custom enum with 3 states,Success
,DispatchError
orTransactionValidityError
. The middle of these contains much more information than previously.- Errors in general have been marked
#[non_exahustive]
since they could grow and change at any time. (Owing to our use ofscale-decode
internally, we are not so contrained when it comes to having precise variant indexes or anything now, and can potentially deprecate rather than remove old variants as needed). - On a lower level, the
rpc.dry_run()
RPC call now returns the raw dry run bytes which can then be decoded with the help of metadata into ourDryRunResult
.
Extrinsic submission changes (#897)
It was found by @furoxr that Substrate nodes will stop sending transaction progress events under more circumstances than we originally expected. Thus, now calls like wait_for_finalized()
and wait_for_in_block()
will stop waiting for events when any of the following is sent from the node:
Usurped
Finalized
FinalityTimeout
Invalid
Dropped
Previously we'd only close the subscription and stop waiting when we saw a Finalized
or FinalityTimeout
event. Thanks for digging into this @furoxr!
Add at_latest()
method (#900 and #904)
A small breaking change; previously we had .at(None)
or .at(Some(block_hash))
methods in a few places to obtain things at either the latest block or some specific block hash.
This API has been clarified; we now have .at_latest()
to obtain the thing at the latest block, or .at(block_hash)
(note; no more option) to obtain the thing at some fixed block hash. In a few instances this has allowed us to ditch the async
from the .at()
call.
That covers the larger changes in this release. For more details, have a look at all of the notable PRs since the last release here:
Added
- added at_latest (#900 and #904)
- Metadata: Retain a subset of metadata pallets (#879)
- Expose signer payload to allow external signing (#861)
- Add ink! as a user of
subxt
(#837) - codegen: Add codegen error (#841)
- codegen: allow documentation to be opted out of (#843)
- re-export
sp_core
andsp_runtime
(#853) - Allow generating only runtime types in subxt macro (#845)
- Add 'Static' type and improve type substitution codegen to accept it (#886)
Changed
- Improve Dispatch Errors (#878)
- Use scale-encode and scale-decode to encode and decode based on metadata (#842)
- For smoldot: support deserializing block number in header from hex or number (#863)
- Bump Substrate dependencies to latest (#905)
Fixed
- wait_for_finalized behavior if the tx dropped, usurped or invalid (#897)