use crate::config::Config;
use crate::config::TransactionExtension;
use crate::config::transaction_extensions::{
ChargeAssetTxPayment, ChargeTransactionPayment, CheckNonce,
};
use crate::error::ExtrinsicError;
use frame_decode::extrinsics::ExtrinsicExtensions as ExtrinsicExtensionsInfo;
use scale_decode::DecodeAsType;
use subxt_metadata::ArcMetadata;
#[derive(Debug, Clone)]
pub struct ExtrinsicTransactionExtensions<'extrinsic, T: Config> {
bytes: &'extrinsic [u8],
metadata: ArcMetadata,
decoded_info: &'extrinsic ExtrinsicExtensionsInfo<'extrinsic, u32>,
marker: core::marker::PhantomData<T>,
}
impl<'extrinsic, T: Config> ExtrinsicTransactionExtensions<'extrinsic, T> {
pub(crate) fn new(
bytes: &'extrinsic [u8],
metadata: ArcMetadata,
decoded_info: &'extrinsic ExtrinsicExtensionsInfo<'extrinsic, u32>,
) -> Self {
Self {
bytes,
metadata,
decoded_info,
marker: core::marker::PhantomData,
}
}
pub fn iter(&self) -> impl Iterator<Item = ExtrinsicTransactionExtension<'extrinsic, T>> {
self.decoded_info
.iter()
.map(move |s| ExtrinsicTransactionExtension {
bytes: &self.bytes[s.range()],
ty_id: *s.ty(),
identifier: s.name(),
metadata: self.metadata.clone(),
_marker: core::marker::PhantomData,
})
}
pub fn find<S: TransactionExtension<T>>(&self) -> Option<Result<S::Decoded, ExtrinsicError>> {
for ext in self.iter() {
if let Some(e) = ext.decode_as::<S>() {
return Some(e);
}
}
None
}
pub fn tip(&self) -> Option<u128> {
if let Some(tip) = self.find::<ChargeTransactionPayment>() {
return Some(tip.ok()?.tip());
}
if let Some(tip) = self.find::<ChargeAssetTxPayment<T>>() {
return Some(tip.ok()?.tip());
}
None
}
pub fn nonce(&self) -> Option<u64> {
self.find::<CheckNonce>()?.ok()
}
}
#[derive(Debug, Clone)]
pub struct ExtrinsicTransactionExtension<'extrinsic, T: Config> {
bytes: &'extrinsic [u8],
ty_id: u32,
identifier: &'extrinsic str,
metadata: ArcMetadata,
_marker: core::marker::PhantomData<T>,
}
impl<'extrinsic, T: Config> ExtrinsicTransactionExtension<'extrinsic, T> {
pub fn bytes(&self) -> &'extrinsic [u8] {
self.bytes
}
pub fn name(&self) -> &'extrinsic str {
self.identifier
}
pub fn type_id(&self) -> u32 {
self.ty_id
}
pub fn decode_as<S: TransactionExtension<T>>(
&self,
) -> Option<Result<S::Decoded, ExtrinsicError>> {
if S::NAME != self.identifier {
return None;
}
Some(self.decode_unchecked_as::<S::Decoded>())
}
pub fn decode_unchecked_as<E: DecodeAsType>(&self) -> Result<E, ExtrinsicError> {
let value = E::decode_as_type(&mut &self.bytes[..], self.ty_id, self.metadata.types())
.map_err(|e| ExtrinsicError::CouldNotDecodeTransactionExtension {
name: self.identifier.to_owned(),
error: e,
})?;
Ok(value)
}
}