pallet_block_producer_metadata_rpc/lib.rs
1//! Crate providing Json RPC methods for the Block Producer Metadata feature of the Partner Chains Toolkit
2//!
3//! ## Contents
4//!
5//! This crate provides the [BlockProducerMetadataRpcApiServer] trait defining the JsonRPC methods related to
6//! block producer metadata and its concrete implementation [BlockProducerMetadataRpc]. Currently, only a
7//! single method is provided:
8//! - `pc_getBlockProducerMetadata`
9//!
10//! ## Usage - PC Builders
11//!
12//! To use the Json RPC service defined in this crate, first make your runtime implement
13//! [sp_block_producer_metadata::BlockProducerMetadataApi]. Eg. assuming the pallet `BlockProducerMetadataPallet`
14//! in your runtime uses `BlockProducerMetadataType` as the metadata type, the following should be included in your
15//! `impl_runtime_apis` block:
16//! ```rust, ignore
17//! impl BlockProducerMetadataApi<Block, BlockProducerMetadataType> for Runtime
18//! {
19//! fn get_metadata_for(
20//! cross_chain_pub_key: &CrossChainPublicKey,
21//! ) -> Option<BlockProducerMetadataType> {
22//! BlockProducerMetadataPallet::get_metadata_for(&cross_chain_pub_key)
23//! }
24//! }
25//! ```
26//!
27//! Afterwards, the [BlockProducerMetadataRpc] Json RPC service can be added into the Json RPC stack of your node, eg.:
28//!
29//! ```rust
30//! use jsonrpsee::RpcModule;
31//! use std::sync::Arc;
32//! use sp_block_producer_metadata::*;
33//! use pallet_block_producer_metadata_rpc::*;
34//!
35//! fn create_rpc<C, Block, Metadata>(client: Arc<C>) -> Result<RpcModule<()>, Box<dyn std::error::Error>>
36//! where
37//! C: Send + Sync + 'static,
38//! Block: sp_runtime::traits::Block,
39//! Metadata: Send + Sync + Clone + sp_core::Decode + sp_runtime::Serialize + 'static,
40//! C: sp_api::ProvideRuntimeApi<Block>,
41//! C: sp_blockchain::HeaderBackend<Block>,
42//! C::Api: BlockProducerMetadataApi<Block, Metadata>
43//! {
44//! let mut module = RpcModule::new(());
45//! module.merge(BlockProducerMetadataRpc::new(client.clone()).into_rpc())?;
46//! // other RPC modules
47//! Ok(module)
48//! }
49//! ```
50#![deny(missing_docs)]
51use derive_new::new;
52use jsonrpsee::{
53 core::{RpcResult, async_trait},
54 proc_macros::rpc,
55 types::{ErrorObject, ErrorObjectOwned},
56};
57use parity_scale_codec::Decode;
58use sidechain_domain::CrossChainPublicKey;
59use sp_api::ProvideRuntimeApi;
60use sp_block_producer_metadata::BlockProducerMetadataApi;
61use sp_blockchain::HeaderBackend;
62use sp_runtime::traits::Block as BlockT;
63use std::sync::Arc;
64
65/// Json RPC methods related to the Block Producer Metadata feature of Partner Chains Toolkit
66#[rpc(client, server, namespace = "pc")]
67pub trait BlockProducerMetadataRpcApi<Metadata> {
68 /// Returns JSON-encoded metadata for given `cross_chain_public_key` from the storage of the current tip if it exists.
69 #[method(name = "getMetadata")]
70 fn get_block_producer_metadata(
71 &self,
72 cross_chain_public_key: CrossChainPublicKey,
73 ) -> RpcResult<Option<Metadata>>;
74}
75
76/// Concrete implementation of [BlockProducerMetadataRpcApiServer] that uses [BlockProducerMetadataApi] for querying runtime storage.
77#[derive(new)]
78pub struct BlockProducerMetadataRpc<C, Block, Metadata> {
79 client: Arc<C>,
80 _marker: std::marker::PhantomData<(Block, Metadata)>,
81}
82
83#[async_trait]
84impl<C, Block, Metadata: Decode + Sync + Send + 'static> BlockProducerMetadataRpcApiServer<Metadata>
85 for BlockProducerMetadataRpc<C, Block, Metadata>
86where
87 Block: BlockT,
88 C: Send + Sync + 'static,
89 C: ProvideRuntimeApi<Block>,
90 C: HeaderBackend<Block>,
91 C::Api: BlockProducerMetadataApi<Block, Metadata>,
92{
93 fn get_block_producer_metadata(
94 &self,
95 cross_chain_public_key: CrossChainPublicKey,
96 ) -> RpcResult<Option<Metadata>> {
97 let api = self.client.runtime_api();
98 let best_block = self.client.info().best_hash;
99 api.get_metadata_for(best_block, &cross_chain_public_key)
100 .map_err(error_object_from)
101 }
102}
103
104fn error_object_from<T: std::fmt::Debug>(err: T) -> ErrorObjectOwned {
105 ErrorObject::owned::<u8>(-1, format!("{err:?}"), None)
106}