use super::methods;
pub fn payment_info_parameters(extrinsic: &[u8]) -> impl Iterator<Item = impl AsRef<[u8]>> + Clone {
[
either::Left(extrinsic),
either::Right(u32::try_from(extrinsic.len()).unwrap().to_le_bytes()),
]
.into_iter()
}
pub const PAYMENT_FEES_FUNCTION_NAME: &str = "TransactionPaymentApi_query_info";
pub fn decode_payment_info(
scale_encoded: &[u8],
api_version: u32,
) -> Result<methods::RuntimeDispatchInfo, DecodeError> {
let is_api_v2 = match api_version {
1 => false,
2 => true,
_ => return Err(DecodeError::UnknownRuntimeVersion),
};
match nom::Parser::parse(
&mut nom::combinator::all_consuming(nom_decode_payment_info::<nom::error::Error<&[u8]>>(
is_api_v2,
)),
scale_encoded,
) {
Ok((_, info)) => Ok(info),
Err(_) => Err(DecodeError::ParseError),
}
}
#[derive(Debug, derive_more::Display, derive_more::Error)]
pub enum DecodeError {
ParseError,
UnknownRuntimeVersion,
}
fn nom_decode_payment_info<'a, E: nom::error::ParseError<&'a [u8]>>(
is_api_v2: bool,
) -> impl nom::Parser<&'a [u8], Output = methods::RuntimeDispatchInfo, Error = E> {
nom::combinator::map(
(
move |bytes| {
if is_api_v2 {
nom::number::streaming::le_u64(bytes)
} else {
nom::Parser::parse(
&mut nom::combinator::map(
(
crate::util::nom_scale_compact_u64,
crate::util::nom_scale_compact_u64,
),
|(ref_time, _proof_size)| ref_time,
),
bytes,
)
}
},
nom::combinator::map_opt(nom::number::streaming::u8, |n| match n {
0 => Some(methods::DispatchClass::Normal),
1 => Some(methods::DispatchClass::Operational),
2 => Some(methods::DispatchClass::Mandatory),
_ => None,
}),
|bytes| {
let mut num = 0u128;
let mut shift = 0u32;
for byte in <[u8]>::iter(bytes) {
let shifted =
u128::from(*byte)
.checked_mul(1 << shift)
.ok_or(nom::Err::Error(nom::error::make_error(
bytes,
nom::error::ErrorKind::Digit,
)))?;
num =
num.checked_add(shifted)
.ok_or(nom::Err::Error(nom::error::make_error(
bytes,
nom::error::ErrorKind::Digit,
)))?;
shift =
shift
.checked_add(16)
.ok_or(nom::Err::Error(nom::error::make_error(
bytes,
nom::error::ErrorKind::Digit,
)))?;
}
Ok((&[][..], num))
},
),
|(weight, class, partial_fee)| methods::RuntimeDispatchInfo {
weight,
class,
partial_fee,
},
)
}