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}