use core::{marker::PhantomData, result::Result};
use pezframe_support::traits::{Contains, OriginTrait};
use pezsp_runtime::{traits::Dispatchable, DispatchErrorWithPostInfo};
use xcm::latest::prelude::*;
pub trait ConvertLocation<AccountId> {
fn convert_location(location: &Location) -> Option<AccountId>;
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl<AccountId> ConvertLocation<AccountId> for Tuple {
fn convert_location(l: &Location) -> Option<AccountId> {
for_tuples!( #(
match Tuple::convert_location(l) {
Some(result) => return Some(result),
None => {},
}
)* );
None
}
}
pub trait ConvertOrigin<Origin> {
fn convert_origin(origin: impl Into<Location>, kind: OriginKind) -> Result<Origin, Location>;
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl<O> ConvertOrigin<O> for Tuple {
fn convert_origin(origin: impl Into<Location>, kind: OriginKind) -> Result<O, Location> {
let origin = origin.into();
tracing::trace!(
target: "xcm::convert_origin",
?origin,
?kind,
"Converting origin",
);
for_tuples!( #(
let convert_origin = core::any::type_name::<Tuple>();
let origin = match Tuple::convert_origin(origin, kind) {
Err(o) => {
tracing::trace!(
target: "xcm::convert_origin",
%convert_origin,
"Convert origin step failed",
);
o
},
Ok(o) => {
tracing::trace!(
target: "xcm::convert_origin",
%convert_origin,
"Convert origin step succeeded",
);
return Ok(o)
}
};
)* );
tracing::trace!(
target: "xcm::convert_origin",
"Converting origin failed",
);
Err(origin)
}
}
pub trait CallDispatcher<Call: Dispatchable> {
fn dispatch(
call: Call,
origin: Call::RuntimeOrigin,
) -> Result<Call::PostInfo, DispatchErrorWithPostInfo<Call::PostInfo>>;
}
pub struct WithOriginFilter<Filter>(PhantomData<Filter>);
impl<Call, Filter> CallDispatcher<Call> for WithOriginFilter<Filter>
where
Call: Dispatchable,
Call::RuntimeOrigin: OriginTrait,
<<Call as Dispatchable>::RuntimeOrigin as OriginTrait>::Call: 'static,
Filter: Contains<<<Call as Dispatchable>::RuntimeOrigin as OriginTrait>::Call> + 'static,
{
fn dispatch(
call: Call,
mut origin: <Call as Dispatchable>::RuntimeOrigin,
) -> Result<
<Call as Dispatchable>::PostInfo,
DispatchErrorWithPostInfo<<Call as Dispatchable>::PostInfo>,
> {
origin.add_filter(Filter::contains);
call.dispatch(origin)
}
}
impl<Call: Dispatchable> CallDispatcher<Call> for Call {
fn dispatch(
call: Call,
origin: Call::RuntimeOrigin,
) -> Result<Call::PostInfo, DispatchErrorWithPostInfo<Call::PostInfo>> {
call.dispatch(origin)
}
}