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, (AssetsInHolding, XcmError)>;
fn refund_weight(&mut self, _weight: Weight, _context: &XcmContext) -> Option<AssetsInHolding> {
None
}
fn quote_weight(
&mut self,
_weight: Weight,
_given: AssetId,
_context: &XcmContext,
) -> Result<Asset, XcmError> {
Err(XcmError::TooExpensive)
}
}
#[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,
mut payment: AssetsInHolding,
context: &XcmContext,
) -> Result<AssetsInHolding, (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, context) {
Ok(assets) => {
tracing::trace!(
target: "xcm::buy_weight",
%weight_trader,
"Buy weight succeeded",
);
return Ok(assets)
},
Err((unused, error)) => {
payment = unused;
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((
payment,
if too_expensive_error_found {
XcmError::TooExpensive
} else {
last_error.unwrap_or(XcmError::TooExpensive)
},
))
}
fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option<AssetsInHolding> {
for_tuples!( #(
if let Some(asset) = Tuple.refund_weight(weight, context) {
return Some(asset);
}
)* );
None
}
fn quote_weight(
&mut self,
weight: Weight,
given: AssetId,
context: &XcmContext,
) -> Result<Asset, XcmError> {
for_tuples!( #(
if let Ok(asset) = Tuple.quote_weight(weight, given.clone(), context) {
return Ok(asset);
}
)* );
Err(XcmError::TooExpensive)
}
}