pallet_handles_rpc/
lib.rs1#![deny(
3 rustdoc::broken_intra_doc_links,
4 rustdoc::missing_crate_level_docs,
5 rustdoc::invalid_codeblock_attributes,
6 missing_docs
7)]
8
9use 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#[rpc(client, server)]
35pub trait HandlesApi<BlockHash> {
36 #[method(name = "handles_getHandleForMsa")]
38 fn get_handle_for_msa(&self, msa_id: MessageSourceId) -> RpcResult<Option<HandleResponse>>;
39
40 #[method(name = "handles_getNextSuffixes")]
42 fn get_next_suffixes(
43 &self,
44 base_handle: String,
45 count: Option<u16>,
46 ) -> RpcResult<PresumptiveSuffixesResponse>;
47
48 #[method(name = "handles_getMsaForHandle")]
50 fn get_msa_for_handle(&self, display_handle: String) -> RpcResult<Option<MessageSourceId>>;
51
52 #[method(name = "handles_validateHandle")]
54 fn validate_handle(&self, base_handle: String) -> RpcResult<bool>;
55}
56
57pub struct HandlesHandler<C, M> {
59 client: Arc<C>,
60 _marker: std::marker::PhantomData<M>,
61}
62
63impl<C, M> HandlesHandler<C, M> {
64 pub fn new(client: Arc<C>) -> Self {
66 Self { client, _marker: Default::default() }
67 }
68}
69
70#[derive(Debug)]
72pub enum HandlesRpcError {
73 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}