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}