add wasm support (#700)

* get started

* make it work again

* make it compile again

* Use async-wasm-feature of jsonrpsee from the master branch

* Ensure we enable JS feature of getrandom for the wasm target

* Update subxt/src/lib.rs

* update jsonrpsee

* fix CI

* cargo fmt

* fix wasm test

* fix grumbles

* exclude wasm-tests from workspace

To avoid leaking `jsonrpsee-web` feature into the workspace

Co-authored-by: Igor Matuszewski <xanewok@gmail.com>
This commit is contained in:
Niklas Adolfsson
2022-11-14 12:45:21 +01:00
committed by GitHub
parent 71e58b2c16
commit 14e8e6f6b6
13 changed files with 144 additions and 50 deletions
+30 -4
View File
@@ -61,7 +61,10 @@ impl<T: Config> std::fmt::Debug for OnlineClient<T> {
}
// The default constructors assume Jsonrpsee.
#[cfg(feature = "jsonrpsee")]
#[cfg(any(
feature = "jsonrpsee-ws",
all(feature = "jsonrpsee-web", target_arch = "wasm32")
))]
impl<T: Config> OnlineClient<T> {
/// Construct a new [`OnlineClient`] using default settings which
/// point to a locally running node on `ws://127.0.0.1:9944`.
@@ -72,7 +75,7 @@ impl<T: Config> OnlineClient<T> {
/// Construct a new [`OnlineClient`], providing a URL to connect to.
pub async fn from_url(url: impl AsRef<str>) -> Result<OnlineClient<T>, Error> {
let client = jsonrpsee_helpers::ws_client(url.as_ref())
let client = jsonrpsee_helpers::client(url.as_ref())
.await
.map_err(|e| crate::error::RpcError::ClientError(Box::new(e)))?;
OnlineClient::from_rpc_client(Arc::new(client)).await
@@ -346,7 +349,7 @@ impl Update {
}
// helpers for a jsonrpsee specific OnlineClient.
#[cfg(feature = "jsonrpsee")]
#[cfg(feature = "jsonrpsee-ws")]
mod jsonrpsee_helpers {
pub use jsonrpsee::{
client_transport::ws::{
@@ -366,7 +369,7 @@ mod jsonrpsee_helpers {
};
/// Build WS RPC client from URL
pub async fn ws_client(url: &str) -> Result<Client, Error> {
pub async fn client(url: &str) -> Result<Client, Error> {
let (sender, receiver) = ws_transport(url).await?;
Ok(ClientBuilder::default()
.max_notifs_per_subscription(4096)
@@ -383,3 +386,26 @@ mod jsonrpsee_helpers {
.map_err(|e| Error::Transport(e.into()))
}
}
// helpers for a jsonrpsee specific OnlineClient.
#[cfg(all(feature = "jsonrpsee-web", target_arch = "wasm32"))]
mod jsonrpsee_helpers {
pub use jsonrpsee::{
client_transport::web,
core::{
client::{
Client,
ClientBuilder,
},
Error,
},
};
/// Build web RPC client from URL
pub async fn client(url: &str) -> Result<Client, Error> {
let (sender, receiver) = web::connect(url).await.unwrap();
Ok(ClientBuilder::default()
.max_notifs_per_subscription(4096)
.build_with_wasm(sender, receiver))
}
}
+7
View File
@@ -140,6 +140,13 @@ use tokio as _;
pub use subxt_macro::subxt;
// Used to enable the js feature for wasm.
#[cfg(target_arch = "wasm32")]
pub use getrandom as _;
#[cfg(all(feature = "jsonrpsee-ws", feature = "jsonrpsee-web"))]
std::compile_error!("Both the features `jsonrpsee-ws` and `jsonrpsee-web` are enabled which are mutually exclusive");
pub mod blocks;
pub mod client;
pub mod config;
+16 -30
View File
@@ -12,18 +12,24 @@ use futures::stream::{
StreamExt,
TryStreamExt,
};
use jsonrpsee::{
core::client::{
use jsonrpsee::core::{
client::{
Client,
ClientT,
SubscriptionClientT,
},
types::ParamsSer,
};
use serde_json::value::{
RawValue,
Value,
traits::ToRpcParams,
Error as JsonRpseeError,
};
use serde_json::value::RawValue;
struct Params(Option<Box<RawValue>>);
impl ToRpcParams for Params {
fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, JsonRpseeError> {
Ok(self.0)
}
}
impl RpcClientT for Client {
fn request_raw<'a>(
@@ -32,8 +38,7 @@ impl RpcClientT for Client {
params: Option<Box<RawValue>>,
) -> RpcFuture<'a, Box<RawValue>> {
Box::pin(async move {
let params = prep_params_for_jsonrpsee(params);
let res = ClientT::request(self, method, Some(params))
let res = ClientT::request(self, method, Params(params))
.await
.map_err(|e| RpcError::ClientError(Box::new(e)))?;
Ok(res)
@@ -47,11 +52,10 @@ impl RpcClientT for Client {
unsub: &'a str,
) -> RpcFuture<'a, RpcSubscription> {
Box::pin(async move {
let params = prep_params_for_jsonrpsee(params);
let sub = SubscriptionClientT::subscribe::<Box<RawValue>>(
let sub = SubscriptionClientT::subscribe::<Box<RawValue>, _>(
self,
sub,
Some(params),
Params(params),
unsub,
)
.await
@@ -62,21 +66,3 @@ impl RpcClientT for Client {
})
}
}
// This is ugly; we have to encode to Value's to be compat with the jsonrpc interface.
// Remove and simplify this once something like https://github.com/paritytech/jsonrpsee/issues/862 is in:
fn prep_params_for_jsonrpsee(params: Option<Box<RawValue>>) -> ParamsSer<'static> {
let params = match params {
Some(params) => params,
// No params? avoid any work and bail early.
None => return ParamsSer::Array(Vec::new()),
};
let val = serde_json::to_value(&params).expect("RawValue guarantees valid JSON");
let arr = match val {
Value::Array(arr) => arr,
_ => {
panic!("RPC Params are expected to be an array but got {params}");
}
};
ParamsSer::Array(arr)
}