diff --git a/Cargo.dev.toml b/Cargo.dev.toml
index bffa0dd42..ff41946a4 100644
--- a/Cargo.dev.toml
+++ b/Cargo.dev.toml
@@ -16,6 +16,7 @@ members = [
"rewards",
"nft",
"xcm",
+ "xnft",
"xtokens",
"xcm-support",
"unknown-tokens",
diff --git a/xcm-support/Cargo.toml b/xcm-support/Cargo.toml
index 3151c8994..33f254ffe 100644
--- a/xcm-support/Cargo.toml
+++ b/xcm-support/Cargo.toml
@@ -9,16 +9,22 @@ edition = "2021"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false }
+scale-info = { version = "2.9.0", default-features = false, features = [
+ "derive",
+] }
-frame-support = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "release-polkadot-v1.1.0" }
-sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "release-polkadot-v1.1.0" }
-sp-std = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "release-polkadot-v1.1.0" }
+frame-support = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.1.0" }
+sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.1.0" }
+sp-std = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.1.0" }
-xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "release-polkadot-v1.1.0" }
-xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "release-polkadot-v1.1.0" }
+xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.1.0" }
+xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.1.0" }
+xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.1.0" }
orml-traits = { path = "../traits", version = "0.4.1-dev", default-features = false }
+log = { version = "0.4.17", default-features = false }
+
[features]
default = ["std"]
std = [
@@ -29,4 +35,5 @@ std = [
"sp-std/std",
"xcm-executor/std",
"xcm/std",
+ "xcm-builder/std",
]
diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs
index 1b3ed2e69..07d2caa22 100644
--- a/xcm-support/src/lib.rs
+++ b/xcm-support/src/lib.rs
@@ -22,9 +22,8 @@ use xcm_executor::traits::MatchesFungible;
use orml_traits::{location::Reserve, GetByKey};
pub use currency_adapter::{DepositToAlternative, MultiCurrencyAdapter, OnDepositFail};
-
mod currency_adapter;
-
+pub mod parity_adapters;
mod tests;
/// A `MatchesFungible` implementation. It matches concrete fungible assets
diff --git a/xcm-support/src/parity_adapters.rs b/xcm-support/src/parity_adapters.rs
new file mode 100644
index 000000000..750a78dc4
--- /dev/null
+++ b/xcm-support/src/parity_adapters.rs
@@ -0,0 +1,416 @@
+// 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::tokens::nonfungibles_v2`]
+//! through XCM.
+use codec::{Decode, Encode, MaxEncodedLen};
+use frame_support::{
+ ensure,
+ traits::{tokens::nonfungibles_v2, Get},
+};
+use sp_runtime::scale_info::TypeInfo;
+use sp_std::{marker::PhantomData, prelude::*, result};
+use xcm::latest::prelude::*;
+use xcm_builder::{AssetChecking, MintLocation};
+use xcm_executor::traits::{ConvertLocation, Error as MatchError, MatchesNonFungibles, TransactAsset};
+
+const LOG_TARGET: &str = "xcm::nonfungibles_v2_adapter";
+/// Adapter for transferring non-fungible tokens (NFTs) using
+/// [`nonfungibles_v2`].
+///
+/// This adapter facilitates the transfer of NFTs between different locations.
+pub struct NonFungiblesV2TransferAdapter(
+ PhantomData<(Assets, Matcher, AccountIdConverter, AccountId)>,
+);
+impl<
+ Assets: nonfungibles_v2::Transfer,
+ Matcher: MatchesNonFungibles,
+ AccountIdConverter: ConvertLocation,
+ AccountId: Clone, // can't get away without it since `nonfungibles_v2` is generic over it.
+ > TransactAsset for NonFungiblesV2TransferAdapter
+{
+ fn transfer_asset(
+ what: &MultiAsset,
+ from: &MultiLocation,
+ to: &MultiLocation,
+ context: &XcmContext,
+ ) -> result::Result {
+ log::trace!(
+ target: LOG_TARGET,
+ "transfer_asset what: {:?}, from: {:?}, to: {:?}, context: {:?}",
+ what,
+ from,
+ to,
+ context,
+ );
+ // Check we handle this asset.
+ let (class, instance) = Matcher::matches_nonfungibles(what)?;
+ let destination = AccountIdConverter::convert_location(to).ok_or(MatchError::AccountIdConversionFailed)?;
+ Assets::transfer(&class, &instance, &destination).map_err(|e| XcmError::FailedToTransactAsset(e.into()))?;
+ Ok(what.clone().into())
+ }
+}
+
+/// Adapter for mutating non-fungible tokens (NFTs) using [`nonfungibles_v2`].
+///
+/// This adapter provides functions to withdraw, deposit, check in and check out
+/// non fungibles.
+pub struct NonFungiblesV2MutateAdapter<
+ Assets,
+ Matcher,
+ AccountIdConverter,
+ AccountId,
+ CheckAsset,
+ CheckingAccount,
+ ItemConfig,
+>(
+ PhantomData<(
+ Assets,
+ Matcher,
+ AccountIdConverter,
+ AccountId,
+ CheckAsset,
+ CheckingAccount,
+ ItemConfig,
+ )>,
+)
+where
+ ItemConfig: Default;
+
+impl<
+ Assets: nonfungibles_v2::Mutate,
+ Matcher: MatchesNonFungibles,
+ AccountIdConverter: ConvertLocation,
+ AccountId: Clone + Eq, // can't get away without it since `nonfungibles_v2` is generic over it.
+ CheckAsset: AssetChecking,
+ CheckingAccount: Get