// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi 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.
// Pezkuwi 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 Pezkuwi. If not, see .
//! Adapters to work with [`frame_support::traits::tokens::nonfungible`] through XCM.
use crate::MintLocation;
use core::{fmt::Debug, marker::PhantomData, result};
use frame_support::{
ensure,
traits::{tokens::nonfungible, Get},
};
use xcm::latest::prelude::*;
use xcm_executor::traits::{
ConvertLocation, Error as MatchError, MatchesNonFungible, TransactAsset,
};
const LOG_TARGET: &str = "xcm::nonfungible_adapter";
/// [`TransactAsset`] implementation that allows the use of a [`nonfungible`] implementation for
/// handling an asset in the XCM executor.
/// Only works for transfers.
pub struct NonFungibleTransferAdapter(
PhantomData<(NonFungible, Matcher, AccountIdConverter, AccountId)>,
)
where
NonFungible: nonfungible::Transfer;
impl<
NonFungible: nonfungible::Transfer,
Matcher: MatchesNonFungible,
AccountIdConverter: ConvertLocation,
AccountId: Clone + Debug, // can't get away without it since Currency is generic over it.
> TransactAsset for NonFungibleTransferAdapter
where
NonFungible::ItemId: Debug,
{
fn transfer_asset(
what: &Asset,
from: &Location,
to: &Location,
context: &XcmContext,
) -> result::Result {
tracing::trace!(
target: LOG_TARGET,
?what,
?from,
?to,
?context,
"transfer_asset",
);
// Check we handle this asset.
let instance = Matcher::matches_nonfungible(what).ok_or(MatchError::AssetNotHandled)?;
let destination = AccountIdConverter::convert_location(to)
.ok_or(MatchError::AccountIdConversionFailed)?;
NonFungible::transfer(&instance, &destination).map_err(|e| {
tracing::debug!(target: LOG_TARGET, ?e, ?instance, ?destination, "Failed to transfer non-fungible asset");
XcmError::FailedToTransactAsset(e.into())
})?;
Ok(what.clone().into())
}
}
/// [`TransactAsset`] implementation that allows the use of a [`nonfungible`] implementation for
/// handling an asset in the XCM executor.
/// Works for teleport bookkeeping.
pub struct NonFungibleMutateAdapter<
NonFungible,
Matcher,
AccountIdConverter,
AccountId,
CheckingAccount,
>(PhantomData<(NonFungible, Matcher, AccountIdConverter, AccountId, CheckingAccount)>)
where
NonFungible: nonfungible::Mutate,
NonFungible::ItemId: Debug;
impl<
NonFungible: nonfungible::Mutate,
Matcher: MatchesNonFungible,
AccountIdConverter: ConvertLocation,
AccountId: Clone + Eq + Debug, /* can't get away without it since Currency is generic
* over it. */
CheckingAccount: Get