mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 10:27:59 +00:00
4210d014ec
* staking miner: use config for emergency solution Fixes #4678 * bump jsonrpsee * run `monitor_cmd_for` until the connection is closed * new tokio task for submit_and_watch xt * re-use header subscription * update jsonrpsee + simplify code * revert polkadot runtime changes * fix grumbles * Update utils/staking-miner/src/monitor.rs * staking miner: reuse ws conn for remote-ext * Revert "revert polkadot runtime changes" This reverts commit 5fddbbec40702c122b079526915cabac8facdbc1. * cargo fmt * revert unintentional change * revert unintentional change * add type SharedRpcClient * cargo fmt * fix nits * spelling * use tracing_subcriber and cleanup * remove some needless clones * fix some nits * fix spellcheck
167 lines
5.1 KiB
Rust
167 lines
5.1 KiB
Rust
// Copyright 2021 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 <http://www.gnu.org/licenses/>.
|
|
|
|
//! JSON-RPC related types and helpers.
|
|
|
|
use super::*;
|
|
use jsonrpsee::{
|
|
core::{Error as RpcError, RpcResult},
|
|
proc_macros::rpc,
|
|
};
|
|
use pallet_transaction_payment::RuntimeDispatchInfo;
|
|
use sc_transaction_pool_api::TransactionStatus;
|
|
use sp_core::{storage::StorageKey, Bytes};
|
|
use sp_version::RuntimeVersion;
|
|
use std::{future::Future, time::Duration};
|
|
|
|
const MAX_CONNECTION_DURATION: Duration = Duration::from_secs(20);
|
|
const MAX_REQUEST_DURATION: Duration = Duration::from_secs(60);
|
|
|
|
#[derive(frame_support::DebugNoBound, thiserror::Error)]
|
|
pub(crate) enum RpcHelperError {
|
|
JsonRpsee(#[from] jsonrpsee::core::Error),
|
|
Codec(#[from] codec::Error),
|
|
}
|
|
|
|
impl std::fmt::Display for RpcHelperError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
<RpcHelperError as std::fmt::Debug>::fmt(self, f)
|
|
}
|
|
}
|
|
|
|
#[rpc(client)]
|
|
pub trait RpcApi {
|
|
/// Fetch system name.
|
|
#[method(name = "system_chain")]
|
|
async fn system_chain(&self) -> RpcResult<String>;
|
|
|
|
/// Fetch a storage key.
|
|
#[method(name = "state_getStorage")]
|
|
async fn storage(&self, key: &StorageKey, hash: Option<Hash>) -> RpcResult<Option<Bytes>>;
|
|
|
|
/// Fetch the runtime version.
|
|
#[method(name = "state_getRuntimeVersion")]
|
|
async fn runtime_version(&self, at: Option<Hash>) -> RpcResult<RuntimeVersion>;
|
|
|
|
/// Fetch the payment query info.
|
|
#[method(name = "payment_queryInfo")]
|
|
async fn payment_query_info(
|
|
&self,
|
|
encoded_xt: &Bytes,
|
|
at: Option<&Hash>,
|
|
) -> RpcResult<RuntimeDispatchInfo<Balance>>;
|
|
|
|
/// Dry run an extrinsic at a given block. Return SCALE encoded [`sp_runtine::ApplyExtrinsicResult`].
|
|
#[method(name = "system_dryRun")]
|
|
async fn dry_run(&self, extrinsic: &Bytes, at: Option<Hash>) -> RpcResult<Bytes>;
|
|
|
|
/// Submit an extrinsic to watch.
|
|
///
|
|
/// See [`TransactionStatus`](sc_transaction_pool_api::TransactionStatus) for details on
|
|
/// transaction life cycle.
|
|
//
|
|
// TODO: https://github.com/paritytech/jsonrpsee/issues/698.
|
|
#[subscription(
|
|
name = "author_submitAndWatchExtrinsic" => "author_extrinsicUpdate",
|
|
item = TransactionStatus<Hash, Hash>,
|
|
)]
|
|
fn watch_extrinsic(&self, bytes: &Bytes) -> RpcResult<()>;
|
|
|
|
/// New head subscription.
|
|
#[subscription(
|
|
name = "chain_subscribeNewHeads" => "newHead",
|
|
item = Header
|
|
)]
|
|
fn subscribe_new_heads(&self) -> RpcResult<()>;
|
|
|
|
/// Finalized head subscription.
|
|
#[subscription(
|
|
name = "chain_subscribeFinalizedHeads" => "chain_finalizedHead",
|
|
item = Header
|
|
)]
|
|
fn subscribe_finalized_heads(&self) -> RpcResult<()>;
|
|
}
|
|
|
|
/// Wraps a shared web-socket JSON-RPC client that can be cloned.
|
|
#[derive(Clone, Debug)]
|
|
pub(crate) struct SharedRpcClient(Arc<WsClient>);
|
|
|
|
impl Deref for SharedRpcClient {
|
|
type Target = WsClient;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl SharedRpcClient {
|
|
/// Consume and extract the inner client.
|
|
pub fn into_inner(self) -> Arc<WsClient> {
|
|
self.0
|
|
}
|
|
|
|
/// Create a new shared JSON-RPC web-socket client.
|
|
pub(crate) async fn new(uri: &str) -> Result<Self, RpcError> {
|
|
let client = WsClientBuilder::default()
|
|
.connection_timeout(MAX_CONNECTION_DURATION)
|
|
.max_request_body_size(u32::MAX)
|
|
.request_timeout(MAX_REQUEST_DURATION)
|
|
.build(uri)
|
|
.await?;
|
|
Ok(Self(Arc::new(client)))
|
|
}
|
|
|
|
/// Get a storage item and decode it as `T`.
|
|
///
|
|
/// # Return value:
|
|
///
|
|
/// The function returns:
|
|
///
|
|
/// * `Ok(Some(val))` if successful.
|
|
/// * `Ok(None)` if the storage item was not found.
|
|
/// * `Err(e)` if the JSON-RPC call failed.
|
|
pub(crate) async fn get_storage_and_decode<'a, T: codec::Decode>(
|
|
&self,
|
|
key: &StorageKey,
|
|
hash: Option<Hash>,
|
|
) -> Result<Option<T>, RpcHelperError> {
|
|
if let Some(bytes) = self.storage(key, hash).await? {
|
|
let decoded = <T as codec::Decode>::decode(&mut &*bytes.0)
|
|
.map_err::<RpcHelperError, _>(Into::into)?;
|
|
Ok(Some(decoded))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Takes a future that returns `Bytes` and tries to decode those bytes into the type `Dec`.
|
|
/// Warning: don't use for storage, it will fail for non-existent storage items.
|
|
///
|
|
/// # Return value:
|
|
///
|
|
/// The function returns:
|
|
///
|
|
/// * `Ok(val)` if successful.
|
|
/// * `Err(RpcHelperError::JsonRpsee)` if the JSON-RPC call failed.
|
|
/// * `Err(RpcHelperError::Codec)` if `Bytes` could not be decoded.
|
|
pub(crate) async fn await_request_and_decode<'a, Dec: codec::Decode>(
|
|
req: impl Future<Output = Result<Bytes, RpcError>>,
|
|
) -> Result<Dec, RpcHelperError> {
|
|
let bytes = req.await?;
|
|
Dec::decode(&mut &*bytes.0).map_err::<RpcHelperError, _>(Into::into)
|
|
}
|