Files
pezkuwi-subxt/lightclient/src/client.rs
T
Alexandru Vasile 4bda673847 Add light client platform WASM compatible (#1026)
* Cargo update in prep for wasm build

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Add light client test

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Implement low level socket

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Add native platform primitives

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Add wasm platform primitives

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Implement smoldot platform

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Adjust code to use custom platform

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Adjust feature flags

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* tests: Adjust wasm endpoint to accept ws for p2p

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Adjust wasm socket

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Book mention of wasm

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Propagate env variable properly

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* subxt: Revert to native feature flags

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* cli: Use tokio rt-multi-thread feature

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* subxt: Add tokio feature flags for native platform

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm: Use polkadot live for wasm testing

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm: Add support for DNS p2p addresses

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm: Disable logs

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm: Run wasm test for firefox driver

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm: Reenable chrome driver

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Move lightclient RPC to dedicated crate for better feature flags and modularity

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Use subxt-lightclient low level RPC crate

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Apply cargo fmt

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Enable default:native feature for cargo check

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Extra step for subxt-lightclient similar to signer crate

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Remove native platform code and use smoldot instead

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* codegen: Enable tokio/multi-threads

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* lightclient: Refactor modules

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Adjust testing crates

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Run light-client WASM tests

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm-rpc: Remove light-client imports

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* testing: Update wasm cargo.lock files

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* ci: Spawn substrate node with deterministic p2p address for WASM tests

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm_socket: Use rc and refcell

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* wasm_socket: Switch back to Arc<Mutex<>>

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Add comments

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
2023-07-18 14:27:16 +03:00

115 lines
3.7 KiB
Rust

// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use super::{
background::{BackgroundTask, FromSubxt, MethodResponse},
LightClientRpcError,
};
use serde_json::value::RawValue;
use tokio::sync::{mpsc, mpsc::error::SendError, oneshot};
use super::platform::build_platform;
pub const LOG_TARGET: &str = "light-client";
/// The light-client RPC implementation that is used to connect with the chain.
#[derive(Clone)]
pub struct LightClientRpc {
/// Communicate with the backend task that multiplexes the responses
/// back to the frontend.
to_backend: mpsc::UnboundedSender<FromSubxt>,
}
impl LightClientRpc {
/// Constructs a new [`LightClientRpc`], providing the chain specification.
///
/// The chain specification can be downloaded from a trusted network via
/// the `sync_state_genSyncSpec` RPC method. This parameter expects the
/// chain spec in text format (ie not in hex-encoded scale-encoded as RPC methods
/// will provide).
///
/// ## Panics
///
/// Panics if being called outside of `tokio` runtime context.
pub fn new(
config: smoldot_light::AddChainConfig<'_, (), impl Iterator<Item = smoldot_light::ChainId>>,
) -> Result<LightClientRpc, LightClientRpcError> {
tracing::trace!(target: LOG_TARGET, "Create light client");
let mut client = smoldot_light::Client::new(build_platform());
let smoldot_light::AddChainSuccess {
chain_id,
json_rpc_responses,
} = client
.add_chain(config)
.map_err(|err| LightClientRpcError::AddChainError(err.to_string()))?;
let (to_backend, backend) = mpsc::unbounded_channel();
// `json_rpc_responses` can only be `None` if we had passed `json_rpc: Disabled`.
let rpc_responses = json_rpc_responses.expect("Light client RPC configured; qed");
let future = async move {
let mut task = BackgroundTask::new(client, chain_id);
task.start_task(backend, rpc_responses).await;
};
#[cfg(feature = "native")]
tokio::spawn(future);
#[cfg(feature = "web")]
wasm_bindgen_futures::spawn_local(future);
Ok(LightClientRpc { to_backend })
}
/// Submits an RPC method request to the light-client.
///
/// This method sends a request to the light-client to execute an RPC method with the provided parameters.
/// The parameters are parsed into a valid JSON object in the background.
pub fn method_request(
&self,
method: String,
params: String,
) -> Result<oneshot::Receiver<MethodResponse>, SendError<FromSubxt>> {
let (sender, receiver) = oneshot::channel();
self.to_backend.send(FromSubxt::Request {
method,
params,
sender,
})?;
Ok(receiver)
}
/// Makes an RPC subscription call to the light-client.
///
/// This method sends a request to the light-client to establish an RPC subscription with the provided parameters.
/// The parameters are parsed into a valid JSON object in the background.
pub fn subscription_request(
&self,
method: String,
params: String,
) -> Result<
(
oneshot::Receiver<MethodResponse>,
mpsc::UnboundedReceiver<Box<RawValue>>,
),
SendError<FromSubxt>,
> {
let (sub_id, sub_id_rx) = oneshot::channel();
let (sender, receiver) = mpsc::unbounded_channel();
self.to_backend.send(FromSubxt::Subscription {
method,
params,
sub_id,
sender,
})?;
Ok((sub_id_rx, receiver))
}
}