#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarks;
pub mod foreign_creators;
pub mod fungible_conversion;
pub mod local_and_foreign_assets;
pub mod matching;
pub mod runtime_api;
extern crate alloc;
use crate::matching::{LocalLocationPattern, ParentLocation};
use alloc::vec::Vec;
use codec::{Decode, EncodeLike};
use core::cmp::PartialEq;
use frame_support::traits::{Equals, EverythingBut};
use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId};
use sp_runtime::traits::TryConvertInto;
use xcm::prelude::*;
use xcm_builder::{
AsPrefixedGeneralIndex, MatchedConvertedConcreteId, StartsWith, WithLatestLocationConverter,
};
pub type AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation, L = Location> =
AsPrefixedGeneralIndex<
TrustBackedAssetsPalletLocation,
AssetIdForTrustBackedAssets,
TryConvertInto,
L,
>;
pub type CollectionIdForUniquesConvert<UniquesPalletLocation> =
AsPrefixedGeneralIndex<UniquesPalletLocation, CollectionId, TryConvertInto>;
pub type TrustBackedAssetsConvertedConcreteId<
TrustBackedAssetsPalletLocation,
Balance,
L = Location,
> = MatchedConvertedConcreteId<
AssetIdForTrustBackedAssets,
Balance,
StartsWith<TrustBackedAssetsPalletLocation>,
AssetIdForTrustBackedAssetsConvert<TrustBackedAssetsPalletLocation, L>,
TryConvertInto,
>;
pub type UniquesConvertedConcreteId<UniquesPalletLocation> = MatchedConvertedConcreteId<
CollectionId,
ItemId,
StartsWith<UniquesPalletLocation>,
CollectionIdForUniquesConvert<UniquesPalletLocation>,
TryConvertInto,
>;
pub type TrustBackedAssetsAsLocation<
TrustBackedAssetsPalletLocation,
Balance,
L,
LocationConverter = WithLatestLocationConverter<L>,
> = MatchedConvertedConcreteId<
L,
Balance,
StartsWith<TrustBackedAssetsPalletLocation>,
LocationConverter,
TryConvertInto,
>;
pub type ForeignAssetsConvertedConcreteId<
AdditionalLocationExclusionFilter,
Balance,
AssetId,
LocationToAssetIdConverter = WithLatestLocationConverter<AssetId>,
BalanceConverter = TryConvertInto,
> = MatchedConvertedConcreteId<
AssetId,
Balance,
EverythingBut<(
Equals<ParentLocation>,
StartsWith<LocalLocationPattern>,
AdditionalLocationExclusionFilter,
)>,
LocationToAssetIdConverter,
BalanceConverter,
>;
type AssetIdForPoolAssets = u32;
pub type AssetIdForPoolAssetsConvert<PoolAssetsPalletLocation> =
AsPrefixedGeneralIndex<PoolAssetsPalletLocation, AssetIdForPoolAssets, TryConvertInto>;
pub type PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance> =
MatchedConvertedConcreteId<
AssetIdForPoolAssets,
Balance,
StartsWith<PoolAssetsPalletLocation>,
AssetIdForPoolAssetsConvert<PoolAssetsPalletLocation>,
TryConvertInto,
>;
pub fn get_assets_in_pool_with<
Runtime: pallet_asset_conversion::Config<PoolId = (L, L)>,
L: TryInto<Location> + Clone + Decode + EncodeLike + PartialEq,
>(
asset: &L,
) -> Result<Vec<AssetId>, ()> {
pallet_asset_conversion::Pools::<Runtime>::iter_keys()
.filter_map(|(asset_1, asset_2)| {
if asset_1 == *asset {
Some(asset_2)
} else if asset_2 == *asset {
Some(asset_1)
} else {
None
}
})
.map(|location| location.try_into().map_err(|_| ()).map(AssetId))
.collect::<Result<Vec<_>, _>>()
}
#[cfg(test)]
mod tests {
use super::*;
use sp_runtime::traits::MaybeEquivalence;
use xcm_builder::{StartsWithExplicitGlobalConsensus, WithLatestLocationConverter};
use xcm_executor::traits::{Error as MatchError, MatchesFungibles};
#[test]
fn asset_id_for_trust_backed_assets_convert_works() {
frame_support::parameter_types! {
pub TrustBackedAssetsPalletLocation: Location = Location::new(5, [PalletInstance(13)]);
}
let local_asset_id = 123456789 as AssetIdForTrustBackedAssets;
let expected_reverse_ref =
Location::new(5, [PalletInstance(13), GeneralIndex(local_asset_id.into())]);
assert_eq!(
AssetIdForTrustBackedAssetsConvert::<TrustBackedAssetsPalletLocation>::convert_back(
&local_asset_id
)
.unwrap(),
expected_reverse_ref
);
assert_eq!(
AssetIdForTrustBackedAssetsConvert::<TrustBackedAssetsPalletLocation>::convert(
&expected_reverse_ref
)
.unwrap(),
local_asset_id
);
}
#[test]
fn trust_backed_assets_match_fungibles_works() {
frame_support::parameter_types! {
pub TrustBackedAssetsPalletLocation: Location = Location::new(0, [PalletInstance(13)]);
}
type TrustBackedAssetsConvert =
TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, u128>;
let test_data = vec![
(ma_1000(0, [PalletInstance(13)].into()), Err(MatchError::AssetIdConversionFailed)),
(
ma_1000(0, [PalletInstance(13), GeneralKey { data: [0; 32], length: 32 }].into()),
Err(MatchError::AssetIdConversionFailed),
),
(
ma_1000(0, [PalletInstance(13), Parachain(1000)].into()),
Err(MatchError::AssetIdConversionFailed),
),
(ma_1000(0, [PalletInstance(13), GeneralIndex(1234)].into()), Ok((1234, 1000))),
(
ma_1000(0, [PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222)].into()),
Ok((1234, 1000)),
),
(
ma_1000(
0,
[
PalletInstance(13),
GeneralIndex(1234),
GeneralIndex(2222),
GeneralKey { data: [0; 32], length: 32 },
]
.into(),
),
Ok((1234, 1000)),
),
(
ma_1000(0, [PalletInstance(77), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(0, [PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [PalletInstance(13), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [PalletInstance(77), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [PalletInstance(77), GeneralIndex(1234), GeneralIndex(2222)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(2, [PalletInstance(13), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(2, [PalletInstance(13), GeneralIndex(1234), GeneralIndex(2222)].into()),
Err(MatchError::AssetNotHandled),
),
(ma_1000(0, [PalletInstance(77)].into()), Err(MatchError::AssetNotHandled)),
(ma_1000(1, [PalletInstance(13)].into()), Err(MatchError::AssetNotHandled)),
(ma_1000(2, [PalletInstance(13)].into()), Err(MatchError::AssetNotHandled)),
];
for (asset, expected_result) in test_data {
assert_eq!(
<TrustBackedAssetsConvert as MatchesFungibles<AssetIdForTrustBackedAssets, u128>>::matches_fungibles(&asset.clone().try_into().unwrap()),
expected_result, "asset: {:?}", asset);
}
}
#[test]
fn foreign_assets_converted_concrete_id_converter_works() {
frame_support::parameter_types! {
pub Parachain100Pattern: Location = Location::new(1, [Parachain(100)]);
pub UniversalLocationNetworkId: NetworkId = NetworkId::ByGenesis([9; 32]);
}
type Convert = ForeignAssetsConvertedConcreteId<
(
StartsWith<Parachain100Pattern>,
StartsWithExplicitGlobalConsensus<UniversalLocationNetworkId>,
),
u128,
xcm::v4::Location,
WithLatestLocationConverter<xcm::v4::Location>,
>;
let test_data = vec![
(ma_1000(0, Here), Err(MatchError::AssetNotHandled)),
(ma_1000(0, [Parachain(100)].into()), Err(MatchError::AssetNotHandled)),
(
ma_1000(0, [PalletInstance(13), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(ma_1000(1, Here), Err(MatchError::AssetNotHandled)),
(ma_1000(1, [Parachain(100)].into()), Err(MatchError::AssetNotHandled)),
(
ma_1000(1, [Parachain(100), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [Parachain(100), PalletInstance(13), GeneralIndex(1234)].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [GlobalConsensus(NetworkId::ByGenesis([9; 32]))].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(2, [GlobalConsensus(NetworkId::ByGenesis([9; 32]))].into()),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(
2,
[
GlobalConsensus(NetworkId::ByGenesis([9; 32])),
Parachain(200),
GeneralIndex(1234),
]
.into(),
),
Err(MatchError::AssetNotHandled),
),
(
ma_1000(1, [Parachain(200)].into()),
Ok((xcm::v4::Location::new(1, [xcm::v4::Junction::Parachain(200)]), 1000)),
),
(
ma_1000(2, [Parachain(200)].into()),
Ok((xcm::v4::Location::new(2, [xcm::v4::Junction::Parachain(200)]), 1000)),
),
(
ma_1000(1, [Parachain(200), GeneralIndex(1234)].into()),
Ok((
xcm::v4::Location::new(
1,
[xcm::v4::Junction::Parachain(200), xcm::v4::Junction::GeneralIndex(1234)],
),
1000,
)),
),
(
ma_1000(2, [Parachain(200), GeneralIndex(1234)].into()),
Ok((
xcm::v4::Location::new(
2,
[xcm::v4::Junction::Parachain(200), xcm::v4::Junction::GeneralIndex(1234)],
),
1000,
)),
),
(
ma_1000(2, [GlobalConsensus(NetworkId::ByGenesis([7; 32]))].into()),
Ok((
xcm::v4::Location::new(
2,
[xcm::v4::Junction::GlobalConsensus(xcm::v4::NetworkId::ByGenesis(
[7; 32],
))],
),
1000,
)),
),
(
ma_1000(
2,
[
GlobalConsensus(NetworkId::ByGenesis([7; 32])),
Parachain(200),
GeneralIndex(1234),
]
.into(),
),
Ok((
xcm::v4::Location::new(
2,
[
xcm::v4::Junction::GlobalConsensus(xcm::v4::NetworkId::ByGenesis(
[7; 32],
)),
xcm::v4::Junction::Parachain(200),
xcm::v4::Junction::GeneralIndex(1234),
],
),
1000,
)),
),
];
for (asset, expected_result) in test_data {
assert_eq!(
<Convert as MatchesFungibles<xcm::v4::Location, u128>>::matches_fungibles(
&asset.clone().try_into().unwrap()
),
expected_result,
"asset: {:?}",
asset
);
}
}
fn ma_1000(parents: u8, interior: Junctions) -> Asset {
(Location::new(parents, interior), 1000).into()
}
}