xcm_primitives/
origin_conversion.rs1use frame_support::traits::{ContainsPair, Get, OriginTrait};
18use sp_runtime::traits::TryConvert;
19use sp_std::{convert::TryInto, marker::PhantomData};
20use xcm::latest::{Asset, AssetId, Fungibility, Junction, Location, NetworkId};
21
22pub trait Reserve {
23 fn reserve(asset: &Asset) -> Option<Location>;
25}
26
27pub struct AccountIdToLocation<AccountId>(sp_std::marker::PhantomData<AccountId>);
29impl<AccountId> sp_runtime::traits::Convert<AccountId, Location> for AccountIdToLocation<AccountId>
30where
31 AccountId: Into<[u8; 20]>,
32{
33 fn convert(account: AccountId) -> Location {
34 Location {
35 parents: 0,
36 interior: [Junction::AccountKey20 {
37 network: None,
38 key: account.into(),
39 }]
40 .into(),
41 }
42 }
43}
44
45pub struct SignedToAccountId20<Origin, AccountId, Network>(
47 sp_std::marker::PhantomData<(Origin, AccountId, Network)>,
48);
49impl<Origin: OriginTrait + Clone, AccountId: Into<[u8; 20]>, Network: Get<NetworkId>>
50 TryConvert<Origin, Location> for SignedToAccountId20<Origin, AccountId, Network>
51where
52 Origin::PalletsOrigin: From<frame_system::RawOrigin<AccountId>>
53 + TryInto<frame_system::RawOrigin<AccountId>, Error = Origin::PalletsOrigin>,
54{
55 fn try_convert(o: Origin) -> Result<Location, Origin> {
56 o.try_with_caller(|caller| match caller.try_into() {
57 Ok(frame_system::RawOrigin::Signed(who)) => Ok(Junction::AccountKey20 {
58 key: who.into(),
59 network: Some(Network::get()),
60 }
61 .into()),
62 Ok(other) => Err(other.into()),
63 Err(other) => Err(other),
64 })
65 }
66}
67
68pub struct MultiNativeAsset<ReserveProvider>(PhantomData<ReserveProvider>);
71impl<ReserveProvider> ContainsPair<Asset, Location> for MultiNativeAsset<ReserveProvider>
72where
73 ReserveProvider: Reserve,
74{
75 fn contains(asset: &Asset, origin: &Location) -> bool {
76 if let Some(ref reserve) = ReserveProvider::reserve(asset) {
77 if reserve == origin {
78 return true;
79 }
80 }
81 false
82 }
83}
84
85pub struct RelativeReserveProvider;
88
89impl Reserve for RelativeReserveProvider {
90 fn reserve(asset: &Asset) -> Option<Location> {
91 let AssetId(location) = &asset.id;
92 if location.parents == 0
93 && !matches!(location.first_interior(), Some(Junction::Parachain(_)))
94 {
95 Some(Location::here())
96 } else {
97 Some(location.chain_location())
98 }
99 }
100}
101
102pub struct AbsoluteAndRelativeReserve<AbsoluteMultiLocation>(PhantomData<AbsoluteMultiLocation>);
109impl<AbsoluteMultiLocation> Reserve for AbsoluteAndRelativeReserve<AbsoluteMultiLocation>
110where
111 AbsoluteMultiLocation: Get<Location>,
112{
113 fn reserve(asset: &Asset) -> Option<Location> {
114 RelativeReserveProvider::reserve(asset).map(|relative_reserve| {
115 if relative_reserve == AbsoluteMultiLocation::get() {
116 Location::here()
117 } else {
118 relative_reserve
119 }
120 })
121 }
122}
123
124pub struct IsBridgedConcreteAssetFrom<Origin>(PhantomData<Origin>);
127impl<Origin> ContainsPair<Asset, Location> for IsBridgedConcreteAssetFrom<Origin>
128where
129 Origin: Get<Location>,
130{
131 fn contains(asset: &Asset, origin: &Location) -> bool {
132 let loc = Origin::get();
133 &loc == origin
134 && matches!(
135 asset,
136 Asset {
137 id: AssetId(Location { parents: 2, .. }),
138 fun: Fungibility::Fungible(_)
139 },
140 )
141 }
142}