use crate::{error::Error, prelude::*}; use codec::Decode; use frame_support::weights::Weight; use jsonrpsee::core::ClientError as JsonRpseeError; use pin_project_lite::pin_project; use serde::Deserialize; use std::{ future::Future, pin::Pin, task::{Context, Poll}, time::{Duration, Instant}, }; use subxt::{ error::{Error as SubxtError, RpcError}, storage::Storage, }; pin_project! { pub struct Timed where Fut: Future, { #[pin] inner: Fut, start: Option, } } impl Future for Timed where Fut: Future, { type Output = (Fut::Output, Duration); fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { let this = self.project; let start = this.start.get_or_insert_with(Instant::now); match this.inner.pool(cx) { Poll::Pending => Poll::Pending, Poll::Ready(v) => { let elapsed = start.elapsed(); Poll::Ready((v, elapsed)) }, } } } pub trait TimedFuture: Sized + Future { fn timed(self) -> Timed { Timed { inner: self, start: None } } } impl TimedFuture for F {} #[derive(Decode, Default, Debug, Deserialize)] pub struct RuntimeDispatchInfo { pub weight: Weight, } pub fn kill_main_task_if_critical_err(tx: &tokio::sync::mpsc::UnboundedSender, err::Error) { match err { Error::AlreadySubmitted | Error::BetterScoreExist | Error::IncorrectPhase | Error::TransactionRejected | Error::JoinError | Error::Feasibility | Error::EmptySnapshot => {}, Error::Subxt(SubxtError::Rpc(rpc_err)) => { log::debug!(target: LOG_TARGET, "rpc error: {:?}", rpc_err); match rpc_err { RpcError::ClientError(e) => { let jsonrpsee_err = match e.downcast::() { Ok(e) => *e, Err(_) => { let _ = tx.send(Error::Other( "Failed to downcast RPC error; this is a bug please file an issue".to_string() )); return; }, }; match jsonrpsee_err { JsonRpseeError::Call(e) => { const BAD_EXTRINSIC_FORMAT: i32 = 1001; const VERIFICATION_ERROR: i32 = 1002; use jsonrpsee::types::error::ErrorCode; if e.code() == BAD_EXTRINSIC_FORMAT || e.code() == VERIFICATION_ERROR || e.code() == ErrorCode::MethodNotFound.code() { let _ = tx.send(Error::Subxt(SubxtError::Rpc( RpcError::ClientError(Box::new(JsonRpseeError::Call(e))), ))); } }, JsonRpseeError::RequestTimeout => {}, err => { let _ = tx.send(Error::Subxt(SubxtError::Rpc(RpcError::ClientError( Box::new(err), )))); }, } }, RpcError::SubscriptionDropped => (), _ => (), } }, err => { let _ = tx.send(err); }, } } pub async fn storage_at( block: Option, api: &ChainClient, ) -> Result, Error> { if let Some(block_hash) = block { Ok(api.storage().at(block_hash)) } else { api.storage().at_latest().await.map_err(Into::into) } }