1234567891011121314151617use frame_support::{parameter_types, traits::Get};18use orml_traits::location::AbsoluteReserveProvider;19use orml_xcm_support::MultiNativeAsset;20use pallet_foreign_assets::{21 AssetId, AssetIdMapping, CurrencyId, ForeignAssetId, FreeForAll, NativeCurrency, TryAsForeign,22 XcmForeignAssetIdMapping,23};24use sp_runtime::traits::{Convert, MaybeEquivalence};25use sp_std::marker::PhantomData;26use staging_xcm::latest::{prelude::*, MultiAsset, MultiLocation};27use staging_xcm_builder::{ConvertedConcreteId, FungiblesAdapter, NoChecking};28use staging_xcm_executor::traits::{JustTry, TransactAsset};29use up_common::types::{AccountId, Balance};3031use super::{LocationToAccountId, RelayLocation};32use crate::{Balances, ForeignAssets, ParachainInfo, PolkadotXcm, Runtime};3334parameter_types! {35 pub CheckingAccount: AccountId = PolkadotXcm::check_account();36}3738pub struct AsInnerId<ConvertAssetId>(PhantomData<(AssetId, ConvertAssetId)>);39impl<ConvertAssetId: MaybeEquivalence<AssetId, AssetId>> MaybeEquivalence<MultiLocation, AssetId>40 for AsInnerId<ConvertAssetId>41{42 fn convert(id: &MultiLocation) -> Option<AssetId> {43 log::trace!(44 target: "xcm::AsInnerId::Convert",45 "AsInnerId {:?}",46 id47 );4849 let parent = MultiLocation::parent();50 let here = MultiLocation::here();51 let self_location = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into())));5253 if *id == parent {54 return ConvertAssetId::convert(&AssetId::NativeAssetId(NativeCurrency::Parent));55 }5657 if *id == here || *id == self_location {58 return ConvertAssetId::convert(&AssetId::NativeAssetId(NativeCurrency::Here));59 }6061 match XcmForeignAssetIdMapping::<Runtime>::get_currency_id(*id) {62 Some(AssetId::ForeignAssetId(foreign_asset_id)) => {63 ConvertAssetId::convert(&AssetId::ForeignAssetId(foreign_asset_id))64 }65 _ => None,66 }67 }6869 fn convert_back(asset_id: &AssetId) -> Option<MultiLocation> {70 log::trace!(71 target: "xcm::AsInnerId::Reverse",72 "AsInnerId",73 );7475 let parent_id =76 ConvertAssetId::convert(&AssetId::NativeAssetId(NativeCurrency::Parent)).unwrap();77 let here_id =78 ConvertAssetId::convert(&AssetId::NativeAssetId(NativeCurrency::Here)).unwrap();7980 if *asset_id == parent_id {81 return Some(MultiLocation::parent());82 }8384 if *asset_id == here_id {85 return Some(MultiLocation::new(86 1,87 X1(Parachain(ParachainInfo::get().into())),88 ));89 }9091 let fid = <AssetId as TryAsForeign<AssetId, ForeignAssetId>>::try_as_foreign(*asset_id)?;92 XcmForeignAssetIdMapping::<Runtime>::get_multi_location(fid)93 }94}959697pub type FungiblesTransactor = FungiblesAdapter<98 99 ForeignAssets,100 101 ConvertedConcreteId<AssetId, Balance, AsInnerId<JustTry>, JustTry>,102 103 LocationToAccountId,104 105 AccountId,106 107 NoChecking,108 109 CheckingAccount,110>;111112113pub struct AssetTransactor;114impl TransactAsset for AssetTransactor {115 fn can_check_in(116 _origin: &MultiLocation,117 _what: &MultiAsset,118 _context: &XcmContext,119 ) -> XcmResult {120 Err(XcmError::Unimplemented)121 }122123 fn check_in(_origin: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}124125 fn can_check_out(126 _dest: &MultiLocation,127 _what: &MultiAsset,128 _context: &XcmContext,129 ) -> XcmResult {130 Err(XcmError::Unimplemented)131 }132133 fn check_out(_dest: &MultiLocation, _what: &MultiAsset, _context: &XcmContext) {}134135 fn deposit_asset(136 what: &MultiAsset,137 who: &MultiLocation,138 context: Option<&XcmContext>,139 ) -> XcmResult {140 FungiblesTransactor::deposit_asset(what, who, context)141 }142143 fn withdraw_asset(144 what: &MultiAsset,145 who: &MultiLocation,146 maybe_context: Option<&XcmContext>,147 ) -> Result<staging_xcm_executor::Assets, XcmError> {148 FungiblesTransactor::withdraw_asset(what, who, maybe_context)149 }150151 fn internal_transfer_asset(152 what: &MultiAsset,153 from: &MultiLocation,154 to: &MultiLocation,155 context: &XcmContext,156 ) -> Result<staging_xcm_executor::Assets, XcmError> {157 FungiblesTransactor::internal_transfer_asset(what, from, to, context)158 }159}160161pub type IsReserve = MultiNativeAsset<AbsoluteReserveProvider>;162163pub type Trader<T> = FreeForAll<164 pallet_configuration::WeightToFee<T, Balance>,165 RelayLocation,166 AccountId,167 Balances,168 (),169>;170171pub struct CurrencyIdConvert;172impl Convert<AssetId, Option<MultiLocation>> for CurrencyIdConvert {173 fn convert(id: AssetId) -> Option<MultiLocation> {174 match id {175 AssetId::NativeAssetId(NativeCurrency::Here) => Some(MultiLocation::new(176 1,177 X1(Parachain(ParachainInfo::get().into())),178 )),179 AssetId::NativeAssetId(NativeCurrency::Parent) => Some(MultiLocation::parent()),180 AssetId::ForeignAssetId(foreign_asset_id) => {181 XcmForeignAssetIdMapping::<Runtime>::get_multi_location(foreign_asset_id)182 }183 }184 }185}186187impl Convert<MultiLocation, Option<CurrencyId>> for CurrencyIdConvert {188 fn convert(location: MultiLocation) -> Option<CurrencyId> {189 if location == MultiLocation::here()190 || location == MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into())))191 {192 return Some(AssetId::NativeAssetId(NativeCurrency::Here));193 }194195 if location == MultiLocation::parent() {196 return Some(AssetId::NativeAssetId(NativeCurrency::Parent));197 }198199 if let Some(currency_id) = XcmForeignAssetIdMapping::<Runtime>::get_currency_id(location) {200 return Some(currency_id);201 }202203 None204 }205}