// Copyright 2019-2021 Parity Technologies (UK) Ltd. // This file is part of Parity Bridges Common. // Parity Bridges Common 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. // Parity Bridges Common 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 Parity Bridges Common. If not, see . //! The most generic Substrate node RPC interface. use async_trait::async_trait; use crate::{Chain, ChainWithGrandpa, TransactionStatusOf}; use jsonrpsee::{ core::{client::Subscription, RpcResult}, proc_macros::rpc, ws_client::WsClient, }; use pallet_transaction_payment_rpc_runtime_api::FeeDetails; use sc_rpc_api::{state::ReadProof, system::Health}; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, }; use sp_rpc::number::NumberOrHex; use sp_version::RuntimeVersion; /// RPC methods of Substrate `system` namespace, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "system")] pub(crate) trait SubstrateSystem { /// Return node health. #[method(name = "health")] async fn health(&self) -> RpcResult; /// Return system properties. #[method(name = "properties")] async fn properties(&self) -> RpcResult; } /// RPC methods of Substrate `chain` namespace, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "chain")] pub(crate) trait SubstrateChain { /// Get block hash by its number. #[method(name = "getBlockHash")] async fn block_hash(&self, block_number: Option) -> RpcResult; /// Return block header by its hash. #[method(name = "getHeader")] async fn header(&self, block_hash: Option) -> RpcResult; /// Return best finalized block hash. #[method(name = "getFinalizedHead")] async fn finalized_head(&self) -> RpcResult; /// Return signed block (with justifications) by its hash. #[method(name = "getBlock")] async fn block(&self, block_hash: Option) -> RpcResult; } /// RPC methods of Substrate `author` namespace, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "author")] pub(crate) trait SubstrateAuthor { /// Submit extrinsic to the transaction pool. #[method(name = "submitExtrinsic")] async fn submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; /// Return vector of pending extrinsics from the transaction pool. #[method(name = "pendingExtrinsics")] async fn pending_extrinsics(&self) -> RpcResult>; /// Submit and watch for extrinsic state. #[subscription(name = "submitAndWatchExtrinsic", unsubscribe = "unwatchExtrinsic", item = TransactionStatusOf)] async fn submit_and_watch_extrinsic(&self, extrinsic: Bytes); } /// RPC methods of Substrate `state` namespace, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "state")] pub(crate) trait SubstrateState { /// Get current runtime version. #[method(name = "getRuntimeVersion")] async fn runtime_version(&self) -> RpcResult; /// Call given runtime method. #[method(name = "call")] async fn call( &self, method: String, data: Bytes, at_block: Option, ) -> RpcResult; /// Get value of the runtime storage. #[method(name = "getStorage")] async fn storage( &self, key: StorageKey, at_block: Option, ) -> RpcResult>; /// Get proof of the runtime storage value. #[method(name = "getReadProof")] async fn prove_storage( &self, keys: Vec, hash: Option, ) -> RpcResult>; } /// RPC methods that we are using for a certain finality gadget. #[async_trait] pub trait SubstrateFinalityClient { /// Subscribe to finality justifications. async fn subscribe_justifications(client: &WsClient) -> RpcResult>; } /// RPC methods of Substrate `grandpa` namespace, that we are using. #[rpc(client, client_bounds(C: ChainWithGrandpa), namespace = "grandpa")] pub(crate) trait SubstrateGrandpa { /// Subscribe to GRANDPA justifications. #[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)] async fn subscribe_justifications(&self); } /// RPC finality methods of Substrate `grandpa` namespace, that we are using. pub struct SubstrateGrandpaFinalityClient; #[async_trait] impl SubstrateFinalityClient for SubstrateGrandpaFinalityClient { async fn subscribe_justifications(client: &WsClient) -> RpcResult> { SubstrateGrandpaClient::::subscribe_justifications(client).await } } // TODO: Use `ChainWithBeefy` instead of `Chain` after #1606 is merged /// RPC methods of Substrate `beefy` namespace, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "beefy")] pub(crate) trait SubstrateBeefy { /// Subscribe to BEEFY justifications. #[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)] async fn subscribe_justifications(&self); } /// RPC finality methods of Substrate `beefy` namespace, that we are using. pub struct SubstrateBeefyFinalityClient; // TODO: Use `ChainWithBeefy` instead of `Chain` after #1606 is merged #[async_trait] impl SubstrateFinalityClient for SubstrateBeefyFinalityClient { async fn subscribe_justifications(client: &WsClient) -> RpcResult> { SubstrateBeefyClient::::subscribe_justifications(client).await } } /// RPC methods of Substrate `system` frame pallet, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "system")] pub(crate) trait SubstrateFrameSystem { /// Return index of next account transaction. #[method(name = "accountNextIndex")] async fn account_next_index(&self, account_id: C::AccountId) -> RpcResult; } /// RPC methods of Substrate `pallet_transaction_payment` frame pallet, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "payment")] pub(crate) trait SubstrateTransactionPayment { /// Query transaction fee details. #[method(name = "queryFeeDetails")] async fn fee_details( &self, extrinsic: Bytes, at_block: Option, ) -> RpcResult>; }