Skip to content

Commit

Permalink
Update version, tweak docs, and write up changelog (paritytech#616)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsdw committed Aug 11, 2022
1 parent 7e51b3e commit a3ea126
Show file tree
Hide file tree
Showing 11 changed files with 241 additions and 24 deletions.
204 changes: 204 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,210 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.23.0] - 2022-08-11

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](https://github.com/paritytech/subxt/pull/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:

```rust
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:

``` rust
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:

```rust
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:

```rust
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:

```rust
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:

```rust
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:

```rust
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:

```rust
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:

```rust
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:

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

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

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

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](https://github.com/paritytech/subxt/pull/614))
- Add support for `ws` in `subxt-cli` ([#579](https://github.com/paritytech/subxt/pull/579))
- Expose the SCALE encoded call data of an extrinsic ([#573](https://github.com/paritytech/subxt/pull/573))
- Validate absolute path for `substitute_type` ([#577](https://github.com/paritytech/subxt/pull/577))

### Changed

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

## [0.22.0] - 2022-06-20

With this release, subxt can subscribe to the node's runtime upgrades to ensure that the metadata is updated and
Expand Down
6 changes: 3 additions & 3 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "subxt-cli"
version = "0.22.0"
version = "0.23.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"

Expand All @@ -16,9 +16,9 @@ path = "src/main.rs"

[dependencies]
# perform subxt codegen
subxt-codegen = { version = "0.22.0", path = "../codegen" }
subxt-codegen = { version = "0.23.0", path = "../codegen" }
# perform node compatibility
subxt-metadata = { version = "0.22.0", path = "../metadata" }
subxt-metadata = { version = "0.23.0", path = "../metadata" }
# parse command line args
structopt = "0.3.25"
# colourful error reports
Expand Down
4 changes: 2 additions & 2 deletions codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "subxt-codegen"
version = "0.22.0"
version = "0.23.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"

Expand All @@ -20,7 +20,7 @@ proc-macro-error = "1.0.4"
quote = "1.0.8"
syn = "1.0.58"
scale-info = { version = "2.0.0", features = ["bit-vec"] }
subxt-metadata = { version = "0.22.0", path = "../metadata" }
subxt-metadata = { version = "0.23.0", path = "../metadata" }

[dev-dependencies]
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
Expand Down
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "subxt-examples"
version = "0.22.0"
version = "0.23.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
publish = false
Expand Down
4 changes: 2 additions & 2 deletions macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "subxt-macro"
version = "0.22.0"
version = "0.23.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
autotests = false
Expand All @@ -19,4 +19,4 @@ darling = "0.14.0"
proc-macro-error = "1.0.4"
syn = "1.0.58"

subxt-codegen = { path = "../codegen", version = "0.22.0" }
subxt-codegen = { path = "../codegen", version = "0.23.0" }
2 changes: 1 addition & 1 deletion metadata/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "subxt-metadata"
version = "0.22.0"
version = "0.23.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
autotests = false
Expand Down
6 changes: 3 additions & 3 deletions subxt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "subxt"
version = "0.22.0"
version = "0.23.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"

Expand Down Expand Up @@ -33,8 +33,8 @@ thiserror = "1.0.24"
tracing = "0.1.34"
parking_lot = "0.12.0"

subxt-macro = { version = "0.22.0", path = "../macro" }
subxt-metadata = { version = "0.22.0", path = "../metadata" }
subxt-macro = { version = "0.23.0", path = "../macro" }
subxt-metadata = { version = "0.23.0", path = "../metadata" }

sp-core = { version = "6.0.0", default-features = false }
sp-runtime = "6.0.0"
Expand Down
27 changes: 20 additions & 7 deletions subxt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@
//!
//! # Generating runtime types
//!
//! Subxt can generate types at compile time to help you interact with a node. The metadata can be downloaded using the
//! [subxt-cli](https://crates.io/crates/subxt-cli) tool.
//! Subxt can optionally generate types at compile time to help you interact with a node. These types are
//! generated using metadata which can be downloaded from a node using the [subxt-cli](https://crates.io/crates/subxt-cli)
//! tool. These generated types provide a degree of type safety when interacting with a node that is compatible with
//! the metadata that they were generated using. We also do runtime checks in case the node you're talking to has
//! deviated from the types you're using to communicate with it (see below).
//!
//! To generate the types, use the `subxt` attribute which points at downloaded static metadata.
//! To generate the types, use the `subxt` macro and point it at the metadata you've downloaded, like so:
//!
//! ```ignore
//! #[subxt::subxt(runtime_metadata_path = "metadata.scale")]
Expand All @@ -47,9 +50,12 @@
//! For more information, please visit the [subxt-codegen](https://docs.rs/subxt-codegen/latest/subxt_codegen/)
//! documentation.
//!
//! You can opt to skip this step and use dynamic queries to talk to nodes instead, which can be useful in some cases,
//! but doesn't provide any type safety.
//!
//! # Interacting with the API
//!
//! Once instantiated, a client, exposes four functions:
//! Once instantiated, a client exposes four core functions:
//! - `.tx()` for submitting extrinsics/transactions. See [`crate::tx::TxClient`] for more details, or see
//! the [balance_transfer](../examples/examples/balance_transfer.rs) example.
//! - `.storage()` for fetching and iterating over storage entries. See [`crate::storage::StorageClient`] for more details, or see
Expand Down Expand Up @@ -86,13 +92,20 @@
//! }
//! # }
//! ```
//! ## Opting out of static validation
//!
//! The static types that are used to query/access information are validated by default, to make sure that they are
//! compatible with the node being queried. You can generally call `.unvalidated()` on these static types to
//! disable this validation.
//!
//! # 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 node you're connected to may occasionally perform runtime updates while you're connected, which would ordinarily
//! leave the runtime state of the node out of sync with the information Subxt requires to do things like submit
//! transactions.
//!
//! The `UpdateClient` API keeps the `RuntimeVersion` and `Metadata` of the client synced with the target node.
//! If this is a concern, you can use the `UpdateClient` API to keep 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.

Expand Down
6 changes: 3 additions & 3 deletions testing/integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "integration-tests"
version = "0.22.0"
version = "0.23.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"

Expand All @@ -26,8 +26,8 @@ sp-core = { version = "6.0.0", default-features = false }
sp-keyring = "6.0.0"
sp-runtime = "6.0.0"
syn = "1.0.0"
subxt = { version = "0.22.0", path = "../../subxt" }
subxt-codegen = { version = "0.22.0", path = "../../codegen" }
subxt = { version = "0.23.0", path = "../../subxt" }
subxt-codegen = { version = "0.23.0", path = "../../codegen" }
test-runtime = { path = "../test-runtime" }
tokio = { version = "1.8", features = ["macros", "time"] }
tracing = "0.1.34"
Expand Down
2 changes: 1 addition & 1 deletion testing/test-runtime/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "test-runtime"
version = "0.22.0"
version = "0.23.0"
edition = "2021"

[dependencies]
Expand Down
2 changes: 1 addition & 1 deletion testing/ui-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ui-tests"
version = "0.22.0"
version = "0.23.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down

0 comments on commit a3ea126

Please sign in to comment.