git.delta.rocks / unique-network / refs/commits / 5189324f5050

difftreelog

Adjust node and rpc to work with different runtimes

Daniel Shiposha2022-03-14parent: #ea9e87e.patch.diff
in: master

7 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -11942,6 +11942,7 @@
  "opal-runtime",
  "pallet-ethereum",
  "pallet-transaction-payment-rpc",
+ "pallet-transaction-payment-rpc-runtime-api",
  "parity-scale-codec",
  "parking_lot 0.11.2",
  "polkadot-cli",
@@ -11988,7 +11989,9 @@
  "substrate-prometheus-endpoint",
  "unique-rpc",
  "unique-runtime",
+ "unique-runtime-common",
  "up-data-structs",
+ "up-rpc",
 ]
 
 [[package]]
@@ -12003,12 +12006,11 @@
  "futures 0.3.21",
  "jsonrpc-core",
  "jsonrpc-pubsub",
- "opal-runtime",
+ "pallet-common",
  "pallet-ethereum",
  "pallet-transaction-payment-rpc",
  "pallet-transaction-payment-rpc-runtime-api",
  "pallet-unique",
- "quartz-runtime",
  "sc-client-api",
  "sc-consensus-aura",
  "sc-consensus-epochs",
@@ -12020,6 +12022,7 @@
  "sc-rpc-api",
  "sc-service",
  "sc-transaction-pool",
+ "serde",
  "sp-api",
  "sp-block-builder",
  "sp-blockchain",
@@ -12034,7 +12037,7 @@
  "substrate-frame-rpc-system",
  "tokio 0.2.25",
  "uc-rpc",
- "unique-runtime",
+ "unique-runtime-common",
  "up-rpc",
 ]
 
@@ -12118,10 +12121,13 @@
 name = "unique-runtime-common"
 version = "0.1.0"
 dependencies = [
+ "fp-rpc",
  "frame-support",
  "frame-system",
+ "pallet-common",
  "parity-scale-codec",
  "scale-info",
+ "sp-consensus-aura",
  "sp-core",
  "sp-runtime",
 ]
modifiednode/cli/Cargo.tomldiffbeforeafterboth
--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -238,6 +238,10 @@
 ################################################################################
 # Local dependencies
 
+[dependencies.unique-runtime-common]
+default-features = false
+path = "../../runtime/common"
+
 [dependencies.unique-runtime]
 path = '../../runtime/unique'
 optional = true
@@ -254,6 +258,13 @@
 path = "../../primitives/data-structs"
 default-features = false
 
+[dependencies.up-rpc]
+path = "../../primitives/rpc"
+
+[dependencies.pallet-transaction-payment-rpc-runtime-api]
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.17'
+
 ################################################################################
 # Package
 
@@ -295,7 +306,7 @@
 unique-rpc = { default-features = false, path = "../rpc" }
 
 [features]
-default = ["unique-runtime"]
+default = ["unique-runtime", "quartz-runtime", "opal-runtime"]
 runtime-benchmarks = [
     'unique-runtime/runtime-benchmarks',
     'polkadot-service/runtime-benchmarks',
modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -24,20 +24,33 @@
 use serde::{Deserialize, Serialize};
 use serde_json::map::Map;
 
-#[cfg(feature = "unique-runtime")]
-use unique_runtime as runtime;
+use unique_runtime_common::types::*;
 
-#[cfg(feature = "quartz-runtime")]
-use quartz_runtime as runtime;
+/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
+pub type ChainSpec = sc_service::GenericChainSpec<unique_runtime::GenesisConfig, Extensions>;
 
-#[cfg(feature = "opal-runtime")]
-use opal_runtime as runtime;
+pub trait RuntimeIdentification {
+	fn is_unique(&self) -> bool;
+
+	fn is_quartz(&self) -> bool;
 
-use runtime::{*, opaque::*};
+	fn is_opal(&self) -> bool;
+}
 
-/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
-pub type ChainSpec = sc_service::GenericChainSpec<runtime::GenesisConfig, Extensions>;
+impl RuntimeIdentification for Box<dyn sc_service::ChainSpec> {
+	fn is_unique(&self) -> bool {
+		self.id().starts_with("unique")
+	}
 
+	fn is_quartz(&self) -> bool {
+		self.id().starts_with("quartz")
+	}
+
+	fn is_opal(&self) -> bool {
+		self.id().starts_with("opal")
+	}
+}
+
 /// Helper function to generate a crypto pair from seed
 pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
 	TPublic::Pair::from_string(&format!("//{}", seed), None)
@@ -225,10 +238,12 @@
 	initial_authorities: Vec<AuraId>,
 	endowed_accounts: Vec<AccountId>,
 	id: ParaId,
-) -> GenesisConfig {
+) -> unique_runtime::GenesisConfig {
+	use unique_runtime::*;
+
 	GenesisConfig {
-		system: runtime::SystemConfig {
-			code: runtime::WASM_BINARY
+		system: SystemConfig {
+			code: WASM_BINARY
 				.expect("WASM binary was not build, please build it!")
 				.to_vec(),
 		},
@@ -245,9 +260,9 @@
 			key: Some(root_key),
 		},
 		vesting: VestingConfig { vesting: vec![] },
-		parachain_info: runtime::ParachainInfoConfig { parachain_id: id },
+		parachain_info: ParachainInfoConfig { parachain_id: id },
 		parachain_system: Default::default(),
-		aura: runtime::AuraConfig {
+		aura: AuraConfig {
 			authorities: initial_authorities,
 		},
 		aura_ext: Default::default(),
modifiednode/cli/src/command.rsdiffbeforeafterboth
before · node/cli/src/command.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license18// This file is part of Substrate.1920// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd.21// SPDX-License-Identifier: Apache-2.02223// Licensed under the Apache License, Version 2.0 (the "License");24// you may not use this file except in compliance with the License.25// You may obtain a copy of the License at26//27// 	http://www.apache.org/licenses/LICENSE-2.028//29// Unless required by applicable law or agreed to in writing, software30// distributed under the License is distributed on an "AS IS" BASIS,31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.32// See the License for the specific language governing permissions and33// limitations under the License.3435use crate::{36	chain_spec,37	cli::{Cli, RelayChainCli, Subcommand},38	service::{new_partial, ParachainRuntimeExecutor},39};40use codec::Encode;41use cumulus_primitives_core::ParaId;42use cumulus_client_service::genesis::generate_genesis_block;43use log::info;44use polkadot_parachain::primitives::AccountIdConversion;45use sc_cli::{46	ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,47	NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli,48};49use sc_service::{50	config::{BasePath, PrometheusConfig},51};52use sp_core::hexdisplay::HexDisplay;53use sp_runtime::traits::Block as BlockT;54use std::{io::Write, net::SocketAddr};5556#[cfg(feature = "unique-runtime")]57use unique_runtime as runtime;5859#[cfg(feature = "quartz-runtime")]60use quartz_runtime as runtime;6162#[cfg(feature = "opal-runtime")]63use opal_runtime as runtime;6465use runtime::Block;6667fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {68	Ok(match id {69		"westend-local" => Box::new(chain_spec::local_testnet_westend_config()),70		"rococo-local" => Box::new(chain_spec::local_testnet_rococo_config()),71		"dev" => Box::new(chain_spec::development_config()),72		"" | "local" => Box::new(chain_spec::local_testnet_rococo_config()),73		path => Box::new(chain_spec::ChainSpec::from_json_file(74			std::path::PathBuf::from(path),75		)?),76	})77}7879impl SubstrateCli for Cli {80	// TODO use args81	fn impl_name() -> String {82		format!("{} Node", runtime::RUNTIME_NAME)83	}8485	fn impl_version() -> String {86		env!("SUBSTRATE_CLI_IMPL_VERSION").into()87	}88	// TODO use args89	fn description() -> String {90		format!(91			"{} Node\n\nThe command-line arguments provided first will be \92		passed to the parachain node, while the arguments provided after -- will be passed \93		to the relaychain node.\n\n\94		{} [parachain-args] -- [relaychain-args]",95			runtime::RUNTIME_NAME,96			Self::executable_name()97		)98	}99100	fn author() -> String {101		env!("CARGO_PKG_AUTHORS").into()102	}103104	//TODO use args105	fn support_url() -> String {106		"support@unique.network".into()107	}108109	fn copyright_start_year() -> i32 {110		2019111	}112113	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {114		load_spec(id)115	}116117	fn native_runtime_version(_: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {118		&runtime::VERSION119	}120}121122impl SubstrateCli for RelayChainCli {123	// TODO use args124	fn impl_name() -> String {125		format!("{} Node", runtime::RUNTIME_NAME)126	}127128	fn impl_version() -> String {129		env!("SUBSTRATE_CLI_IMPL_VERSION").into()130	}131	// TODO use args132	fn description() -> String {133		format!(134			"{} Node\n\nThe command-line arguments provided first will be \135		passed to the parachain node, while the arguments provided after -- will be passed \136		to the relaychain node.\n\n\137		parachain-collator [parachain-args] -- [relaychain-args]",138			runtime::RUNTIME_NAME139		)140	}141142	fn author() -> String {143		env!("CARGO_PKG_AUTHORS").into()144	}145	// TODO use args146	fn support_url() -> String {147		"support@unique.network".into()148	}149150	fn copyright_start_year() -> i32 {151		2019152	}153154	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {155		polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id)156	}157158	fn native_runtime_version(chain_spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {159		polkadot_cli::Cli::native_runtime_version(chain_spec)160	}161}162163#[allow(clippy::borrowed_box)]164fn extract_genesis_wasm(chain_spec: &Box<dyn sc_service::ChainSpec>) -> Result<Vec<u8>> {165	let mut storage = chain_spec.build_storage()?;166167	storage168		.top169		.remove(sp_core::storage::well_known_keys::CODE)170		.ok_or_else(|| "Could not find wasm file in genesis state!".into())171}172173macro_rules! construct_async_run {174	(|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{175		let runner = $cli.create_runner($cmd)?;176		runner.async_run(|$config| {177			let $components = new_partial::<178				_179			>(180				&$config,181				crate::service::parachain_build_import_queue,182			)?;183			let task_manager = $components.task_manager;184			{ $( $code )* }.map(|v| (v, task_manager))185		})186	}}187}188189/// Parse command line arguments into service configuration.190pub fn run() -> Result<()> {191	let cli = Cli::from_args();192193	match &cli.subcommand {194		Some(Subcommand::BuildSpec(cmd)) => {195			let runner = cli.create_runner(cmd)?;196			runner.sync_run(|config| cmd.run(config.chain_spec, config.network))197		}198		Some(Subcommand::CheckBlock(cmd)) => {199			construct_async_run!(|components, cli, cmd, config| {200				Ok(cmd.run(components.client, components.import_queue))201			})202		}203		Some(Subcommand::ExportBlocks(cmd)) => {204			construct_async_run!(|components, cli, cmd, config| {205				Ok(cmd.run(components.client, config.database))206			})207		}208		Some(Subcommand::ExportState(cmd)) => {209			construct_async_run!(|components, cli, cmd, config| {210				Ok(cmd.run(components.client, config.chain_spec))211			})212		}213		Some(Subcommand::ImportBlocks(cmd)) => {214			construct_async_run!(|components, cli, cmd, config| {215				Ok(cmd.run(components.client, components.import_queue))216			})217		}218		Some(Subcommand::PurgeChain(cmd)) => {219			let runner = cli.create_runner(cmd)?;220221			runner.sync_run(|config| {222				let polkadot_cli = RelayChainCli::new(223					&config,224					[RelayChainCli::executable_name()]225						.iter()226						.chain(cli.relaychain_args.iter()),227				);228229				let polkadot_config = SubstrateCli::create_configuration(230					&polkadot_cli,231					&polkadot_cli,232					config.tokio_handle.clone(),233				)234				.map_err(|err| format!("Relay chain argument error: {}", err))?;235236				cmd.run(config, polkadot_config)237			})238		}239		Some(Subcommand::Revert(cmd)) => construct_async_run!(|components, cli, cmd, config| {240			Ok(cmd.run(components.client, components.backend))241		}),242		Some(Subcommand::ExportGenesisState(params)) => {243			let mut builder = sc_cli::LoggerBuilder::new("");244			builder.with_profiling(sc_tracing::TracingReceiver::Log, "");245			let _ = builder.init();246247			let spec = load_spec(&params.chain.clone().unwrap_or_default())?;248			let state_version = Cli::native_runtime_version(&spec).state_version();249			let block: Block = generate_genesis_block(&spec, state_version)?;250			let raw_header = block.header().encode();251			let output_buf = if params.raw {252				raw_header253			} else {254				format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes()255			};256257			if let Some(output) = &params.output {258				std::fs::write(output, output_buf)?;259			} else {260				std::io::stdout().write_all(&output_buf)?;261			}262263			Ok(())264		}265		Some(Subcommand::ExportGenesisWasm(params)) => {266			let mut builder = sc_cli::LoggerBuilder::new("");267			builder.with_profiling(sc_tracing::TracingReceiver::Log, "");268			let _ = builder.init();269270			let raw_wasm_blob =271				extract_genesis_wasm(&cli.load_spec(&params.chain.clone().unwrap_or_default())?)?;272			let output_buf = if params.raw {273				raw_wasm_blob274			} else {275				format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes()276			};277278			if let Some(output) = &params.output {279				std::fs::write(output, output_buf)?;280			} else {281				std::io::stdout().write_all(&output_buf)?;282			}283284			Ok(())285		}286		Some(Subcommand::Benchmark(cmd)) => {287			if cfg!(feature = "runtime-benchmarks") {288				let runner = cli.create_runner(cmd)?;289290				runner.sync_run(|config| cmd.run::<Block, ParachainRuntimeExecutor>(config))291			} else {292				Err("Benchmarking wasn't enabled when building the node. \293				You can enable it with `--features runtime-benchmarks`."294					.into())295			}296		}297		None => {298			let runner = cli.create_runner(&cli.run.normalize())?;299300			runner.run_node_until_exit(|config| async move {301				let para_id = chain_spec::Extensions::try_get(&*config.chain_spec)302					.map(|e| e.para_id)303					.ok_or("Could not find parachain ID in chain-spec.")?;304305				let polkadot_cli = RelayChainCli::new(306					&config,307					[RelayChainCli::executable_name()]308						.iter()309						.chain(cli.relaychain_args.iter()),310				);311312				let id = ParaId::from(para_id);313314				let parachain_account =315					AccountIdConversion::<polkadot_primitives::v0::AccountId>::into_account(&id);316317				let state_version =318					RelayChainCli::native_runtime_version(&config.chain_spec).state_version();319				let block: Block = generate_genesis_block(&config.chain_spec, state_version)320					.map_err(|e| format!("{:?}", e))?;321				let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode()));322				let genesis_hash = format!("0x{:?}", HexDisplay::from(&block.header().hash().0));323324				let polkadot_config = SubstrateCli::create_configuration(325					&polkadot_cli,326					&polkadot_cli,327					config.tokio_handle.clone(),328				)329				.map_err(|err| format!("Relay chain argument error: {}", err))?;330331				info!("Parachain id: {:?}", id);332				info!("Parachain Account: {}", parachain_account);333				info!("Parachain genesis state: {}", genesis_state);334				info!("Parachain genesis hash: {}", genesis_hash);335				info!(336					"Is collating: {}",337					if config.role.is_authority() {338						"yes"339					} else {340						"no"341					}342				);343344				crate::service::start_node(config, polkadot_config, id)345					.await346					.map(|r| r.0)347					.map_err(Into::into)348			})349		}350	}351}352353impl DefaultConfigurationValues for RelayChainCli {354	fn p2p_listen_port() -> u16 {355		30334356	}357358	fn rpc_ws_listen_port() -> u16 {359		9945360	}361362	fn rpc_http_listen_port() -> u16 {363		9934364	}365366	fn prometheus_listen_port() -> u16 {367		9616368	}369}370371impl CliConfiguration<Self> for RelayChainCli {372	fn shared_params(&self) -> &SharedParams {373		self.base.base.shared_params()374	}375376	fn import_params(&self) -> Option<&ImportParams> {377		self.base.base.import_params()378	}379380	fn network_params(&self) -> Option<&NetworkParams> {381		self.base.base.network_params()382	}383384	fn keystore_params(&self) -> Option<&KeystoreParams> {385		self.base.base.keystore_params()386	}387388	fn base_path(&self) -> Result<Option<BasePath>> {389		Ok(self390			.shared_params()391			.base_path()392			.or_else(|| self.base_path.clone().map(Into::into)))393	}394395	fn rpc_http(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {396		self.base.base.rpc_http(default_listen_port)397	}398399	fn rpc_ipc(&self) -> Result<Option<String>> {400		self.base.base.rpc_ipc()401	}402403	fn rpc_ws(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {404		self.base.base.rpc_ws(default_listen_port)405	}406407	fn prometheus_config(408		&self,409		default_listen_port: u16,410		chain_spec: &Box<dyn ChainSpec>,411	) -> Result<Option<PrometheusConfig>> {412		self.base413			.base414			.prometheus_config(default_listen_port, chain_spec)415	}416417	fn init<F>(418		&self,419		_support_url: &String,420		_impl_version: &String,421		_logger_hook: F,422		_config: &sc_service::Configuration,423	) -> Result<()> {424		unreachable!("PolkadotCli is never initialized; qed");425	}426427	fn chain_id(&self, is_dev: bool) -> Result<String> {428		let chain_id = self.base.base.chain_id(is_dev)?;429430		Ok(if chain_id.is_empty() {431			self.chain_id.clone().unwrap_or_default()432		} else {433			chain_id434		})435	}436437	fn role(&self, is_dev: bool) -> Result<sc_service::Role> {438		self.base.base.role(is_dev)439	}440441	fn transaction_pool(&self) -> Result<sc_service::config::TransactionPoolOptions> {442		self.base.base.transaction_pool()443	}444445	fn state_cache_child_ratio(&self) -> Result<Option<usize>> {446		self.base.base.state_cache_child_ratio()447	}448449	fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {450		self.base.base.rpc_methods()451	}452453	fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {454		self.base.base.rpc_ws_max_connections()455	}456457	fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {458		self.base.base.rpc_cors(is_dev)459	}460461	fn default_heap_pages(&self) -> Result<Option<u64>> {462		self.base.base.default_heap_pages()463	}464465	fn force_authoring(&self) -> Result<bool> {466		self.base.base.force_authoring()467	}468469	fn disable_grandpa(&self) -> Result<bool> {470		self.base.base.disable_grandpa()471	}472473	fn max_runtime_instances(&self) -> Result<Option<usize>> {474		self.base.base.max_runtime_instances()475	}476477	fn announce_block(&self) -> Result<bool> {478		self.base.base.announce_block()479	}480481	fn telemetry_endpoints(482		&self,483		chain_spec: &Box<dyn ChainSpec>,484	) -> Result<Option<sc_telemetry::TelemetryEndpoints>> {485		self.base.base.telemetry_endpoints(chain_spec)486	}487}
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -25,17 +25,8 @@
 use futures::StreamExt;
 
 use unique_rpc::overrides_handle;
-// Local Runtime Types
-#[cfg(feature = "unique-runtime")]
-use unique_runtime as runtime;
-
-#[cfg(feature = "quartz-runtime")]
-use quartz_runtime as runtime;
 
-#[cfg(feature = "opal-runtime")]
-use opal_runtime as runtime;
-
-use runtime::RuntimeApi;
+use serde::{Serialize, Deserialize};
 
 // Cumulus Imports
 use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion};
@@ -71,18 +62,46 @@
 pub type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
 type Hash = sp_core::H256;
 
+use unique_runtime_common::types::{AuraId, RuntimeInstance, AccountId, Balance, Index};
+
 /// Native executor instance.
-pub struct ParachainRuntimeExecutor;
+pub struct UniqueRuntimeExecutor;
+pub struct QuartzRuntimeExecutor;
+pub struct OpalRuntimeExecutor;
+
+impl NativeExecutionDispatch for UniqueRuntimeExecutor {
+	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
+
+	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
+		unique_runtime::api::dispatch(method, data)
+	}
+
+	fn native_version() -> sc_executor::NativeVersion {
+		unique_runtime::native_version()
+	}
+}
+
+impl NativeExecutionDispatch for QuartzRuntimeExecutor {
+	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
 
-impl NativeExecutionDispatch for ParachainRuntimeExecutor {
+	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
+		unique_runtime::api::dispatch(method, data)
+	}
+
+	fn native_version() -> sc_executor::NativeVersion {
+		unique_runtime::native_version()
+	}
+}
+
+impl NativeExecutionDispatch for OpalRuntimeExecutor {
 	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
 
 	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-		runtime::api::dispatch(method, data)
+		unique_runtime::api::dispatch(method, data)
 	}
 
 	fn native_version() -> sc_executor::NativeVersion {
-		runtime::native_version()
+		unique_runtime::native_version()
 	}
 }
 
@@ -106,9 +125,7 @@
 	)?))
 }
 
-type ExecutorDispatch = ParachainRuntimeExecutor;
-
-type FullClient =
+type FullClient<RuntimeApi, ExecutorDispatch> =
 	sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;
 type FullBackend = sc_service::TFullBackend<Block>;
 type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
@@ -118,16 +135,16 @@
 /// Use this macro if you don't actually need the full service, but just the builder in order to
 /// be able to perform chain operations.
 #[allow(clippy::type_complexity)]
-pub fn new_partial<BIQ>(
+pub fn new_partial<RuntimeApi, ExecutorDispatch, BIQ>(
 	config: &Configuration,
 	build_import_queue: BIQ,
 ) -> Result<
 	PartialComponents<
-		FullClient,
+		FullClient<RuntimeApi, ExecutorDispatch>,
 		FullBackend,
 		FullSelectChain,
-		sc_consensus::DefaultImportQueue<Block, FullClient>,
-		sc_transaction_pool::FullPool<Block, FullClient>,
+		sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,
+		sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,
 		(
 			Option<Telemetry>,
 			Option<FilterPool>,
@@ -140,13 +157,21 @@
 >
 where
 	sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,
+	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
+		+ Send
+		+ Sync
+		+ 'static,
+	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,
 	ExecutorDispatch: NativeExecutionDispatch + 'static,
 	BIQ: FnOnce(
-		Arc<FullClient>,
+		Arc<FullClient<RuntimeApi, ExecutorDispatch>>,
 		&Configuration,
 		Option<TelemetryHandle>,
 		&TaskManager,
-	) -> Result<sc_consensus::DefaultImportQueue<Block, FullClient>, sc_service::Error>,
+	) -> Result<
+		sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,
+		sc_service::Error,
+	>,
 {
 	let _telemetry = config
 		.telemetry_endpoints
@@ -240,29 +265,50 @@
 ///
 /// This is the actual implementation that is abstract over the executor and the runtime api.
 #[sc_tracing::logging::prefix_logs_with("Parachain")]
-async fn start_node_impl<BIQ, BIC>(
+async fn start_node_impl<Runtime, RuntimeApi, ExecutorDispatch, BIQ, BIC>(
 	parachain_config: Configuration,
 	polkadot_config: Configuration,
 	id: ParaId,
 	build_import_queue: BIQ,
 	build_consensus: BIC,
-) -> sc_service::error::Result<(TaskManager, Arc<FullClient>)>
+) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>
 where
 	sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,
+	Runtime: RuntimeInstance + Send + Sync + 'static,
+	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,
+	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,
+	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
+		+ Send
+		+ Sync
+		+ 'static,
+	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+		+ fp_rpc::EthereumRuntimeRPCApi<Block>
+		+ sp_session::SessionKeys<Block>
+		+ sp_block_builder::BlockBuilder<Block>
+		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
+		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+		+ sp_api::Metadata<Block>
+		+ sp_offchain::OffchainWorkerApi<Block>
+		+ cumulus_primitives_core::CollectCollationInfo<Block>,
 	ExecutorDispatch: NativeExecutionDispatch + 'static,
 	BIQ: FnOnce(
-		Arc<FullClient>,
+		Arc<FullClient<RuntimeApi, ExecutorDispatch>>,
 		&Configuration,
 		Option<TelemetryHandle>,
 		&TaskManager,
-	) -> Result<sc_consensus::DefaultImportQueue<Block, FullClient>, sc_service::Error>,
+	) -> Result<
+		sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,
+		sc_service::Error,
+	>,
 	BIC: FnOnce(
-		Arc<FullClient>,
+		Arc<FullClient<RuntimeApi, ExecutorDispatch>>,
 		Option<&Registry>,
 		Option<TelemetryHandle>,
 		&TaskManager,
 		Arc<dyn RelayChainInterface>,
-		Arc<sc_transaction_pool::FullPool<Block, FullClient>>,
+		Arc<sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>>,
 		Arc<NetworkService<Block, Hash>>,
 		SyncCryptoStorePtr,
 		bool,
@@ -274,7 +320,8 @@
 
 	let parachain_config = prepare_node_config(parachain_config);
 
-	let params = new_partial::<BIQ>(&parachain_config, build_import_queue)?;
+	let params =
+		new_partial::<RuntimeApi, ExecutorDispatch, BIQ>(&parachain_config, build_import_queue)?;
 	let (mut telemetry, filter_pool, frontier_backend, telemetry_worker_handle, fee_history_cache) =
 		params.other;
 
@@ -320,7 +367,7 @@
 
 	let block_data_cache = Arc::new(fc_rpc::EthBlockDataCache::new(
 		task_manager.spawn_handle(),
-		overrides_handle(client.clone()),
+		overrides_handle::<_, _, Runtime>(client.clone()),
 		50,
 		50,
 	));
@@ -346,10 +393,12 @@
 			fee_history_limit: 2048,
 		};
 
-		Ok(unique_rpc::create_full::<_, _, _, _, RuntimeApi, _>(
-			full_deps,
-			subscription_executor.clone(),
-		))
+		Ok(
+			unique_rpc::create_full::<_, _, _, _, Runtime, RuntimeApi, _>(
+				full_deps,
+				subscription_executor.clone(),
+			),
+		)
 	});
 
 	task_manager.spawn_essential_handle().spawn(
@@ -436,12 +485,26 @@
 }
 
 /// Build the import queue for the the parachain runtime.
-pub fn parachain_build_import_queue(
-	client: Arc<FullClient>,
+pub fn parachain_build_import_queue<RuntimeApi, ExecutorDispatch>(
+	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,
 	config: &Configuration,
 	telemetry: Option<TelemetryHandle>,
 	task_manager: &TaskManager,
-) -> Result<sc_consensus::DefaultImportQueue<Block, FullClient>, sc_service::Error> {
+) -> Result<
+	sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,
+	sc_service::Error,
+>
+where
+	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
+		+ Send
+		+ Sync
+		+ 'static,
+	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+		+ sp_block_builder::BlockBuilder<Block>
+		+ sp_consensus_aura::AuraApi<Block, AuraId>
+		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
+	ExecutorDispatch: NativeExecutionDispatch + 'static,
+{
 	let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;
 
 	cumulus_client_consensus_aura::import_queue::<
@@ -475,12 +538,34 @@
 }
 
 /// Start a normal parachain node.
-pub async fn start_node(
+pub async fn start_node<Runtime, RuntimeApi, ExecutorDispatch>(
 	parachain_config: Configuration,
 	polkadot_config: Configuration,
 	id: ParaId,
-) -> sc_service::error::Result<(TaskManager, Arc<FullClient>)> {
-	start_node_impl::<_, _>(
+) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>
+where
+	Runtime: RuntimeInstance + Send + Sync + 'static,
+	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,
+	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,
+	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
+		+ Send
+		+ Sync
+		+ 'static,
+	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+		+ fp_rpc::EthereumRuntimeRPCApi<Block>
+		+ sp_session::SessionKeys<Block>
+		+ sp_block_builder::BlockBuilder<Block>
+		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
+		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
+		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+		+ sp_api::Metadata<Block>
+		+ sp_offchain::OffchainWorkerApi<Block>
+		+ cumulus_primitives_core::CollectCollationInfo<Block>
+		+ sp_consensus_aura::AuraApi<Block, AuraId>,
+	ExecutorDispatch: NativeExecutionDispatch + 'static,
+{
+	start_node_impl::<Runtime, RuntimeApi, ExecutorDispatch, _, _>(
 		parachain_config,
 		polkadot_config,
 		id,
modifiednode/rpc/Cargo.tomldiffbeforeafterboth
--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -48,13 +48,16 @@
 fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.17" }
 fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.17" }
 
+pallet-common = { default-features = false, path = "../../pallets/common" }
+unique-runtime-common = { default-features = false, path = "../../runtime/common" }
 pallet-unique = { path = "../../pallets/unique" }
 uc-rpc = { path = "../../client/rpc" }
 up-rpc = { path = "../../primitives/rpc" }
-unique-runtime = { path = "../../runtime/unique", optional = true }
-quartz-runtime = { path = "../../runtime/quartz", optional = true }
-opal-runtime = { path = "../../runtime/opal", optional = true }
 
+[dependencies.serde]
+features = ['derive']
+version = '1.0.130'
+
 [features]
-default = ["unique-runtime"]
+default = []
 std = []
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -40,16 +40,9 @@
 use sc_service::TransactionPool;
 use std::{collections::BTreeMap, marker::PhantomData, sync::Arc};
 
-#[cfg(feature = "unique-runtime")]
-use unique_runtime as runtime;
-
-#[cfg(feature = "quartz-runtime")]
-use quartz_runtime as runtime;
-
-#[cfg(feature = "opal-runtime")]
-use opal_runtime as runtime;
-
-use runtime::opaque::{Hash, AccountId, CrossAccountId, Index, Block, BlockNumber, Balance};
+use unique_runtime_common::types::{
+	Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance,
+};
 
 /// Public io handler for exporting into other modules
 pub type IoHandler = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
@@ -100,29 +93,33 @@
 	pub block_data_cache: Arc<EthBlockDataCache<Block>>,
 }
 
-struct AccountCodes<C, B> {
+struct AccountCodes<C, B, R> {
 	client: Arc<C>,
-	_marker: PhantomData<B>,
+	_blk_marker: PhantomData<B>,
+	_runtime_marker: PhantomData<R>,
 }
 
-impl<C, Block> AccountCodes<C, Block>
+impl<C, Block, R> AccountCodes<C, Block, R>
 where
 	Block: sp_api::BlockT,
 	C: ProvideRuntimeApi<Block>,
+	R: RuntimeInstance,
 {
 	fn new(client: Arc<C>) -> Self {
 		Self {
 			client,
-			_marker: PhantomData,
+			_blk_marker: PhantomData,
+			_runtime_marker: PhantomData,
 		}
 	}
 }
 
-impl<C, Block> fc_rpc::AccountCodeProvider<Block> for AccountCodes<C, Block>
+impl<C, Block, Runtime> fc_rpc::AccountCodeProvider<Block> for AccountCodes<C, Block, Runtime>
 where
 	Block: sp_api::BlockT,
 	C: ProvideRuntimeApi<Block>,
-	C::Api: up_rpc::UniqueApi<Block, CrossAccountId, AccountId>,
+	C::Api: up_rpc::UniqueApi<Block, <Runtime as RuntimeInstance>::CrossAccountId, AccountId>,
+	Runtime: RuntimeInstance,
 {
 	fn code(&self, block: &sp_api::BlockId<Block>, account: sp_core::H160) -> Option<Vec<u8>> {
 		use up_rpc::UniqueApi;
@@ -134,22 +131,23 @@
 	}
 }
 
-pub fn overrides_handle<C, BE>(client: Arc<C>) -> Arc<OverrideHandle<Block>>
+pub fn overrides_handle<C, BE, R>(client: Arc<C>) -> Arc<OverrideHandle<Block>>
 where
 	C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,
 	C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,
 	C: Send + Sync + 'static,
 	C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
-	C::Api: up_rpc::UniqueApi<Block, CrossAccountId, AccountId>,
+	C::Api: up_rpc::UniqueApi<Block, <R as RuntimeInstance>::CrossAccountId, AccountId>,
 	BE: Backend<Block> + 'static,
 	BE::State: StateBackend<BlakeTwo256>,
+	R: RuntimeInstance + Send + Sync + 'static,
 {
 	let mut overrides_map = BTreeMap::new();
 	overrides_map.insert(
 		EthereumStorageSchema::V1,
 		Box::new(SchemaV1Override::new_with_code_provider(
 			client.clone(),
-			Arc::new(AccountCodes::<C, Block>::new(client.clone())),
+			Arc::new(AccountCodes::<C, Block, R>::new(client.clone())),
 		)) as Box<dyn StorageOverride<_> + Send + Sync>,
 	);
 	overrides_map.insert(
@@ -170,7 +168,7 @@
 }
 
 /// Instantiate all Full RPC extensions.
-pub fn create_full<C, P, SC, CA, A, B>(
+pub fn create_full<C, P, SC, CA, R, A, B>(
 	deps: FullDeps<C, P, SC, CA>,
 	subscription_task_executor: SubscriptionTaskExecutor,
 ) -> jsonrpc_core::IoHandler<sc_rpc_api::Metadata>
@@ -184,11 +182,14 @@
 	// C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
 	C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
 	C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
-	C::Api: up_rpc::UniqueApi<Block, CrossAccountId, AccountId>,
+	C::Api: up_rpc::UniqueApi<Block, <R as RuntimeInstance>::CrossAccountId, AccountId>,
 	B: sc_client_api::Backend<Block> + Send + Sync + 'static,
 	B::State: sc_client_api::backend::StateBackend<sp_runtime::traits::HashFor<Block>>,
 	P: TransactionPool<Block = Block> + 'static,
 	CA: ChainApi<Block = Block> + 'static,
+	R: RuntimeInstance + Send + Sync + 'static,
+	<R as RuntimeInstance>::CrossAccountId: serde::Serialize,
+	for<'de> <R as RuntimeInstance>::CrossAccountId: serde::Deserialize<'de>,
 {
 	use fc_rpc::{
 		EthApi, EthApiServer, EthDevSigner, EthFilterApi, EthFilterApiServer, EthPubSubApi,
@@ -235,13 +236,13 @@
 		signers.push(Box::new(EthDevSigner::new()) as Box<dyn EthSigner>);
 	}
 
-	let overrides = overrides_handle(client.clone());
+	let overrides = overrides_handle::<_, _, R>(client.clone());
 
 	io.extend_with(EthApiServer::to_delegate(EthApi::new(
 		client.clone(),
 		pool.clone(),
 		graph,
-		runtime::TransactionConverter,
+		<R as RuntimeInstance>::get_transaction_converter(),
 		network.clone(),
 		signers,
 		overrides.clone(),