use super::*;
use crate as pallet_derivatives;
use frame_support::{
construct_runtime, derive_impl, parameter_types,
traits::{
tokens::asset_ops::{common_ops::*, common_strategies::*, *},
ContainsPair, Everything, Nothing, PalletInfoAccess,
},
};
use frame_system::{EnsureNever, EnsureRoot, EnsureSigned};
use sp_runtime::{traits::TryConvertInto, BuildStorage};
use xcm::prelude::*;
use xcm_builder::{
unique_instances::{
ExtractAssetId, NonFungibleAsset, UniqueInstancesAdapter, UniqueInstancesDepositAdapter,
},
AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, FixedWeightBounds, MatchInClassInstances,
MatchedConvertedConcreteId, StartsWith,
};
use xcm_executor::traits::ConvertLocation;
mod auto_id_collections;
mod auto_id_nfts;
mod predefined_id_collections;
pub use auto_id_collections::*;
pub use auto_id_nfts::*;
pub use predefined_id_collections::*;
type AccountId = u64;
type Block = frame_system::mocking::MockBlock<Test>;
type Balance = u64;
#[frame_support::pallet]
pub mod unique_items {
use frame_support::pallet_prelude::*;
#[pallet::config]
pub trait Config<I: 'static = ()>: frame_system::Config {
type ItemId: Member + Parameter + MaxEncodedLen + TypeInfo;
}
#[pallet::pallet]
pub struct Pallet<T, I = ()>(_);
#[pallet::error]
pub enum Error<T, I = ()> {
AlreadyExists,
NoPermission,
UnknownItem,
}
#[pallet::event]
pub enum Event<T: Config<I>, I: 'static = ()> {}
#[pallet::storage]
pub type CurrentItemId<T: Config<I>, I: 'static = ()> = StorageValue<_, T::ItemId, OptionQuery>;
#[pallet::storage]
pub type ItemOwner<T: Config<I>, I: 'static = ()> =
StorageMap<_, Blake2_128Concat, T::ItemId, T::AccountId, OptionQuery>;
}
construct_runtime!(
pub enum Test
{
System: frame_system,
Balances: pallet_balances,
PredefinedIdCollections: unique_items::<Instance1>,
PredefinedIdDerivativeCollections: pallet_derivatives::<Instance1>,
AutoIdCollections: unique_items::<Instance2>,
AutoIdDerivativeCollections: pallet_derivatives::<Instance2>,
PredefinedIdNfts: unique_items::<Instance3>,
DerivativeNfts: pallet_derivatives::<Instance3>,
}
);
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for Test {
type AccountId = AccountId;
type Block = Block;
type AccountData = pallet_balances::AccountData<Balance>;
}
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
impl pallet_balances::Config for Test {
type AccountStore = System;
}
parameter_types! {
pub const DeliveryFees: u128 = 20; pub const ExistentialDeposit: u128 = 1; pub const BaseXcmWeight: Weight = Weight::from_parts(100, 10); pub UniversalLocation: InteriorLocation = [GlobalConsensus(NetworkId::ByGenesis([0; 32])), Parachain(2000)].into();
pub const HereLocation: Location = Location::here();
pub const RelayLocation: Location = Location::parent();
pub const MaxAssetsIntoHolding: u32 = 64;
pub const AnyNetwork: Option<NetworkId> = None;
pub LocalNftsPalletLocation: Location = PalletInstance(<PredefinedIdNfts as PalletInfoAccess>::index() as u8).into();
pub StashAccountId: AccountId = u64::MAX;
}
pub struct TrustAssetsFromSiblings;
impl ContainsPair<Asset, Location> for TrustAssetsFromSiblings {
fn contains(asset: &Asset, origin: &Location) -> bool {
let AssetId(asset_location) = &asset.id;
match (asset_location.unpack(), origin.unpack()) {
((1, [Parachain(asset_para_id), ..]), (1, [Parachain(origin_para_id)]))
if asset_para_id == origin_para_id =>
{
true
},
_ => false,
}
}
}
pub struct AccountIndex64Aliases<Network, AccountId>(PhantomData<(Network, AccountId)>);
impl<Network: Get<Option<NetworkId>>, AccountId: From<u64>> ConvertLocation<AccountId>
for AccountIndex64Aliases<Network, AccountId>
{
fn convert_location(location: &Location) -> Option<AccountId> {
let index = match location.unpack() {
(0, [AccountIndex64 { index, network: None }]) => index,
(0, [AccountIndex64 { index, network }]) if *network == Network::get() => index,
_ => return None,
};
Some((*index).into())
}
}
pub struct SiblingChainToIndex64;
impl ConvertLocation<AccountId> for SiblingChainToIndex64 {
fn convert_location(location: &Location) -> Option<AccountId> {
let index = match location.unpack() {
(1, [Parachain(id)]) => id,
_ => return None,
};
Some((*index).into())
}
}
pub type LocationToAccountId = (AccountIndex64Aliases<AnyNetwork, u64>, SiblingChainToIndex64);
pub struct SiblingAssetToReserveLocationConvert;
impl ConvertLocation<AccountId> for SiblingAssetToReserveLocationConvert {
fn convert_location(location: &Location) -> Option<AccountId> {
match location.unpack() {
(1, [Parachain(para_id), ..]) => {
LocationToAccountId::convert_location(&Location::new(1, Parachain(*para_id)))
},
_ => None,
}
}
}
pub type CreateDerivativeOwnedBySovAcc<IdAssignment, CreateOp, InvalidAssetErr> =
DeriveStrategyThenCreate<
WithConfig<ConfigValue<Owner<AccountId>>, IdAssignment>,
OwnerConvertedLocation<SiblingAssetToReserveLocationConvert, IdAssignment, InvalidAssetErr>,
CreateOp,
>;
pub type PredefinedIdDerivativeCollectionsInstance = pallet_derivatives::Instance1;
impl pallet_derivatives::Config<PredefinedIdDerivativeCollectionsInstance> for Test {
type WeightInfo = pallet_derivatives::TestWeightInfo;
type Original = AssetId;
type Derivative = AssetId;
type DerivativeExtra = ();
type CreateOrigin = EnsureSigned<AccountId>;
type CreateOp = pallet_derivatives::NoStoredMapping<
CreateDerivativeOwnedBySovAcc<
PredefinedId<AssetId>,
PredefinedIdCollections,
pallet_derivatives::InvalidAssetError<PredefinedIdDerivativeCollections>,
>,
>;
type DestroyOrigin = EnsureRoot<AccountId>;
type DestroyOp = PredefinedIdCollections;
}
pub type AutoIdDerivativeCollectionsInstance = pallet_derivatives::Instance2;
impl pallet_derivatives::Config<AutoIdDerivativeCollectionsInstance> for Test {
type WeightInfo = pallet_derivatives::TestWeightInfo;
type Original = AssetId;
type Derivative = CollectionAutoId;
type DerivativeExtra = NftLocalId;
type CreateOrigin = EnsureSigned<AccountId>;
type CreateOp = pallet_derivatives::StoreMapping<
CreateDerivativeOwnedBySovAcc<
AutoId<Self::Derivative>,
AutoIdCollections,
pallet_derivatives::InvalidAssetError<AutoIdDerivativeCollections>,
>,
>;
type DestroyOrigin = EnsureRoot<AccountId>;
type DestroyOp = MapId<
Self::Original,
Self::Derivative,
OriginalToDerivativeConvert<AutoIdDerivativeCollections>,
AutoIdCollections,
>;
}
pub type DerivativeNftsInstance = pallet_derivatives::Instance3;
impl pallet_derivatives::Config<DerivativeNftsInstance> for Test {
type WeightInfo = pallet_derivatives::TestWeightInfo;
type Original = NonFungibleAsset;
type Derivative = NftFullId;
type DerivativeExtra = ();
type CreateOrigin = EnsureNever<AccountId>;
type CreateOp = DisabledOps<Self::Original>;
type DestroyOrigin = EnsureNever<AccountId>;
type DestroyOp = DisabledOps<Self::Original>;
}
pub type LocalNftsMatcher = MatchInClassInstances<
MatchedConvertedConcreteId<
CollectionAutoId,
NftLocalId,
StartsWith<LocalNftsPalletLocation>,
AsPrefixedGeneralIndex<LocalNftsPalletLocation, CollectionAutoId, TryConvertInto>,
TryConvertInto,
>,
>;
pub type LocalNftsTransactor = UniqueInstancesAdapter<
AccountId,
LocationToAccountId,
EnsureNotDerivativeInstance<DerivativeNfts, LocalNftsMatcher>,
StashAccountAssetOps<StashAccountId, PredefinedIdNfts>,
>;
pub type RegisteredDerivativeNftsTransactor = UniqueInstancesAdapter<
AccountId,
LocationToAccountId,
MatchDerivativeInstances<DerivativeNfts>,
StashAccountAssetOps<StashAccountId, PredefinedIdNfts>,
>;
pub type CreateUsingXcmNft<CreateOp> = MapId<NonFungibleAsset, AssetId, ExtractAssetId, CreateOp>;
pub type CreateUsingXcmAssetId<CreateOp> = MapId<
AssetId,
CollectionAutoId,
OriginalToDerivativeConvert<AutoIdDerivativeCollections>,
CreateOp,
>;
pub type DeriveNft = ConcatIncrementalExtra<
CollectionAutoId,
NftLocalId,
AutoIdDerivativeCollections,
PredefinedIdNfts,
>;
pub type CreateDerivativeNft = CreateUsingXcmNft<CreateUsingXcmAssetId<DeriveNft>>;
pub type DerivativeNftsRegistrar = UniqueInstancesDepositAdapter<
AccountId,
LocationToAccountId,
NftFullId,
RegisterDerivative<DerivativeNfts, CreateDerivativeNft>,
>;
pub type AssetTransactors =
(LocalNftsTransactor, RegisteredDerivativeNftsTransactor, DerivativeNftsRegistrar);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall;
type XcmSender = ();
type XcmEventEmitter = ();
type AssetTransactor = AssetTransactors;
type OriginConverter = ();
type IsReserve = TrustAssetsFromSiblings;
type IsTeleporter = ();
type UniversalLocation = UniversalLocation;
type Barrier = AllowUnpaidExecutionFrom<Everything>;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, ConstU32<100>>;
type Trader = ();
type ResponseHandler = ();
type AssetTrap = ();
type AssetLocker = ();
type AssetExchanger = ();
type SubscriptionService = ();
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = ();
type MessageExporter = ();
type UniversalAliases = ();
type CallDispatcher = RuntimeCall;
type SafeCallFilter = Nothing;
type Aliasers = Nothing;
type TransactionalProcessor = ();
type HrmpNewChannelOpenRequestHandler = ();
type HrmpChannelAcceptedHandler = ();
type HrmpChannelClosingHandler = ();
type XcmRecorder = ();
}
pub fn new_test_ext() -> sp_io::TestExternalities {
let t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
sp_io::TestExternalities::new(t)
}