pallet_frequency_tx_payment_rpc/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(clippy::too_many_arguments)]
3#![allow(clippy::unnecessary_mut_passed)]
4#![allow(rustdoc::bare_urls)]
5// Strong Documentation Lints
6#![deny(
7	rustdoc::broken_intra_doc_links,
8	rustdoc::missing_crate_level_docs,
9	rustdoc::invalid_codeblock_attributes,
10	missing_docs
11)]
12
13//! Runtime API definition for [Capacity](../pallet_capacity/index.html)
14//!
15//! This api must be implemented by the node runtime.
16//! Runtime APIs Provide:
17//! - An interface between the runtime and Custom RPCs.
18//! - Runtime interfaces for end users beyond just State Queries
19
20use std::{convert::TryInto, sync::Arc};
21
22use jsonrpsee::{
23	core::{async_trait, RpcResult},
24	proc_macros::rpc,
25	types::{error::ErrorCode, ErrorObject},
26};
27use pallet_frequency_tx_payment_runtime_api::{FeeDetails, InclusionFee};
28use parity_scale_codec::{Codec, Decode};
29use sp_api::ProvideRuntimeApi;
30use sp_blockchain::HeaderBackend;
31use sp_core::Bytes;
32use sp_rpc::number::NumberOrHex;
33use sp_runtime::traits::{Block as BlockT, MaybeDisplay};
34
35pub use pallet_frequency_tx_payment_runtime_api::CapacityTransactionPaymentRuntimeApi;
36
37#[cfg(test)]
38mod tests;
39
40/// CapacityTransactionPayment RPC methods.
41#[rpc(client, server)]
42pub trait CapacityPaymentApi<BlockHash, Balance> {
43	/// Query the capcity fee details for a given extrinsic.
44	#[method(name = "frequencyTxPayment_computeCapacityFeeDetails")]
45	fn compute_capacity_fee_details(
46		&self,
47		encoded_xt: Bytes,
48		at: Option<BlockHash>,
49	) -> RpcResult<FeeDetails<NumberOrHex>>;
50}
51
52/// Provides RPC methods to query a dispatchable's class, weight and fee.
53pub struct CapacityPaymentHandler<C, P> {
54	/// Shared reference to the client.
55	client: Arc<C>,
56	_marker: std::marker::PhantomData<P>,
57}
58
59impl<C, P> CapacityPaymentHandler<C, P> {
60	/// Creates a new instance of the TransactionPayment Rpc helper.
61	pub fn new(client: Arc<C>) -> Self {
62		Self { client, _marker: Default::default() }
63	}
64}
65
66/// Error type of this RPC api.
67pub enum Error {
68	/// The transaction was not decodable.
69	DecodeError,
70	/// The call to runtime failed.
71	RuntimeError,
72}
73
74impl From<Error> for i32 {
75	fn from(e: Error) -> i32 {
76		match e {
77			Error::RuntimeError => 1,
78			Error::DecodeError => 2,
79		}
80	}
81}
82
83#[async_trait]
84impl<C, Block, Balance> CapacityPaymentApiServer<<Block as BlockT>::Hash, Balance>
85	for CapacityPaymentHandler<C, Block>
86where
87	Block: BlockT,
88	C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
89	C::Api: CapacityTransactionPaymentRuntimeApi<Block, Balance>,
90	Balance: Codec + MaybeDisplay + Copy + TryInto<NumberOrHex> + Send + Sync + 'static,
91{
92	fn compute_capacity_fee_details(
93		&self,
94		encoded_xt: Bytes,
95		at: Option<Block::Hash>,
96	) -> RpcResult<FeeDetails<NumberOrHex>> {
97		let api = self.client.runtime_api();
98		let at_hash = at.unwrap_or_else(|| self.client.info().best_hash);
99
100		let encoded_len = encoded_xt.len() as u32;
101		let uxt: Block::Extrinsic = Decode::decode(&mut &*encoded_xt).map_err(|e| {
102			ErrorObject::owned(
103				Error::DecodeError.into(),
104				"Unable to query capacity fee details.",
105				Some(format!("{e:?}")),
106			)
107		})?;
108		let fee_details = api.compute_capacity_fee(at_hash, uxt, encoded_len).map_err(|e| {
109			ErrorObject::owned(
110				Error::RuntimeError.into(),
111				"Unable to query capacity fee details.",
112				Some(format!("{e:?}")),
113			)
114		})?;
115
116		let try_into_rpc_balance = |value: Balance| {
117			value.try_into().map_err(|_| {
118				ErrorObject::owned(
119					ErrorCode::InvalidParams.code(),
120					format!("{value} doesn't fit in NumberOrHex representation"),
121					None::<()>,
122				)
123			})
124		};
125
126		Ok(FeeDetails {
127			inclusion_fee: if let Some(inclusion_fee) = fee_details.inclusion_fee {
128				Some(InclusionFee {
129					base_fee: try_into_rpc_balance(inclusion_fee.base_fee)?,
130					len_fee: try_into_rpc_balance(inclusion_fee.len_fee)?,
131					adjusted_weight_fee: try_into_rpc_balance(inclusion_fee.adjusted_weight_fee)?,
132				})
133			} else {
134				None
135			},
136			tip: Default::default(),
137		})
138	}
139}