mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-24 11:21:08 +00:00
Merge branch 'master' into aj/update-substrate-crates
This commit is contained in:
@@ -34,7 +34,7 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1
|
uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
|
||||||
|
|
||||||
- name: Cargo test
|
- name: Cargo test
|
||||||
uses: actions-rs/cargo@v1.0.3
|
uses: actions-rs/cargo@v1.0.3
|
||||||
|
|||||||
@@ -40,13 +40,16 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1
|
uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
|
||||||
|
|
||||||
- name: Build
|
- name: Install cargo-hack
|
||||||
uses: actions-rs/cargo@v1.0.3
|
uses: baptiste0928/cargo-install@v1
|
||||||
with:
|
with:
|
||||||
command: check
|
crate: cargo-hack
|
||||||
args: --all-targets --all-features --workspace
|
version: 0.5
|
||||||
|
|
||||||
|
- name: Cargo check
|
||||||
|
run: cargo hack --exclude-all-features --each-feature check --all-targets --workspace
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
name: Cargo fmt
|
name: Cargo fmt
|
||||||
@@ -64,7 +67,7 @@ jobs:
|
|||||||
components: rustfmt
|
components: rustfmt
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1
|
uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
|
||||||
|
|
||||||
- name: Cargo fmt
|
- name: Cargo fmt
|
||||||
uses: actions-rs/cargo@v1.0.3
|
uses: actions-rs/cargo@v1.0.3
|
||||||
@@ -94,7 +97,7 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1
|
uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
|
||||||
|
|
||||||
- name: Check internal documentation links
|
- name: Check internal documentation links
|
||||||
run: RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc -vv --workspace --no-deps --document-private-items
|
run: RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc -vv --workspace --no-deps --document-private-items
|
||||||
@@ -127,7 +130,7 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1
|
uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
|
||||||
|
|
||||||
- name: Cargo test
|
- name: Cargo test
|
||||||
uses: actions-rs/cargo@v1.0.3
|
uses: actions-rs/cargo@v1.0.3
|
||||||
@@ -158,10 +161,35 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1
|
uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # v2.2.0
|
||||||
|
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: clippy
|
command: clippy
|
||||||
args: --all-targets -- -D warnings
|
args: --all-targets -- -D warnings
|
||||||
|
|
||||||
|
wasm_tests:
|
||||||
|
name: Test wasm
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3.1.0
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
|
|
||||||
|
- name: Download Substrate
|
||||||
|
run: |
|
||||||
|
curl $SUBSTRATE_URL --output substrate --location
|
||||||
|
chmod +x substrate
|
||||||
|
mkdir -p ~/.local/bin
|
||||||
|
mv substrate ~/.local/bin
|
||||||
|
|
||||||
|
- name: Run WASM tests
|
||||||
|
run: |
|
||||||
|
substrate --dev --tmp > /dev/null 2>&1 &
|
||||||
|
wasm-pack test --headless --firefox
|
||||||
|
wasm-pack test --headless --chrome
|
||||||
|
pkill substrate
|
||||||
|
working-directory: testing/wasm-tests
|
||||||
|
|||||||
+4
-1
@@ -9,5 +9,8 @@ members = [
|
|||||||
"testing/ui-tests",
|
"testing/ui-tests",
|
||||||
"macro",
|
"macro",
|
||||||
"metadata",
|
"metadata",
|
||||||
"subxt",
|
"subxt"
|
||||||
]
|
]
|
||||||
|
exclude = ["testing/wasm-tests"]
|
||||||
|
|
||||||
|
resolver = "2"
|
||||||
|
|||||||
+1
-1
@@ -36,6 +36,6 @@ scale = { package = "parity-scale-codec", version = "3.0.0", default-features =
|
|||||||
# generate the item mod for codegen
|
# generate the item mod for codegen
|
||||||
syn = "1.0.80"
|
syn = "1.0.80"
|
||||||
# communicate with the substrate nodes
|
# communicate with the substrate nodes
|
||||||
jsonrpsee = { version = "0.15.1", features = ["async-client", "client-ws-transport", "http-client"] }
|
jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport", "http-client"] }
|
||||||
# async runtime
|
# async runtime
|
||||||
tokio = { version = "1.8", features = ["rt-multi-thread", "macros", "time"] }
|
tokio = { version = "1.8", features = ["rt-multi-thread", "macros", "time"] }
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ quote = "1.0.8"
|
|||||||
syn = "1.0.58"
|
syn = "1.0.58"
|
||||||
scale-info = { version = "2.0.0", features = ["bit-vec"] }
|
scale-info = { version = "2.0.0", features = ["bit-vec"] }
|
||||||
subxt-metadata = { version = "0.24.0", path = "../metadata" }
|
subxt-metadata = { version = "0.24.0", path = "../metadata" }
|
||||||
jsonrpsee = { version = "0.15.1", features = ["async-client", "client-ws-transport", "http-client"] }
|
jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport", "http-client"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
tokio = { version = "1.8", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.8", features = ["macros", "rt-multi-thread"] }
|
||||||
|
|
||||||
|
|||||||
@@ -92,14 +92,13 @@ impl<'a> TypeGenerator<'a> {
|
|||||||
let mut root_mod =
|
let mut root_mod =
|
||||||
Module::new(self.types_mod_ident.clone(), self.types_mod_ident.clone());
|
Module::new(self.types_mod_ident.clone(), self.types_mod_ident.clone());
|
||||||
|
|
||||||
for (id, ty) in self.type_registry.types().iter().enumerate() {
|
for ty in self.type_registry.types().iter() {
|
||||||
if ty.ty().path().namespace().is_empty() {
|
if ty.ty().path().namespace().is_empty() {
|
||||||
// prelude types e.g. Option/Result have no namespace, so we don't generate them
|
// prelude types e.g. Option/Result have no namespace, so we don't generate them
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
self.insert_type(
|
self.insert_type(
|
||||||
ty.ty().clone(),
|
ty.ty().clone(),
|
||||||
id as u32,
|
|
||||||
ty.ty().path().namespace().to_vec(),
|
ty.ty().path().namespace().to_vec(),
|
||||||
&self.types_mod_ident,
|
&self.types_mod_ident,
|
||||||
&mut root_mod,
|
&mut root_mod,
|
||||||
@@ -112,7 +111,6 @@ impl<'a> TypeGenerator<'a> {
|
|||||||
fn insert_type(
|
fn insert_type(
|
||||||
&'a self,
|
&'a self,
|
||||||
ty: Type<PortableForm>,
|
ty: Type<PortableForm>,
|
||||||
id: u32,
|
|
||||||
path: Vec<String>,
|
path: Vec<String>,
|
||||||
root_mod_ident: &Ident,
|
root_mod_ident: &Ident,
|
||||||
module: &mut Module,
|
module: &mut Module,
|
||||||
@@ -136,7 +134,7 @@ impl<'a> TypeGenerator<'a> {
|
|||||||
TypeDefGen::from_type(ty, self, &self.crate_path),
|
TypeDefGen::from_type(ty, self, &self.crate_path),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.insert_type(ty, id, path[1..].to_vec(), root_mod_ident, child_mod)
|
self.insert_type(ty, path[1..].to_vec(), root_mod_ident, child_mod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ async fn fetch_metadata_http(url: &Uri) -> Result<String, FetchMetadataError> {
|
|||||||
.request_timeout(Duration::from_secs(180))
|
.request_timeout(Duration::from_secs(180))
|
||||||
.build(url.to_string())?;
|
.build(url.to_string())?;
|
||||||
|
|
||||||
Ok(client.request::<String>("state_getMetadata", None).await?)
|
Ok(client.request("state_getMetadata", rpc_params![]).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
println!(" account controlled by: {:?}", controller_acc);
|
println!(" account controlled by: {:?}", controller_acc);
|
||||||
|
|
||||||
let era_reward_addr = polkadot::storage().staking().eras_reward_points(&era.index);
|
let era_reward_addr = polkadot::storage().staking().eras_reward_points(era.index);
|
||||||
let era_result = api.storage().fetch(&era_reward_addr, None).await?;
|
let era_result = api.storage().fetch(&era_reward_addr, None).await?;
|
||||||
println!("Era reward points: {:?}", era_result);
|
println!("Era reward points: {:?}", era_result);
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
println!("Example 2. Obtained keys:");
|
println!("Example 2. Obtained keys:");
|
||||||
for key in keys.iter() {
|
for key in keys.iter() {
|
||||||
println!("Key: 0x{}", hex::encode(&key));
|
println!("Key: 0x{}", hex::encode(key));
|
||||||
|
|
||||||
if let Some(storage_data) = api.storage().fetch_raw(&key.0, None).await? {
|
if let Some(storage_data) = api.storage().fetch_raw(&key.0, None).await? {
|
||||||
// We know the return value to be `QueryId` (`u64`) from inspecting either:
|
// We know the return value to be `QueryId` (`u64`) from inspecting either:
|
||||||
@@ -80,7 +80,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
// We know that the first key is a u32 (the `XcmVersion`) and is hashed by twox64_concat.
|
// We know that the first key is a u32 (the `XcmVersion`) and is hashed by twox64_concat.
|
||||||
// We can build a `StorageMapKey` that replicates that, and append those bytes to the above.
|
// We can build a `StorageMapKey` that replicates that, and append those bytes to the above.
|
||||||
StorageMapKey::new(&2u32, StorageHasher::Twox64Concat).to_bytes(&mut query_key);
|
StorageMapKey::new(2u32, StorageHasher::Twox64Concat).to_bytes(&mut query_key);
|
||||||
|
|
||||||
// The final query key is essentially the result of:
|
// The final query key is essentially the result of:
|
||||||
// `twox_128("XcmPallet") ++ twox_128("VersionNotifiers") ++ twox_64(2u32) ++ 2u32`
|
// `twox_128("XcmPallet") ++ twox_128("VersionNotifiers") ++ twox_64(2u32) ++ 2u32`
|
||||||
@@ -90,7 +90,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
println!("Obtained keys:");
|
println!("Obtained keys:");
|
||||||
for key in keys.iter() {
|
for key in keys.iter() {
|
||||||
println!("Key: 0x{}", hex::encode(&key));
|
println!("Key: 0x{}", hex::encode(key));
|
||||||
|
|
||||||
if let Some(storage_data) = api.storage().fetch_raw(&key.0, None).await? {
|
if let Some(storage_data) = api.storage().fetch_raw(&key.0, None).await? {
|
||||||
// We know the return value to be `QueryId` (`u64`) from inspecting either:
|
// We know the return value to be `QueryId` (`u64`) from inspecting either:
|
||||||
|
|||||||
+9
-5
@@ -13,7 +13,7 @@ description = "Submit extrinsics (transactions) to a substrate node via RPC"
|
|||||||
keywords = ["parity", "substrate", "blockchain"]
|
keywords = ["parity", "substrate", "blockchain"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["jsonrpsee"]
|
default = ["jsonrpsee-ws"]
|
||||||
|
|
||||||
# Activate this to expose functionality only used for integration testing.
|
# Activate this to expose functionality only used for integration testing.
|
||||||
# The exposed functionality is subject to breaking changes at any point,
|
# The exposed functionality is subject to breaking changes at any point,
|
||||||
@@ -22,7 +22,8 @@ integration-tests = []
|
|||||||
|
|
||||||
# Jsonrpsee if the default RPC provider used in Subxt. However, it can be
|
# Jsonrpsee if the default RPC provider used in Subxt. However, it can be
|
||||||
# swapped out for an alternative implementation, and so is optional.
|
# swapped out for an alternative implementation, and so is optional.
|
||||||
jsonrpsee = ["dep:jsonrpsee"]
|
jsonrpsee-ws = ["jsonrpsee/async-client", "jsonrpsee/client-ws-transport"]
|
||||||
|
jsonrpsee-web = ["jsonrpsee/async-wasm-client", "jsonrpsee/client-web-transport"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
|
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
|
||||||
@@ -30,11 +31,11 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features =
|
|||||||
scale-info = { version = "2.0.0", features = ["bit-vec"] }
|
scale-info = { version = "2.0.0", features = ["bit-vec"] }
|
||||||
scale-value = "0.6.0"
|
scale-value = "0.6.0"
|
||||||
scale-decode = "0.4.0"
|
scale-decode = "0.4.0"
|
||||||
futures = "0.3.13"
|
futures = { version = "0.3.13", default-features = false }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
jsonrpsee = { version = "0.15.1", features = ["async-client", "client-ws-transport", "jsonrpsee-types"], optional = true }
|
jsonrpsee = { version = "0.16", optional = true, features = ["jsonrpsee-types"] }
|
||||||
serde = { version = "1.0.124", features = ["derive"] }
|
serde = { version = "1.0.124", features = ["derive"] }
|
||||||
serde_json = "1.0.64"
|
serde_json = { version = "1.0.64", features = ["raw_value"] }
|
||||||
thiserror = "1.0.24"
|
thiserror = "1.0.24"
|
||||||
tracing = "0.1.34"
|
tracing = "0.1.34"
|
||||||
parking_lot = "0.12.0"
|
parking_lot = "0.12.0"
|
||||||
@@ -49,5 +50,8 @@ sp-runtime = { version = "6.0.0", git = "https://github.com/paritytech/substrate
|
|||||||
frame-metadata = "15.0.0"
|
frame-metadata = "15.0.0"
|
||||||
derivative = "2.2.0"
|
derivative = "2.2.0"
|
||||||
|
|
||||||
|
[target.wasm32-unknown-unknown.dependencies]
|
||||||
|
getrandom = { version = "0.2", features = ["js"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1.8", features = ["macros", "time", "rt-multi-thread"] }
|
tokio = { version = "1.8", features = ["macros", "time", "rt-multi-thread"] }
|
||||||
|
|||||||
@@ -61,7 +61,10 @@ impl<T: Config> std::fmt::Debug for OnlineClient<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The default constructors assume Jsonrpsee.
|
// 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> {
|
impl<T: Config> OnlineClient<T> {
|
||||||
/// Construct a new [`OnlineClient`] using default settings which
|
/// Construct a new [`OnlineClient`] using default settings which
|
||||||
/// point to a locally running node on `ws://127.0.0.1:9944`.
|
/// 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.
|
/// Construct a new [`OnlineClient`], providing a URL to connect to.
|
||||||
pub async fn from_url(url: impl AsRef<str>) -> Result<OnlineClient<T>, Error> {
|
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
|
.await
|
||||||
.map_err(|e| crate::error::RpcError::ClientError(Box::new(e)))?;
|
.map_err(|e| crate::error::RpcError::ClientError(Box::new(e)))?;
|
||||||
OnlineClient::from_rpc_client(Arc::new(client)).await
|
OnlineClient::from_rpc_client(Arc::new(client)).await
|
||||||
@@ -346,7 +349,7 @@ impl Update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// helpers for a jsonrpsee specific OnlineClient.
|
// helpers for a jsonrpsee specific OnlineClient.
|
||||||
#[cfg(feature = "jsonrpsee")]
|
#[cfg(feature = "jsonrpsee-ws")]
|
||||||
mod jsonrpsee_helpers {
|
mod jsonrpsee_helpers {
|
||||||
pub use jsonrpsee::{
|
pub use jsonrpsee::{
|
||||||
client_transport::ws::{
|
client_transport::ws::{
|
||||||
@@ -366,7 +369,7 @@ mod jsonrpsee_helpers {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Build WS RPC client from URL
|
/// 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?;
|
let (sender, receiver) = ws_transport(url).await?;
|
||||||
Ok(ClientBuilder::default()
|
Ok(ClientBuilder::default()
|
||||||
.max_notifs_per_subscription(4096)
|
.max_notifs_per_subscription(4096)
|
||||||
@@ -383,3 +386,26 @@ mod jsonrpsee_helpers {
|
|||||||
.map_err(|e| Error::Transport(e.into()))
|
.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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ impl DecodeWithMetadata for DecodedValueThunk {
|
|||||||
metadata: &Metadata,
|
metadata: &Metadata,
|
||||||
) -> Result<Self::Target, Error> {
|
) -> Result<Self::Target, Error> {
|
||||||
let mut v = Vec::with_capacity(bytes.len());
|
let mut v = Vec::with_capacity(bytes.len());
|
||||||
v.extend_from_slice(*bytes);
|
v.extend_from_slice(bytes);
|
||||||
*bytes = &[];
|
*bytes = &[];
|
||||||
Ok(DecodedValueThunk {
|
Ok(DecodedValueThunk {
|
||||||
type_id,
|
type_id,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ where
|
|||||||
|
|
||||||
let event_bytes = client
|
let event_bytes = client
|
||||||
.rpc()
|
.rpc()
|
||||||
.storage(&*system_events_key().0, Some(block_hash))
|
.storage(&system_events_key().0, Some(block_hash))
|
||||||
.await?
|
.await?
|
||||||
.map(|e| e.0)
|
.map(|e| e.0)
|
||||||
.unwrap_or_else(Vec::new);
|
.unwrap_or_else(Vec::new);
|
||||||
|
|||||||
@@ -140,6 +140,13 @@ use tokio as _;
|
|||||||
|
|
||||||
pub use subxt_macro::subxt;
|
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 blocks;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
|||||||
@@ -12,18 +12,24 @@ use futures::stream::{
|
|||||||
StreamExt,
|
StreamExt,
|
||||||
TryStreamExt,
|
TryStreamExt,
|
||||||
};
|
};
|
||||||
use jsonrpsee::{
|
use jsonrpsee::core::{
|
||||||
core::client::{
|
client::{
|
||||||
Client,
|
Client,
|
||||||
ClientT,
|
ClientT,
|
||||||
SubscriptionClientT,
|
SubscriptionClientT,
|
||||||
},
|
},
|
||||||
types::ParamsSer,
|
traits::ToRpcParams,
|
||||||
};
|
Error as JsonRpseeError,
|
||||||
use serde_json::value::{
|
|
||||||
RawValue,
|
|
||||||
Value,
|
|
||||||
};
|
};
|
||||||
|
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 {
|
impl RpcClientT for Client {
|
||||||
fn request_raw<'a>(
|
fn request_raw<'a>(
|
||||||
@@ -32,8 +38,7 @@ impl RpcClientT for Client {
|
|||||||
params: Option<Box<RawValue>>,
|
params: Option<Box<RawValue>>,
|
||||||
) -> RpcFuture<'a, Box<RawValue>> {
|
) -> RpcFuture<'a, Box<RawValue>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let params = prep_params_for_jsonrpsee(params);
|
let res = ClientT::request(self, method, Params(params))
|
||||||
let res = ClientT::request(self, method, Some(params))
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| RpcError::ClientError(Box::new(e)))?;
|
.map_err(|e| RpcError::ClientError(Box::new(e)))?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
@@ -47,11 +52,10 @@ impl RpcClientT for Client {
|
|||||||
unsub: &'a str,
|
unsub: &'a str,
|
||||||
) -> RpcFuture<'a, RpcSubscription> {
|
) -> RpcFuture<'a, RpcSubscription> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let params = prep_params_for_jsonrpsee(params);
|
let sub = SubscriptionClientT::subscribe::<Box<RawValue>, _>(
|
||||||
let sub = SubscriptionClientT::subscribe::<Box<RawValue>>(
|
|
||||||
self,
|
self,
|
||||||
sub,
|
sub,
|
||||||
Some(params),
|
Params(params),
|
||||||
unsub,
|
unsub,
|
||||||
)
|
)
|
||||||
.await
|
.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(¶ms).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)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ pub fn write_storage_address_root_bytes<Address: StorageAddress>(
|
|||||||
addr: &Address,
|
addr: &Address,
|
||||||
out: &mut Vec<u8>,
|
out: &mut Vec<u8>,
|
||||||
) {
|
) {
|
||||||
out.extend(&sp_core::twox_128(addr.pallet_name().as_bytes()));
|
out.extend(sp_core::twox_128(addr.pallet_name().as_bytes()));
|
||||||
out.extend(&sp_core::twox_128(addr.entry_name().as_bytes()));
|
out.extend(sp_core::twox_128(addr.entry_name().as_bytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outputs the [`storage_address_root_bytes`] as well as any additional bytes that represent
|
/// Outputs the [`storage_address_root_bytes`] as well as any additional bytes that represent
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ impl<'a> TxPayload for DynamicTxPayload<'a> {
|
|||||||
let pallet = metadata.pallet(&self.pallet_name)?;
|
let pallet = metadata.pallet(&self.pallet_name)?;
|
||||||
let call_id = pallet.call_ty_id().ok_or(MetadataError::CallNotFound)?;
|
let call_id = pallet.call_ty_id().ok_or(MetadataError::CallNotFound)?;
|
||||||
let call_value =
|
let call_value =
|
||||||
Value::unnamed_variant(self.call_name.to_owned(), self.fields.clone());
|
Value::unnamed_variant(self.call_name.clone(), self.fields.clone());
|
||||||
|
|
||||||
pallet.index().encode_to(out);
|
pallet.index().encode_to(out);
|
||||||
scale_value::scale::encode_as_type(&call_value, call_id, metadata.types(), out)?;
|
scale_value::scale::encode_as_type(&call_value, call_id, metadata.types(), out)?;
|
||||||
|
|||||||
@@ -101,12 +101,12 @@ async fn tx_dynamic_transfer() -> Result<(), subxt::Error> {
|
|||||||
let alice_account_addr = subxt::dynamic::storage(
|
let alice_account_addr = subxt::dynamic::storage(
|
||||||
"System",
|
"System",
|
||||||
"Account",
|
"Account",
|
||||||
vec![Value::from_bytes(&alice.account_id())],
|
vec![Value::from_bytes(alice.account_id())],
|
||||||
);
|
);
|
||||||
let bob_account_addr = subxt::dynamic::storage(
|
let bob_account_addr = subxt::dynamic::storage(
|
||||||
"System",
|
"System",
|
||||||
"Account",
|
"Account",
|
||||||
vec![Value::from_bytes(&bob.account_id())],
|
vec![Value::from_bytes(bob.account_id())],
|
||||||
);
|
);
|
||||||
|
|
||||||
let alice_pre = api
|
let alice_pre = api
|
||||||
@@ -122,7 +122,7 @@ async fn tx_dynamic_transfer() -> Result<(), subxt::Error> {
|
|||||||
"Balances",
|
"Balances",
|
||||||
"transfer",
|
"transfer",
|
||||||
vec![
|
vec![
|
||||||
Value::unnamed_variant("Id", vec![Value::from_bytes(&bob.account_id())]),
|
Value::unnamed_variant("Id", vec![Value::from_bytes(bob.account_id())]),
|
||||||
Value::u128(10_000u128),
|
Value::u128(10_000u128),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -145,11 +145,11 @@ async fn tx_dynamic_transfer() -> Result<(), subxt::Error> {
|
|||||||
let expected_fields = Composite::Named(vec![
|
let expected_fields = Composite::Named(vec![
|
||||||
(
|
(
|
||||||
"from".into(),
|
"from".into(),
|
||||||
Value::unnamed_composite(vec![Value::from_bytes(&alice.account_id())]),
|
Value::unnamed_composite(vec![Value::from_bytes(alice.account_id())]),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"to".into(),
|
"to".into(),
|
||||||
Value::unnamed_composite(vec![Value::from_bytes(&bob.account_id())]),
|
Value::unnamed_composite(vec![Value::from_bytes(bob.account_id())]),
|
||||||
),
|
),
|
||||||
("amount".into(), Value::u128(10_000)),
|
("amount".into(), Value::u128(10_000)),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ async fn storage_current_era() -> Result<(), Error> {
|
|||||||
async fn storage_era_reward_points() -> Result<(), Error> {
|
async fn storage_era_reward_points() -> Result<(), Error> {
|
||||||
let ctx = test_context().await;
|
let ctx = test_context().await;
|
||||||
let api = ctx.client();
|
let api = ctx.client();
|
||||||
let reward_points_addr = node_runtime::storage().staking().eras_reward_points(&0);
|
let reward_points_addr = node_runtime::storage().staking().eras_reward_points(0);
|
||||||
let current_era_result = api.storage().fetch(&reward_points_addr, None).await;
|
let current_era_result = api.storage().fetch(&reward_points_addr, None).await;
|
||||||
assert!(current_era_result.is_ok());
|
assert!(current_era_result.is_ok());
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ async fn storage_n_mapish_key_is_properly_created() -> Result<(), subxt::Error>
|
|||||||
bytes.extend(&sp_core::twox_128("KeyOwner".as_bytes())[..]);
|
bytes.extend(&sp_core::twox_128("KeyOwner".as_bytes())[..]);
|
||||||
// twox64_concat a *tuple* of the args expected:
|
// twox64_concat a *tuple* of the args expected:
|
||||||
let suffix = (KeyTypeId([1, 2, 3, 4]), vec![5u8, 6, 7, 8]).encode();
|
let suffix = (KeyTypeId([1, 2, 3, 4]), vec![5u8, 6, 7, 8]).encode();
|
||||||
bytes.extend(&sp_core::twox_64(&suffix));
|
bytes.extend(sp_core::twox_64(&suffix));
|
||||||
bytes.extend(&suffix);
|
bytes.extend(&suffix);
|
||||||
bytes
|
bytes
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ subxt = { path = "../../subxt" }
|
|||||||
sp-core = { version = "6.0.0", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.33", package = "sp-core", default-features = false }
|
sp-core = { version = "6.0.0", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.33", package = "sp-core", default-features = false }
|
||||||
tokio = { version = "1.8", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.8", features = ["macros", "rt-multi-thread"] }
|
||||||
which = "4.2.2"
|
which = "4.2.2"
|
||||||
jsonrpsee = { version = "0.15.1", features = ["async-client", "client-ws-transport"] }
|
jsonrpsee = { version = "0.16.0", features = ["async-client", "client-ws-transport"] }
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ async fn run() {
|
|||||||
// Thus, the connection might get rejected a few times.
|
// Thus, the connection might get rejected a few times.
|
||||||
use client::ClientT;
|
use client::ClientT;
|
||||||
let res = match client::build(&format!("ws://localhost:{}", port)).await {
|
let res = match client::build(&format!("ws://localhost:{}", port)).await {
|
||||||
Ok(c) => c.request("state_getMetadata", None).await,
|
Ok(c) => c.request("state_getMetadata", client::rpc_params![]).await,
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,7 +174,10 @@ mod client {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use jsonrpsee::core::client::ClientT;
|
pub use jsonrpsee::core::{
|
||||||
|
client::ClientT,
|
||||||
|
rpc_params,
|
||||||
|
};
|
||||||
|
|
||||||
/// Build WS RPC client from URL
|
/// Build WS RPC client from URL
|
||||||
pub async fn build(url: &str) -> Result<Client, Error> {
|
pub async fn build(url: &str) -> Result<Client, Error> {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasm-test"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
wasm-bindgen-test = "0.3.24"
|
||||||
|
tracing-wasm = "0.2.1"
|
||||||
|
console_error_panic_hook = "0.1.7"
|
||||||
|
serde_json = "1.0.57"
|
||||||
|
subxt = { path = "../../subxt", default-features = false, features = ["jsonrpsee-web"] }
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#![cfg(target_arch = "wasm32")]
|
||||||
|
|
||||||
|
use subxt::config::PolkadotConfig;
|
||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
|
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
|
||||||
|
|
||||||
|
/// Run the tests by `$ wasm-pack test --firefox --headless`
|
||||||
|
|
||||||
|
fn init_tracing() {
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
tracing_wasm::set_as_global_default();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
async fn wasm_ws_transport_works() {
|
||||||
|
init_tracing();
|
||||||
|
|
||||||
|
let client =
|
||||||
|
subxt::client::OnlineClient::<PolkadotConfig>::from_url("ws://127.0.0.1:9944")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let chain = client.rpc().system_chain().await.unwrap();
|
||||||
|
assert_eq!(&chain, "Development");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user