// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
//! Adapters to work with [`frame_support::traits::fungible`] through XCM.
use super::MintLocation;
use frame_support::traits::{
tokens::{
fungible, Fortitude::Polite, Precision::Exact, Preservation::Preserve, Provenance::Minted,
},
Get,
};
use sp_std::{marker::PhantomData, prelude::*, result};
use xcm::latest::prelude::*;
use xcm_executor::{
traits::{ConvertLocation, Error as MatchError, MatchesFungible, TransactAsset},
AssetsInHolding,
};
/// [`TransactAsset`] implementation that allows the use of a [`fungible`] implementation for
/// handling an asset in the XCM executor.
/// Only works for transfers.
pub struct FungibleTransferAdapter(
PhantomData<(Fungible, Matcher, AccountIdConverter, AccountId)>,
);
impl<
Fungible: fungible::Mutate,
Matcher: MatchesFungible,
AccountIdConverter: ConvertLocation,
AccountId: Eq + Clone,
> TransactAsset for FungibleTransferAdapter
{
fn internal_transfer_asset(
what: &Asset,
from: &Location,
to: &Location,
_context: &XcmContext,
) -> result::Result {
log::trace!(
target: "xcm::fungible_adapter",
"internal_transfer_asset what: {:?}, from: {:?}, to: {:?}",
what, from, to
);
// Check we handle the asset
let amount = Matcher::matches_fungible(what).ok_or(MatchError::AssetNotHandled)?;
let source = AccountIdConverter::convert_location(from)
.ok_or(MatchError::AccountIdConversionFailed)?;
let dest = AccountIdConverter::convert_location(to)
.ok_or(MatchError::AccountIdConversionFailed)?;
Fungible::transfer(&source, &dest, amount, Preserve)
.map_err(|error| XcmError::FailedToTransactAsset(error.into()))?;
Ok(what.clone().into())
}
}
/// [`TransactAsset`] implementation that allows the use of a [`fungible`] implementation for
/// handling an asset in the XCM executor.
/// Works for everything but transfers.
pub struct FungibleMutateAdapter(
PhantomData<(Fungible, Matcher, AccountIdConverter, AccountId, CheckingAccount)>,
);
impl<
Fungible: fungible::Mutate,
Matcher: MatchesFungible,
AccountIdConverter: ConvertLocation,
AccountId: Eq + Clone,
CheckingAccount: Get