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