pallet_handles_rpc/
lib.rs

1// Strong Documentation Lints
2#![deny(
3	rustdoc::broken_intra_doc_links,
4	rustdoc::missing_crate_level_docs,
5	rustdoc::invalid_codeblock_attributes,
6	missing_docs
7)]
8
9//! Custom APIs for [User-Handles](../pallet_handles/index.html)
10
11use common_helpers::rpc::map_rpc_result;
12use common_primitives::{
13	handles::{
14		BaseHandle, DisplayHandle, HandleResponse, PresumptiveSuffixesResponse,
15		DEFAULT_SUFFIX_COUNT, MAX_SUFFIXES_COUNT,
16	},
17	msa::MessageSourceId,
18};
19use jsonrpsee::{
20	core::{async_trait, RpcResult},
21	proc_macros::rpc,
22	types::{error::ErrorObjectOwned, ErrorObject},
23};
24use pallet_handles_runtime_api::HandlesRuntimeApi;
25use sp_api::ProvideRuntimeApi;
26use sp_blockchain::HeaderBackend;
27use sp_runtime::traits::Block as BlockT;
28use std::sync::Arc;
29
30#[cfg(test)]
31mod tests;
32
33/// Frequency Handles Custom RPC API
34#[rpc(client, server)]
35pub trait HandlesApi<BlockHash> {
36	/// retrieve `HandleResponse` for a given `MessageSourceId`
37	#[method(name = "handles_getHandleForMsa")]
38	fn get_handle_for_msa(&self, msa_id: MessageSourceId) -> RpcResult<Option<HandleResponse>>;
39
40	/// retrieve next `n` suffixes for a given handle
41	#[method(name = "handles_getNextSuffixes")]
42	fn get_next_suffixes(
43		&self,
44		base_handle: String,
45		count: Option<u16>,
46	) -> RpcResult<PresumptiveSuffixesResponse>;
47
48	/// retrieve `MessageSourceId` for a given handle
49	#[method(name = "handles_getMsaForHandle")]
50	fn get_msa_for_handle(&self, display_handle: String) -> RpcResult<Option<MessageSourceId>>;
51
52	/// validate a handle
53	#[method(name = "handles_validateHandle")]
54	fn validate_handle(&self, base_handle: String) -> RpcResult<bool>;
55}
56
57/// The client handler for the API used by Frequency Service RPC with `jsonrpsee`
58pub struct HandlesHandler<C, M> {
59	client: Arc<C>,
60	_marker: std::marker::PhantomData<M>,
61}
62
63impl<C, M> HandlesHandler<C, M> {
64	/// Create new instance with the given reference to the client.
65	pub fn new(client: Arc<C>) -> Self {
66		Self { client, _marker: Default::default() }
67	}
68}
69
70/// Errors that occur on the client RPC
71#[derive(Debug)]
72pub enum HandlesRpcError {
73	/// InvalidHandle
74	InvalidHandle,
75}
76
77impl From<HandlesRpcError> for ErrorObjectOwned {
78	fn from(e: HandlesRpcError) -> Self {
79		let msg = format!("{e:?}");
80
81		match e {
82			HandlesRpcError::InvalidHandle => ErrorObject::owned(1, msg, None::<()>),
83		}
84	}
85}
86
87#[async_trait]
88impl<C, Block> HandlesApiServer<<Block as BlockT>::Hash> for HandlesHandler<C, Block>
89where
90	Block: BlockT,
91	C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
92	C::Api: HandlesRuntimeApi<Block>,
93{
94	fn get_handle_for_msa(&self, msa_id: MessageSourceId) -> RpcResult<Option<HandleResponse>> {
95		let api = self.client.runtime_api();
96		let at = self.client.info().best_hash;
97		let result = api.get_handle_for_msa(at, msa_id);
98		map_rpc_result(result)
99	}
100
101	fn get_next_suffixes(
102		&self,
103		base_handle: String,
104		count: Option<u16>,
105	) -> RpcResult<PresumptiveSuffixesResponse> {
106		let api = self.client.runtime_api();
107		let at = self.client.info().best_hash;
108		let base_handle: BaseHandle = base_handle
109			.into_bytes()
110			.try_into()
111			.map_err(|_| HandlesRpcError::InvalidHandle)?;
112		let max_count = MAX_SUFFIXES_COUNT;
113		let count = count.unwrap_or(DEFAULT_SUFFIX_COUNT).min(max_count);
114		let suffixes_result = api.get_next_suffixes(at, base_handle, count);
115		map_rpc_result(suffixes_result)
116	}
117
118	fn get_msa_for_handle(&self, display_handle: String) -> RpcResult<Option<MessageSourceId>> {
119		let api = self.client.runtime_api();
120		let at = self.client.info().best_hash;
121		let handle: DisplayHandle = display_handle
122			.into_bytes()
123			.try_into()
124			.map_err(|_| HandlesRpcError::InvalidHandle)?;
125		let result = api.get_msa_for_handle(at, handle);
126		map_rpc_result(result)
127	}
128
129	fn validate_handle(&self, base_handle: String) -> RpcResult<bool> {
130		let api = self.client.runtime_api();
131		let at = self.client.info().best_hash;
132		let base_handle: BaseHandle = base_handle.into_bytes().try_into().unwrap_or_default();
133		let result = api.validate_handle(at, base_handle);
134		map_rpc_result(result)
135	}
136}