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 */