1use super::substrate::extrinsic::EXTRINSIC_FORMAT_VERSION;
2use crate::{
3 decoded_events::check_header,
4 types::{ExtrinsicSignature, metadata::StringOrBytes},
5 utils::decode_already_decoded,
6};
7use codec::{Compact, Decode, Encode, Error, Input};
8use serde::{Deserialize, Serialize};
9
10pub trait HasHeader {
11 const HEADER_INDEX: (u8, u8);
13}
14
15pub trait TransactionEncodable {
16 fn to_call(&self) -> Vec<u8>;
20}
21
22pub trait ExtrinsicDecodable: Sized {
23 fn from_call<'a>(call: impl Into<StringOrBytes<'a>>) -> Result<Self, String>;
24 fn from_ext<'a>(call: impl Into<StringOrBytes<'a>>) -> Result<Self, String>;
25}
26
27impl<T: HasHeader + Encode> TransactionEncodable for T {
28 fn to_call(&self) -> Vec<u8> {
29 let pallet_id = Self::HEADER_INDEX.0;
30 let variant_id = Self::HEADER_INDEX.1;
31 let mut encoded_event: Vec<u8> = vec![pallet_id, variant_id];
32 Self::encode_to(self, &mut encoded_event);
33
34 encoded_event
35 }
36}
37
38impl<T: HasHeader + Decode> ExtrinsicDecodable for T {
39 fn from_call<'a>(call: impl Into<StringOrBytes<'a>>) -> Result<T, String> {
40 fn inner<T: HasHeader + Decode>(call: StringOrBytes) -> Result<T, String> {
41 let call: &[u8] = match &call {
42 StringOrBytes::StringRef(s) => {
43 &const_hex::decode(s.trim_start_matches("0x")).map_err(|x| x.to_string())?
44 },
45 StringOrBytes::BoxedString(s) => {
46 &const_hex::decode(s.trim_start_matches("0x")).map_err(|x| x.to_string())?
47 },
48 StringOrBytes::Bytes(b) => b,
49 StringOrBytes::BoxedBytes(b) => b,
50 };
51
52 check_header(call, T::HEADER_INDEX)?;
53
54 let mut data = if call.len() <= 2 { &[] } else { &call[2..] };
55 Ok(T::decode(&mut data).map_err(|x| x.to_string())?)
56 }
57
58 inner(call.into())
59 }
60
61 fn from_ext<'a>(ext: impl Into<StringOrBytes<'a>>) -> Result<T, String> {
62 fn inner<T: HasHeader + Decode>(ext: StringOrBytes) -> Result<T, String> {
63 let ext: &[u8] = match &ext {
64 StringOrBytes::StringRef(s) => &const_hex::decode(s.trim_start_matches("0x"))
65 .map_err(|x: const_hex::FromHexError| x.to_string())?,
66 StringOrBytes::BoxedString(s) => {
67 &const_hex::decode(s.trim_start_matches("0x")).map_err(|x| x.to_string())?
68 },
69 StringOrBytes::Bytes(b) => b,
70 StringOrBytes::BoxedBytes(b) => b,
71 };
72
73 let ext = Extrinsic::<T>::try_from(ext)?;
74 Ok(ext.call)
75 }
76
77 inner(ext.into())
78 }
79}
80
81#[derive(Clone)]
82pub struct EncodedExtrinsic {
83 pub signature: Option<ExtrinsicSignature>,
87 pub call: Vec<u8>,
89}
90
91impl<'a> TryFrom<StringOrBytes<'a>> for EncodedExtrinsic {
92 type Error = String;
93
94 fn try_from(value: StringOrBytes<'a>) -> Result<Self, Self::Error> {
95 match value {
96 StringOrBytes::StringRef(s) => Self::try_from(s),
97 StringOrBytes::BoxedString(s) => Self::try_from(&*s),
98 StringOrBytes::Bytes(b) => Self::try_from(b),
99 StringOrBytes::BoxedBytes(b) => Self::try_from(&*b),
100 }
101 }
102}
103
104impl TryFrom<Vec<u8>> for EncodedExtrinsic {
105 type Error = String;
106
107 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
108 Self::try_from(value.as_slice())
109 }
110}
111
112impl TryFrom<&Vec<u8>> for EncodedExtrinsic {
113 type Error = String;
114
115 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
116 Self::try_from(value.as_slice())
117 }
118}
119
120impl TryFrom<&[u8]> for EncodedExtrinsic {
121 type Error = String;
122
123 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
124 let mut value = value;
125 Self::decode(&mut value).map_err(|x| x.to_string())
126 }
127}
128
129impl TryFrom<String> for EncodedExtrinsic {
130 type Error = String;
131
132 fn try_from(value: String) -> Result<Self, Self::Error> {
133 Self::try_from(value.as_str())
134 }
135}
136
137impl TryFrom<&String> for EncodedExtrinsic {
138 type Error = String;
139
140 fn try_from(value: &String) -> Result<Self, Self::Error> {
141 Self::try_from(value.as_str())
142 }
143}
144
145impl TryFrom<&str> for EncodedExtrinsic {
146 type Error = String;
147
148 fn try_from(value: &str) -> Result<Self, Self::Error> {
149 let Ok(hex_decoded) = const_hex::decode(value.trim_start_matches("0x")) else {
150 return Err("Failed to hex decode transaction".into());
151 };
152
153 Self::try_from(hex_decoded.as_slice())
154 }
155}
156
157impl Decode for EncodedExtrinsic {
158 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
159 let expected_length: Compact<u32> = Decode::decode(input)?;
163 let before_length = input.remaining_len()?;
164
165 let version = input.read_byte()?;
166
167 let is_signed = version & 0b1000_0000 != 0;
168 let version = version & 0b0111_1111;
169 if version != EXTRINSIC_FORMAT_VERSION {
170 return Err("Invalid transaction version".into());
171 }
172
173 let signature = is_signed.then(|| Decode::decode(input)).transpose()?;
174 let call = decode_already_decoded(input)?;
175
176 if let Some((before_length, after_length)) = input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a)))
177 {
178 let length = before_length.saturating_sub(after_length);
179
180 if length != expected_length.0 as usize {
181 return Err("Invalid length prefix".into());
182 }
183 }
184
185 Ok(Self { signature, call })
186 }
187}
188
189impl Encode for EncodedExtrinsic {
190 fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
191 let mut encoded_tx_inner = Vec::new();
192 if let Some(signed) = &self.signature {
193 0x84u8.encode_to(&mut encoded_tx_inner);
194 signed.address.encode_to(&mut encoded_tx_inner);
195 signed.signature.encode_to(&mut encoded_tx_inner);
196 signed.extra.encode_to(&mut encoded_tx_inner);
197 } else {
198 0x4u8.encode_to(&mut encoded_tx_inner);
199 }
200
201 encoded_tx_inner.extend(&self.call);
202 let mut encoded_tx = Compact(encoded_tx_inner.len() as u32).encode();
203 encoded_tx.append(&mut encoded_tx_inner);
204
205 dest.write(&encoded_tx)
206 }
207}
208
209impl Serialize for EncodedExtrinsic {
210 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
211 where
212 S: serde::Serializer,
213 {
214 let bytes = self.encode();
215 impl_serde::serialize::serialize(&bytes, serializer)
216 }
217}
218
219impl<'a> Deserialize<'a> for EncodedExtrinsic {
220 fn deserialize<D>(de: D) -> Result<Self, D::Error>
221 where
222 D: serde::Deserializer<'a>,
223 {
224 let r = impl_serde::serialize::deserialize(de)?;
225 Decode::decode(&mut &r[..]).map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
226 }
227}
228
229#[derive(Debug, Clone)]
230pub struct SignedExtrinsic<T: HasHeader + Decode + Sized> {
231 pub signature: ExtrinsicSignature,
232 pub call: T,
233}
234
235impl<'a, T: HasHeader + Decode> TryFrom<StringOrBytes<'a>> for SignedExtrinsic<T> {
236 type Error = String;
237
238 fn try_from(value: StringOrBytes<'a>) -> Result<Self, Self::Error> {
239 match value {
240 StringOrBytes::StringRef(s) => Self::try_from(s),
241 StringOrBytes::BoxedString(s) => Self::try_from(&*s),
242 StringOrBytes::Bytes(b) => Self::try_from(b),
243 StringOrBytes::BoxedBytes(b) => Self::try_from(&*b),
244 }
245 }
246}
247
248impl<T: HasHeader + Decode> TryFrom<Vec<u8>> for SignedExtrinsic<T> {
249 type Error = String;
250
251 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
252 Self::try_from(value.as_slice())
253 }
254}
255
256impl<T: HasHeader + Decode> TryFrom<&Vec<u8>> for SignedExtrinsic<T> {
257 type Error = String;
258
259 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
260 Self::try_from(value.as_slice())
261 }
262}
263
264impl<T: HasHeader + Decode> TryFrom<&[u8]> for SignedExtrinsic<T> {
265 type Error = String;
266
267 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
268 let ext = EncodedExtrinsic::try_from(value)?;
269 Self::try_from(ext)
270 }
271}
272
273impl<T: HasHeader + Decode> TryFrom<String> for SignedExtrinsic<T> {
274 type Error = String;
275
276 fn try_from(value: String) -> Result<Self, Self::Error> {
277 Self::try_from(value.as_str())
278 }
279}
280
281impl<T: HasHeader + Decode> TryFrom<&String> for SignedExtrinsic<T> {
282 type Error = String;
283
284 fn try_from(value: &String) -> Result<Self, Self::Error> {
285 Self::try_from(value.as_str())
286 }
287}
288
289impl<T: HasHeader + Decode> TryFrom<&str> for SignedExtrinsic<T> {
290 type Error = String;
291
292 fn try_from(value: &str) -> Result<Self, Self::Error> {
293 let ext = EncodedExtrinsic::try_from(value)?;
294 Self::try_from(ext)
295 }
296}
297
298impl<T: HasHeader + Decode> TryFrom<EncodedExtrinsic> for SignedExtrinsic<T> {
299 type Error = String;
300
301 fn try_from(value: EncodedExtrinsic) -> Result<Self, Self::Error> {
302 let signature = value.signature.ok_or("Extrinsic has no signature")?;
303 let call = T::from_call(&value.call)?;
304 Ok(Self { signature, call })
305 }
306}
307
308impl<T: HasHeader + Decode> TryFrom<&EncodedExtrinsic> for SignedExtrinsic<T> {
309 type Error = String;
310
311 fn try_from(value: &EncodedExtrinsic) -> Result<Self, Self::Error> {
312 let signature = value.signature.as_ref().ok_or("Extrinsic has no signature")?.clone();
313 let call = T::from_call(&value.call)?;
314 Ok(Self { signature, call })
315 }
316}
317
318#[derive(Debug, Clone)]
319pub struct Extrinsic<T: HasHeader + Decode + Sized> {
320 pub signature: Option<ExtrinsicSignature>,
321 pub call: T,
322}
323
324impl<'a, T: HasHeader + Decode> TryFrom<StringOrBytes<'a>> for Extrinsic<T> {
325 type Error = String;
326
327 fn try_from(value: StringOrBytes<'a>) -> Result<Self, Self::Error> {
328 match value {
329 StringOrBytes::StringRef(s) => Self::try_from(s),
330 StringOrBytes::BoxedString(s) => Self::try_from(&*s),
331 StringOrBytes::Bytes(b) => Self::try_from(b),
332 StringOrBytes::BoxedBytes(b) => Self::try_from(&*b),
333 }
334 }
335}
336
337impl<T: HasHeader + Decode> TryFrom<Vec<u8>> for Extrinsic<T> {
338 type Error = String;
339
340 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
341 Self::try_from(value.as_slice())
342 }
343}
344
345impl<T: HasHeader + Decode> TryFrom<&Vec<u8>> for Extrinsic<T> {
346 type Error = String;
347
348 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
349 Self::try_from(value.as_slice())
350 }
351}
352
353impl<T: HasHeader + Decode> TryFrom<&[u8]> for Extrinsic<T> {
354 type Error = String;
355
356 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
357 let ext = EncodedExtrinsic::try_from(value)?;
358 Self::try_from(ext)
359 }
360}
361
362impl<T: HasHeader + Decode> TryFrom<String> for Extrinsic<T> {
363 type Error = String;
364
365 fn try_from(value: String) -> Result<Self, Self::Error> {
366 Self::try_from(value.as_str())
367 }
368}
369
370impl<T: HasHeader + Decode> TryFrom<&String> for Extrinsic<T> {
371 type Error = String;
372
373 fn try_from(value: &String) -> Result<Self, Self::Error> {
374 Self::try_from(value.as_str())
375 }
376}
377
378impl<T: HasHeader + Decode> TryFrom<&str> for Extrinsic<T> {
379 type Error = String;
380
381 fn try_from(value: &str) -> Result<Self, Self::Error> {
382 let ext = EncodedExtrinsic::try_from(value)?;
383 Self::try_from(ext)
384 }
385}
386
387impl<T: HasHeader + Decode> TryFrom<EncodedExtrinsic> for Extrinsic<T> {
388 type Error = String;
389
390 fn try_from(value: EncodedExtrinsic) -> Result<Self, Self::Error> {
391 Self::try_from(&value)
392 }
393}
394
395impl<T: HasHeader + Decode> TryFrom<&EncodedExtrinsic> for Extrinsic<T> {
396 type Error = String;
397
398 fn try_from(value: &EncodedExtrinsic) -> Result<Self, Self::Error> {
399 let call = T::from_call(&value.call)?;
400 Ok(Self { signature: value.signature.clone(), call })
401 }
402}
403
404#[cfg(test)]
405pub mod test {
406 }