pallet_messages/
types.rs

1use common_primitives::{
2	messages::MessageResponse,
3	msa::MessageSourceId,
4	node::BlockNumber,
5	schema::{PayloadLocation, SchemaId},
6};
7use core::fmt::Debug;
8use frame_support::{traits::Get, BoundedVec};
9use multibase::Base;
10use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
11use scale_info::TypeInfo;
12extern crate alloc;
13use alloc::vec::Vec;
14use common_primitives::messages::MessageResponseV2;
15
16/// Payloads stored offchain contain a tuple of (bytes(the payload reference), payload length).
17pub type OffchainPayloadType = (Vec<u8>, u32);
18/// Index of message in the block
19pub type MessageIndex = u16;
20
21/// A single message type definition.
22#[derive(Default, Encode, Decode, PartialEq, Debug, TypeInfo, Eq, MaxEncodedLen)]
23#[scale_info(skip_type_params(MaxDataSize))]
24#[codec(mel_bound(MaxDataSize: MaxEncodedLen))]
25pub struct Message<MaxDataSize>
26where
27	MaxDataSize: Get<u32> + Debug,
28{
29	///  Data structured by the associated schema's model.
30	pub payload: BoundedVec<u8, MaxDataSize>,
31	/// Message source account id of the Provider. This may be the same id as contained in `msa_id`,
32	/// indicating that the original source MSA is acting as its own provider. An id differing from that
33	/// of `msa_id` indicates that `provider_msa_id` was delegated by `msa_id` to send this message on
34	/// its behalf.
35	pub provider_msa_id: MessageSourceId,
36	///  Message source account id (the original source).
37	pub msa_id: Option<MessageSourceId>,
38	///  The SchemaId of the schema that defines the format of the payload
39	pub schema_id: SchemaId,
40}
41
42/// Trait for converting message storage to response type
43pub trait MapToResponse<I, R> {
44	/// Maps a stored message to an RPC response
45	fn map_to_response(&self, index_values: I) -> Option<R>;
46}
47
48impl<MaxDataSize: Get<u32> + Debug>
49	MapToResponse<(BlockNumber, PayloadLocation, u16), MessageResponse> for Message<MaxDataSize>
50{
51	fn map_to_response(
52		&self,
53		index_values: (BlockNumber, PayloadLocation, u16),
54	) -> Option<MessageResponse> {
55		let (block_number, payload_location, index) = index_values;
56		let base_response = MessageResponse {
57			provider_msa_id: self.provider_msa_id,
58			index,
59			block_number,
60			msa_id: self.msa_id,
61			..Default::default()
62		};
63
64		match payload_location {
65			PayloadLocation::OnChain => Some(MessageResponse {
66				payload: Some(self.payload.to_vec()),
67				cid: None,
68				payload_length: None,
69				..base_response
70			}),
71			PayloadLocation::IPFS => {
72				let (binary_cid, payload_length) =
73					OffchainPayloadType::decode(&mut &self.payload[..]).unwrap_or_default();
74				Some(MessageResponse {
75					cid: Some(multibase::encode(Base::Base32Lower, binary_cid).as_bytes().to_vec()),
76					payload_length: Some(payload_length),
77					payload: None,
78					..base_response
79				})
80			}, // Message types of Itemized and Paginated are retrieved differently
81			_ => None,
82		}
83	}
84}
85
86impl<MaxDataSize: Get<u32> + Debug>
87	MapToResponse<(BlockNumber, SchemaId, PayloadLocation, u16), MessageResponseV2>
88	for Message<MaxDataSize>
89{
90	/// Helper function to handle response type [`MessageResponseV2`] depending on the Payload Location (on chain or IPFS)
91	fn map_to_response(
92		&self,
93		index_values: (BlockNumber, SchemaId, PayloadLocation, u16),
94	) -> Option<MessageResponseV2> {
95		let (block_number, schema_id, payload_location, index) = index_values;
96		let base_response = MessageResponseV2 {
97			provider_msa_id: self.provider_msa_id,
98			index,
99			block_number,
100			msa_id: self.msa_id,
101			schema_id,
102			..Default::default()
103		};
104
105		match payload_location {
106			PayloadLocation::OnChain => Some(MessageResponseV2 {
107				payload: Some(self.payload.to_vec()),
108				cid: None,
109				payload_length: None,
110				..base_response
111			}),
112			PayloadLocation::IPFS => {
113				let (binary_cid, payload_length) =
114					OffchainPayloadType::decode(&mut &self.payload[..]).unwrap_or_default();
115				Some(MessageResponseV2 {
116					cid: Some(multibase::encode(Base::Base32Lower, binary_cid).as_bytes().to_vec()),
117					payload_length: Some(payload_length),
118					payload: None,
119					..base_response
120				})
121			}, // Message types of Itemized and Paginated are retrieved differently
122			_ => None,
123		}
124	}
125}
126
127impl<MaxDataSize: Get<u32> + Debug>
128	MapToResponse<(BlockNumber, PayloadLocation, u16), MessageResponseV2> for Message<MaxDataSize>
129{
130	/// Helper function to handle response type [`MessageResponseV2`] depending on the Payload Location (on chain or IPFS)
131	fn map_to_response(
132		&self,
133		index_values: (BlockNumber, PayloadLocation, u16),
134	) -> Option<MessageResponseV2> {
135		let (block_number, payload_location, index) = index_values;
136		let base_response = MessageResponseV2 {
137			provider_msa_id: self.provider_msa_id,
138			index,
139			block_number,
140			msa_id: self.msa_id,
141			schema_id: self.schema_id,
142			..Default::default()
143		};
144
145		match payload_location {
146			PayloadLocation::OnChain => Some(MessageResponseV2 {
147				payload: Some(self.payload.to_vec()),
148				cid: None,
149				payload_length: None,
150				..base_response
151			}),
152			PayloadLocation::IPFS => {
153				let (binary_cid, payload_length) =
154					OffchainPayloadType::decode(&mut &self.payload[..]).unwrap_or_default();
155				Some(MessageResponseV2 {
156					cid: Some(multibase::encode(Base::Base32Lower, binary_cid).as_bytes().to_vec()),
157					payload_length: Some(payload_length),
158					payload: None,
159					..base_response
160				})
161			}, // Message types of Itemized and Paginated are retrieved differently
162			_ => None,
163		}
164	}
165}