pallet_messages_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
9#[cfg(feature = "std")]
12use common_helpers::rpc::map_rpc_result;
13use common_primitives::{messages::*, schema::*};
14use frame_support::{ensure, fail};
15use jsonrpsee::{
16 core::{async_trait, RpcResult},
17 proc_macros::rpc,
18 types::{ErrorObject, ErrorObjectOwned},
19};
20use pallet_messages_runtime_api::MessagesRuntimeApi;
21use sp_api::ProvideRuntimeApi;
22use sp_blockchain::HeaderBackend;
23use sp_runtime::traits::Block as BlockT;
24use std::sync::Arc;
25
26#[cfg(test)]
27mod tests;
28
29#[rpc(client, server)]
31pub trait MessagesApi {
32 #[method(name = "messages_getBySchemaId")]
34 fn get_messages_by_schema_id(
35 &self,
36 schema_id: SchemaId,
37 pagination: BlockPaginationRequest,
38 ) -> RpcResult<BlockPaginationResponse<MessageResponse>>;
39}
40
41pub struct MessagesHandler<C, M> {
43 client: Arc<C>,
44 _marker: std::marker::PhantomData<M>,
45}
46
47impl<C, M> MessagesHandler<C, M> {
48 pub fn new(client: Arc<C>) -> Self {
50 Self { client, _marker: Default::default() }
51 }
52}
53
54#[derive(Debug)]
56pub enum MessageRpcError {
57 InvalidPaginationRequest,
59 TypeConversionOverflow,
61 InvalidSchemaId,
63}
64
65impl From<MessageRpcError> for ErrorObjectOwned {
66 fn from(e: MessageRpcError) -> Self {
67 let msg = format!("{e:?}");
68 match e {
69 MessageRpcError::InvalidPaginationRequest => ErrorObject::owned(1, msg, None::<()>),
70 MessageRpcError::TypeConversionOverflow => ErrorObject::owned(2, msg, None::<()>),
71 MessageRpcError::InvalidSchemaId => ErrorObject::owned(3, msg, None::<()>),
72 }
73 }
74}
75
76#[async_trait]
77impl<C, Block> MessagesApiServer for MessagesHandler<C, Block>
78where
79 Block: BlockT,
80 C: ProvideRuntimeApi<Block> + HeaderBackend<Block> + 'static,
81 C::Api: MessagesRuntimeApi<Block>,
82{
83 fn get_messages_by_schema_id(
84 &self,
85 schema_id: SchemaId,
86 pagination: BlockPaginationRequest,
87 ) -> RpcResult<BlockPaginationResponse<MessageResponse>> {
88 ensure!(pagination.validate(), MessageRpcError::InvalidPaginationRequest);
90
91 let api = self.client.runtime_api();
93 let at = self.client.info().best_hash;
94
95 let schema: SchemaResponse = match api.get_schema_by_id(at, schema_id) {
97 Ok(Some(s)) => s,
98 _ => fail!(MessageRpcError::InvalidSchemaId),
99 };
100
101 let mut response = BlockPaginationResponse::new();
102 let from: u32 = pagination.from_block;
103 let to: u32 = pagination.to_block;
104 let mut from_index = pagination.from_index;
105
106 'loops: for block_number in from..to {
107 let list: Vec<MessageResponse> = api
108 .get_messages_by_schema_and_block(
109 at,
110 schema.schema_id,
111 schema.payload_location,
112 block_number,
113 )
114 .unwrap_or_default();
115
116 let list_size: u32 =
117 list.len().try_into().map_err(|_| MessageRpcError::TypeConversionOverflow)?;
118 for i in from_index..list_size {
119 response.content.push(list[i as usize].clone());
120
121 if response.check_end_condition_and_set_next_pagination(
122 block_number,
123 i,
124 list_size,
125 &pagination,
126 ) {
127 break 'loops
128 }
129 }
130
131 from_index = 0;
133 }
134
135 map_rpc_result(Ok(response))
136 }
137}