From 4fa4dfb77b1d44fb1283d5eb01a69d5b0ad7f7cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Silva?= <andre.beat@gmail.com>
Date: Mon, 6 Jan 2020 14:52:14 +0000
Subject: [PATCH] client: helper to create standalone client without service
 (#4536)

---
 substrate/client/service/src/builder.rs | 123 +++++++++++++++---------
 substrate/client/service/src/lib.rs     |   1 +
 2 files changed, 78 insertions(+), 46 deletions(-)

diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs
index 8e51cf18375..849203b09d1 100644
--- a/substrate/client/service/src/builder.rs
+++ b/substrate/client/service/src/builder.rs
@@ -139,6 +139,82 @@ pub type TLightCallExecutor<TBl, TExecDisp> = sc_client::light::call_executor::G
 	>,
 >;
 
+type TFullParts<TBl, TRtApi, TExecDisp> = (
+	TFullClient<TBl, TRtApi, TExecDisp>,
+	Arc<TFullBackend<TBl>>,
+	Arc<RwLock<sc_keystore::Store>>,
+);
+
+/// Creates a new full client for the given config.
+pub fn new_full_client<TBl, TRtApi, TExecDisp, TCfg, TGen, TCSExt>(
+	config: &Configuration<TCfg, TGen, TCSExt>,
+) -> Result<TFullClient<TBl, TRtApi, TExecDisp>, Error> where
+	TBl: BlockT<Hash=H256>,
+	TExecDisp: NativeExecutionDispatch,
+	TGen: sp_runtime::BuildStorage + serde::Serialize + for<'de> serde::Deserialize<'de>,
+	TCSExt: Extension,
+{
+	new_full_parts(config).map(|parts| parts.0)
+}
+
+fn new_full_parts<TBl, TRtApi, TExecDisp, TCfg, TGen, TCSExt>(
+	config: &Configuration<TCfg, TGen, TCSExt>,
+) -> Result<TFullParts<TBl, TRtApi, TExecDisp>,	Error> where
+	TBl: BlockT<Hash=H256>,
+	TExecDisp: NativeExecutionDispatch,
+	TGen: sp_runtime::BuildStorage + serde::Serialize + for<'de> serde::Deserialize<'de>,
+	TCSExt: Extension,
+{
+	let keystore = Keystore::open(
+		config.keystore_path.clone().ok_or("No basepath configured")?,
+		config.keystore_password.clone()
+	)?;
+
+	let executor = NativeExecutor::<TExecDisp>::new(
+		config.wasm_method,
+		config.default_heap_pages,
+	);
+
+	let fork_blocks = config.chain_spec
+		.extensions()
+		.get::<sc_client::ForkBlocks<TBl>>()
+		.cloned()
+		.unwrap_or_default();
+
+	let (client, backend) = {
+		let db_config = sc_client_db::DatabaseSettings {
+			state_cache_size: config.state_cache_size,
+			state_cache_child_ratio:
+			config.state_cache_child_ratio.map(|v| (v, 100)),
+			pruning: config.pruning.clone(),
+			source: match &config.database {
+				DatabaseConfig::Path { path, cache_size } =>
+					sc_client_db::DatabaseSettingsSrc::Path {
+						path: path.clone(),
+						cache_size: cache_size.clone().map(|u| u as usize),
+					},
+				DatabaseConfig::Custom(db) =>
+					sc_client_db::DatabaseSettingsSrc::Custom(db.clone()),
+			},
+		};
+
+		let extensions = sc_client_api::execution_extensions::ExecutionExtensions::new(
+			config.execution_strategies.clone(),
+			Some(keystore.clone()),
+		);
+
+		sc_client_db::new_client(
+			db_config,
+			executor,
+			&config.chain_spec,
+			fork_blocks,
+			extensions,
+		)?
+	};
+
+	Ok((client, backend, keystore))
+}
+
 impl<TCfg, TGen, TCSExt> ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), ()>
 where TGen: RuntimeGenesis, TCSExt: Extension {
 	/// Start the service builder with a configuration.
@@ -161,52 +237,7 @@ where TGen: RuntimeGenesis, TCSExt: Extension {
 		(),
 		TFullBackend<TBl>,
 	>, Error> {
-		let keystore = Keystore::open(
-			config.keystore_path.clone().ok_or("No basepath configured")?,
-			config.keystore_password.clone()
-		)?;
-
-		let executor = NativeExecutor::<TExecDisp>::new(
-			config.wasm_method,
-			config.default_heap_pages,
-		);
-
-		let fork_blocks = config.chain_spec
-			.extensions()
-			.get::<sc_client::ForkBlocks<TBl>>()
-			.cloned()
-			.unwrap_or_default();
-
-		let (client, backend) = {
-			let db_config = sc_client_db::DatabaseSettings {
-				state_cache_size: config.state_cache_size,
-				state_cache_child_ratio:
-					config.state_cache_child_ratio.map(|v| (v, 100)),
-				pruning: config.pruning.clone(),
-				source: match &config.database {
-					DatabaseConfig::Path { path, cache_size } =>
-						sc_client_db::DatabaseSettingsSrc::Path {
-							path: path.clone(),
-							cache_size: cache_size.clone().map(|u| u as usize),
-						},
-					DatabaseConfig::Custom(db) =>
-						sc_client_db::DatabaseSettingsSrc::Custom(db.clone()),
-				},
-			};
-
-			let extensions = sc_client_api::execution_extensions::ExecutionExtensions::new(
-				config.execution_strategies.clone(),
-				Some(keystore.clone()),
-			);
-
-			sc_client_db::new_client(
-				db_config,
-				executor,
-				&config.chain_spec,
-				fork_blocks,
-				extensions,
-			)?
-		};
+		let (client, backend, keystore) = new_full_parts(&config)?;
 
 		let client = Arc::new(client);
 
diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs
index 5073f09acde..dc1966f0aca 100644
--- a/substrate/client/service/src/lib.rs
+++ b/substrate/client/service/src/lib.rs
@@ -54,6 +54,7 @@ use sp_runtime::traits::{NumberFor, Block as BlockT};
 
 pub use self::error::Error;
 pub use self::builder::{
+	new_full_client,
 	ServiceBuilder, ServiceBuilderCommand, TFullClient, TLightClient, TFullBackend, TLightBackend,
 	TFullCallExecutor, TLightCallExecutor,
 };
-- 
GitLab