use crate::AssetsInHolding;
use core::result::Result;
use xcm::latest::{prelude::*, Weight};
pub trait WeightBounds<RuntimeCall> {
fn weight(
message: &mut Xcm<RuntimeCall>,
weight_limit: Weight,
) -> Result<Weight, InstructionError>;
fn instr_weight(instruction: &mut Instruction<RuntimeCall>) -> Result<Weight, XcmError>;
}
pub trait WeightTrader: Sized {
fn new() -> Self;
fn buy_weight(
&mut self,
weight: Weight,
payment: AssetsInHolding,
context: &XcmContext,
) -> Result<AssetsInHolding, XcmError>;
fn refund_weight(&mut self, _weight: Weight, _context: &XcmContext) -> Option<Asset> {
None
}
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl WeightTrader for Tuple {
fn new() -> Self {
for_tuples!( ( #( Tuple::new() ),* ) )
}
fn buy_weight(
&mut self,
weight: Weight,
payment: AssetsInHolding,
context: &XcmContext,
) -> Result<AssetsInHolding, XcmError> {
let mut too_expensive_error_found = false;
let mut last_error = None;
for_tuples!( #(
let weight_trader = core::any::type_name::<Tuple>();
match Tuple.buy_weight(weight, payment.clone(), context) {
Ok(assets) => {
tracing::trace!(
target: "xcm::buy_weight",
%weight_trader,
"Buy weight succeeded",
);
return Ok(assets)
},
Err(error) => {
if let XcmError::TooExpensive = error {
too_expensive_error_found = true;
}
last_error = Some(error);
tracing::trace!(
target: "xcm::buy_weight",
?error,
%weight_trader,
"Weight trader failed",
);
}
}
)* );
tracing::trace!(
target: "xcm::buy_weight",
"Buy weight failed",
);
Err(if too_expensive_error_found {
XcmError::TooExpensive
} else {
last_error.unwrap_or(XcmError::TooExpensive)
})
}
fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option<Asset> {
for_tuples!( #(
if let Some(asset) = Tuple.refund_weight(weight, context) {
return Some(asset);
}
)* );
None
}
}