diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e1819ecf19..8289041a31 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -301,7 +301,7 @@ jobs: uses: "andymckay/cancel-action@a955d435292c0d409d104b57d8e78435a93a6ef1" # v0.5 unstable_backend_tests: - name: "Test (Unstable Backend)" + name: "Test chainhead backend" runs-on: ubuntu-latest-16-cores needs: [clippy, wasm_clippy, check, wasm_check, docs] timeout-minutes: 30 @@ -329,7 +329,7 @@ jobs: uses: actions-rs/cargo@v1.0.3 with: command: nextest - args: run --workspace --features unstable-backend-client + args: run --workspace --features chainhead-backend - if: "failure()" uses: "andymckay/cancel-action@a955d435292c0d409d104b57d8e78435a93a6ef1" # v0.5 diff --git a/subxt/Cargo.toml b/subxt/Cargo.toml index b44faa476d..35da47c543 100644 --- a/subxt/Cargo.toml +++ b/subxt/Cargo.toml @@ -47,12 +47,21 @@ web = [ "finito?/wasm-bindgen", ] +# Feature flag to enable the default future executor. +# Technically it's a hack enable to both but simplifies the conditional compilation +# and subxt is selecting executor based on the used platform. +# +# For instance `wasm-bindgen-futures` panics if the platform isn't wasm32 and +# similar for tokio that requires a tokio runtime to be initialized. +runtime = ["tokio/rt", "wasm-bindgen-futures"] + # Enable this to use the reconnecting rpc client -unstable-reconnecting-rpc-client = ["dep:finito", "dep:tokio", "jsonrpsee", "wasm-bindgen-futures"] +unstable-reconnecting-rpc-client = ["dep:finito", "jsonrpsee"] # Enable this to use jsonrpsee (allowing for example `OnlineClient::from_url`). jsonrpsee = [ "dep:jsonrpsee", + "runtime", ] # Enable this to pull in extra Substrate dependencies which make it possible to diff --git a/subxt/examples/setup_reconnecting_rpc_client.rs b/subxt/examples/setup_reconnecting_rpc_client.rs index f89e08d0e1..42485161bf 100644 --- a/subxt/examples/setup_reconnecting_rpc_client.rs +++ b/subxt/examples/setup_reconnecting_rpc_client.rs @@ -34,20 +34,13 @@ async fn main() -> Result<(), Box> { .build("ws://localhost:9944".to_string()) .await?; - // If you want to use the unstable backend with the reconnecting RPC client, you can do so like this: + // If you want to use the chainhead backend with the reconnecting RPC client, you can do so like this: // // ``` - // use subxt::backend::unstable::UnstableBackend; + // use subxt::backend::chain_head:ChainHeadBackend; // use subxt::OnlineClient; // - // let (backend, mut driver) = UnstableBackend::builder().build(RpcClient::new(rpc.clone())); - // tokio::spawn(async move { - // while let Some(val) = driver.next().await { - // if let Err(e) = val { - // eprintln!("Error driving unstable backend: {e}; terminating client"); - // } - // } - // }); + // let backend = ChainHeadBackend::builder().build_with_background_task(RpcClient::new(rpc.clone())); // let api: OnlineClient = OnlineClient::from_backend(Arc::new(backend)).await?; // ``` diff --git a/subxt/examples/setup_rpc_chainhead_backend.rs b/subxt/examples/setup_rpc_chainhead_backend.rs new file mode 100644 index 0000000000..37da5fce19 --- /dev/null +++ b/subxt/examples/setup_rpc_chainhead_backend.rs @@ -0,0 +1,35 @@ +//! Example to utilize the ChainHeadBackend rpc backend to subscribe to finalized blocks. + +#![allow(missing_docs)] + +use futures::StreamExt; +use subxt::backend::chain_head::{ChainHeadBackend, ChainHeadBackendBuilder}; +use subxt::backend::rpc::RpcClient; +use subxt::{OnlineClient, PolkadotConfig}; + +// Generate an interface that we can use from the node's metadata. +#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")] +pub mod polkadot {} + +#[tokio::main] +async fn main() -> Result<(), Box> { + tracing_subscriber::fmt::init(); + + let rpc = RpcClient::from_url("ws://localhost:9944".to_string()).await?; + let backend: ChainHeadBackend = + ChainHeadBackendBuilder::default().build_with_background_driver(rpc.clone()); + let api = OnlineClient::from_backend(std::sync::Arc::new(backend)).await?; + + let mut blocks_sub = api.blocks().subscribe_finalized().await?.take(100); + + while let Some(block) = blocks_sub.next().await { + let block = block?; + + let block_number = block.number(); + let block_hash = block.hash(); + + println!("Block #{block_number} ({block_hash})"); + } + + Ok(()) +} diff --git a/subxt/src/backend/unstable/follow_stream.rs b/subxt/src/backend/chain_head/follow_stream.rs similarity index 98% rename from subxt/src/backend/unstable/follow_stream.rs rename to subxt/src/backend/chain_head/follow_stream.rs index 1a5316f962..f68d3ba0be 100644 --- a/subxt/src/backend/unstable/follow_stream.rs +++ b/subxt/src/backend/chain_head/follow_stream.rs @@ -2,7 +2,7 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use super::rpc_methods::{FollowEvent, UnstableRpcMethods}; +use super::rpc_methods::{ChainHeadRpcMethods, FollowEvent}; use crate::config::Config; use crate::error::Error; use futures::{FutureExt, Stream, StreamExt}; @@ -99,7 +99,7 @@ impl FollowStream { } /// Create a new [`FollowStream`] given the RPC methods. - pub fn from_methods(methods: UnstableRpcMethods) -> FollowStream { + pub fn from_methods(methods: ChainHeadRpcMethods) -> FollowStream { FollowStream { stream_getter: Box::new(move || { let methods = methods.clone(); @@ -215,7 +215,7 @@ impl Stream for FollowStream { #[cfg(test)] pub(super) mod test_utils { use super::*; - use crate::backend::unstable::rpc_methods::{ + use crate::backend::chain_head::rpc_methods::{ BestBlockChanged, Finalized, Initialized, NewBlock, }; use crate::config::substrate::H256; diff --git a/subxt/src/backend/unstable/follow_stream_driver.rs b/subxt/src/backend/chain_head/follow_stream_driver.rs similarity index 99% rename from subxt/src/backend/unstable/follow_stream_driver.rs rename to subxt/src/backend/chain_head/follow_stream_driver.rs index a9bd508990..702ac5cdb0 100644 --- a/subxt/src/backend/unstable/follow_stream_driver.rs +++ b/subxt/src/backend/chain_head/follow_stream_driver.rs @@ -3,7 +3,7 @@ // see LICENSE for license details. use super::follow_stream_unpin::{BlockRef, FollowStreamMsg, FollowStreamUnpin}; -use crate::backend::unstable::rpc_methods::{FollowEvent, Initialized, RuntimeEvent}; +use crate::backend::chain_head::rpc_methods::{FollowEvent, Initialized, RuntimeEvent}; use crate::config::BlockHash; use crate::error::{Error, RpcError}; use futures::stream::{Stream, StreamExt}; diff --git a/subxt/src/backend/unstable/follow_stream_unpin.rs b/subxt/src/backend/chain_head/follow_stream_unpin.rs similarity index 99% rename from subxt/src/backend/unstable/follow_stream_unpin.rs rename to subxt/src/backend/chain_head/follow_stream_unpin.rs index ecff8b0d58..0ae0ef0a89 100644 --- a/subxt/src/backend/unstable/follow_stream_unpin.rs +++ b/subxt/src/backend/chain_head/follow_stream_unpin.rs @@ -3,8 +3,8 @@ // see LICENSE for license details. use super::follow_stream::FollowStream; -use super::UnstableRpcMethods; -use crate::backend::unstable::rpc_methods::{ +use super::ChainHeadRpcMethods; +use crate::backend::chain_head::rpc_methods::{ BestBlockChanged, Finalized, FollowEvent, Initialized, NewBlock, }; use crate::config::{BlockHash, Config}; @@ -275,7 +275,7 @@ impl FollowStreamUnpin { /// Create a new [`FollowStreamUnpin`] given the RPC methods. pub fn from_methods( follow_stream: FollowStream, - methods: UnstableRpcMethods, + methods: ChainHeadRpcMethods, max_block_life: usize, ) -> FollowStreamUnpin { let unpin_method = Box::new(move |hash: T::Hash, sub_id: Arc| { diff --git a/subxt/src/backend/unstable/mod.rs b/subxt/src/backend/chain_head/mod.rs similarity index 90% rename from subxt/src/backend/unstable/mod.rs rename to subxt/src/backend/chain_head/mod.rs index ead0af1d9e..9c70df5bff 100644 --- a/subxt/src/backend/unstable/mod.rs +++ b/subxt/src/backend/chain_head/mod.rs @@ -38,22 +38,22 @@ use std::task::Poll; use storage_items::StorageItems; // Expose the RPC methods. -pub use rpc_methods::UnstableRpcMethods; +pub use rpc_methods::ChainHeadRpcMethods; -/// Configure and build an [`UnstableBackend`]. -pub struct UnstableBackendBuilder { +/// Configure and build an [`ChainHeadBackend`]. +pub struct ChainHeadBackendBuilder { max_block_life: usize, _marker: std::marker::PhantomData, } -impl Default for UnstableBackendBuilder { +impl Default for ChainHeadBackendBuilder { fn default() -> Self { Self::new() } } -impl UnstableBackendBuilder { - /// Create a new [`UnstableBackendBuilder`]. +impl ChainHeadBackendBuilder { + /// Create a new [`ChainHeadBackendBuilder`]. pub fn new() -> Self { Self { max_block_life: usize::MAX, @@ -73,15 +73,20 @@ impl UnstableBackendBuilder { self } - /// Given an [`RpcClient`] to use to make requests, this returns a tuple of an [`UnstableBackend`], - /// which implements the [`Backend`] trait, and an [`UnstableBackendDriver`] which must be polled in - /// order for the backend to make progress. + /// A low-level API to build the backend and driver which requires polling the driver for the backend + /// to make progress. + /// + /// This is useful if you want to manage the driver yourself, for example if you want to run it in on + /// a specific runtime. + /// + /// If you just want to run the driver in the background until completion in on the default runtime, + /// use [`ChainHeadBackendBuilder::build_with_background_driver`] instead. pub fn build( self, client: impl Into, - ) -> (UnstableBackend, UnstableBackendDriver) { + ) -> (ChainHeadBackend, ChainHeadBackendDriver) { // Construct the underlying follow_stream layers: - let rpc_methods = UnstableRpcMethods::new(client.into()); + let rpc_methods = ChainHeadRpcMethods::new(client.into()); let follow_stream = follow_stream::FollowStream::::from_methods(rpc_methods.clone()); let follow_stream_unpin = follow_stream_unpin::FollowStreamUnpin::::from_methods( @@ -92,26 +97,61 @@ impl UnstableBackendBuilder { let follow_stream_driver = FollowStreamDriver::new(follow_stream_unpin); // Wrap these into the backend and driver that we'll expose. - let backend = UnstableBackend { + let backend = ChainHeadBackend { methods: rpc_methods, follow_handle: follow_stream_driver.handle(), }; - let driver = UnstableBackendDriver { + let driver = ChainHeadBackendDriver { driver: follow_stream_driver, }; (backend, driver) } + + /// An API to build the backend and driver which will run in the background until completion + /// on the default runtime. + /// + /// - On non-wasm targets, this will spawn the driver on `tokio`. + /// - On wasm targets, this will spawn the driver on `wasm-bindgen-futures`. + #[cfg(feature = "runtime")] + #[cfg_attr(docsrs, doc(cfg(feature = "runtime")))] + pub fn build_with_background_driver(self, client: impl Into) -> ChainHeadBackend { + fn spawn(future: F) { + #[cfg(not(target_family = "wasm"))] + tokio::spawn(async move { + future.await; + }); + #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] + wasm_bindgen_futures::spawn_local(async move { + future.await; + }); + } + + let (backend, mut driver) = self.build(client); + + spawn(async move { + while let Some(res) = driver.next().await { + if let Err(e) = res { + if !e.is_disconnected_will_reconnect() { + tracing::debug!(target: "subxt", "chainHead driver was closed: {e}"); + break; + } + } + } + }); + + backend + } } -/// Driver for the [`UnstableBackend`]. This must be polled in order for the +/// Driver for the [`ChainHeadBackend`]. This must be polled in order for the /// backend to make progress. #[derive(Debug)] -pub struct UnstableBackendDriver { +pub struct ChainHeadBackendDriver { driver: FollowStreamDriver, } -impl Stream for UnstableBackendDriver { +impl Stream for ChainHeadBackendDriver { type Item = as Stream>::Item; fn poll_next( mut self: std::pin::Pin<&mut Self>, @@ -121,19 +161,19 @@ impl Stream for UnstableBackendDriver { } } -/// The unstable backend. +/// The chainHead backend. #[derive(Debug, Clone)] -pub struct UnstableBackend { +pub struct ChainHeadBackend { // RPC methods we'll want to call: - methods: UnstableRpcMethods, + methods: ChainHeadRpcMethods, // A handle to the chainHead_follow subscription: follow_handle: FollowStreamDriverHandle, } -impl UnstableBackend { - /// Configure and construct an [`UnstableBackend`] and the associated [`UnstableBackendDriver`]. - pub fn builder() -> UnstableBackendBuilder { - UnstableBackendBuilder::new() +impl ChainHeadBackend { + /// Configure and construct an [`ChainHeadBackend`] and the associated [`ChainHeadBackendDriver`]. + pub fn builder() -> ChainHeadBackendBuilder { + ChainHeadBackendBuilder::new() } /// Stream block headers based on the provided filter fn @@ -193,10 +233,10 @@ impl From> for Bl } } -impl super::sealed::Sealed for UnstableBackend {} +impl super::sealed::Sealed for ChainHeadBackend {} #[async_trait] -impl Backend for UnstableBackend { +impl Backend for ChainHeadBackend { async fn storage_fetch_values( &self, keys: Vec>, diff --git a/subxt/src/backend/unstable/rpc_methods.rs b/subxt/src/backend/chain_head/rpc_methods.rs similarity index 97% rename from subxt/src/backend/unstable/rpc_methods.rs rename to subxt/src/backend/chain_head/rpc_methods.rs index 7acd55006e..900efa361c 100644 --- a/subxt/src/backend/unstable/rpc_methods.rs +++ b/subxt/src/backend/chain_head/rpc_methods.rs @@ -19,15 +19,15 @@ use std::task::Poll; /// some `T: Config` trait which determines some of the types that the RPC methods will /// take or hand back. #[derive_where(Clone, Debug)] -pub struct UnstableRpcMethods { +pub struct ChainHeadRpcMethods { client: RpcClient, _marker: std::marker::PhantomData, } -impl UnstableRpcMethods { +impl ChainHeadRpcMethods { /// Instantiate the legacy RPC method interface. pub fn new(client: RpcClient) -> Self { - UnstableRpcMethods { + ChainHeadRpcMethods { client, _marker: std::marker::PhantomData, } @@ -36,15 +36,15 @@ impl UnstableRpcMethods { /// Subscribe to `chainHead_v1_follow` to obtain all reported blocks by the chain. /// /// The subscription ID can be used to make queries for the - /// block's body ([`chainHead_v1_body`](UnstableRpcMethods::chainhead_v1_follow)), - /// block's header ([`chainHead_v1_header`](UnstableRpcMethods::chainhead_v1_header)), - /// block's storage ([`chainHead_v1_storage`](UnstableRpcMethods::chainhead_v1_storage)) and submitting - /// runtime API calls at this block ([`chainHead_v1_call`](UnstableRpcMethods::chainhead_v1_call)). + /// block's body ([`chainHead_v1_body`](ChainHeadRpcMethods::chainhead_v1_follow)), + /// block's header ([`chainHead_v1_header`](ChainHeadRpcMethods::chainhead_v1_header)), + /// block's storage ([`chainHead_v1_storage`](ChainHeadRpcMethods::chainhead_v1_storage)) and submitting + /// runtime API calls at this block ([`chainHead_v1_call`](ChainHeadRpcMethods::chainhead_v1_call)). /// /// # Note /// /// When the user is no longer interested in a block, the user is responsible - /// for calling the [`chainHead_v1_unpin`](UnstableRpcMethods::chainhead_v1_unpin) method. + /// for calling the [`chainHead_v1_unpin`](ChainHeadRpcMethods::chainhead_v1_unpin) method. /// Failure to do so will result in the subscription being stopped by generating the `Stop` event. pub async fn chainhead_v1_follow( &self, @@ -106,7 +106,7 @@ impl UnstableRpcMethods { /// # Note /// /// The subscription ID is obtained from an open subscription created by - /// [`chainHead_v1_follow`](UnstableRpcMethods::chainhead_v1_follow). + /// [`chainHead_v1_follow`](ChainHeadRpcMethods::chainhead_v1_follow). pub async fn chainhead_v1_body( &self, subscription_id: &str, @@ -125,7 +125,7 @@ impl UnstableRpcMethods { /// # Note /// /// The subscription ID is obtained from an open subscription created by - /// [`chainHead_v1_follow`](UnstableRpcMethods::chainhead_v1_follow). + /// [`chainHead_v1_follow`](ChainHeadRpcMethods::chainhead_v1_follow). pub async fn chainhead_v1_header( &self, subscription_id: &str, @@ -151,7 +151,7 @@ impl UnstableRpcMethods { /// # Note /// /// The subscription ID is obtained from an open subscription created by - /// [`chainHead_v1_follow`](UnstableRpcMethods::chainhead_v1_follow). + /// [`chainHead_v1_follow`](ChainHeadRpcMethods::chainhead_v1_follow). pub async fn chainhead_v1_storage( &self, subscription_id: &str, @@ -186,7 +186,7 @@ impl UnstableRpcMethods { /// # Note /// /// The subscription ID is obtained from an open subscription created by - /// [`chainHead_v1_follow`](UnstableRpcMethods::chainhead_v1_follow). + /// [`chainHead_v1_follow`](ChainHeadRpcMethods::chainhead_v1_follow). pub async fn chainhead_v1_call( &self, subscription_id: &str, @@ -210,7 +210,7 @@ impl UnstableRpcMethods { /// # Note /// /// The subscription ID is obtained from an open subscription created by - /// [`chainHead_v1_follow`](UnstableRpcMethods::chainhead_v1_follow). + /// [`chainHead_v1_follow`](ChainHeadRpcMethods::chainhead_v1_follow). pub async fn chainhead_v1_unpin( &self, subscription_id: &str, diff --git a/subxt/src/backend/unstable/storage_items.rs b/subxt/src/backend/chain_head/storage_items.rs similarity index 98% rename from subxt/src/backend/unstable/storage_items.rs rename to subxt/src/backend/chain_head/storage_items.rs index 0e7aa46772..403cc45117 100644 --- a/subxt/src/backend/unstable/storage_items.rs +++ b/subxt/src/backend/chain_head/storage_items.rs @@ -5,7 +5,7 @@ use super::follow_stream_driver::FollowStreamDriverHandle; use super::follow_stream_unpin::BlockRef; use super::rpc_methods::{ - FollowEvent, MethodResponse, StorageQuery, StorageResult, UnstableRpcMethods, + ChainHeadRpcMethods, FollowEvent, MethodResponse, StorageQuery, StorageResult, }; use crate::config::Config; use crate::error::{Error, RpcError}; @@ -35,7 +35,7 @@ impl StorageItems { queries: impl Iterator>, at: T::Hash, follow_handle: &FollowStreamDriverHandle, - methods: UnstableRpcMethods, + methods: ChainHeadRpcMethods, ) -> Result { let sub_id = super::get_subscription_id(follow_handle).await?; diff --git a/subxt/src/backend/mod.rs b/subxt/src/backend/mod.rs index cc48e1a0a7..eeb66eb85d 100644 --- a/subxt/src/backend/mod.rs +++ b/subxt/src/backend/mod.rs @@ -6,9 +6,9 @@ //! the necessary information (probably from a JSON-RPC API, but that's up to the //! implementation). +pub mod chain_head; pub mod legacy; pub mod rpc; -pub mod unstable; pub mod utils; use subxt_core::client::RuntimeVersion; @@ -881,18 +881,18 @@ mod test { OperationStorageItems, RuntimeSpec, RuntimeVersionEvent, }; - use super::unstable::*; + use super::chain_head::*; use super::*; fn build_backend( rpc_client: impl RpcClientT, - ) -> (UnstableBackend, UnstableBackendDriver) { - let (backend, driver): (UnstableBackend, _) = - UnstableBackend::builder().build(rpc_client); + ) -> (ChainHeadBackend, ChainHeadBackendDriver) { + let (backend, driver): (ChainHeadBackend, _) = + ChainHeadBackend::builder().build(rpc_client); (backend, driver) } - fn build_backend_spawn_background(rpc_client: impl RpcClientT) -> UnstableBackend { + fn build_backend_spawn_background(rpc_client: impl RpcClientT) -> ChainHeadBackend { let (backend, mut driver) = build_backend(rpc_client); tokio::spawn(async move { while let Some(val) = driver.next().await { @@ -931,7 +931,7 @@ mod test { serde_json::from_value(spec).unwrap() } - type FollowEvent = unstable::rpc_methods::FollowEvent<::Hash>; + type FollowEvent = chain_head::rpc_methods::FollowEvent<::Hash>; fn setup_mock_rpc_client(cycle_ids: bool) -> MockRpcBuilder { let hash = random_hash(); @@ -993,13 +993,16 @@ mod test { operation_id: id.to_owned(), }) } - fn storage_result(key: &str, value: &str) -> unstable::rpc_methods::StorageResult { - unstable::rpc_methods::StorageResult { + fn storage_result(key: &str, value: &str) -> chain_head::rpc_methods::StorageResult { + chain_head::rpc_methods::StorageResult { key: Bytes(key.to_owned().into()), result: rpc_methods::StorageResultType::Value(Bytes(value.to_owned().into())), } } - fn storage_items(id: &str, items: &[unstable::rpc_methods::StorageResult]) -> FollowEvent { + fn storage_items( + id: &str, + items: &[chain_head::rpc_methods::StorageResult], + ) -> FollowEvent { FollowEvent::OperationStorageItems(OperationStorageItems { operation_id: id.to_owned(), items: VecDeque::from(items.to_owned()), @@ -1400,7 +1403,7 @@ mod test { .add_mock_data(mock_data) .add_mock_data(response_data) .build(); - let (backend, mut driver): (UnstableBackend, _) = build_backend(rpc_client); + let (backend, mut driver): (ChainHeadBackend, _) = build_backend(rpc_client); let _ = driver.next().await.unwrap(); let _ = driver.next().await.unwrap(); diff --git a/subxt/src/book/usage/rpc.rs b/subxt/src/book/usage/rpc.rs index a5fb61863a..3b4fae4b14 100644 --- a/subxt/src/book/usage/rpc.rs +++ b/subxt/src/book/usage/rpc.rs @@ -5,7 +5,7 @@ //! # RPC calls //! //! Subxt exposes low level interfaces that can be used to make RPC requests; [`crate::backend::legacy::rpc_methods`] -//! and [`crate::backend::unstable::rpc_methods`]. +//! and [`crate::backend::chain_head::rpc_methods`]. //! //! These interfaces cannot be accessed directly through an [`crate::OnlineClient`]; this is so that the high level //! Subxt APIs can target either the "legacy" or the more modern "unstable" sets of RPC methods by selecting an appropriate diff --git a/testing/integration-tests/Cargo.toml b/testing/integration-tests/Cargo.toml index ecf485d57b..8680b3b9c4 100644 --- a/testing/integration-tests/Cargo.toml +++ b/testing/integration-tests/Cargo.toml @@ -21,9 +21,9 @@ unstable-light-client = ["subxt/unstable-light-client"] # Enable to run the full-client tests with Light Client support. unstable-light-client-long-running = ["subxt/unstable-light-client"] -# Enable this to use the unstable backend in tests _instead of_ +# Enable this to use the chainhead backend in tests _instead of_ # the default one which relies on the "old" RPC methods. -unstable-backend-client = [] +chainhead-backend = [] [dev-dependencies] assert_matches = { workspace = true } diff --git a/testing/integration-tests/build.rs b/testing/integration-tests/build.rs index 992c3b3e81..bce3d4dcb2 100644 --- a/testing/integration-tests/build.rs +++ b/testing/integration-tests/build.rs @@ -5,5 +5,7 @@ fn main() { cfg_aliases! { lightclient: { any(feature = "unstable-light-client", feature = "unstable-light-client-long-running") }, fullclient: { all(not(feature = "unstable-light-client"), not(feature = "unstable-light-client-long-running")) }, + legacy_backend: { not(feature = "chainhead-backend") }, + chainhead_backend: { feature = "chainhead-backend" }, } } diff --git a/testing/integration-tests/src/full_client/client/mod.rs b/testing/integration-tests/src/full_client/client/mod.rs index 880601dbad..4ec35b1fed 100644 --- a/testing/integration-tests/src/full_client/client/mod.rs +++ b/testing/integration-tests/src/full_client/client/mod.rs @@ -77,8 +77,8 @@ async fn storage_iter() { async fn storage_child_values_same_across_backends() { let ctx = test_context().await; - let unstable_client = ctx.unstable_client().await; - let legacy_client = ctx.legacy_client().await; + let chainhead_client = ctx.chainhead_backend().await; + let legacy_client = ctx.legacy_backend().await; let addr = node_runtime::storage().system().account_iter(); let block_ref = legacy_client @@ -88,7 +88,7 @@ async fn storage_child_values_same_across_backends() { .unwrap() .reference(); - let a: Vec<_> = unstable_client + let a: Vec<_> = chainhead_client .storage() .at(block_ref.clone()) .iter(addr.clone()) @@ -215,9 +215,9 @@ async fn external_signing() { } #[cfg(fullclient)] -// TODO: Investigate and fix this test failure when using the UnstableBackend. +// TODO: Investigate and fix this test failure when using the ChainHeadBackend. // (https://github.com/paritytech/subxt/issues/1308) -#[cfg(not(feature = "unstable-backend-client"))] +#[cfg(legacy_backend)] #[subxt_test] async fn submit_large_extrinsic() { let ctx = test_context().await; @@ -415,8 +415,8 @@ async fn partial_fee_estimate_correct() { #[subxt_test] async fn legacy_and_unstable_block_subscription_reconnect() { let ctx = test_context_reconnecting_rpc_client().await; - let api = ctx.unstable_client().await; - let unstable_client_blocks = move |num: usize| { + let api = ctx.chainhead_backend().await; + let chainhead_client_blocks = move |num: usize| { let api = api.clone(); async move { let mut missed_blocks = false; @@ -445,17 +445,17 @@ async fn legacy_and_unstable_block_subscription_reconnect() { } }; - let (blocks, _) = unstable_client_blocks(3).await; + let (blocks, _) = chainhead_client_blocks(3).await; let blocks: HashSet = HashSet::from_iter(blocks.into_iter()); assert!(blocks.len() == 3); let ctx = ctx.restart().await; - // Make client aware that connection was dropped and force them to reconnect - let _ = ctx.unstable_client().await.backend().genesis_hash().await; + // Make client aware that connection was dropped and force them to reconnect + let _ = ctx.chainhead_backend().await.backend().genesis_hash().await; - let (unstable_blocks, blocks_missed) = unstable_client_blocks(6).await; + let (unstable_blocks, blocks_missed) = chainhead_client_blocks(6).await; if !blocks_missed { let unstable_blocks: HashSet = HashSet::from_iter(unstable_blocks.into_iter()); diff --git a/testing/integration-tests/src/full_client/client/unstable_rpcs.rs b/testing/integration-tests/src/full_client/client/unstable_rpcs.rs index 3df3696e94..dbc2defd9e 100644 --- a/testing/integration-tests/src/full_client/client/unstable_rpcs.rs +++ b/testing/integration-tests/src/full_client/client/unstable_rpcs.rs @@ -13,7 +13,7 @@ use assert_matches::assert_matches; use codec::Encode; use futures::Stream; use subxt::{ - backend::unstable::rpc_methods::{ + backend::chain_head::rpc_methods::{ FollowEvent, Initialized, MethodResponse, RuntimeEvent, RuntimeVersionEvent, StorageQuery, StorageQueryType, }, @@ -27,7 +27,7 @@ use subxt_signer::sr25519::dev; #[subxt_test] async fn chainhead_v1_follow() { let ctx = test_context().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let legacy_rpc = ctx.legacy_rpc_methods().await; // Check subscription with runtime updates set on false. @@ -67,7 +67,7 @@ async fn chainhead_v1_follow() { #[subxt_test] async fn chainhead_v1_body() { let ctx = test_context().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let mut blocks = rpc.chainhead_v1_follow(false).await.unwrap(); let event = blocks.next().await.unwrap().unwrap(); @@ -95,7 +95,7 @@ async fn chainhead_v1_body() { #[subxt_test] async fn chainhead_v1_header() { let ctx = test_context().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let legacy_rpc = ctx.legacy_rpc_methods().await; let mut blocks = rpc.chainhead_v1_follow(false).await.unwrap(); @@ -124,7 +124,7 @@ async fn chainhead_v1_header() { async fn chainhead_v1_storage() { let ctx = test_context().await; let api = ctx.client(); - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let mut blocks = rpc.chainhead_v1_follow(false).await.unwrap(); let event = blocks.next().await.unwrap().unwrap(); @@ -169,7 +169,7 @@ async fn chainhead_v1_storage() { #[subxt_test] async fn chainhead_v1_call() { let ctx = test_context().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let mut blocks = rpc.chainhead_v1_follow(true).await.unwrap(); let event = blocks.next().await.unwrap().unwrap(); @@ -206,7 +206,7 @@ async fn chainhead_v1_call() { #[subxt_test] async fn chainhead_v1_unpin() { let ctx = test_context().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let mut blocks = rpc.chainhead_v1_follow(true).await.unwrap(); let event = blocks.next().await.unwrap().unwrap(); @@ -226,7 +226,7 @@ async fn chainhead_v1_unpin() { async fn chainspec_v1_genesishash() { let ctx = test_context().await; let old_rpc = ctx.legacy_rpc_methods().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let a = old_rpc.genesis_hash().await.unwrap(); let b = rpc.chainspec_v1_genesis_hash().await.unwrap(); @@ -239,7 +239,7 @@ async fn chainspec_v1_genesishash() { async fn chainspec_v1_chainname() { let ctx = test_context().await; let old_rpc = ctx.legacy_rpc_methods().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let a = old_rpc.system_chain().await.unwrap(); let b = rpc.chainspec_v1_chain_name().await.unwrap(); @@ -252,7 +252,7 @@ async fn chainspec_v1_chainname() { async fn chainspec_v1_properties() { let ctx = test_context().await; let old_rpc = ctx.legacy_rpc_methods().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let a = old_rpc.system_properties().await.unwrap(); let b = rpc.chainspec_v1_properties().await.unwrap(); @@ -264,7 +264,7 @@ async fn chainspec_v1_properties() { #[subxt_test] async fn transactionwatch_v1_submit_and_watch() { let ctx = test_context().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; // Build and sign some random tx, just to get some appropriate bytes: let payload = node_runtime::tx().system().remark(b"hello".to_vec()); @@ -327,7 +327,7 @@ async fn transaction_v1_broadcast() { let ctx = test_context().await; let api = ctx.client(); - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; let tx_payload = node_runtime::tx() .balances() @@ -391,7 +391,7 @@ async fn transaction_v1_stop() { let bob_address: MultiAddress = bob.public_key().into(); let ctx = test_context().await; - let rpc = ctx.unstable_rpc_methods().await; + let rpc = ctx.chainhead_rpc_methods().await; // Cannot stop an operation that was not started. let _err = rpc diff --git a/testing/integration-tests/src/lib.rs b/testing/integration-tests/src/lib.rs index a57790d452..a9952d5fc5 100644 --- a/testing/integration-tests/src/lib.rs +++ b/testing/integration-tests/src/lib.rs @@ -2,9 +2,9 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -#[cfg(all(feature = "unstable-light-client", feature = "unstable-backend-client"))] +#[cfg(all(feature = "unstable-light-client", feature = "chainhead-backend"))] compile_error!( - "The features 'unstable-light-client' and 'unstable-backend-client' cannot be used together" + "The features 'unstable-light-client' and 'chainhead-backend' cannot be used together" ); #[cfg(test)] diff --git a/testing/integration-tests/src/light_client/mod.rs b/testing/integration-tests/src/light_client/mod.rs index 80fe1de484..45d66528a0 100644 --- a/testing/integration-tests/src/light_client/mod.rs +++ b/testing/integration-tests/src/light_client/mod.rs @@ -31,8 +31,8 @@ use crate::utils::node_runtime; use codec::Compact; use futures::StreamExt; use std::sync::Arc; +use subxt::backend::chain_head::ChainHeadBackend; use subxt::backend::rpc::RpcClient; -use subxt::backend::unstable::UnstableBackend; use subxt::{client::OnlineClient, config::PolkadotConfig, lightclient::LightClient}; use subxt_metadata::Metadata; @@ -184,7 +184,7 @@ async fn run_test(backend: BackendType) -> Result<(), subxt::Error> { let api = match backend { BackendType::Unstable => { - let (backend, mut driver) = UnstableBackend::builder().build(RpcClient::new(rpc)); + let (backend, mut driver) = ChainHeadBackend::builder().build(RpcClient::new(rpc)); tokio::spawn(async move { while let Some(val) = driver.next().await { if let Err(e) = val { diff --git a/testing/integration-tests/src/utils/node_proc.rs b/testing/integration-tests/src/utils/node_proc.rs index 96e2cbd22a..65cf0586a4 100644 --- a/testing/integration-tests/src/utils/node_proc.rs +++ b/testing/integration-tests/src/utils/node_proc.rs @@ -9,7 +9,7 @@ use std::time::Duration; use substrate_runner::SubstrateNode; use subxt::backend::rpc::reconnecting_rpc_client::{ExponentialBackoff, RpcClientBuilder}; use subxt::{ - backend::{legacy, rpc, unstable}, + backend::{chain_head, legacy, rpc}, Config, OnlineClient, }; @@ -41,8 +41,8 @@ pub struct TestNodeProcess { proc: Option, // Lazily construct these when asked for. - unstable_client: RefCell>>, - legacy_client: RefCell>>, + chainhead_backend: RefCell>>, + legacy_backend: RefCell>>, rpc_client: rpc::RpcClient, client: OnlineClient, @@ -78,38 +78,38 @@ where } /// Hand back an RPC client connected to the test node which exposes the unstable RPC methods. - pub async fn unstable_rpc_methods(&self) -> unstable::UnstableRpcMethods { + pub async fn chainhead_rpc_methods(&self) -> chain_head::ChainHeadRpcMethods { let rpc_client = self.rpc_client.clone(); - unstable::UnstableRpcMethods::new(rpc_client) + chain_head::ChainHeadRpcMethods::new(rpc_client) } - /// Always return a client using the unstable backend. + /// Always return a client using the chainhead backend. /// Only use for comparing backends; use [`TestNodeProcess::client()`] normally, /// which enables us to run each test against both backends. - pub async fn unstable_client(&self) -> OnlineClient { - if self.unstable_client.borrow().is_none() { - let c = build_unstable_client(self.rpc_client.clone()) + pub async fn chainhead_backend(&self) -> OnlineClient { + if self.chainhead_backend.borrow().is_none() { + let c = build_chainhead_backend(self.rpc_client.clone()) .await .unwrap(); - self.unstable_client.replace(Some(c)); + self.chainhead_backend.replace(Some(c)); } - self.unstable_client.borrow().as_ref().unwrap().clone() + self.chainhead_backend.borrow().as_ref().unwrap().clone() } /// Always return a client using the legacy backend. /// Only use for comparing backends; use [`TestNodeProcess::client()`] normally, /// which enables us to run each test against both backends. - pub async fn legacy_client(&self) -> OnlineClient { - if self.legacy_client.borrow().is_none() { - let c = build_legacy_client(self.rpc_client.clone()).await.unwrap(); - self.legacy_client.replace(Some(c)); + pub async fn legacy_backend(&self) -> OnlineClient { + if self.legacy_backend.borrow().is_none() { + let c = build_legacy_backend(self.rpc_client.clone()).await.unwrap(); + self.legacy_backend.replace(Some(c)); } - self.legacy_client.borrow().as_ref().unwrap().clone() + self.legacy_backend.borrow().as_ref().unwrap().clone() } /// Returns the subxt client connected to the running node. This client - /// will use the legacy backend by default or the unstable backend if the - /// "unstable-backend-client" feature is enabled, so that we can run each + /// will use the legacy backend by default or the chainhead backend if the + /// "chainhead-backend" feature is enabled, so that we can run each /// test against both. pub fn client(&self) -> OnlineClient { self.client.clone() @@ -187,38 +187,38 @@ impl TestNodeProcessBuilder { let ws_url = get_url(proc.as_ref().map(|p| p.ws_port())); let rpc_client = match self.rpc_client { RpcClientKind::Legacy => build_rpc_client(&ws_url).await, - RpcClientKind::UnstableReconnecting => build_unstable_rpc_client(&ws_url).await, + RpcClientKind::UnstableReconnecting => build_reconnecting_rpc_client(&ws_url).await, } .map_err(|e| format!("Failed to connect to node at {ws_url}: {e}"))?; // Cache whatever client we build, and None for the other. #[allow(unused_assignments, unused_mut)] - let mut unstable_client = None; + let mut chainhead_backend = None; #[allow(unused_assignments, unused_mut)] - let mut legacy_client = None; + let mut legacy_backend = None; #[cfg(lightclient)] let client = build_light_client(&proc).await?; - #[cfg(feature = "unstable-backend-client")] + #[cfg(chainhead_backend)] let client = { - let client = build_unstable_client(rpc_client.clone()).await?; - unstable_client = Some(client.clone()); + let client = build_chainhead_backend(rpc_client.clone()).await?; + chainhead_backend = Some(client.clone()); client }; - #[cfg(all(not(lightclient), not(feature = "unstable-backend-client")))] + #[cfg(all(not(lightclient), legacy_backend))] let client = { - let client = build_legacy_client(rpc_client.clone()).await?; - legacy_client = Some(client.clone()); + let client = build_legacy_backend(rpc_client.clone()).await?; + legacy_backend = Some(client.clone()); client }; Ok(TestNodeProcess { proc, client, - legacy_client: RefCell::new(legacy_client), - unstable_client: RefCell::new(unstable_client), + legacy_backend: RefCell::new(legacy_backend), + chainhead_backend: RefCell::new(chainhead_backend), rpc_client, }) } @@ -232,7 +232,7 @@ async fn build_rpc_client(ws_url: &str) -> Result { Ok(rpc_client) } -async fn build_unstable_rpc_client(ws_url: &str) -> Result { +async fn build_reconnecting_rpc_client(ws_url: &str) -> Result { let client = RpcClientBuilder::new() .retry_policy(ExponentialBackoff::from_millis(100).max_delay(Duration::from_secs(10))) .build(ws_url.to_string()) @@ -242,7 +242,7 @@ async fn build_unstable_rpc_client(ws_url: &str) -> Result( +async fn build_legacy_backend( rpc_client: rpc::RpcClient, ) -> Result, String> { let backend = legacy::LegacyBackend::builder().build(rpc_client); @@ -253,23 +253,10 @@ async fn build_legacy_client( Ok(client) } -async fn build_unstable_client( +async fn build_chainhead_backend( rpc_client: rpc::RpcClient, ) -> Result, String> { - let (backend, mut driver) = unstable::UnstableBackend::builder().build(rpc_client); - - // The unstable backend needs driving: - tokio::spawn(async move { - use futures::StreamExt; - while let Some(val) = driver.next().await { - if let Err(e) = val { - // This is a test; bail if something does wrong and try to - // ensure that the message makes it to some logs. - eprintln!("Error driving unstable backend in tests (will panic): {e}"); - panic!("Error driving unstable backend in tests: {e}"); - } - } - }); + let backend = chain_head::ChainHeadBackend::builder().build_with_background_driver(rpc_client); let client = OnlineClient::from_backend(Arc::new(backend)) .await @@ -323,5 +310,5 @@ async fn build_light_client( .map_err(|e| format!("Light client: cannot add relay chain: {e}"))?; // Instantiate subxt client from this. - build_unstable_client(rpc.into()).await + build_chainhead_backend(rpc.into()).await } diff --git a/testing/wasm-rpc-tests/Cargo.lock b/testing/wasm-rpc-tests/Cargo.lock index d42f541e11..8a27e550aa 100644 --- a/testing/wasm-rpc-tests/Cargo.lock +++ b/testing/wasm-rpc-tests/Cargo.lock @@ -97,7 +97,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -445,7 +445,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -493,7 +493,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -515,7 +515,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -526,7 +526,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -539,7 +539,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -667,6 +667,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "frame-decode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed90459016b06a2855321469cb01fbc74208c80c06b085d1ed13162cf8bd7e1b" +dependencies = [ + "frame-metadata 16.0.0", + "hex", + "parity-scale-codec", + "scale-decode", + "scale-info", + "scale-type-resolver", + "sp-crypto-hashing", +] + [[package]] name = "frame-metadata" version = "15.1.0" @@ -750,7 +765,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -1301,11 +1316,11 @@ dependencies = [ [[package]] name = "keccak-hash" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b286e6b663fb926e1eeb68528e69cb70ed46c6d65871a21b2215ae8154c6d3c" +checksum = "3e1b8590eb6148af2ea2d75f38e7d29f5ca970d5a4df456b3ef19b8b415d0264" dependencies = [ - "primitive-types", + "primitive-types 0.13.1", "tiny-keccak", ] @@ -1485,7 +1500,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -1608,7 +1623,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -1653,7 +1668,17 @@ dependencies = [ "impl-codec", "impl-serde", "scale-info", - "uint", + "uint 0.9.5", +] + +[[package]] +name = "primitive-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" +dependencies = [ + "fixed-hash", + "uint 0.10.0", ] [[package]] @@ -1694,7 +1719,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -1920,7 +1945,7 @@ checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" dependencies = [ "derive_more", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-bits", "scale-decode-derive", "scale-type-resolver", @@ -1947,7 +1972,7 @@ checksum = "4ba0b9c48dc0eb20c60b083c29447c0c4617cb7c4a4c9fef72aa5c5bc539e15e" dependencies = [ "derive_more", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-bits", "scale-encode-derive", "scale-type-resolver", @@ -2012,15 +2037,15 @@ dependencies = [ "proc-macro2", "quote", "scale-info", - "syn 2.0.75", + "syn 2.0.79", "thiserror", ] [[package]] name = "scale-value" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4d772cfb7569e03868400344a1695d16560bf62b86b918604773607d39ec84" +checksum = "8cd6ab090d823e75cfdb258aad5fe92e13f2af7d04b43a55d607d25fcc38c811" dependencies = [ "base58", "blake2", @@ -2139,7 +2164,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -2423,7 +2448,7 @@ dependencies = [ "instant", "jsonrpsee", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-bits", "scale-decode", "scale-encode", @@ -2458,7 +2483,7 @@ dependencies = [ "scale-info", "scale-typegen", "subxt-metadata", - "syn 2.0.75", + "syn 2.0.79", "thiserror", "tokio", ] @@ -2470,13 +2495,14 @@ dependencies = [ "base58", "blake2", "derive-where", + "frame-decode", "frame-metadata 16.0.0", "hashbrown", "hex", "impl-serde", "keccak-hash", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-bits", "scale-decode", "scale-encode", @@ -2524,13 +2550,14 @@ dependencies = [ "quote", "scale-typegen", "subxt-codegen", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] name = "subxt-metadata" version = "0.37.0" dependencies = [ + "frame-decode", "frame-metadata 16.0.0", "hashbrown", "parity-scale-codec", @@ -2551,9 +2578,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2583,7 +2610,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -2644,7 +2671,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -2759,7 +2786,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -2828,6 +2855,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -2929,7 +2968,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -2963,7 +3002,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2997,7 +3036,7 @@ checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -3248,7 +3287,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] [[package]] @@ -3268,5 +3307,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.79", ] diff --git a/testing/wasm-rpc-tests/Cargo.toml b/testing/wasm-rpc-tests/Cargo.toml index 103091739c..597acd93e6 100644 --- a/testing/wasm-rpc-tests/Cargo.toml +++ b/testing/wasm-rpc-tests/Cargo.toml @@ -15,4 +15,4 @@ futures-util = "0.3.30" # This crate is not a part of the workspace, because it # requires the "jsonrpsee web" features to be enabled, which we don't # want enabled for workspace builds in general. -subxt = { path = "../../subxt", default-features = false, features = ["web", "jsonrpsee", "unstable-reconnecting-rpc-client"] } +subxt = { path = "../../subxt", default-features = false, features = ["web", "jsonrpsee", "unstable-reconnecting-rpc-client", "runtime"] } \ No newline at end of file diff --git a/testing/wasm-rpc-tests/tests/wasm.rs b/testing/wasm-rpc-tests/tests/wasm.rs index a62102333d..8302892695 100644 --- a/testing/wasm-rpc-tests/tests/wasm.rs +++ b/testing/wasm-rpc-tests/tests/wasm.rs @@ -36,6 +36,16 @@ async fn wasm_ws_transport_works() { assert!(stream.next().await.is_some()); } +#[wasm_bindgen_test] +async fn wasm_ws_chainhead_works() { + let rpc = subxt::backend::rpc::RpcClient::from_url("ws://127.0.0.1:9944").await.unwrap(); + let backend = subxt::backend::chain_head::ChainHeadBackendBuilder::new().build_with_background_driver(rpc); + let client = subxt::client::OnlineClient::::from_backend(std::sync::Arc::new(backend)).await.unwrap(); + + let mut stream = client.backend().stream_best_block_headers().await.unwrap(); + assert!(stream.next().await.is_some()); +} + #[wasm_bindgen_test] async fn reconnecting_rpc_client_ws_transport_works() { let rpc = ReconnectingRpcClient::builder().build("ws://127.0.0.1:9944".to_string()).await.unwrap();