Skip to content

Releases: paritytech/subxt

v0.23.0

12 Aug 11:01
a3ea126
Compare
Choose a tag to compare

This is one of the most significant releases to date in Subxt, and carries with it a number of significant breaking changes, but in exchange, a number of significant improvements. The most significant PR is #593; the fundamental change that this makes is to separate creating a query/transaction/address from submitting it. This gives us flexibility when creating queries; they can be either dynamically or statically generated, but also flexibility in our client, enabling methods to be exposed for online or offline use.

The best place to look to get a feel for what's changed, aside from the documentation itself, is the examples folder. What follows are some examples of the changes you'll need to make, which all follow a similar pattern:

Submitting a transaction

Previously, we'd build a client which is tied to the static codegen, and then use the client to build and submit a transaction like so:

let api = ClientBuilder::new()
    .build()
    .await?
    .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<_>>>();

let balance_transfer = api
    .tx()
    .balances()
    .transfer(dest, 10_000)?
    .sign_and_submit_then_watch_default(&signer)
    .await?
    .wait_for_finalized_success()
    .await?;

Now, we build a transaction separately (in this case, using static codegen to guide us as before) and then submit it to a client like so:

let api = OnlineClient::<PolkadotConfig>::new().await?;

let balance_transfer_tx = polkadot::tx().balances().transfer(dest, 10_000);

let balance_transfer = api
    .tx()
    .sign_and_submit_then_watch_default(&balance_transfer_tx, &signer)
    .await?
    .wait_for_finalized_success()
    .await?;

See the examples/examples/submit_and_watch.rs example for more.

Fetching a storage entry

Previously, we build and submit a storage query in one step:

let api = ClientBuilder::new()
    .build()
    .await?
    .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();

let entry = api.storage().staking().bonded(&addr, None).await;

Now, we build the storage query separately and submit it to the client:

let api = OnlineClient::<PolkadotConfig>::new().await?;

let staking_bonded = polkadot::storage().staking().bonded(&addr);

let entry = api.storage().fetch(&staking_bonded, None).await;

Note that previously, the generated code would do the equivalent of fetch_or_default if possible, or fetch if no default existed. You must now decide whether to:

  • fetch an entry, returning None if it's not found (api.storage().fetch(..)), or
  • fetch an entry, returning the default if it's not found (api.storage().fetch_or_default(..)).

The static types will protect you against using fetch_or_default when no such default exists, and so the recommendation is to try changing all storage requests to use fetch_or_default, falling back to using fetch where doing so leads to compile errors.

See examples/examples/concurrent_storage_requests.rs for an example of fetching entries.

Iterating over storage entries

Previously:

let api = ClientBuilder::new()
    .build()
    .await?
    .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();

let mut iter = api
    .storage()
    .xcm_pallet()
    .version_notifiers_iter(None)
    .await?;

while let Some((key, value)) = iter.next().await? {
    // ...
}

Now, as before, building the storage query to iterate over is separate from using it:

let api = OnlineClient::<PolkadotConfig>::new().await?;

let key_addr = polkadot::storage()
    .xcm_pallet()
    .version_notifiers_root();

let mut iter = api
    .storage()
    .iter(key_addr, 10, None).await?;

while let Some((key, value)) = iter.next().await? {
    // ...
}

Note that the _root() suffix on generated storage queries accesses the root entry at that address,
and is available when the address is a map that can be iterated over. By not appending _root(), you'll
be asked to provide the values needed to access a specific entry in the map.

See the examples/examples/storage_iterating.rs example for more.

Accessing constants

Before, we'd build a client and use the client to select and query a constant:

let api = ClientBuilder::new()
    .build()
    .await?
    .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();

let existential_deposit = api
    .constants()
    .balances()
    .existential_deposit()?;

Now, similar to the other examples, we separately build a constant address and provide that address to the client to look it up:

let api = OnlineClient::<PolkadotConfig>::new().await?;

let address = polkadot::constants()
    .balances()
    .existential_deposit();

let existential_deposit = api.constants().at(&address)?;

See the examples/examples/fetch_constants.rs example for more.

Subscribing to events

Event subscriptions themselves are relatively unchanged (although the data you can access/get back has changed a little). Before:

let api = ClientBuilder::new()
    .build()
    .await?
    .to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, PolkadotExtrinsicParams<DefaultConfig>>>();

let mut event_sub = api.events().subscribe().await?;

while let Some(events) = event_sub.next().await {
    // ...
}

Now, we simply swap the client out for our new one, and the rest is similar:

let api = OnlineClient::<PolkadotConfig>::new().await?;

let mut event_sub = api.events().subscribe().await?;

while let Some(events) = event_sub.next().await {
    // ...
}

Note that when working with a single event, the method event.bytes() previously returned just the bytes associated with the event fields. Now, event.bytes() returns all of the bytes associated with the event. There is a separate method, event.field_bytes(), that returns the bytes for just the fields in the event. This change will not lead to a compile error, and so it's worth keeping an eye out for any uses of .bytes() to update them to .field_bytes().

See the examples/examples/subscribe_all_events.rs example for more.

The general pattern, as seen above, is that we break apart constructing a query/address and using it. You can now construct queries dynamically instead and forego all static codegen by using the functionality exposed in the subxt::dynamic module instead.

Other smaller breaking changes have happened, but they should be easier to address by following compile errors.

For more details about all of the changes, the full commit history since the last release is as follows:

Added

  • Expose the extrinsic hash from TxProgress (#614)
  • Add support for ws in subxt-cli (#579)
  • Expose the SCALE encoded call data of an extrinsic (#573)
  • Validate absolute path for substitute_type (#577)

Changed

  • Rework Subxt API to support offline and dynamic transactions (#593)
  • Use scale-decode to help optimise event decoding (#607)
  • Decode raw events using scale_value and return the decoded Values, too (#576)
  • dual license (#590)
  • Don't hash constant values; only their types (#587)
  • metadata: Exclude field::type_name from metadata validation (#595)
  • Bump Swatinem/rust-cache from 1.4.0 to 2.0.0 (#597)
  • Update jsonrpsee requirement from 0.14.0 to 0.15.1 (#603)

V0.22.0

20 Jun 14:29
v0.22.0
c07b9e4
Compare
Choose a tag to compare

With this release, subxt can subscribe to the node's runtime upgrades to ensure that the metadata is updated and
extrinsics are properly constructed.

We have also made some slight API improvements to make in the area of storage keys, and thanks to an external contribution we now support dry running transactions before submitting them.

This release also improves the documentation, adds UI tests, and defaults the subxt-cli to return metadata
bytes instead of the JSON format.

Fixed

  • Handle StorageEntry empty keys (#565)
  • Fix documentation examples (#568)
  • Fix cargo clippy (#548)
  • fix: Find substrate port on different log lines (#536)

Added

  • Followup test for checking propagated documentation (#514)
  • feat: refactor signing in order to more easily be able to dryrun (#547)
  • Add subxt documentation (#546)
  • Add ability to iterate over N map storage keys (#537)
  • Subscribe to Runtime upgrades for proper extrinsic construction (#513)

Changed

  • Move test crates into a "testing" folder and add a ui (trybuild) test and ui-test helpers (#567)
  • Update jsonrpsee requirement from 0.13.0 to 0.14.0 (#566)
  • Make storage futures only borrow client, not self, for better ergonomics (#561)
  • Bump actions/checkout from 2 to 3 (#557)
  • Deny unused crate dependencies (#549)
  • Implement Clone for the generated RuntimeApi (#544)
  • Update color-eyre requirement from 0.5.11 to 0.6.1 (#540)
  • Update jsonrpsee requirement from 0.12.0 to 0.13.0 (#541)
  • Update artifacts and polkadot.rs and change CLI to default bytes (#533)
  • Replace log with tracing and record extrinsic info (#535)
  • Bump jsonrpsee (#528)

V0.21.0

02 May 16:23
v0.21.0
6d73172
Compare
Choose a tag to compare

This release adds static metadata validation, via comparing the statically generated API with the target node's runtime
metadata. This implies a breaking change in the subxt API, as the user receives an error when interacting with an
incompatible API at the storage, call, and constant level.

The subxt-cli can check the compatibility of multiple runtime nodes, either full metadata compatibility or
compatibility at the pallet level.

Users can define custom derives for specific generated types of the API via adding the derive_for_type configuration
to the subxt attribute.

The metadata documentation is propagated to the statically generated API.

Previously developers wanting to build the subxt crate needed the substrate binary dependency in their local
environment. This restriction is removed via moving the integration tests to a dedicated crate.

The number of dependencies is reduced for individual subxt crates.

Fixed

  • test-runtime: Add exponential backoff (#518)

Added

  • Add custom derives for specific generated types (#520)
  • Static Metadata Validation (#478)
  • Propagate documentation to runtime API (#511)
  • Add tidext in real world usage (#508)
  • Add system health rpc (#510)

Changed

  • Put integration tests behind feature flag (#515)
  • Use minimum amount of dependencies for crates (#524)
  • Export BaseExtrinsicParams (#516)
  • bump jsonrpsee to v0.10.1 (#504)

v0.20.0

06 Apr 16:41
v0.20.0
dffeee4
Compare
Choose a tag to compare

The most significant change in this release is how we create and sign extrinsics, and how we manage the
"additional" and "extra" data that is attached to them. See #477, and the
associated PR #490 for a more detailed look at the code changes.

If you're targeting a node with compatible additional and extra transaction data to Substrate or Polkadot, the main
change you'll have to make is to import and use subxt::PolkadotExtrinsicParams or subxt::SubstrateExtrinsicParams
instead of subxt::DefaultExtra (depending on what node you're compatible with), and then use sign_and_submit_default
instead of sign_and_submit when making a call. Now, sign_and_submit accepts a second argument which allows these
parameters (such as mortality and tip payment) to be customized. See examples/balance_transfer_with_params.rs for a
small usage example.

If you're targeting a node which involves custom additional and extra transaction data, you'll need to implement the
trait subxt::extrinsic::ExtrinsicParams, which determines the parameters that can be provided to sign_and_submit, as
well as how to encode these into the "additional" and "extra" data needed for a transaction. Have a look at
subxt/src/extrinsic/params.rs for the trait definition and Substrate/Polkadot implementations. The aim with this change
is to make it easier to customise this for your own chains, and provide a simple way to provide values at runtime.

Fixed

  • Test utils: parse port from substrate binary output to avoid races (#501)
  • Rely on the kernel for port allocation (#498)

Changed

  • Export ModuleError for downstream matching (#499)
  • Bump jsonrpsee to v0.9.0 (#496)
  • Use tokio instead of async-std in tests/examples (#495)
  • Read constants from metadata at runtime (#494)
  • Handle sp_runtime::ModuleError substrate updates (#492)
  • Simplify creating and signing extrinsics (#490)
  • Add dev_getBlockStats RPC (#489)
  • scripts: Hardcode github subxt pull link for changelog consistency (#482)

v0.19.0

21 Mar 11:29
v0.19.0
3758c85
Compare
Choose a tag to compare

Changed

  • Return events from blocks skipped over during Finalization, too (#473)
  • Use RPC call to get account nonce (#476)
  • Add script to generate release changelog based on commits (#465)
  • README updates (#472)
  • Make EventSubscription and FilterEvents Send-able (#471)

v0.18.1

04 Mar 12:02
v0.18.1
14ef6c8
Compare
Choose a tag to compare

Fixed

  • Remove unused sp_version dependency to fix duplicate parity-scale-codec deps (#466)

v0.18.0

02 Mar 19:25
v0.18.0
3baaa01
Compare
Choose a tag to compare

Added

  • Expose method to fetch nonce via Client (#451)

Changed

  • Reference key storage api (#447)
  • Filter one or multiple events by type from an EventSubscription (#461)
  • New Event Subscription API (#442)
  • Distinct handling for N fields + 1 hasher vs N fields + N hashers (#458)
  • Update scale-info and parity-scale-codec requirements (#462)
  • Substitute BTreeMap/BTreeSet generated types for Vec (#459)
  • Obtain DispatchError::Module info dynamically (#453)
  • Add hardcoded override to ElectionScore (#455)
  • DispatchError::Module is now a tuple variant in latest Substrate (#439)
  • Fix flaky event subscription test (#450)
  • Improve documentation (#449)
  • Export codegen::TypeGenerator (#444)
  • Fix conversion of Call struct names to UpperCamelCase (#441)
  • Update release documentation with dry-run (#435)

v0.17.0

07 Feb 10:44
v0.17.0
19ae2aa
Compare
Choose a tag to compare

Note: owing to a hiccup only found at publish time, subxt-macro and subxt-codegen releases come from e9be43a, whereas subxt is released at a7c54f7.

Added

  • introduce jsonrpsee client abstraction + kill HTTP support. (#341)
  • Get event context on EventSubscription (#423)

Changed

  • Add more tests for events.rs/decode_and_consume_type (#430)
  • Update substrate dependencies (#429)
  • export RuntimeError struct (#427)
  • remove unused PalletError struct (#425)
  • Move Subxt crate into a subfolder (#424)
  • Add release checklist (#418)

v0.16.0

01 Feb 11:22
667dfa2
Compare
Choose a tag to compare

Note: This is a significant release which introduces support for V14 metadata and macro based codegen, as well as making many breaking changes to the API.

Changed

  • Log debug message for JSON-RPC response (#415)
  • Only convert struct names to camel case for Call variant structs (#412)
  • Parameterize AccountData (#409)
  • Allow decoding Events containing BitVecs (#408)
  • Custom derive for cli (#407)
  • make storage-n-map fields public too (#404)
  • add constants api to codegen (#402)
  • Expose transaction::TransactionProgress as public (#401)
  • add interbtc-clients to real world usage section (#397)
  • Make own version of RuntimeVersion to avoid mismatches (#395)
  • Use the generated DispatchError instead of the hardcoded Substrate one (#394)
  • Remove bounds on Config trait that aren't strictly necessary (#389)
  • add crunch to readme (#388)
  • fix remote example (#386)
  • fetch system chain, name and version (#385)
  • Fix compact event field decoding (#384)
  • fix: use index override when decoding enums in events (#382)
  • Update to jsonrpsee 0.7 and impl Stream on TransactionProgress (#380)
  • Add links to projects using subxt (#376)
  • Use released substrate dependencies (#375)
  • Configurable Config and Extra types (#373)
  • Implement pre_dispatch for SignedExtensions (#370)
  • Export TransactionEvents (#363)
  • Rebuild test-runtime if substrate binary is updated (#362)
  • Expand the subscribe_and_watch example (#361)
  • Add TooManyConsumers variant to track latest sp-runtime addition (#360)
  • Implement new API for sign_and_submit_then_watch (#354)
  • Simpler dependencies (#353)
  • Refactor type generation, remove code duplication (#352)
  • Make system properties an arbitrary JSON object, plus CI fixes (#349)
  • Fix a couple of CI niggles (#344)
  • Add timestamp pallet test (#340)
  • Add nightly CI check against latest substrate. (#335)
  • Ensure metadata is in sync with running node during tests (#333)
  • Update to jsonrpsee 0.5.1 (#332)
  • Update substrate and hardcoded default ChargeAssetTxPayment extension (#330)
  • codegen: fix compact unnamed fields (#327)
  • Check docs and run clippy on PRs (#326)
  • Additional parameters for SignedExtra (#322)
  • fix: also processess initialize and finalize events in event subscription (#321)
  • Release initial versions of subxt-codegen and subxt-cli (#320)
  • Add some basic usage docs to README. (#319)
  • Update jsonrpsee (#317)
  • Add missing cargo metadata fields for new crates (#311)
  • fix: keep processing a block's events after encountering a dispatch error (#310)
  • Codegen: enum variant indices (#308)
  • fix extrinsics retracted (#307)
  • Add utility pallet tests (#300)
  • fix metadata constants (#299)
  • Generate runtime API from metadata (#294)
  • Add NextKeys and QueuedKeys for session module (#291)
  • deps: update jsonrpsee 0.3.0 (#289)
  • deps: update jsonrpsee 0.2.0 (#285)
  • deps: Reorg the order of deps (#284)
  • Expose the rpc client in Client (#267)
  • update jsonrpsee to 0.2.0-alpha.6 (#266)
  • Remove funty pin, upgrade codec (#265)
  • Use async-trait (#264)
  • [jsonrpsee http client]: support tokio1 & tokio02. (#263)
  • impl From<Arc<WsClient>> and From<Arc<HttpClient>> (#257)
  • update jsonrpsee (#251)
  • return none if subscription returns early (#250)

v0.15.0

22 Mar 17:38
1a8e0bc
Compare
Choose a tag to compare

Added

  • implement variant of subscription that returns finalized storage changes - #237
  • implement session handling for unsubscribe in subxt-client - #242

Changed

  • update jsonrpsee #251
  • return none if subscription returns early #250
  • export ModuleError and RuntimeError for downstream usage - #246
  • rpc client methods should be public for downstream usage - #240
  • re-export WasmExecutionMethod for downstream usage - #239
  • integration with jsonrpsee v2 - #214
  • expose wasm execution method on subxt client config - #230
  • Add hooks to register event types for decoding - #227
  • Substrate 3.0 - #232