pallet_block_producer_fees_rpc/
lib.rs

1//! Json RPC for the Block Producer Fees pallet
2//!
3//! ## Contents
4//!
5//! This crate provides the [BlockProducerFeesRpcApiServer] trait defining the JsonRPC method to display
6//! block producer fees and its concrete implementation [BlockProducerFeesRpc].
7//! ## Usage - PC Builders
8//!
9//! To use the Json RPC service defined in this crate, first make your runtime implement
10//! [sp_block_producer_fees::BlockProducerFeesApi]. Eg. assuming the pallet `BlockProducerFeesPallet`
11//! in your runtime uses `AccountId` as the account id type, the following should be included in your
12//! `impl_runtime_apis` block:
13//! ```rust, ignore
14//! impl BlockProducerFeesApi<Block, AccountId> for Runtime
15//! {
16//! 	fn get_all_fees() -> Vec<(AccountId, sp_block_producer_fees::PerTenThousands)> {
17//!			BlockProducerFees::get_all_latest().map(|(account_id, (_slot, fee))| (account_id, fee)).collect()
18//!		}
19//! }
20//! ```
21//!
22//! Afterwards, the [BlockProducerFeesRpc] Json RPC service can be added into the Json RPC stack of your node.
23//! Example where AccountId type parameter is set to AccountId32:
24//!
25//! ```rust
26//! use jsonrpsee::RpcModule;
27//! use std::sync::Arc;
28//! use sp_block_producer_fees::*;
29//! use pallet_block_producer_fees_rpc::*;
30//!
31//! fn create_rpc<C, Block>(client: Arc<C>) -> Result<RpcModule<()>, Box<dyn std::error::Error>>
32//! where
33//!   C: Send + Sync + 'static,
34//!   Block: sp_runtime::traits::Block,
35//!   C: sp_api::ProvideRuntimeApi<Block>,
36//!   C: sp_blockchain::HeaderBackend<Block>,
37//!   C::Api: BlockProducerFeesApi<Block, sp_runtime::AccountId32>
38//! {
39//!     let mut module = RpcModule::new(());
40//!     module.merge(BlockProducerFeesRpc::new(client.clone()).into_rpc())?;
41//!     // other RPC modules
42//!     Ok(module)
43//! }
44//! ```
45#![deny(missing_docs)]
46use derive_new::new;
47use jsonrpsee::{
48	core::{RpcResult, async_trait},
49	proc_macros::rpc,
50	types::{ErrorObject, ErrorObjectOwned},
51};
52use parity_scale_codec::Decode;
53use serde::{Deserialize, Serialize};
54use sp_api::ProvideRuntimeApi;
55use sp_block_producer_fees::BlockProducerFeesApi;
56use sp_blockchain::HeaderBackend;
57use sp_runtime::traits::Block as BlockT;
58use std::sync::Arc;
59
60/// Json RPC methods related to the Block Producer Metadata feature of Partner Chains Toolkit
61#[rpc(client, server, namespace = "pc")]
62pub trait BlockProducerFeesRpc<AccountId: Decode> {
63	/// Returns the latest recorded fees. To get all stored data query pallet storage directly.
64	#[method(name = "getBlockProducerFees")]
65	fn get_block_producer_fees(&self) -> RpcResult<Vec<FeesSettings<AccountId>>>;
66}
67
68/// Concrete implementation of [BlockProducerFeesRpcApiServer] that uses [BlockProducerFeesRpcApi] for querying runtime storage.
69#[derive(new)]
70pub struct BlockProducerFeesRpc<C, Block, AccountId> {
71	client: Arc<C>,
72	_marker: std::marker::PhantomData<(Block, AccountId)>,
73}
74
75/// Fees settings for given account
76#[derive(Clone, Deserialize, Serialize)]
77pub struct FeesSettings<AccountId> {
78	account_id: AccountId,
79	/// Margin fee in percent
80	margin_fee: f64,
81}
82
83#[async_trait]
84impl<C, Block, AccountId: Decode + Sync + Send + 'static> BlockProducerFeesRpcServer<AccountId>
85	for BlockProducerFeesRpc<C, Block, AccountId>
86where
87	Block: BlockT,
88	C: Send + Sync + 'static,
89	C: ProvideRuntimeApi<Block>,
90	C: HeaderBackend<Block>,
91	C::Api: BlockProducerFeesApi<Block, AccountId>,
92{
93	fn get_block_producer_fees(&self) -> RpcResult<Vec<FeesSettings<AccountId>>> {
94		let api = self.client.runtime_api();
95		let best_block = self.client.info().best_hash;
96		let fees = api.get_all_fees(best_block).map_err(error_object_from)?;
97		Ok(fees
98			.into_iter()
99			.map(|(account_id, fee)| {
100				let fee: f64 = fee.into();
101				FeesSettings { account_id, margin_fee: fee / 100f64 }
102			})
103			.collect())
104	}
105}
106
107fn error_object_from<T: std::fmt::Debug>(err: T) -> ErrorObjectOwned {
108	ErrorObject::owned::<u8>(-1, format!("{err:?}"), None)
109}