diff --git a/runtime/devnet/src/config/api/mod.rs b/runtime/devnet/src/config/api/mod.rs index 035a6014..d96fd85b 100644 --- a/runtime/devnet/src/config/api/mod.rs +++ b/runtime/devnet/src/config/api/mod.rs @@ -11,7 +11,8 @@ use sp_std::vec::Vec; use versioning::*; use crate::{ - config::assets::TrustBackedAssetsInstance, fungibles, Runtime, RuntimeCall, RuntimeEvent, + config::assets::{TrustBackedAssetsInstance, TrustBackedNftsInstance}, + fungibles, nonfungibles, Runtime, RuntimeCall, RuntimeEvent, }; mod versioning; @@ -32,6 +33,9 @@ pub enum RuntimeRead { /// Fungible token queries. #[codec(index = 150)] Fungibles(fungibles::Read), + /// Non-fungible token queries. + #[codec(index = 151)] + NonFungibles(nonfungibles::Read), } impl Readable for RuntimeRead { @@ -43,6 +47,7 @@ impl Readable for RuntimeRead { fn weight(&self) -> Weight { match self { RuntimeRead::Fungibles(key) => fungibles::Pallet::weight(key), + RuntimeRead::NonFungibles(key) => nonfungibles::Pallet::weight(key), } } @@ -50,16 +55,20 @@ impl Readable for RuntimeRead { fn read(self) -> Self::Result { match self { RuntimeRead::Fungibles(key) => RuntimeResult::Fungibles(fungibles::Pallet::read(key)), + RuntimeRead::NonFungibles(key) => + RuntimeResult::NonFungibles(nonfungibles::Pallet::read(key)), } } } /// The result of a runtime state read. #[derive(Debug)] -#[cfg_attr(test, derive(PartialEq, Clone))] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] pub enum RuntimeResult { /// Fungible token read results. Fungibles(fungibles::ReadResult), + /// Non-fungible token read results. + NonFungibles(nonfungibles::ReadResult), } impl RuntimeResult { @@ -67,6 +76,7 @@ impl RuntimeResult { fn encode(&self) -> Vec { match self { RuntimeResult::Fungibles(result) => result.encode(), + RuntimeResult::NonFungibles(result) => result.encode(), } } } @@ -77,6 +87,12 @@ impl fungibles::Config for Runtime { type WeightInfo = fungibles::weights::SubstrateWeight; } +impl nonfungibles::Config for Runtime { + type NftsInstance = TrustBackedNftsInstance; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + #[derive(Default)] pub struct Config; impl pallet_api::extension::Config for Config { @@ -130,8 +146,8 @@ pub struct Filter(PhantomData); impl> Contains for Filter { fn contains(c: &RuntimeCall) -> bool { - use fungibles::Call::*; - T::BaseCallFilter::contains(c) && + let contain_fungibles: bool = { + use fungibles::Call::*; matches!( c, RuntimeCall::Fungibles( @@ -142,26 +158,63 @@ impl> Contains f create { .. } | set_metadata { .. } | start_destroy { .. } | clear_metadata { .. } | - mint { .. } | burn { .. } + mint { .. } | burn { .. }, + ) + ) + }; + + let contain_nonfungibles: bool = { + use nonfungibles::Call::*; + matches!( + c, + RuntimeCall::NonFungibles( + transfer { .. } | + approve { .. } | create { .. } | + destroy { .. } | set_metadata { .. } | + clear_metadata { .. } | + set_attribute { .. } | + clear_attribute { .. } | + approve_item_attributes { .. } | + cancel_item_attributes_approval { .. } | + mint { .. } | burn { .. } | + set_max_supply { .. }, ) ) + }; + + T::BaseCallFilter::contains(c) && contain_fungibles | contain_nonfungibles } } impl Contains for Filter { fn contains(r: &RuntimeRead) -> bool { - use fungibles::Read::*; - matches!( - r, - RuntimeRead::Fungibles( - TotalSupply(..) | - BalanceOf { .. } | - Allowance { .. } | - TokenName(..) | TokenSymbol(..) | - TokenDecimals(..) | - TokenExists(..) + let contain_fungibles: bool = { + use fungibles::Read::*; + matches!( + r, + RuntimeRead::Fungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + TokenName(..) | TokenSymbol(..) | + TokenDecimals(..) | TokenExists(..), + ) + ) + }; + let contain_nonfungibles: bool = { + use nonfungibles::Read::*; + matches!( + r, + RuntimeRead::NonFungibles( + TotalSupply(..) | + BalanceOf { .. } | Allowance { .. } | + OwnerOf { .. } | GetAttribute { .. } | + Collection { .. } | NextCollectionId | + ItemMetadata { .. }, + ) ) - ) + }; + + contain_fungibles | contain_nonfungibles } } @@ -169,8 +222,9 @@ impl Contains for Filter { mod tests { use codec::Encode; use pallet_api::fungibles::Call::*; - use sp_core::crypto::AccountId32; - use RuntimeCall::{Balances, Fungibles}; + use pallet_nfts::MintWitness; + use sp_core::{bounded_vec, crypto::AccountId32}; + use RuntimeCall::{Balances, Fungibles, NonFungibles}; use super::*; @@ -181,6 +235,10 @@ mod tests { let value = 1_000; let result = fungibles::ReadResult::::TotalSupply(value); assert_eq!(RuntimeResult::Fungibles(result).encode(), value.encode()); + + let value = 1_000; + let result = nonfungibles::ReadResult::::TotalSupply(value); + assert_eq!(RuntimeResult::NonFungibles(result).encode(), value.encode()); } #[test] @@ -228,6 +286,76 @@ mod tests { } } + #[test] + fn filter_allows_nonfungibles_calls() { + use pallet_api::nonfungibles::{ + Call::*, CollectionConfig, CollectionSettings, MintSettings, + }; + use pallet_nfts::{CancelAttributesApprovalWitness, DestroyWitness}; + + for call in vec![ + NonFungibles(transfer { collection: 0, item: 0, to: ACCOUNT }), + NonFungibles(approve { + collection: 0, + item: Some(0), + operator: ACCOUNT, + approved: false, + }), + NonFungibles(create { + admin: ACCOUNT, + config: CollectionConfig { + max_supply: Some(0), + mint_settings: MintSettings::default(), + settings: CollectionSettings::all_enabled(), + }, + }), + NonFungibles(destroy { + collection: 0, + witness: DestroyWitness { + attributes: 0, + item_configs: 0, + item_metadatas: 0, + item_holders: 0, + allowances: 0, + }, + }), + NonFungibles(set_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + value: bounded_vec![], + }), + NonFungibles(clear_attribute { + collection: 0, + item: Some(0), + namespace: pallet_nfts::AttributeNamespace::Pallet, + key: bounded_vec![], + }), + NonFungibles(set_metadata { collection: 0, item: 0, data: bounded_vec![] }), + NonFungibles(clear_metadata { collection: 0, item: 0 }), + NonFungibles(approve_item_attributes { collection: 0, item: 0, delegate: ACCOUNT }), + NonFungibles(cancel_item_attributes_approval { + collection: 0, + item: 0, + delegate: ACCOUNT, + witness: CancelAttributesApprovalWitness { account_attributes: 0 }, + }), + NonFungibles(set_max_supply { collection: 0, max_supply: 0 }), + NonFungibles(mint { + to: ACCOUNT, + collection: 0, + item: 0, + witness: MintWitness { mint_price: None, owned_item: None }, + }), + NonFungibles(burn { collection: 0, item: 0 }), + ] + .iter() + { + assert!(Filter::::contains(call)) + } + } + #[test] fn filter_allows_fungibles_reads() { use super::{fungibles::Read::*, RuntimeRead::*}; @@ -245,4 +373,33 @@ mod tests { assert!(Filter::::contains(&read)) } } + + #[test] + fn filter_allows_nonfungibles_reads() { + use super::{nonfungibles::Read::*, RuntimeRead::*}; + + for read in vec![ + NonFungibles(TotalSupply(1)), + NonFungibles(BalanceOf { collection: 1, owner: ACCOUNT }), + NonFungibles(Allowance { + collection: 1, + item: None, + owner: ACCOUNT, + operator: ACCOUNT, + }), + NonFungibles(OwnerOf { collection: 1, item: 1 }), + NonFungibles(GetAttribute { + collection: 0, + item: 0, + namespace: pallet_nfts::AttributeNamespace::CollectionOwner, + key: bounded_vec![], + }), + NonFungibles(Collection(1)), + NonFungibles(NextCollectionId), + ] + .iter() + { + assert!(Filter::::contains(read)) + } + } } diff --git a/runtime/devnet/src/config/assets.rs b/runtime/devnet/src/config/assets.rs index 326b7e59..65405ea4 100644 --- a/runtime/devnet/src/config/assets.rs +++ b/runtime/devnet/src/config/assets.rs @@ -6,7 +6,7 @@ use frame_support::{ use frame_system::{EnsureRoot, EnsureSigned}; use pallet_nfts::PalletFeatures; use parachains_common::{AssetIdForTrustBackedAssets, CollectionId, ItemId, Signature}; -use sp_runtime::traits::Verify; +use sp_runtime::traits::{Get, Verify}; use crate::{ deposit, AccountId, Assets, Balance, Balances, BlockNumber, Nfts, Runtime, RuntimeEvent, @@ -37,7 +37,18 @@ parameter_types! { pub const NftsMaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; } -impl pallet_nfts::Config for Runtime { +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(PartialEq, Clone))] +pub struct KeyLimit; +impl Get for KeyLimit { + fn get() -> u32 { + N + } +} + +pub(crate) type TrustBackedNftsInstance = pallet_nfts::Instance1; +pub type TrustBackedNftsCall = pallet_nfts::Call; +impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ApprovalsLimit = ConstU32<20>; type AttributeDepositBase = NftsAttributeDepositBase; @@ -56,7 +67,7 @@ impl pallet_nfts::Config for Runtime { // TODO: source from primitives type ItemId = ItemId; // TODO: source from primitives - type KeyLimit = ConstU32<64>; + type KeyLimit = KeyLimit<64>; type Locker = (); type MaxAttributesPerCall = ConstU32<10>; type MaxDeadlineDuration = NftsMaxDeadlineDuration; @@ -86,8 +97,8 @@ impl pallet_nft_fractionalization::Config for Runtime { type Deposit = AssetDeposit; type NewAssetName = NewAssetName; type NewAssetSymbol = NewAssetSymbol; - type NftCollectionId = ::CollectionId; - type NftId = ::ItemId; + type NftCollectionId = >::CollectionId; + type NftId = >::ItemId; type Nfts = Nfts; type PalletId = NftFractionalizationPalletId; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/devnet/src/config/proxy.rs b/runtime/devnet/src/config/proxy.rs index ff70240e..48653027 100644 --- a/runtime/devnet/src/config/proxy.rs +++ b/runtime/devnet/src/config/proxy.rs @@ -5,7 +5,7 @@ use pop_runtime_common::proxy::{ }; use sp_runtime::traits::BlakeTwo256; -use super::assets::TrustBackedAssetsCall; +use super::assets::{TrustBackedAssetsCall, TrustBackedNftsCall}; use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; impl InstanceFilter for ProxyType { @@ -45,13 +45,13 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::create { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::destroy { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::redeposit { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::transfer_ownership { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_team { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_collection { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), @@ -66,17 +66,17 @@ impl InstanceFilter for ProxyType { RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::force_mint { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::update_mint_settings { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::mint_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::lock_item_properties { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::set_collection_metadata { .. }) | + RuntimeCall::Nfts(TrustBackedNftsCall::clear_collection_metadata { .. }) | RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. } ), diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs index f539cbde..736f0be7 100644 --- a/runtime/devnet/src/lib.rs +++ b/runtime/devnet/src/lib.rs @@ -39,7 +39,7 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; -use pallet_api::fungibles; +use pallet_api::{fungibles, nonfungibles}; use pallet_balances::Call as BalancesCall; use pallet_ismp::mmr::{Leaf, Proof, ProofKeys}; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; @@ -628,7 +628,7 @@ mod runtime { // Assets #[runtime::pallet_index(50)] - pub type Nfts = pallet_nfts::Pallet; + pub type Nfts = pallet_nfts::Pallet; #[runtime::pallet_index(51)] pub type NftFractionalization = pallet_nft_fractionalization::Pallet; #[runtime::pallet_index(52)] @@ -637,6 +637,8 @@ mod runtime { // Pop API #[runtime::pallet_index(150)] pub type Fungibles = fungibles::Pallet; + #[runtime::pallet_index(151)] + pub type NonFungibles = nonfungibles::Pallet; } #[cfg(feature = "runtime-benchmarks")] @@ -644,10 +646,12 @@ mod benches { frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] [fungibles, Fungibles] + [nonfungibles, NonFungibles] [pallet_balances, Balances] [pallet_session, SessionBench::] [pallet_timestamp, Timestamp] [pallet_message_queue, MessageQueue] + [pallet_nfts, Nfts] [pallet_sudo, Sudo] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem]