avail_rust_core/
decoded_events.rs

1use crate::{HasHeader, types::metadata::StringOrBytes};
2use codec::{Decode, Encode};
3
4pub trait TransactionEventEncodable {
5	/// SCALE encodes the event
6	///
7	/// If you need to Hex and SCALE encode then call `encode_as_hex_event`
8	fn to_event(&self) -> Vec<u8>;
9}
10
11pub trait TransactionEventDecodable: Sized {
12	/// Decodes the SCALE encoded Event
13	///
14	/// If you need to decode Hex string call `decode_hex_event`
15	fn from_event<'a>(event: impl Into<StringOrBytes<'a>>) -> Result<Self, String>;
16}
17
18impl<T: HasHeader + Encode> TransactionEventEncodable for T {
19	fn to_event(&self) -> Vec<u8> {
20		let pallet_id = Self::HEADER_INDEX.0;
21		let variant_id = Self::HEADER_INDEX.1;
22		let mut encoded_event: Vec<u8> = vec![pallet_id, variant_id];
23		Self::encode_to(self, &mut encoded_event);
24
25		encoded_event
26	}
27}
28
29impl<T: HasHeader + Decode> TransactionEventDecodable for T {
30	fn from_event<'a>(event: impl Into<StringOrBytes<'a>>) -> Result<Self, String> {
31		fn inner<T: HasHeader + Decode>(event: StringOrBytes) -> Result<T, String> {
32			let event: &[u8] = match &event {
33				StringOrBytes::StringRef(s) => {
34					&const_hex::decode(s.trim_start_matches("0x")).map_err(|x| x.to_string())?
35				},
36				StringOrBytes::BoxedString(s) => {
37					&const_hex::decode(s.trim_start_matches("0x")).map_err(|x| x.to_string())?
38				},
39				StringOrBytes::Bytes(b) => b,
40				StringOrBytes::BoxedBytes(b) => b,
41			};
42
43			// This was moved out in order to decrease compilation times
44			check_header(event, T::HEADER_INDEX)?;
45
46			let mut data = if event.len() <= 2 { &[] } else { &event[2..] };
47			Ok(T::decode(&mut data).map_err(|x| x.to_string())?)
48		}
49
50		inner(event.into())
51	}
52}
53
54// Purely here to decrease compilation times
55pub(crate) fn check_header(data: &[u8], header_index: (u8, u8)) -> Result<(), String> {
56	if data.len() < 2 {
57		return Err("Failed to decode. Not have enough bytes to decode the header".into());
58	}
59
60	let (pallet_id, variant_id) = (data[0], data[1]);
61	if header_index.0 != pallet_id || header_index.1 != variant_id {
62		let err = std::format!(
63			"Failed to decode. Mismatch in pallet and/or variant id. Actual: PI: {}, VI: {} Expected: PI: {}, VI: {}",
64			pallet_id,
65			variant_id,
66			header_index.0,
67			header_index.1
68		);
69		return Err(err);
70	}
71
72	Ok(())
73}
74
75/* /// Contains only the event body. Phase and topics are not included here.
76#[derive(Debug, Clone)]
77pub struct RawEvent(pub Vec<u8>);
78
79impl RawEvent {
80	pub fn pallet_index(&self) -> u8 {
81		self.0[0]
82	}
83
84	pub fn variant_index(&self) -> u8 {
85		self.0[1]
86	}
87
88	pub fn event_data(&self) -> &[u8] {
89		if self.0.len() <= 2 { &[] } else { &self.0[2..] }
90	}
91}
92
93impl TryFrom<String> for RawEvent {
94	type Error = String;
95
96	fn try_from(value: String) -> Result<Self, Self::Error> {
97		Self::try_from(value.as_str())
98	}
99}
100
101impl TryFrom<&String> for RawEvent {
102	type Error = String;
103
104	fn try_from(value: &String) -> Result<Self, Self::Error> {
105		Self::try_from(value.as_str())
106	}
107}
108
109impl TryFrom<&str> for RawEvent {
110	type Error = String;
111
112	fn try_from(value: &str) -> Result<Self, Self::Error> {
113		let value = const_hex::decode(value).map_err(|x| x.to_string())?;
114		Self::try_from(value)
115	}
116}
117
118impl TryFrom<Vec<u8>> for RawEvent {
119	type Error = String;
120
121	fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
122		Self::try_from(value.as_slice())
123	}
124}
125
126impl TryFrom<&Vec<u8>> for RawEvent {
127	type Error = String;
128
129	fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
130		Self::try_from(value.as_slice())
131	}
132}
133
134impl TryFrom<&[u8]> for RawEvent {
135	type Error = String;
136
137	fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
138		if value.len() < 2 {
139			return Err("Event must have more than one byte".into());
140		}
141
142		Ok(RawEvent(value.to_owned()))
143	}
144}
145 */