// Copyright 2017-2020 Parity Technologies (UK) Ltd. // This file is part of Polkadot. // Polkadot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Polkadot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . //! Polkadot Client abstractions. use std::sync::Arc; use sp_api::{ProvideRuntimeApi, CallApiAt}; use sp_blockchain::HeaderBackend; use sp_runtime::traits::{Block as BlockT, BlakeTwo256}; use sc_client_api::{Backend as BackendT, BlockchainEvents}; use polkadot_primitives::v0::{Block, ParachainHost, AccountId, Nonce, Balance}; /// A set of APIs that polkadot-like runtimes must implement. pub trait RuntimeApiCollection: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::ApiExt + babe_primitives::BabeApi + grandpa_primitives::GrandpaApi + ParachainHost + sp_block_builder::BlockBuilder + frame_system_rpc_runtime_api::AccountNonceApi + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + sp_api::Metadata + sp_offchain::OffchainWorkerApi + sp_session::SessionKeys + authority_discovery_primitives::AuthorityDiscoveryApi where >::StateBackend: sp_api::StateBackend, {} impl RuntimeApiCollection for Api where Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::ApiExt + babe_primitives::BabeApi + grandpa_primitives::GrandpaApi + ParachainHost + sp_block_builder::BlockBuilder + frame_system_rpc_runtime_api::AccountNonceApi + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + sp_api::Metadata + sp_offchain::OffchainWorkerApi + sp_session::SessionKeys + authority_discovery_primitives::AuthorityDiscoveryApi, >::StateBackend: sp_api::StateBackend, {} /// Trait that abstracts over all available client implementations. /// /// For a concrete type there exists [`Client`]. pub trait AbstractClient: BlockchainEvents + Sized + Send + Sync + ProvideRuntimeApi + HeaderBackend + CallApiAt< Block, Error = sp_blockchain::Error, StateBackend = Backend::State > where Block: BlockT, Backend: BackendT, Backend::State: sp_api::StateBackend, Self::Api: RuntimeApiCollection, {} impl AbstractClient for Client where Block: BlockT, Backend: BackendT, Backend::State: sp_api::StateBackend, Client: BlockchainEvents + ProvideRuntimeApi + HeaderBackend + Sized + Send + Sync + CallApiAt< Block, Error = sp_blockchain::Error, StateBackend = Backend::State >, Client::Api: RuntimeApiCollection, {} /// Execute something with the client instance. /// /// As there exist multiple chains inside Polkadot, like Polkadot itself, Kusama, Westend etc, /// there can exist different kinds of client types. As these client types differ in the generics /// that are being used, we can not easily return them from a function. For returning them from a /// function there exists [`Client`]. However, the problem on how to use this client instance still /// exists. This trait "solves" it in a dirty way. It requires a type to implement this trait and /// than the [`execute_with_client`](ExecuteWithClient::execute_with_client) function can be called /// with any possible client instance. /// /// In a perfect world, we could make a closure work in this way. pub trait ExecuteWithClient { /// The return type when calling this instance. type Output; /// Execute whatever should be executed with the given client instance. fn execute_with_client(self, client: Arc) -> Self::Output where >::StateBackend: sp_api::StateBackend, Backend: sc_client_api::Backend, Backend::State: sp_api::StateBackend, Api: crate::RuntimeApiCollection, Client: AbstractClient + 'static; } /// A client instance of Polkadot. /// /// See [`ExecuteWithClient`] for more information. #[derive(Clone)] pub enum Client { Polkadot(Arc>), Westend(Arc>), Kusama(Arc>), Rococo(Arc>), } impl Client { /// Execute the given something with the client. pub fn execute_with(&self, t: T) -> T::Output { match self { Self::Polkadot(client) => { T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()) }, Self::Westend(client) => { T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()) }, Self::Kusama(client) => { T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()) }, Self::Rococo(client) => { T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()) } } } }