diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 51bf1481f7fc..5c14d4e05b87 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -10,41 +10,27 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
log = "0.4.8"
-tokio = "0.1.22"
futures = { version = "0.3.1", features = ["compat"] }
futures01 = { package = "futures", version = "0.1.29" }
structopt = "=0.3.7"
-cli = { package = "sc-cli", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
+sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
service = { package = "polkadot-service", path = "../service", default-features = false }
-libp2p = { version = "0.13.1", default-features = false, optional = true }
-wasm-bindgen = { version = "0.2.55", optional = true }
-wasm-bindgen-futures = { version = "0.4.5", optional = true }
-console_log = { version = "0.1.2", optional = true }
-console_error_panic_hook = { version = "0.1.1", optional = true }
-js-sys = { version = "0.3.22", optional = true }
-kvdb-web = { version = "0.1.1", optional = true }
-substrate-service = { package = "sc-service", git = "https://github.com/paritytech/substrate", branch = "polkadot-master", optional = true, default-features = false }
-substrate-network = { package = "sc-network", git = "https://github.com/paritytech/substrate", branch = "polkadot-master", optional = true }
+tokio = { version = "0.1.22", optional = true }
-# Imported just for the `wasm-bindgen` feature
-rand = { version = "0.7", features = ["wasm-bindgen"], optional = true }
-rand6 = { package = "rand", version = "0.6.5", features = ["wasm-bindgen"], optional = true }
+wasm-bindgen = { version = "0.2.57", optional = true }
+wasm-bindgen-futures = { version = "0.4.7", optional = true }
+browser-utils = { package = "browser-utils", git = "https://github.com/paritytech/substrate", branch = "polkadot-master", optional = true }
+substrate-service = { package = "sc-service", git = "https://github.com/paritytech/substrate", branch = "polkadot-master", optional = true, default-features = false }
[features]
-default = [ "wasmtime", "rocksdb" ]
-wasmtime = [ "cli/wasmtime" ]
+default = [ "wasmtime", "rocksdb", "cli" ]
+wasmtime = [ "sc-cli/wasmtime" ]
rocksdb = [ "service/rocksdb" ]
+cli = [ "tokio" ]
browser = [
- "libp2p",
"wasm-bindgen",
- "console_error_panic_hook",
"wasm-bindgen-futures",
- "console_log",
- "js-sys",
- "kvdb-web",
+ "browser-utils",
"substrate-service",
- "substrate-network",
- "rand",
- "rand6",
]
diff --git a/cli/src/browser.rs b/cli/src/browser.rs
index 27c60a2d6cb4..32b03fcc8842 100644
--- a/cli/src/browser.rs
+++ b/cli/src/browser.rs
@@ -15,51 +15,28 @@
// along with Substrate. If not, see .
use crate::ChainSpec;
-use futures01::{prelude::*, sync::oneshot, sync::mpsc};
-use libp2p::wasm_ext;
-use log::{debug, info};
-use std::sync::Arc;
-use service::{AbstractService, Roles as ServiceRoles};
-use substrate_service::{RpcSession, Configuration, config::DatabaseConfig};
+use log::info;
+use substrate_service::Configuration;
use wasm_bindgen::prelude::*;
-use futures::{compat::*, TryFutureExt as _, TryStreamExt as _, FutureExt as _};
+use service::CustomConfiguration;
/// Starts the client.
///
/// You must pass a libp2p transport that supports .
#[wasm_bindgen]
-pub async fn start_client(wasm_ext: wasm_ext::ffi::Transport) -> Result {
+pub async fn start_client(wasm_ext: browser_utils::Transport) -> Result {
start_inner(wasm_ext)
.await
.map_err(|err| JsValue::from_str(&err.to_string()))
}
-async fn start_inner(wasm_ext: wasm_ext::ffi::Transport) -> Result> {
- console_error_panic_hook::set_once();
- console_log::init_with_level(log::Level::Info);
+async fn start_inner(wasm_ext: browser_utils::Transport) -> Result> {
+ browser_utils::set_console_error_panic_hook();
+ browser_utils::init_console_log(log::Level::Info)?;
- // Build the configuration to pass to the service.
- let config = {
- let wasm_ext = wasm_ext::ExtTransport::new(wasm_ext);
- let chain_spec = ChainSpec::Kusama.load().map_err(|e| format!("{:?}", e))?;
- let mut config = Configuration::::default_with_spec_and_base_path(chain_spec, None);
- config.network.transport = substrate_network::config::TransportConfig::Normal {
- wasm_external_transport: Some(wasm_ext.clone()),
- allow_private_ipv4: true,
- enable_mdns: false,
- };
- config.telemetry_external_transport = Some(wasm_ext);
- config.roles = ServiceRoles::LIGHT;
- config.name = "Browser node".to_string();
- config.database = {
- let db = kvdb_web::Database::open("polkadot".into(), 10)
- .await
- .unwrap();
- DatabaseConfig::Custom(Arc::new(db))
- };
- config.keystore_path = Some(std::path::PathBuf::from("/"));
- config
- };
+ let chain_spec = ChainSpec::Kusama.load().map_err(|e| format!("{:?}", e))?;
+ let config: Configuration = browser_utils::browser_configuration(wasm_ext, chain_spec)
+ .await?;
info!("Polkadot browser node");
info!(" version {}", config.full_version());
@@ -76,105 +53,7 @@ async fn start_inner(wasm_ext: wasm_ext::ffi::Transport) -> Result();
- wasm_bindgen_futures::spawn_local(futures01::future::poll_fn(move || {
- loop {
- match rpc_send_rx.poll() {
- Ok(Async::Ready(Some(message))) => {
- let fut = service.rpc_query(&message.session, &message.rpc_json);
- let _ = message.send_back.send(Box::new(fut));
- },
- Ok(Async::NotReady) => break,
- Err(_) | Ok(Async::Ready(None)) => return Ok(Async::Ready(())),
- }
- }
-
- loop {
- match service.poll().map_err(|_| ())? {
- Async::Ready(()) => return Ok(Async::Ready(())),
- Async::NotReady => break
- }
- }
-
- Ok::<_, ()>(Async::NotReady)
- }).compat().map(drop));
-
- Ok(Client {
- rpc_send_tx,
- })
-}
-
-/// A running client.
-#[wasm_bindgen]
-pub struct Client {
- rpc_send_tx: mpsc::UnboundedSender,
-}
-
-struct RpcMessage {
- rpc_json: String,
- session: RpcSession,
- send_back: oneshot::Sender, Error = ()> + Unpin>>,
-}
-
-#[wasm_bindgen]
-impl Client {
- /// Allows starting an RPC request. Returns a `Promise` containing the result of that request.
- #[wasm_bindgen(js_name = "rpcSend")]
- pub fn rpc_send(&mut self, rpc: &str) -> js_sys::Promise {
- let rpc_session = RpcSession::new(mpsc::channel(1).0);
- let (tx, rx) = oneshot::channel();
- let _ = self.rpc_send_tx.unbounded_send(RpcMessage {
- rpc_json: rpc.to_owned(),
- session: rpc_session,
- send_back: tx,
- });
- let fut = rx
- .compat()
- .map_err(|_| ())
- .and_then(|fut| fut.compat())
- .map_ok(|s| JsValue::from_str(&s.unwrap_or(String::new())))
- .map_err(|_| JsValue::NULL);
- wasm_bindgen_futures::future_to_promise(fut)
- }
-
- /// Subscribes to an RPC pubsub endpoint.
- #[wasm_bindgen(js_name = "rpcSubscribe")]
- pub fn rpc_subscribe(&mut self, rpc: &str, callback: js_sys::Function) {
- let (tx, rx) = mpsc::channel(4);
- let rpc_session = RpcSession::new(tx);
- let (fut_tx, fut_rx) = oneshot::channel();
- let _ = self.rpc_send_tx.unbounded_send(RpcMessage {
- rpc_json: rpc.to_owned(),
- session: rpc_session.clone(),
- send_back: fut_tx,
- });
- let fut_rx = fut_rx
- .compat()
- .map_err(|_| ())
- .and_then(|fut| fut.compat())
- .map(drop);
- wasm_bindgen_futures::spawn_local(fut_rx);
- wasm_bindgen_futures::spawn_local(rx
- .compat()
- .try_for_each(move |s| {
- match callback.call1(&callback, &JsValue::from_str(&s)) {
- Ok(_) => futures::future::ready(Ok(())),
- Err(_) => futures::future::ready(Err(())),
- }
- })
- .then(move |_| {
- // We need to keep `rpc_session` alive.
- debug!("RPC subscription has ended");
- drop(rpc_session);
- futures::future::ready(())
- })
- );
- }
+ Ok(browser_utils::start_client(service))
}
diff --git a/cli/src/lib.rs b/cli/src/lib.rs
index aa7ff96c743e..c8555ac8dc31 100644
--- a/cli/src/lib.rs
+++ b/cli/src/lib.rs
@@ -27,6 +27,7 @@ use chain_spec::ChainSpec;
use futures::{
Future, FutureExt, TryFutureExt, future::select, channel::oneshot, compat::Future01CompatExt,
};
+#[cfg(feature = "cli")]
use tokio::runtime::Runtime;
use log::info;
use structopt::StructOpt;
@@ -36,8 +37,8 @@ pub use service::{
WrappedExecutor
};
-pub use cli::{VersionInfo, IntoExit, NoCustom, SharedParams};
-pub use cli::{display_role, error};
+pub use sc_cli::{VersionInfo, IntoExit, NoCustom, SharedParams};
+pub use sc_cli::{display_role, error};
/// Load the `ChainSpec` for the given `id`.
pub fn load_spec(id: &str) -> Result