--- a/Cargo.lock +++ b/Cargo.lock @@ -99,9 +99,9 @@ [[package]] name = "anyhow" -version = "1.0.58" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" [[package]] name = "approx" @@ -248,9 +248,9 @@ [[package]] name = "async-std" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "52580991739c5cdb36cde8b2a516371c0a3b70dda36d916cc08b82372916808c" dependencies = [ "async-attributes", "async-channel", @@ -267,6 +267,7 @@ "kv-log-macro", "log", "memchr", + "num_cpus", "once_cell", "pin-project-lite 0.2.9", "pin-utils", @@ -1299,9 +1300,9 @@ [[package]] name = "crossbeam-channel" -version = "0.5.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1320,15 +1321,15 @@ [[package]] name = "crossbeam-epoch" -version = "0.9.9" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", + "lazy_static", "memoffset", - "once_cell", "scopeguard", ] @@ -1344,12 +1345,12 @@ [[package]] name = "crossbeam-utils" -version = "0.8.9" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if 1.0.0", - "once_cell", + "lazy_static", ] [[package]] @@ -2157,9 +2158,9 @@ [[package]] name = "dyn-clone" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140206b78fb2bc3edbcfc9b5ccbd0b30699cfe8d348b8b31b330e47df5291a5a" +checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" [[package]] name = "ecdsa" @@ -3661,12 +3662,12 @@ [[package]] name = "indexmap" -version = "1.9.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3" +checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" dependencies = [ "autocfg", - "hashbrown 0.12.1", + "hashbrown 0.11.2", "serde", ] @@ -4955,9 +4956,9 @@ [[package]] name = "mio" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", @@ -5208,9 +5209,9 @@ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" dependencies = [ "num-traits", ] @@ -8435,9 +8436,9 @@ [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ "unicode-ident", ] @@ -8557,11 +8558,14 @@ "fp-evm-mapping", "fp-rpc", "fp-self-contained", + "frame-benchmarking", "frame-executive", "frame-support", "frame-system", + "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", + "hex-literal", "log", "orml-vesting", "pallet-aura", @@ -8639,9 +8643,9 @@ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] @@ -9264,9 +9268,9 @@ [[package]] name = "rustversion" -version = "1.0.7" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "rw-stream-sink" @@ -11587,7 +11591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ - "strum_macros 0.24.0", + "strum_macros 0.24.1", ] [[package]] @@ -11605,9 +11609,9 @@ [[package]] name = "strum_macros" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" +checksum = "9550962e7cf70d9980392878dfaf1dcc3ece024f4cf3bf3c46b978d0bad61d6c" dependencies = [ "heck 0.4.0", "proc-macro2", @@ -11763,9 +11767,9 @@ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" dependencies = [ "proc-macro2", "quote", @@ -12122,9 +12126,9 @@ [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" @@ -12356,7 +12360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.3", "rand 0.8.5", "static_assertions", --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ .PHONY: _bench _bench: - cargo run --release --features runtime-benchmarks,unique-runtime -- \ + cargo run --release --features runtime-benchmarks,$(RUNTIME) -- \ benchmark pallet --pallet pallet-$(if $(PALLET),$(PALLET),$(error Must set PALLET)) \ --wasm-execution compiled --extrinsic '*' \ --template .maintain/frame-weight-template.hbs --steps=50 --repeat=80 --heap-pages=4096 \ @@ -101,5 +101,9 @@ bench-rmrk-core: make _bench PALLET=proxy-rmrk-core +.PHONY: bench-rmrk-equip +bench-rmrk-equip: + make _bench PALLET=proxy-rmrk-equip + .PHONY: bench -bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-scheduler bench-rmrk-core +bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-scheduler bench-rmrk-core bench-rmrk-equip --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -323,7 +323,9 @@ [features] default = [] runtime-benchmarks = [ - 'unique-runtime/runtime-benchmarks', + 'unique-runtime?/runtime-benchmarks', + 'quartz-runtime?/runtime-benchmarks', + 'opal-runtime/runtime-benchmarks', 'polkadot-service/runtime-benchmarks', ] try-runtime = [] --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -26,13 +26,13 @@ use unique_runtime_common::types::*; #[cfg(feature = "unique-runtime")] -use unique_runtime as default_runtime; +pub use unique_runtime as default_runtime; #[cfg(all(not(feature = "unique-runtime"), feature = "quartz-runtime"))] -use quartz_runtime as default_runtime; +pub use quartz_runtime as default_runtime; #[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))] -use opal_runtime as default_runtime; +pub use opal_runtime as default_runtime; /// The `ChainSpec` parameterized for the unique runtime. #[cfg(feature = "unique-runtime")] --- a/node/cli/src/command.rs +++ b/node/cli/src/command.rs @@ -33,7 +33,9 @@ // limitations under the License. use crate::{ - chain_spec::{self, RuntimeId, RuntimeIdentification, ServiceId, ServiceIdentification}, + chain_spec::{ + self, RuntimeId, RuntimeIdentification, ServiceId, ServiceIdentification, default_runtime, + }, cli::{Cli, RelayChainCli, Subcommand}, service::{new_partial, start_node, start_dev_node}, }; @@ -44,7 +46,7 @@ #[cfg(feature = "quartz-runtime")] use crate::service::QuartzRuntimeExecutor; -use crate::service::OpalRuntimeExecutor; +use crate::service::{OpalRuntimeExecutor, DefaultRuntimeExecutor}; use codec::Encode; use cumulus_primitives_core::ParaId; @@ -372,7 +374,6 @@ Ok(()) } - #[cfg(feature = "unique-runtime")] Some(Subcommand::Benchmark(cmd)) => { use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; let runner = cli.create_runner(cmd)?; @@ -380,7 +381,7 @@ match cmd { BenchmarkCmd::Pallet(cmd) => { if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." @@ -389,16 +390,16 @@ } BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { let partials = new_partial::< - unique_runtime::RuntimeApi, - UniqueRuntimeExecutor, + default_runtime::RuntimeApi, + DefaultRuntimeExecutor, _, >(&config, crate::service::parachain_build_import_queue)?; cmd.run(partials.client) }), BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial::< - unique_runtime::RuntimeApi, - UniqueRuntimeExecutor, + default_runtime::RuntimeApi, + DefaultRuntimeExecutor, _, >(&config, crate::service::parachain_build_import_queue)?; let db = partials.backend.expose_db(); @@ -411,10 +412,6 @@ } BenchmarkCmd::Overhead(_) => Err("Unsupported benchmarking command".into()), } - } - #[cfg(not(feature = "unique-runtime"))] - Some(Subcommand::Benchmark(..)) => { - Err("benchmarking is only available with unique runtime enabled".into()) } Some(Subcommand::TryRuntime(cmd)) => { if cfg!(feature = "try-runtime") { --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -77,13 +77,21 @@ #[cfg(feature = "quartz-runtime")] /// Quartz native executor instance. - pub struct QuartzRuntimeExecutor; /// Opal native executor instance. pub struct OpalRuntimeExecutor; #[cfg(feature = "unique-runtime")] +pub type DefaultRuntimeExecutor = UniqueRuntimeExecutor; + +#[cfg(all(not(feature = "unique-runtime"), feature = "quartz-runtime"))] +pub type DefaultRuntimeExecutor = QuartzRuntimeExecutor; + +#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))] +pub type DefaultRuntimeExecutor = OpalRuntimeExecutor; + +#[cfg(feature = "unique-runtime")] impl NativeExecutionDispatch for UniqueRuntimeExecutor { type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -74,7 +74,7 @@ RmrkPropertyInfo, RmrkBaseInfo, RmrkPartType, - RmrkTheme, + RmrkBoundedTheme, RmrkNftChild, CollectionPermissions, SchemaVersion, @@ -543,7 +543,7 @@ RmrkPropertyInfo, RmrkBaseInfo, RmrkPartType, - RmrkTheme, + RmrkBoundedTheme, RmrkNftChild, )>, ), --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -28,7 +28,7 @@ use up_data_structs::{ AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission, PropertyKey, - PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, TokenChild, + PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, TokenChild, AuxPropertyValue, }; use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm}; use pallet_common::{ @@ -124,6 +124,19 @@ OnEmpty = up_data_structs::TokenProperties, >; + #[pallet::storage] + #[pallet::getter(fn token_aux_property)] + pub type TokenAuxProperties = StorageNMap< + Key = ( + Key, + Key, + Key, + Key, + ), + Value = AuxPropertyValue, + QueryKind = OptionQuery, + >; + /// Used to enumerate tokens owned by account #[pallet::storage] pub type Owned = StorageNMap< @@ -294,6 +307,33 @@ Ok(()) } + pub fn try_mutate_token_aux_property( + collection_id: CollectionId, + token_id: TokenId, + scope: PropertyScope, + key: PropertyKey, + f: impl FnOnce(&mut Option) -> Result, + ) -> Result { + >::try_mutate((collection_id, token_id, scope, key), f) + } + + pub fn remove_token_aux_property( + collection_id: CollectionId, + token_id: TokenId, + scope: PropertyScope, + key: PropertyKey, + ) { + >::remove((collection_id, token_id, scope, key)); + } + + pub fn iterate_token_aux_properties( + collection_id: CollectionId, + token_id: TokenId, + scope: PropertyScope, + ) -> impl Iterator { + >::iter_prefix((collection_id, token_id, scope)) + } + pub fn current_token_id(collection_id: CollectionId) -> TokenId { TokenId(>::get(collection_id)) } @@ -375,6 +415,7 @@ >::insert(collection.id, burnt); >::remove((collection.id, token)); >::remove((collection.id, token)); + >::remove_prefix((collection.id, token), None); let old_spender = >::take((collection.id, token)); if let Some(old_spender) = old_spender { --- a/pallets/proxy-rmrk-core/src/benchmarking.rs +++ b/pallets/proxy-rmrk-core/src/benchmarking.rs @@ -85,7 +85,7 @@ >::mint_nft( RawOrigin::Signed(owner.clone()).into(), - owner.clone(), + None, collection_id, royalty_recipient, royalty_amount, @@ -106,10 +106,6 @@ collection_id, current_nft_id: 0, } - } - - fn current_nft_id(&self) -> RmrkNftId { - self.current_nft_id } fn build(&mut self, owner: &T::AccountId) -> Result { @@ -220,7 +216,6 @@ let b in 0..100; let caller: T::AccountId = account("caller", 0, SEED); - ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); create_max_collection::(&caller)?; let collection_id = 0; @@ -232,7 +227,7 @@ let transferable = true; }: _( RawOrigin::Signed(caller), - owner, + None, collection_id, royalty_recipient, royalty_amount, @@ -381,7 +376,6 @@ add_basic_resource { let caller: T::AccountId = account("caller", 0, SEED); - ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); create_max_collection::(&caller)?; let collection_id = 0; @@ -398,7 +392,6 @@ add_composable_resource { let caller: T::AccountId = account("caller", 0, SEED); - ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); create_max_collection::(&caller)?; let collection_id = 0; @@ -415,7 +408,6 @@ add_slot_resource { let caller: T::AccountId = account("caller", 0, SEED); - ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); create_max_collection::(&caller)?; let collection_id = 0; @@ -432,7 +424,6 @@ remove_resource { let caller: T::AccountId = account("caller", 0, SEED); - ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); create_max_collection::(&caller)?; let collection_id = 0; @@ -448,7 +439,7 @@ resource )?; - let resource_id = 1; + let resource_id = 0; }: _( RawOrigin::Signed(caller), collection_id, @@ -460,8 +451,6 @@ let caller: T::AccountId = account("caller", 0, SEED); let admin: T::AccountId = account("admin", 0, SEED); - ::Currency::deposit_creating(&admin, T::CollectionCreationPrice::get()); - create_max_collection::(&admin)?; let collection_id = 0; @@ -486,7 +475,7 @@ resource )?; - let resource_id = 1; + let resource_id = 0; }: _( RawOrigin::Signed(caller), collection_id, @@ -497,8 +486,6 @@ accept_resource_removal { let caller: T::AccountId = account("caller", 0, SEED); let admin: T::AccountId = account("admin", 0, SEED); - - ::Currency::deposit_creating(&admin, T::CollectionCreationPrice::get()); create_max_collection::(&admin)?; let collection_id = 0; @@ -515,7 +502,7 @@ resource )?; - let resource_id = 1; + let resource_id = 0; let new_owner = >::AccountId(caller.clone()); --- a/pallets/proxy-rmrk-core/src/lib.rs +++ b/pallets/proxy-rmrk-core/src/lib.rs @@ -35,6 +35,7 @@ pub mod benchmarking; pub mod misc; pub mod property; +pub mod rpc; pub mod weights; pub type SelfWeightOf = ::WeightInfo; @@ -154,6 +155,7 @@ NftTypeEncodeError, RmrkPropertyKeyIsTooLong, RmrkPropertyValueIsTooLong, + RmrkPropertyIsNotFound, UnableToDecodeRmrkData, /* RMRK compatible events */ @@ -168,7 +170,9 @@ CannotSendToDescendentOrSelf, CannotAcceptNonOwnedNft, CannotRejectNonOwnedNft, + CannotRejectNonPendingNft, ResourceNotPending, + NoAvailableResourceId, } #[pallet::call] @@ -347,7 +351,7 @@ #[pallet::weight(>::mint_nft(resources.as_ref().map(|r| r.len() as u32).unwrap_or(0)))] pub fn mint_nft( origin: OriginFor, - owner: T::AccountId, + owner: Option, collection_id: RmrkCollectionId, recipient: Option, royalty_amount: Option, @@ -357,6 +361,8 @@ ) -> DispatchResult { let sender = ensure_signed(origin)?; let cross_sender = T::CrossAccountId::from_sub(sender.clone()); + + let owner = owner.unwrap_or(sender.clone()); let cross_owner = T::CrossAccountId::from_sub(owner.clone()); let collection = Self::get_typed_nft_collection( @@ -381,8 +387,8 @@ Self::rmrk_property(RoyaltyInfo, &royalty_info)?, Self::rmrk_property(Metadata, &metadata)?, Self::rmrk_property(Equipped, &false)?, - Self::rmrk_property(ResourceCollection, &None::)?, Self::rmrk_property(ResourcePriorities, &>::new())?, + Self::rmrk_property(NextResourceId, &(0 as RmrkResourceId))?, ] .into_iter(), ) @@ -653,12 +659,17 @@ collection.check_is_external()?; ensure!( + >::get((collection_id, nft_id)).is_some(), + >::NoAvailableNftId + ); + + ensure!( Self::get_nft_property_decoded( collection_id, nft_id, RmrkProperty::PendingNftAccept )?, - >::NoPermission + >::CannotRejectNonPendingNft ); Self::destroy_nft( @@ -686,7 +697,7 @@ origin: OriginFor, rmrk_collection_id: RmrkCollectionId, rmrk_nft_id: RmrkNftId, - rmrk_resource_id: RmrkResourceId, + resource_id: RmrkResourceId, ) -> DispatchResult { let sender = ensure_signed(origin)?; let cross_sender = T::CrossAccountId::from_sub(sender); @@ -698,7 +709,6 @@ collection.check_is_external()?; let nft_id = rmrk_nft_id.into(); - let resource_id = rmrk_resource_id.into(); let budget = budget::Value::new(NESTING_BUDGET); @@ -706,34 +716,18 @@ >::find_topmost_owner(collection_id, nft_id, &budget) .map_err(|_| >::ResourceDoesntExist)?; - let resource_collection_id: Option = - Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection) - .map_err(|_| >::ResourceDoesntExist)?; - - let resource_collection_id = - resource_collection_id.ok_or(>::ResourceDoesntExist)?; - - let is_pending: bool = Self::get_nft_property_decoded( - resource_collection_id, - resource_id, - PendingResourceAccept, - ) - .map_err(|_| >::ResourceDoesntExist)?; + Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| { + ensure!(res.pending, >::ResourceNotPending); + ensure!(cross_sender == nft_owner, >::NoPermission); - ensure!(is_pending, >::ResourceNotPending); + res.pending = false; - ensure!(cross_sender == nft_owner, >::NoPermission); - - >::set_scoped_token_property( - resource_collection_id, - rmrk_resource_id.into(), - PropertyScope::Rmrk, - Self::rmrk_property(PendingResourceAccept, &false)?, - )?; + Ok(()) + })?; Self::deposit_event(Event::::ResourceAccepted { nft_id: rmrk_nft_id, - resource_id: rmrk_resource_id, + resource_id, }); Ok(()) @@ -746,7 +740,7 @@ origin: OriginFor, rmrk_collection_id: RmrkCollectionId, rmrk_nft_id: RmrkNftId, - rmrk_resource_id: RmrkResourceId, + resource_id: RmrkResourceId, ) -> DispatchResult { let sender = ensure_signed(origin)?; let cross_sender = T::CrossAccountId::from_sub(sender); @@ -758,7 +752,6 @@ collection.check_is_external()?; let nft_id = rmrk_nft_id.into(); - let resource_id = rmrk_resource_id.into(); let budget = budget::Value::new(NESTING_BUDGET); @@ -768,42 +761,33 @@ ensure!(cross_sender == nft_owner, >::NoPermission); - let resource_collection_id: Option = - Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection) - .map_err(|_| >::ResourceDoesntExist)?; + let resource_id_key = Self::rmrk_property_key(ResourceId(resource_id))?; - let resource_collection_id = - resource_collection_id.ok_or(>::ResourceDoesntExist)?; + let resource_info = >::token_aux_property(( + collection_id, + nft_id, + PropertyScope::Rmrk, + resource_id_key.clone(), + )) + .ok_or(>::ResourceDoesntExist)?; - let is_pending: bool = Self::get_nft_property_decoded( - resource_collection_id, - resource_id, - PendingResourceRemoval, - ) - .map_err(|_| >::ResourceDoesntExist)?; + let resource_info: RmrkResourceInfo = Self::decode_property(&resource_info)?; - ensure!(is_pending, >::ResourceNotPending); + ensure!( + resource_info.pending_removal, + >::ResourceNotPending + ); - let resource_collection = Self::get_typed_nft_collection( - resource_collection_id, - misc::CollectionType::Resource, - )?; - - let resource_data = >::get((resource_collection_id, resource_id)) - .ok_or(>::ResourceDoesntExist)?; - - let resource_owner = resource_data.owner; - - >::burn( - &resource_collection, - &resource_owner, - rmrk_resource_id.into(), - ) - .map_err(Self::map_unique_err_to_proxy)?; + >::remove_token_aux_property( + collection_id, + nft_id, + PropertyScope::Rmrk, + resource_id_key, + ); Self::deposit_event(Event::::ResourceRemovalAccepted { nft_id: rmrk_nft_id, - resource_id: rmrk_resource_id, + resource_id, }); Ok(()) @@ -1014,7 +998,7 @@ Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?; collection.check_is_external()?; - Self::resource_remove(sender, collection_id, nft_id.into(), resource_id.into())?; + Self::resource_remove(sender, collection_id, nft_id.into(), resource_id)?; Self::deposit_event(Event::ResourceRemoval { nft_id, @@ -1043,17 +1027,27 @@ ) -> Result { let key = rmrk_key.to_key::()?; + let value = Self::encode_property(value)?; + + let property = Property { key, value }; + + Ok(property) + } + + pub fn encode_property>( + value: &E, + ) -> Result, DispatchError> { let value = value .encode() .try_into() .map_err(|_| >::RmrkPropertyValueIsTooLong)?; - let property = Property { key, value }; - - Ok(property) + Ok(value) } - pub fn decode_property(vec: PropertyValue) -> Result { + pub fn decode_property>( + vec: &BoundedBytes, + ) -> Result { vec.decode() .map_err(|_| >::UnableToDecodeRmrkData.into()) } @@ -1153,67 +1147,32 @@ ) } - fn resource_add( - sender: T::AccountId, + fn acquire_next_resource_id( collection_id: CollectionId, nft_id: TokenId, - resource: RmrkResourceTypes, ) -> Result { - match resource { - RmrkResourceTypes::Basic(resource) => Self::resource_add_helper( - sender, - collection_id, - nft_id, - [ - Self::rmrk_property(TokenType, &NftType::Resource)?, - Self::rmrk_property(ResourceType, &misc::ResourceType::Basic)?, - Self::rmrk_property(Src, &resource.src)?, - Self::rmrk_property(Metadata, &resource.metadata)?, - Self::rmrk_property(License, &resource.license)?, - Self::rmrk_property(Thumb, &resource.thumb)?, - ] - .into_iter(), - ), - RmrkResourceTypes::Composable(resource) => Self::resource_add_helper( - sender, - collection_id, - nft_id.into(), - [ - Self::rmrk_property(TokenType, &NftType::Resource)?, - Self::rmrk_property(ResourceType, &misc::ResourceType::Composable)?, - Self::rmrk_property(Parts, &resource.parts)?, - Self::rmrk_property(Base, &resource.base)?, - Self::rmrk_property(Src, &resource.src)?, - Self::rmrk_property(Metadata, &resource.metadata)?, - Self::rmrk_property(License, &resource.license)?, - Self::rmrk_property(Thumb, &resource.thumb)?, - ] - .into_iter(), - ), - RmrkResourceTypes::Slot(resource) => Self::resource_add_helper( - sender, - collection_id, - nft_id.into(), - [ - Self::rmrk_property(TokenType, &NftType::Resource)?, - Self::rmrk_property(ResourceType, &misc::ResourceType::Slot)?, - Self::rmrk_property(Base, &resource.base)?, - Self::rmrk_property(Src, &resource.src)?, - Self::rmrk_property(Metadata, &resource.metadata)?, - Self::rmrk_property(Slot, &resource.slot)?, - Self::rmrk_property(License, &resource.license)?, - Self::rmrk_property(Thumb, &resource.thumb)?, - ] - .into_iter(), - ), - } + let resource_id: RmrkResourceId = + Self::get_nft_property_decoded(collection_id, nft_id, NextResourceId)?; + + let next_id = resource_id + .checked_add(1) + .ok_or(>::NoAvailableResourceId)?; + + >::set_scoped_token_property( + collection_id, + nft_id, + PropertyScope::Rmrk, + Self::rmrk_property(NextResourceId, &next_id)?, + )?; + + Ok(resource_id) } - fn resource_add_helper( + fn resource_add( sender: T::AccountId, collection_id: CollectionId, - token_id: TokenId, - resource_properties: impl Iterator, + nft_id: TokenId, + resource: RmrkResourceTypes, ) -> Result { let collection = Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?; @@ -1222,86 +1181,57 @@ let sender = T::CrossAccountId::from_sub(sender); let budget = budget::Value::new(NESTING_BUDGET); - let nft_owner = >::find_topmost_owner(collection_id, token_id, &budget) + let nft_owner = >::find_topmost_owner(collection_id, nft_id, &budget) .map_err(Self::map_unique_err_to_proxy)?; let pending = sender != nft_owner; - let resource_collection_id: Option = - Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?; + let id = Self::acquire_next_resource_id(collection_id, nft_id)?; - let resource_collection_id = match resource_collection_id { - Some(id) => id, - None => { - let resource_collection_id = Self::init_collection( - sender.clone(), - CreateCollectionData { - ..Default::default() - }, - [Self::rmrk_property( - CollectionType, - &misc::CollectionType::Resource, - )?] - .into_iter(), - )?; - - >::set_scoped_token_property( - collection_id, - token_id, - PropertyScope::Rmrk, - Self::rmrk_property(ResourceCollection, &Some(resource_collection_id))?, - )?; - - resource_collection_id - } + let resource_info = RmrkResourceInfo { + id, + resource, + pending, + pending_removal: false, }; - let resource_collection = - Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?; + >::try_mutate_token_aux_property( + collection_id, + nft_id, + PropertyScope::Rmrk, + Self::rmrk_property_key(ResourceId(id))?, + |value| -> DispatchResult { + *value = Some(Self::encode_property(&resource_info)?); - // todo probably add extra connections to bases, slots, etc., when RMRK starts to use them + Ok(()) + }, + )?; - let resource_id = Self::create_nft( - &sender, - &nft_owner, - &resource_collection, - resource_properties.chain( - [ - Self::rmrk_property(PendingResourceAccept, &pending)?, - Self::rmrk_property(PendingResourceRemoval, &false)?, - ] - .into_iter(), - ), - ) - .map_err(|err| match err { - DispatchError::Arithmetic(_) => >::NoAvailableNftId.into(), - err => Self::map_unique_err_to_proxy(err), - })?; - - Ok(resource_id.0) + Ok(id) } fn resource_remove( sender: T::AccountId, collection_id: CollectionId, nft_id: TokenId, - resource_id: TokenId, + resource_id: RmrkResourceId, ) -> DispatchResult { let collection = Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?; ensure!(collection.owner == sender, Error::::NoPermission); - let resource_collection_id: Option = - Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)?; - - let resource_collection_id = - resource_collection_id.ok_or(Error::::ResourceDoesntExist)?; + let resource_id_key = Self::rmrk_property_key(ResourceId(resource_id))?; + let scope = PropertyScope::Rmrk; - let resource_collection = - Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?; ensure!( - >::token_exists(&resource_collection, resource_id), - Error::::ResourceDoesntExist + >::token_aux_property(( + collection_id, + nft_id, + scope, + resource_id_key.clone() + )) + .is_some(), + >::ResourceDoesntExist ); let budget = up_data_structs::budget::Value::new(NESTING_BUDGET); @@ -1310,20 +1240,49 @@ let sender = T::CrossAccountId::from_sub(sender); if topmost_owner == sender { - >::burn(&resource_collection, &sender, resource_id) - .map_err(Self::map_unique_err_to_proxy)?; - } else { - >::set_scoped_token_property( - resource_collection_id, - resource_id, + >::remove_token_aux_property( + collection_id, + nft_id, PropertyScope::Rmrk, - Self::rmrk_property(PendingResourceRemoval, &true)?, - )?; + Self::rmrk_property_key(ResourceId(resource_id))?, + ); + } else { + Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| { + res.pending_removal = true; + + Ok(()) + })?; } Ok(()) } + fn try_mutate_resource_info( + collection_id: CollectionId, + nft_id: TokenId, + resource_id: RmrkResourceId, + f: impl FnOnce(&mut RmrkResourceInfo) -> DispatchResult, + ) -> DispatchResult { + >::try_mutate_token_aux_property( + collection_id, + nft_id, + PropertyScope::Rmrk, + Self::rmrk_property_key(ResourceId(resource_id))?, + |value| match value { + Some(value) => { + let mut resource_info: RmrkResourceInfo = Self::decode_property(value)?; + + f(&mut resource_info)?; + + *value = Self::encode_property(&resource_info)?; + + Ok(()) + } + None => Err(>::ResourceDoesntExist.into()), + }, + ) + } + fn change_collection_owner( collection_id: CollectionId, collection_type: misc::CollectionType, @@ -1339,7 +1298,7 @@ collection.save() } - fn check_collection_owner( + pub fn check_collection_owner( collection: &NonfungibleHandle, account: &T::CrossAccountId, ) -> DispatchResult { @@ -1397,14 +1356,19 @@ collection_id: CollectionId, key: RmrkProperty, ) -> Result { - Self::decode_property(Self::get_collection_property(collection_id, key)?) + Self::decode_property(&Self::get_collection_property(collection_id, key)?) } pub fn get_collection_type( collection_id: CollectionId, ) -> Result { - Self::get_collection_property_decoded(collection_id, CollectionType) - .map_err(|_| >::CorruptedCollectionType.into()) + Self::get_collection_property_decoded(collection_id, CollectionType).map_err(|err| { + if err != >::CollectionUnknown.into() { + >::CorruptedCollectionType.into() + } else { + err + } + }) } pub fn ensure_collection_type( @@ -1450,7 +1414,7 @@ ) -> Result { let nft_property = >::token_properties((collection_id, nft_id)) .get(&Self::rmrk_property_key(key)?) - .ok_or(>::NoAvailableNftId)? // todo replace with better error? + .ok_or(>::RmrkPropertyIsNotFound)? .clone(); Ok(nft_property) @@ -1461,7 +1425,7 @@ nft_id: TokenId, key: RmrkProperty, ) -> Result { - Self::decode_property(Self::get_nft_property(collection_id, nft_id, key)?) + Self::decode_property(&Self::get_nft_property(collection_id, nft_id, key)?) } pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool { --- a/pallets/proxy-rmrk-core/src/misc.rs +++ b/pallets/proxy-rmrk-core/src/misc.rs @@ -61,22 +61,13 @@ #[derive(Encode, Decode, PartialEq, Eq)] pub enum CollectionType { Regular, - Resource, Base, } #[derive(Encode, Decode, PartialEq, Eq)] pub enum NftType { Regular, - Resource, FixedPart, SlotPart, Theme, -} - -#[derive(Encode, Decode, PartialEq, Eq)] -pub enum ResourceType { - Basic, - Composable, - Slot, } --- a/pallets/proxy-rmrk-core/src/property.rs +++ b/pallets/proxy-rmrk-core/src/property.rs @@ -17,6 +17,8 @@ use super::*; use core::convert::AsRef; +const RESOURCE_ID_PREFIX: &str = "rsid-"; + pub enum RmrkProperty<'r> { Metadata, CollectionType, @@ -25,18 +27,13 @@ Transferable, RoyaltyInfo, Equipped, - ResourceCollection, ResourcePriorities, - ResourceType, + NextResourceId, + ResourceId(RmrkResourceId), PendingNftAccept, - PendingResourceAccept, - PendingResourceRemoval, Parts, Base, Src, - Slot, - License, - Thumb, EquippedNft, BaseType, ExternalPartId, @@ -72,18 +69,13 @@ Self::Transferable => key!("transferable"), Self::RoyaltyInfo => key!("royalty-info"), Self::Equipped => key!("equipped"), - Self::ResourceCollection => key!("resource-collection"), Self::ResourcePriorities => key!("resource-priorities"), - Self::ResourceType => key!("resource-type"), + Self::NextResourceId => key!("next-resource-id"), + Self::ResourceId(id) => key!(RESOURCE_ID_PREFIX, id.to_le_bytes()), Self::PendingNftAccept => key!("pending-nft-accept"), - Self::PendingResourceAccept => key!("pending-resource-accept"), - Self::PendingResourceRemoval => key!("pending-resource-removal"), Self::Parts => key!("parts"), Self::Base => key!("base"), Self::Src => key!("src"), - Self::Slot => key!("slot"), - Self::License => key!("license"), - Self::Thumb => key!("thumb"), Self::EquippedNft => key!("equipped-nft"), Self::BaseType => key!("base-type"), Self::ExternalPartId => key!("ext-part-id"), --- /dev/null +++ b/pallets/proxy-rmrk-core/src/rpc.rs @@ -0,0 +1,265 @@ +use super::*; + +pub fn last_collection_idx() -> Result { + Ok(>::last_collection_idx()) +} + +pub fn collection_by_id( + collection_id: RmrkCollectionId, +) -> Result>, DispatchError> { + let (collection, collection_id) = match >::get_typed_nft_collection_mapped( + collection_id, + misc::CollectionType::Regular, + ) { + Ok(c) => c, + Err(_) => return Ok(None), + }; + + let nfts_count = collection.total_supply(); + + Ok(Some(RmrkCollectionInfo { + issuer: collection.owner.clone(), + metadata: >::get_collection_property_decoded( + collection_id, + RmrkProperty::Metadata, + )?, + max: collection.limits.token_limit, + symbol: >::rebind(&collection.token_prefix)?, + nfts_count, + })) +} + +pub fn nft_by_id( + collection_id: RmrkCollectionId, + nft_by_id: RmrkNftId, +) -> Result>, DispatchError> { + let (collection, collection_id) = match >::get_typed_nft_collection_mapped( + collection_id, + misc::CollectionType::Regular, + ) { + Ok(c) => c, + Err(_) => return Ok(None), + }; + + let nft_id = TokenId(nft_by_id); + if !>::nft_exists(collection_id, nft_id) { + return Ok(None); + } + + let owner = match collection.token_owner(nft_id) { + Some(owner) => match T::CrossTokenAddressMapping::address_to_token(&owner) { + Some((col, tok)) => { + let rmrk_collection = >::rmrk_collection_id(col)?; + + RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0) + } + None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone()), + }, + None => return Ok(None), + }; + + Ok(Some(RmrkInstanceInfo { + owner: owner, + royalty: >::get_nft_property_decoded( + collection_id, + nft_id, + RmrkProperty::RoyaltyInfo, + )?, + metadata: >::get_nft_property_decoded( + collection_id, + nft_id, + RmrkProperty::Metadata, + )?, + equipped: >::get_nft_property_decoded( + collection_id, + nft_id, + RmrkProperty::Equipped, + )?, + pending: >::get_nft_property_decoded( + collection_id, + nft_id, + RmrkProperty::PendingNftAccept, + )?, + })) +} + +pub fn account_tokens( + account_id: T::AccountId, + collection_id: RmrkCollectionId, +) -> Result, DispatchError> { + let cross_account_id = CrossAccountId::from_sub(account_id); + + let (collection, collection_id) = match >::get_typed_nft_collection_mapped( + collection_id, + misc::CollectionType::Regular, + ) { + Ok(c) => c, + Err(_) => return Ok(Vec::new()), + }; + + let tokens = collection + .account_tokens(cross_account_id) + .into_iter() + .filter(|token| { + let is_pending = >::get_nft_property_decoded( + collection_id, + *token, + RmrkProperty::PendingNftAccept, + ) + .unwrap_or(true); + + !is_pending + }) + .map(|token| token.0) + .collect(); + + Ok(tokens) +} + +pub fn nft_children( + collection_id: RmrkCollectionId, + nft_id: RmrkNftId, +) -> Result, DispatchError> { + let collection_id = match >::unique_collection_id(collection_id) { + Ok(id) => id, + Err(_) => return Ok(Vec::new()), + }; + let nft_id = TokenId(nft_id); + if !>::nft_exists(collection_id, nft_id) { + return Ok(Vec::new()); + } + + Ok( + pallet_nonfungible::TokenChildren::::iter_prefix((collection_id, nft_id)) + .filter_map(|((child_collection, child_token), _)| { + let is_pending = >::get_nft_property_decoded( + child_collection, + child_token, + RmrkProperty::PendingNftAccept, + ) + .ok()?; + + if is_pending { + return None; + } + + let rmrk_child_collection = + >::rmrk_collection_id(child_collection).ok()?; + + Some(RmrkNftChild { + collection_id: rmrk_child_collection, + nft_id: child_token.0, + }) + }) + .collect(), + ) +} + +pub fn collection_properties( + collection_id: RmrkCollectionId, + filter_keys: Option>, +) -> Result, DispatchError> { + let collection_id = match >::unique_collection_id(collection_id) { + Ok(id) => id, + Err(_) => return Ok(Vec::new()), + }; + if >::ensure_collection_type(collection_id, misc::CollectionType::Regular).is_err() { + return Ok(Vec::new()); + } + + let properties = >::filter_user_properties( + collection_id, + /* token_id = */ None, + filter_keys, + |key, value| RmrkPropertyInfo { key, value }, + )?; + + Ok(properties) +} + +pub fn nft_properties( + collection_id: RmrkCollectionId, + nft_id: RmrkNftId, + filter_keys: Option>, +) -> Result, DispatchError> { + let collection_id = match >::unique_collection_id(collection_id) { + Ok(id) => id, + Err(_) => return Ok(Vec::new()), + }; + let token_id = TokenId(nft_id); + + if >::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() { + return Ok(Vec::new()); + } + + let properties = >::filter_user_properties( + collection_id, + Some(token_id), + filter_keys, + |key, value| RmrkPropertyInfo { key, value }, + )?; + + Ok(properties) +} + +pub fn nft_resources( + collection_id: RmrkCollectionId, + nft_id: RmrkNftId, +) -> Result, DispatchError> { + let collection_id = match >::unique_collection_id(collection_id) { + Ok(id) => id, + Err(_) => return Ok(Vec::new()), + }; + if >::ensure_collection_type(collection_id, misc::CollectionType::Regular).is_err() { + return Ok(Vec::new()); + } + + let nft_id = TokenId(nft_id); + if >::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { + return Ok(Vec::new()); + } + + let resources = >::iterate_token_aux_properties( + collection_id, + nft_id, + PropertyScope::Rmrk, + ) + .filter_map(|(_, value)| { + let resource_info: RmrkResourceInfo = >::decode_property(&value).ok()?; + + Some(resource_info) + }) + .collect(); + + Ok(resources) +} + +pub fn nft_resource_priority( + collection_id: RmrkCollectionId, + nft_id: RmrkNftId, + resource_id: RmrkResourceId, +) -> Result, DispatchError> { + let collection_id = match >::unique_collection_id(collection_id) { + Ok(id) => id, + Err(_) => return Ok(None), + }; + if >::ensure_collection_type(collection_id, misc::CollectionType::Regular).is_err() { + return Ok(None); + } + + let nft_id = TokenId(nft_id); + if >::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { + return Ok(None); + } + + let priorities: Vec<_> = >::get_nft_property_decoded( + collection_id, + nft_id, + RmrkProperty::ResourcePriorities, + )?; + Ok(priorities + .into_iter() + .enumerate() + .find(|(_, id)| *id == resource_id) + .map(|(priority, _): (usize, RmrkResourceId)| priority as u32)) +} --- a/pallets/proxy-rmrk-core/src/weights.rs +++ b/pallets/proxy-rmrk-core/src/weights.rs @@ -3,7 +3,7 @@ //! Autogenerated weights for pallet_proxy_rmrk_core //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-06-14, STEPS: `50`, REPEAT: 200, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-06-17, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: @@ -19,7 +19,7 @@ // --template // .maintain/frame-weight-template.hbs // --steps=50 -// --repeat=200 +// --repeat=80 // --heap-pages=4096 // --output=./pallets/proxy-rmrk-core/src/weights.rs @@ -64,7 +64,7 @@ // Storage: Common CollectionById (r:0 w:1) // Storage: RmrkCore UniqueCollectionId (r:0 w:1) fn create_collection() -> Weight { - (41_277_000 as Weight) + (42_359_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -77,7 +77,7 @@ // Storage: Nonfungible TokensBurnt (r:0 w:1) // Storage: Common AdminAmount (r:0 w:1) fn destroy_collection() -> Weight { - (43_371_000 as Weight) + (45_375_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -85,7 +85,7 @@ // Storage: Common CollectionById (r:1 w:1) // Storage: Common CollectionProperties (r:1 w:0) fn change_collection_issuer() -> Weight { - (21_891_000 as Weight) + (22_753_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -95,7 +95,7 @@ // Storage: Nonfungible TokensMinted (r:1 w:0) // Storage: Nonfungible TokensBurnt (r:1 w:0) fn lock_collection() -> Weight { - (23_144_000 as Weight) + (24_356_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -107,18 +107,15 @@ // Storage: Nonfungible TokenProperties (r:1 w:1) // Storage: Nonfungible TokenData (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Nonfungible TokenAuxProperties (r:2 w:2) fn mint_nft(b: u32, ) -> Weight { - (68_329_000 as Weight) - // Standard Error: 3_000 - .saturating_add((21_470_000 as Weight).saturating_mul(b as Weight)) - .saturating_add(T::DbWeight::get().reads(12 as Weight)) + (44_853_000 as Weight) + // Standard Error: 2_000 + .saturating_add((10_721_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) - .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(b as Weight))) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) // Storage: Common CollectionProperties (r:1 w:0) @@ -132,8 +129,8 @@ // Storage: Nonfungible TokenProperties (r:0 w:1) fn burn_nft(b: u32, ) -> Weight { (0 as Weight) - // Standard Error: 959_000 - .saturating_add((305_872_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 1_590_000 + .saturating_add((319_825_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight))) .saturating_add(T::DbWeight::get().writes(6 as Weight)) @@ -149,7 +146,7 @@ // Storage: Nonfungible TokenChildren (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:2) fn send() -> Weight { - (71_405_000 as Weight) + (72_576_000 as Weight) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -163,22 +160,22 @@ // Storage: Nonfungible TokenChildren (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:2) fn accept_nft() -> Weight { - (79_159_000 as Weight) + (79_670_000 as Weight) .saturating_add(T::DbWeight::get().reads(15 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) // Storage: Common CollectionProperties (r:1 w:0) // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:5) // Storage: Nonfungible TokenProperties (r:1 w:5) - // Storage: Nonfungible TokenData (r:5 w:5) // Storage: Nonfungible TokenChildren (r:9 w:4) // Storage: Nonfungible TokensBurnt (r:1 w:1) // Storage: Nonfungible AccountBalance (r:5 w:5) // Storage: Nonfungible Allowance (r:5 w:0) // Storage: Nonfungible Owned (r:0 w:5) fn reject_nft() -> Weight { - (238_179_000 as Weight) + (254_989_000 as Weight) .saturating_add(T::DbWeight::get().reads(29 as Weight)) .saturating_add(T::DbWeight::get().writes(25 as Weight)) } @@ -188,7 +185,7 @@ // Storage: Nonfungible TokenProperties (r:1 w:1) // Storage: Nonfungible TokenData (r:5 w:0) fn set_property() -> Weight { - (47_770_000 as Weight) + (48_651_000 as Weight) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -198,100 +195,72 @@ // Storage: Nonfungible TokenProperties (r:1 w:1) // Storage: Nonfungible TokenData (r:5 w:0) fn set_priority() -> Weight { - (46_679_000 as Weight) + (47_579_000 as Weight) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:1 w:1) - // Storage: Common CollectionById (r:1 w:1) - // Storage: Nonfungible TokenData (r:5 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:2) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Nonfungible TokensMinted (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn add_basic_resource() -> Weight { - (100_770_000 as Weight) - .saturating_add(T::DbWeight::get().reads(16 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) + (55_013_000 as Weight) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:1 w:1) - // Storage: Common CollectionById (r:1 w:1) - // Storage: Nonfungible TokenData (r:5 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:2) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Nonfungible TokensMinted (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn add_composable_resource() -> Weight { - (101_791_000 as Weight) - .saturating_add(T::DbWeight::get().reads(16 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) + (55_184_000 as Weight) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:1 w:1) - // Storage: Common CollectionById (r:1 w:1) - // Storage: Nonfungible TokenData (r:5 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:2) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Nonfungible TokensMinted (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn add_slot_resource() -> Weight { - (101_610_000 as Weight) - .saturating_add(T::DbWeight::get().reads(16 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) + (54_792_000 as Weight) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:2 w:0) - // Storage: Common CollectionById (r:2 w:0) - // Storage: Nonfungible TokenProperties (r:1 w:1) - // Storage: Nonfungible TokenData (r:6 w:1) - // Storage: Nonfungible TokenChildren (r:1 w:0) - // Storage: Nonfungible TokensBurnt (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Allowance (r:1 w:0) - // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) + // Storage: Nonfungible TokenData (r:5 w:0) fn remove_resource() -> Weight { - (80_571_000 as Weight) - .saturating_add(T::DbWeight::get().reads(16 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + (46_447_000 as Weight) + .saturating_add(T::DbWeight::get().reads(9 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) // Storage: Common CollectionProperties (r:1 w:0) // Storage: Common CollectionById (r:1 w:0) // Storage: Nonfungible TokenData (r:5 w:0) - // Storage: Nonfungible TokenProperties (r:2 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn accept_resource() -> Weight { - (54_733_000 as Weight) - .saturating_add(T::DbWeight::get().reads(10 as Weight)) + (45_096_000 as Weight) + .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:2 w:0) - // Storage: Common CollectionById (r:2 w:0) - // Storage: Nonfungible TokenData (r:6 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:1) - // Storage: Nonfungible TokenChildren (r:1 w:0) - // Storage: Nonfungible TokensBurnt (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Allowance (r:1 w:0) - // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn accept_resource_removal() -> Weight { - (84_138_000 as Weight) - .saturating_add(T::DbWeight::get().reads(17 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + (45_445_000 as Weight) + .saturating_add(T::DbWeight::get().reads(9 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } } @@ -306,7 +275,7 @@ // Storage: Common CollectionById (r:0 w:1) // Storage: RmrkCore UniqueCollectionId (r:0 w:1) fn create_collection() -> Weight { - (41_277_000 as Weight) + (42_359_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -319,7 +288,7 @@ // Storage: Nonfungible TokensBurnt (r:0 w:1) // Storage: Common AdminAmount (r:0 w:1) fn destroy_collection() -> Weight { - (43_371_000 as Weight) + (45_375_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -327,7 +296,7 @@ // Storage: Common CollectionById (r:1 w:1) // Storage: Common CollectionProperties (r:1 w:0) fn change_collection_issuer() -> Weight { - (21_891_000 as Weight) + (22_753_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -337,7 +306,7 @@ // Storage: Nonfungible TokensMinted (r:1 w:0) // Storage: Nonfungible TokensBurnt (r:1 w:0) fn lock_collection() -> Weight { - (23_144_000 as Weight) + (24_356_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -349,18 +318,15 @@ // Storage: Nonfungible TokenProperties (r:1 w:1) // Storage: Nonfungible TokenData (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Nonfungible TokenAuxProperties (r:2 w:2) fn mint_nft(b: u32, ) -> Weight { - (68_329_000 as Weight) - // Standard Error: 3_000 - .saturating_add((21_470_000 as Weight).saturating_mul(b as Weight)) - .saturating_add(RocksDbWeight::get().reads(12 as Weight)) + (44_853_000 as Weight) + // Standard Error: 2_000 + .saturating_add((10_721_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) - .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(b as Weight))) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) // Storage: Common CollectionProperties (r:1 w:0) @@ -374,8 +340,8 @@ // Storage: Nonfungible TokenProperties (r:0 w:1) fn burn_nft(b: u32, ) -> Weight { (0 as Weight) - // Standard Error: 959_000 - .saturating_add((305_872_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 1_590_000 + .saturating_add((319_825_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight))) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) @@ -391,7 +357,7 @@ // Storage: Nonfungible TokenChildren (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:2) fn send() -> Weight { - (71_405_000 as Weight) + (72_576_000 as Weight) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } @@ -405,22 +371,22 @@ // Storage: Nonfungible TokenChildren (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:2) fn accept_nft() -> Weight { - (79_159_000 as Weight) + (79_670_000 as Weight) .saturating_add(RocksDbWeight::get().reads(15 as Weight)) .saturating_add(RocksDbWeight::get().writes(7 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) // Storage: Common CollectionProperties (r:1 w:0) // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:5) // Storage: Nonfungible TokenProperties (r:1 w:5) - // Storage: Nonfungible TokenData (r:5 w:5) // Storage: Nonfungible TokenChildren (r:9 w:4) // Storage: Nonfungible TokensBurnt (r:1 w:1) // Storage: Nonfungible AccountBalance (r:5 w:5) // Storage: Nonfungible Allowance (r:5 w:0) // Storage: Nonfungible Owned (r:0 w:5) fn reject_nft() -> Weight { - (238_179_000 as Weight) + (254_989_000 as Weight) .saturating_add(RocksDbWeight::get().reads(29 as Weight)) .saturating_add(RocksDbWeight::get().writes(25 as Weight)) } @@ -430,7 +396,7 @@ // Storage: Nonfungible TokenProperties (r:1 w:1) // Storage: Nonfungible TokenData (r:5 w:0) fn set_property() -> Weight { - (47_770_000 as Weight) + (48_651_000 as Weight) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -440,99 +406,71 @@ // Storage: Nonfungible TokenProperties (r:1 w:1) // Storage: Nonfungible TokenData (r:5 w:0) fn set_priority() -> Weight { - (46_679_000 as Weight) + (47_579_000 as Weight) .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:1 w:1) - // Storage: Common CollectionById (r:1 w:1) - // Storage: Nonfungible TokenData (r:5 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:2) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Nonfungible TokensMinted (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn add_basic_resource() -> Weight { - (100_770_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(16 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + (55_013_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(10 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:1 w:1) - // Storage: Common CollectionById (r:1 w:1) - // Storage: Nonfungible TokenData (r:5 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:2) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Nonfungible TokensMinted (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn add_composable_resource() -> Weight { - (101_791_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(16 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + (55_184_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(10 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:1 w:1) - // Storage: Common CollectionById (r:1 w:1) - // Storage: Nonfungible TokenData (r:5 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:2) - // Storage: Common CreatedCollectionCount (r:1 w:1) - // Storage: Common DestroyedCollectionCount (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Nonfungible TokensMinted (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Owned (r:0 w:1) - // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn add_slot_resource() -> Weight { - (101_610_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(16 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + (54_792_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(10 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:2 w:0) - // Storage: Common CollectionById (r:2 w:0) - // Storage: Nonfungible TokenProperties (r:1 w:1) - // Storage: Nonfungible TokenData (r:6 w:1) - // Storage: Nonfungible TokenChildren (r:1 w:0) - // Storage: Nonfungible TokensBurnt (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Allowance (r:1 w:0) - // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) + // Storage: Nonfungible TokenData (r:5 w:0) fn remove_resource() -> Weight { - (80_571_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(16 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + (46_447_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(9 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) // Storage: Common CollectionProperties (r:1 w:0) // Storage: Common CollectionById (r:1 w:0) // Storage: Nonfungible TokenData (r:5 w:0) - // Storage: Nonfungible TokenProperties (r:2 w:1) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn accept_resource() -> Weight { - (54_733_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(10 as Weight)) + (45_096_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(9 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: RmrkCore UniqueCollectionId (r:1 w:0) - // Storage: Common CollectionProperties (r:2 w:0) - // Storage: Common CollectionById (r:2 w:0) - // Storage: Nonfungible TokenData (r:6 w:1) - // Storage: Nonfungible TokenProperties (r:2 w:1) - // Storage: Nonfungible TokenChildren (r:1 w:0) - // Storage: Nonfungible TokensBurnt (r:1 w:1) - // Storage: Nonfungible AccountBalance (r:1 w:1) - // Storage: Nonfungible Allowance (r:1 w:0) - // Storage: Nonfungible Owned (r:0 w:1) + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: Nonfungible TokenData (r:5 w:0) + // Storage: Nonfungible TokenAuxProperties (r:1 w:1) fn accept_resource_removal() -> Weight { - (84_138_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(17 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + (45_445_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(9 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } } --- /dev/null +++ b/pallets/proxy-rmrk-equip/src/benchmarking.rs @@ -0,0 +1,120 @@ +use sp_std::vec; + +use frame_benchmarking::{benchmarks, account}; +use frame_system::RawOrigin; +use frame_support::{ + traits::{Currency, Get}, + BoundedVec, +}; + +use up_data_structs::*; + +use super::*; + +const SEED: u32 = 1; + +fn create_data>() -> BoundedVec { + vec![b'A'; S::get() as usize].try_into().expect("size == S") +} + +fn create_u32_array>() -> BoundedVec { + vec![0; S::get() as usize].try_into().expect("size == S") +} + +fn create_max_part(id: RmrkSlotId) -> RmrkPartType { + RmrkPartType::SlotPart(RmrkSlotPart { + id, + equippable: RmrkEquippableList::Custom(create_u32_array()), + src: create_data(), + z: 1, + }) +} + +fn create_parts_array>(num: u32) -> BoundedVec { + let mut parts: BoundedVec = vec![].try_into().expect("0 <= S"); + + for i in 0..num { + parts.try_push(create_max_part(i)).expect("num <= S"); + } + + parts +} + +fn create_max_theme_property() -> RmrkThemeProperty { + RmrkThemeProperty { + key: create_data(), + value: create_data(), + } +} + +fn create_theme_properties_array>(num: u32) -> BoundedVec { + vec![create_max_theme_property(); num as usize] + .try_into() + .expect("num <= S") +} + +fn create_max_theme(name: RmrkString, props_num: u32) -> RmrkBoundedTheme { + RmrkBoundedTheme { + name, + properties: create_theme_properties_array(props_num), + inherit: false, + } +} + +benchmarks! { + create_base { + let b in 0..RmrkPartsLimit::get(); + + let caller = account("caller", 0, SEED); + ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); + + let base_type = create_data(); + let symbol = create_data(); + let parts = create_parts_array(b); + }: _(RawOrigin::Signed(caller), base_type, symbol, parts) + + theme_add { + let b in 0..MaxPropertiesPerTheme::get(); + + let caller = account("caller", 0, SEED); + ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); + + let base_type = create_data(); + let symbol = create_data(); + let parts = create_parts_array(0); + + >::create_base(RawOrigin::Signed(caller.clone()).into(), base_type, symbol, parts)?; + let base_id = 1; + + + let default_theme_name = b"default".to_vec().try_into().expect("default is a valid name; qed"); + let default_theme = create_max_theme(default_theme_name, 0); + + >::theme_add(RawOrigin::Signed(caller.clone()).into(), base_id, default_theme)?; + + let theme = create_max_theme(create_data(), b); + }: _(RawOrigin::Signed(caller), base_id, theme) + + equippable { + let caller = account("caller", 0, SEED); + ::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); + + let base_id = 1; + let slot_id = 42; + + let base_type = create_data(); + let symbol = create_data(); + let parts = vec! { + RmrkPartType::SlotPart(RmrkSlotPart { + id: slot_id, + equippable: RmrkEquippableList::All, + src: create_data(), + z: 1, + }) + }.try_into().expect("1 <= RmrkPartsLimit"); + + >::create_base(RawOrigin::Signed(caller.clone()).into(), base_type, symbol, parts)?; + + let equippables = RmrkEquippableList::Custom(create_u32_array()); + }: _(RawOrigin::Signed(caller), base_id, slot_id, equippables) +} --- a/pallets/proxy-rmrk-equip/src/lib.rs +++ b/pallets/proxy-rmrk-equip/src/lib.rs @@ -22,15 +22,23 @@ use up_data_structs::*; use pallet_common::{Pallet as PalletCommon, Error as CommonError}; use pallet_rmrk_core::{ - Pallet as PalletCore, + Pallet as PalletCore, Error as CoreError, misc::{self, *}, property::RmrkProperty::*, }; use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle}; use pallet_evm::account::CrossAccountId; +use weights::WeightInfo; pub use pallet::*; +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; +pub mod rpc; +pub mod weights; + +pub type SelfWeightOf = ::WeightInfo; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -38,6 +46,7 @@ #[pallet::config] pub trait Config: frame_system::Config + pallet_rmrk_core::Config { type Event: From> + IsType<::Event>; + type WeightInfo: WeightInfo; } #[pallet::storage] @@ -61,6 +70,10 @@ issuer: T::AccountId, base_id: RmrkBaseId, }, + EquippablesUpdated { + base_id: RmrkBaseId, + slot_id: RmrkSlotId, + }, } #[pallet::error] @@ -70,6 +83,8 @@ NoAvailablePartId, BaseDoesntExist, NeedsDefaultThemeFirst, + PartDoesntExist, + NoEquippableOnFixedPart, } #[pallet::call] @@ -83,12 +98,12 @@ /// - symbol: arbitrary client-chosen symbol /// - parts: array of Fixed and Slot parts composing the base, confined in length by /// RmrkPartsLimit - #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] #[transactional] + #[pallet::weight(>::create_base(parts.len() as u32))] pub fn create_base( origin: OriginFor, base_type: RmrkString, - symbol: RmrkString, + symbol: RmrkBaseSymbol, parts: BoundedVec, ) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -125,17 +140,7 @@ let collection = >::get_nft_collection(collection_id)?; for part in parts { - let part_id = part.id(); - let part_token_id = Self::create_part(&cross_sender, &collection, part)?; - - >::insert(collection_id, part_id, part_token_id); - - >::set_scoped_token_property( - collection_id, - part_token_id, - PropertyScope::Rmrk, - >::rmrk_property(ExternalPartId, &part_id)?, - )?; + Self::create_part(&cross_sender, &collection, part)?; } Self::deposit_event(Event::BaseCreated { @@ -159,12 +164,12 @@ /// - key: arbitrary BoundedString, defined by client /// - value: arbitrary BoundedString, defined by client /// - inherit: optional bool - #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] #[transactional] + #[pallet::weight(>::theme_add(theme.properties.len() as u32))] pub fn theme_add( origin: OriginFor, base_id: RmrkBaseId, - theme: RmrkTheme, + theme: RmrkBoundedTheme, ) -> DispatchResult { let sender = ensure_signed(origin)?; @@ -173,12 +178,7 @@ let collection_id: CollectionId = base_id.into(); - let collection = >::get_typed_nft_collection( - collection_id, - misc::CollectionType::Base, - ) - .map_err(|_| >::BaseDoesntExist)?; - collection.check_is_external()?; + let collection = Self::get_base(collection_id)?; if theme.name.as_slice() == b"default" { >::insert(collection_id, true); @@ -213,6 +213,55 @@ Ok(()) } + + #[transactional] + #[pallet::weight(>::equippable())] + pub fn equippable( + origin: OriginFor, + base_id: RmrkBaseId, + slot_id: RmrkSlotId, + equippables: RmrkEquippableList, + ) -> DispatchResult { + let sender = ensure_signed(origin)?; + + let base_collection_id = base_id.into(); + let collection = Self::get_base(base_collection_id)?; + + >::check_collection_owner( + &collection, + &T::CrossAccountId::from_sub(sender), + ) + .map_err(|err| { + if err == >::NoPermission.into() { + >::PermissionError.into() + } else { + err + } + })?; + + let part_id = Self::internal_part_id(base_collection_id, slot_id) + .ok_or(>::PartDoesntExist)?; + + let nft_type = >::get_nft_type(base_collection_id, part_id) + .map_err(|_| >::PartDoesntExist)?; + + match nft_type { + NftType::Regular | NftType::Theme => return Err(>::PermissionError.into()), + NftType::FixedPart => return Err(>::NoEquippableOnFixedPart.into()), + NftType::SlotPart => { + >::set_scoped_token_property( + base_collection_id, + part_id, + PropertyScope::Rmrk, + >::rmrk_property(EquippableList, &equippables)?, + )?; + } + } + + Self::deposit_event(Event::EquippablesUpdated { base_id, slot_id }); + + Ok(()) + } } } @@ -221,9 +270,10 @@ sender: &T::CrossAccountId, collection: &NonfungibleHandle, part: RmrkPartType, - ) -> Result { + ) -> DispatchResult { let owner = sender; + let part_id = part.id(); let src = part.src(); let z_index = part.z_index(); @@ -232,21 +282,40 @@ RmrkPartType::SlotPart(_) => NftType::SlotPart, }; - let token_id = >::create_nft( - sender, - owner, - collection, + let token_id = match Self::internal_part_id(collection.id, part_id) { + Some(token_id) => token_id, + None => { + let token_id = + >::create_nft(sender, owner, collection, [].into_iter()) + .map_err(|err| match err { + DispatchError::Arithmetic(_) => >::NoAvailablePartId.into(), + err => err, + })?; + + >::insert(collection.id, part_id, token_id); + + >::set_scoped_token_property( + collection.id, + token_id, + PropertyScope::Rmrk, + >::rmrk_property(ExternalPartId, &part_id)?, + )?; + + token_id + } + }; + + >::set_scoped_token_properties( + collection.id, + token_id, + PropertyScope::Rmrk, [ >::rmrk_property(TokenType, &nft_type)?, >::rmrk_property(Src, &src)?, >::rmrk_property(ZIndex, &z_index)?, ] .into_iter(), - ) - .map_err(|err| match err { - DispatchError::Arithmetic(_) => >::NoAvailablePartId.into(), - err => err, - })?; + )?; if let RmrkPartType::SlotPart(part) = part { >::set_scoped_token_property( @@ -257,6 +326,21 @@ )?; } - Ok(token_id) + Ok(()) + } + + fn get_base(base_id: CollectionId) -> Result, DispatchError> { + let collection = + >::get_typed_nft_collection(base_id, misc::CollectionType::Base) + .map_err(|err| { + if err == >::CollectionUnknown.into() { + >::BaseDoesntExist.into() + } else { + err + } + })?; + collection.check_is_external()?; + + Ok(collection) } } --- /dev/null +++ b/pallets/proxy-rmrk-equip/src/rpc.rs @@ -0,0 +1,186 @@ +use super::*; +use pallet_rmrk_core::{misc, property::*}; +use sp_std::vec::Vec; + +pub fn base( + base_id: RmrkBaseId, +) -> Result>, DispatchError> { + let (collection, collection_id) = + match >::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base) + { + Ok(c) => c, + Err(_) => return Ok(None), + }; + + Ok(Some(RmrkBaseInfo { + issuer: collection.owner.clone(), + base_type: >::get_collection_property_decoded( + collection_id, + RmrkProperty::BaseType, + )?, + symbol: >::rebind(&collection.token_prefix)?, + })) +} + +pub fn base_parts(base_id: RmrkBaseId) -> Result, DispatchError> { + use pallet_common::CommonCollectionOperations; + + let (collection, collection_id) = + match >::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base) + { + Ok(c) => c, + Err(_) => return Ok(Vec::new()), + }; + + let parts = collection + .collection_tokens() + .into_iter() + .filter_map(|token_id| { + let nft_type = >::get_nft_type(collection_id, token_id).ok()?; + + match nft_type { + NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart { + id: >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::ExternalPartId, + ) + .ok()?, + src: >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::Src, + ) + .ok()?, + z: >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::ZIndex, + ) + .ok()?, + })), + NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart { + id: >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::ExternalPartId, + ) + .ok()?, + src: >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::Src, + ) + .ok()?, + z: >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::ZIndex, + ) + .ok()?, + equippable: >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::EquippableList, + ) + .ok()?, + })), + _ => None, + } + }) + .collect(); + + Ok(parts) +} + +pub fn theme_names(base_id: RmrkBaseId) -> Result, DispatchError> { + use pallet_common::CommonCollectionOperations; + + let (collection, collection_id) = + match >::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base) + { + Ok(c) => c, + Err(_) => return Ok(Vec::new()), + }; + + let theme_names = collection + .collection_tokens() + .iter() + .filter_map(|token_id| { + let nft_type = >::get_nft_type(collection_id, *token_id).ok()?; + + match nft_type { + NftType::Theme => >::get_nft_property_decoded( + collection_id, + *token_id, + RmrkProperty::ThemeName, + ) + .ok(), + _ => None, + } + }) + .collect(); + + Ok(theme_names) +} + +pub fn theme( + base_id: RmrkBaseId, + theme_name: RmrkThemeName, + filter_keys: Option>, +) -> Result, DispatchError> { + use pallet_common::CommonCollectionOperations; + + let (collection, collection_id) = + match >::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base) + { + Ok(c) => c, + Err(_) => return Ok(None), + }; + + let theme_info = collection + .collection_tokens() + .into_iter() + .find_map(|token_id| { + >::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?; + + let name: RmrkString = >::get_nft_property_decoded( + collection_id, + token_id, + RmrkProperty::ThemeName, + ) + .ok()?; + + if name == theme_name { + Some((name, token_id)) + } else { + None + } + }); + + let (name, theme_id) = match theme_info { + Some((name, theme_id)) => (name, theme_id), + None => return Ok(None), + }; + + let properties = >::filter_user_properties( + collection_id, + Some(theme_id), + filter_keys, + |key, value| RmrkThemeProperty { key, value }, + )?; + + let inherit = >::get_nft_property_decoded( + collection_id, + theme_id, + RmrkProperty::ThemeInherit, + )?; + + let theme = RmrkTheme { + name, + properties, + inherit, + }; + + Ok(Some(theme)) +} --- /dev/null +++ b/pallets/proxy-rmrk-equip/src/weights.rs @@ -0,0 +1,138 @@ +// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs + +//! Autogenerated weights for pallet_proxy_rmrk_equip +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-06-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// target/release/unique-collator +// benchmark +// pallet +// --pallet +// pallet-proxy-rmrk-equip +// --wasm-execution +// compiled +// --extrinsic +// * +// --template +// .maintain/frame-weight-template.hbs +// --steps=50 +// --repeat=80 +// --heap-pages=4096 +// --output=./pallets/proxy-rmrk-equip/src/weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_proxy_rmrk_equip. +pub trait WeightInfo { + fn create_base(b: u32, ) -> Weight; + fn theme_add(b: u32, ) -> Weight; + fn equippable() -> Weight; +} + +/// Weights for pallet_proxy_rmrk_equip using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: Common CreatedCollectionCount (r:1 w:1) + // Storage: Common DestroyedCollectionCount (r:1 w:0) + // Storage: System Account (r:2 w:2) + // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:0 w:1) + // Storage: Common CollectionById (r:0 w:1) + // Storage: RmrkEquip InernalPartId (r:1 w:1) + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:1) + // Storage: Nonfungible Owned (r:0 w:1) + fn create_base(b: u32, ) -> Weight { + (44_927_000 as Weight) + // Standard Error: 9_000 + .saturating_add((18_896_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(b as Weight))) + .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight))) + } + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: RmrkEquip BaseHasDefaultTheme (r:1 w:0) + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:1) + // Storage: Nonfungible Owned (r:0 w:1) + fn theme_add(b: u32, ) -> Weight { + (39_120_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_367_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: RmrkEquip InernalPartId (r:1 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + fn equippable() -> Weight { + (27_172_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: Common CreatedCollectionCount (r:1 w:1) + // Storage: Common DestroyedCollectionCount (r:1 w:0) + // Storage: System Account (r:2 w:2) + // Storage: Common CollectionPropertyPermissions (r:0 w:1) + // Storage: Common CollectionProperties (r:0 w:1) + // Storage: Common CollectionById (r:0 w:1) + // Storage: RmrkEquip InernalPartId (r:1 w:1) + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:1) + // Storage: Nonfungible Owned (r:0 w:1) + fn create_base(b: u32, ) -> Weight { + (44_927_000 as Weight) + // Standard Error: 9_000 + .saturating_add((18_896_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(b as Weight))) + .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight))) + } + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: RmrkEquip BaseHasDefaultTheme (r:1 w:0) + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenProperties (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:1) + // Storage: Nonfungible Owned (r:0 w:1) + fn theme_add(b: u32, ) -> Weight { + (39_120_000 as Weight) + // Standard Error: 11_000 + .saturating_add((2_367_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + } + // Storage: Common CollectionProperties (r:1 w:0) + // Storage: Common CollectionById (r:1 w:0) + // Storage: RmrkEquip InernalPartId (r:1 w:0) + // Storage: Nonfungible TokenProperties (r:1 w:1) + fn equippable() -> Weight { + (27_172_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } +} --- a/primitives/data-structs/src/lib.rs +++ b/primitives/data-structs/src/lib.rs @@ -39,15 +39,15 @@ // RMRK use rmrk_traits::{ CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme, ThemeProperty, - ResourceTypes, BasicResource, ComposableResource, SlotResource, + ResourceTypes, BasicResource, ComposableResource, SlotResource, EquippableList, }; pub use rmrk_traits::{ primitives::{ CollectionId as RmrkCollectionId, NftId as RmrkNftId, BaseId as RmrkBaseId, - PartId as RmrkPartId, ResourceId as RmrkResourceId, + SlotId as RmrkSlotId, PartId as RmrkPartId, ResourceId as RmrkResourceId, }, NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple, - FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, EquippableList as RmrkEquippableList, + FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, }; mod bounded; @@ -104,6 +104,8 @@ pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768; pub const MAX_PROPERTIES_PER_ITEM: u32 = 64; +pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048; + pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960; pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768; @@ -654,8 +656,12 @@ } } -pub type PropertyKey = BoundedVec>; -pub type PropertyValue = BoundedVec>; +pub type BoundedBytes = BoundedVec; + +pub type AuxPropertyValue = BoundedBytes>; + +pub type PropertyKey = BoundedBytes>; +pub type PropertyValue = BoundedBytes>; #[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] @@ -715,7 +721,7 @@ EmptyPropertyKey, } -#[derive(Clone, Copy)] +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)] pub enum PropertyScope { None, Rmrk, @@ -944,7 +950,9 @@ #[derive(PartialEq)] pub const RmrkCollectionSymbolLimit: u32 = MAX_TOKEN_PREFIX_LENGTH; #[derive(PartialEq)] - pub const RmrkResourceSymbolLimit: u32 = MAX_TOKEN_PREFIX_LENGTH; + pub const RmrkResourceSymbolLimit: u32 = 10; + #[derive(PartialEq)] + pub const RmrkBaseSymbolLimit: u32 = MAX_TOKEN_PREFIX_LENGTH; #[derive(PartialEq)] pub const RmrkKeyLimit: u32 = 32; #[derive(PartialEq)] @@ -952,6 +960,8 @@ #[derive(PartialEq)] pub const RmrkMaxCollectionsEquippablePerPart: u32 = 100; #[derive(PartialEq)] + pub const MaxPropertiesPerTheme: u32 = 5; + #[derive(PartialEq)] pub const RmrkPartsLimit: u32 = 25; #[derive(PartialEq)] pub const RmrkMaxPriorities: u32 = 25; @@ -977,10 +987,13 @@ pub type RmrkResourceInfo = ResourceInfo; pub type RmrkPropertyInfo = PropertyInfo; pub type RmrkBaseInfo = BaseInfo; -pub type RmrkPartType = - PartType>; +pub type BoundedEquippableCollectionIds = + BoundedVec; +pub type RmrkPartType = PartType; +pub type RmrkEquippableList = EquippableList; pub type RmrkThemeProperty = ThemeProperty; pub type RmrkTheme = Theme>; +pub type RmrkBoundedTheme = Theme>; pub type RmrkResourceTypes = ResourceTypes; pub type RmrkBasicResource = BasicResource; @@ -989,6 +1002,7 @@ pub type RmrkString = BoundedVec; pub type RmrkCollectionSymbol = BoundedVec; +pub type RmrkBaseSymbol = BoundedVec; pub type RmrkKeyString = BoundedVec; pub type RmrkValueString = BoundedVec; pub type RmrkBoundedResource = BoundedVec; --- a/runtime/common/src/runtime_apis.rs +++ b/runtime/common/src/runtime_apis.rs @@ -454,6 +454,13 @@ list_benchmark!(list, extra, pallet_refungible, Refungible); list_benchmark!(list, extra, pallet_nonfungible, Nonfungible); list_benchmark!(list, extra, pallet_unique_scheduler, Scheduler); + + #[cfg(not(feature = "unique-runtime"))] + list_benchmark!(list, extra, pallet_proxy_rmrk_core, RmrkCore); + + #[cfg(not(feature = "unique-runtime"))] + list_benchmark!(list, extra, pallet_proxy_rmrk_equip, RmrkEquip); + // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate); let storage_info = AllPalletsReversedWithSystemFirst::storage_info(); @@ -498,6 +505,13 @@ add_benchmark!(params, batches, pallet_refungible, Refungible); add_benchmark!(params, batches, pallet_nonfungible, Nonfungible); add_benchmark!(params, batches, pallet_unique_scheduler, Scheduler); + + #[cfg(not(feature = "unique-runtime"))] + add_benchmark!(params, batches, pallet_proxy_rmrk_core, RmrkCore); + + #[cfg(not(feature = "unique-runtime"))] + add_benchmark!(params, batches, pallet_proxy_rmrk_equip, RmrkEquip); + // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } --- a/runtime/opal/Cargo.toml +++ b/runtime/opal/Cargo.toml @@ -34,6 +34,7 @@ 'pallet-refungible/runtime-benchmarks', 'pallet-nonfungible/runtime-benchmarks', 'pallet-proxy-rmrk-core/runtime-benchmarks', + 'pallet-proxy-rmrk-equip/runtime-benchmarks', 'pallet-unique/runtime-benchmarks', 'pallet-inflation/runtime-benchmarks', 'pallet-unique-scheduler/runtime-benchmarks', --- a/runtime/opal/src/lib.rs +++ b/runtime/opal/src/lib.rs @@ -74,10 +74,8 @@ CollectionStats, RpcCollection, mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping}, TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, - RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkThemeProperty, RmrkCollectionId, - RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceTypes, - RmrkBasicResource, RmrkComposableResource, RmrkSlotResource, RmrkResourceId, RmrkBaseId, - RmrkFixedPart, RmrkSlotPart, RmrkString, + RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId, + RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId, }; // use pallet_contracts::weights::WeightInfo; @@ -924,6 +922,7 @@ } impl pallet_proxy_rmrk_equip::Config for Runtime { + type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight; type Event = Event; } @@ -1330,387 +1329,55 @@ RmrkTheme > for Runtime { fn last_collection_idx() -> Result { - Ok(RmrkCore::last_collection_idx()) + pallet_proxy_rmrk_core::rpc::last_collection_idx::() } fn collection_by_id(collection_id: RmrkCollectionId) -> Result>, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - let nfts_count = collection.total_supply(); - - Ok(Some(RmrkCollectionInfo { - issuer: collection.owner.clone(), - metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?, - max: collection.limits.token_limit, - symbol: RmrkCore::rebind(&collection.token_prefix)?, - nfts_count - })) + pallet_proxy_rmrk_core::rpc::collection_by_id::(collection_id) } fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result>, DispatchError> { - use up_data_structs::mapping::TokenAddressMapping; - use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - let nft_id = TokenId(nft_by_id); - if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); } - - let owner = match collection.token_owner(nft_id) { - Some(owner) => match ::CrossTokenAddressMapping::address_to_token(&owner) { - Some((col, tok)) => { - let rmrk_collection = RmrkCore::rmrk_collection_id(col)?; - - RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0) - } - None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone()) - }, - None => return Ok(None) - }; - - Ok(Some(RmrkInstanceInfo { - owner: owner, - royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?, - metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?, - equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?, - pending: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)?, - })) + pallet_proxy_rmrk_core::rpc::nft_by_id::(collection_id, nft_by_id) } fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType}; - use pallet_common::CommonCollectionOperations; - - let cross_account_id = CrossAccountId::from_sub(account_id); - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) { - Ok(c) => c, - Err(_) => return Ok(Vec::new()), - }; - - let tokens = collection.account_tokens(cross_account_id) - .into_iter() - .filter(|token| { - let is_pending = RmrkCore::get_nft_property_decoded( - collection_id, - *token, - RmrkProperty::PendingNftAccept - ).unwrap_or(true); - - !is_pending - }) - .map(|token| token.0) - .collect(); - - Ok(tokens) + pallet_proxy_rmrk_core::rpc::account_tokens::(account_id, collection_id) } fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::RmrkProperty; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - let nft_id = TokenId(nft_id); - if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); } - - Ok( - pallet_nonfungible::TokenChildren::::iter_prefix((collection_id, nft_id)) - .filter_map(|((child_collection, child_token), _)| { - let is_pending = RmrkCore::get_nft_property_decoded( - child_collection, - child_token, - RmrkProperty::PendingNftAccept - ).ok()?; - - if is_pending { - return None; - } - - let rmrk_child_collection = RmrkCore::rmrk_collection_id( - child_collection - ).ok()?; - - Some(RmrkNftChild { - collection_id: rmrk_child_collection, - nft_id: child_token.0, - }) - }).collect() - ) + pallet_proxy_rmrk_core::rpc::nft_children::(collection_id, nft_id) } fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option>) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::misc::CollectionType; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { - return Ok(Vec::new()); - } - - let properties = RmrkCore::filter_user_properties( - collection_id, - /* token_id = */ None, - filter_keys, - |key, value| RmrkPropertyInfo { - key, - value - } - )?; - - Ok(properties) + pallet_proxy_rmrk_core::rpc::collection_properties::(collection_id, filter_keys) } fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option>) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::misc::NftType; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - let token_id = TokenId(nft_id); - - if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() { - return Ok(Vec::new()); - } - - let properties = RmrkCore::filter_user_properties( - collection_id, - Some(token_id), - filter_keys, - |key, value| RmrkPropertyInfo { - key, - value - } - )?; - - Ok(properties) + pallet_proxy_rmrk_core::rpc::nft_properties::(collection_id, nft_id, filter_keys) } fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}}; - use pallet_common::CommonCollectionOperations; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); } - - let nft_id = TokenId(nft_id); - if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); } - - let res_collection_id: Option = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?; - - let res_collection_id = match res_collection_id { - Some(id) => id, - None => return Ok(Vec::new()) - }; - - let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?; - - let resources = resource_collection - .collection_tokens() - .iter() - .filter_map(|res_id| Some(RmrkResourceInfo { - id: res_id.0, - pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).ok()?, - pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).ok()?, - resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).ok()? { - ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource { - src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?, - metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?, - license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?, - thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?, - }), - ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource { - parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).ok()?, - base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?, - src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?, - metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?, - license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?, - thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?, - }), - ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource { - base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?, - src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?, - metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?, - slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).ok()?, - license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?, - thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?, - }), - }, - })) - .collect(); - - Ok(resources) + pallet_proxy_rmrk_core::rpc::nft_resources::(collection_id, nft_id) } fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}}; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(None) - }; - if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(None); } - - let nft_id = TokenId(nft_id); - if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(None); } - - let priorities: Vec<_> = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?; - Ok( - priorities.into_iter() - .enumerate() - .find(|(_, id)| *id == resource_id) - .map(|(priority, _): (usize, RmrkResourceId)| priority as u32) - ) + pallet_proxy_rmrk_core::rpc::nft_resource_priority::(collection_id, nft_id, resource_id) } fn base(base_id: RmrkBaseId) -> Result>, DispatchError> { - use pallet_proxy_rmrk_core::{ - RmrkProperty, misc::{CollectionType}, - }; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - Ok(Some(RmrkBaseInfo { - issuer: collection.owner.clone(), - base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?, - symbol: RmrkCore::rebind(&collection.token_prefix)?, - })) + pallet_proxy_rmrk_equip::rpc::base::(base_id) } fn base_parts(base_id: RmrkBaseId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(Vec::new()), - }; - - let parts = collection.collection_tokens() - .into_iter() - .filter_map(|token_id| { - let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?; - - match nft_type { - NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart { - id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?, - src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?, - z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?, - })), - NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart { - id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?, - src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?, - z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?, - equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?, - })), - _ => None - } - }) - .collect(); - - Ok(parts) + pallet_proxy_rmrk_equip::rpc::base_parts::(base_id) } fn theme_names(base_id: RmrkBaseId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{NftType, CollectionType}}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(Vec::new()), - }; - - let theme_names = collection.collection_tokens() - .iter() - .filter_map(|token_id| { - let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).ok()?; - - match nft_type { - NftType::Theme => RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).ok(), - _ => None - } - }) - .collect(); - - Ok(theme_names) + pallet_proxy_rmrk_equip::rpc::theme_names::(base_id) } fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option>) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{ - RmrkProperty, - misc::{CollectionType, NftType} - }; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - let theme_info = collection.collection_tokens() - .into_iter() - .find_map(|token_id| { - RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?; - - let name: RmrkString = RmrkCore::get_nft_property_decoded( - collection_id, token_id, RmrkProperty::ThemeName - ).ok()?; - - if name == theme_name { - Some((name, token_id)) - } else { - None - } - }); - - let (name, theme_id) = match theme_info { - Some((name, theme_id)) => (name, theme_id), - None => return Ok(None) - }; - - let properties = RmrkCore::filter_user_properties( - collection_id, - Some(theme_id), - filter_keys, - |key, value| RmrkThemeProperty { - key, - value - } - )?; - - let inherit = RmrkCore::get_nft_property_decoded( - collection_id, - theme_id, - RmrkProperty::ThemeInherit - )?; - - let theme = RmrkTheme { - name, - properties, - inherit, - }; - - Ok(Some(theme)) + pallet_proxy_rmrk_equip::rpc::theme::(base_id, theme_name, filter_keys) } } } --- a/runtime/quartz/src/lib.rs +++ b/runtime/quartz/src/lib.rs @@ -74,10 +74,8 @@ CollectionStats, RpcCollection, mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping}, TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, - RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkThemeProperty, RmrkCollectionId, - RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceTypes, - RmrkBasicResource, RmrkComposableResource, RmrkSlotResource, RmrkResourceId, RmrkBaseId, - RmrkFixedPart, RmrkSlotPart, RmrkString, + RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId, + RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId, }; // use pallet_contracts::weights::WeightInfo; @@ -923,6 +921,7 @@ } impl pallet_proxy_rmrk_equip::Config for Runtime { + type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight; type Event = Event; } @@ -1330,387 +1329,55 @@ RmrkTheme > for Runtime { fn last_collection_idx() -> Result { - Ok(RmrkCore::last_collection_idx()) + pallet_proxy_rmrk_core::rpc::last_collection_idx::() } fn collection_by_id(collection_id: RmrkCollectionId) -> Result>, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - let nfts_count = collection.total_supply(); - - Ok(Some(RmrkCollectionInfo { - issuer: collection.owner.clone(), - metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?, - max: collection.limits.token_limit, - symbol: RmrkCore::rebind(&collection.token_prefix)?, - nfts_count - })) + pallet_proxy_rmrk_core::rpc::collection_by_id::(collection_id) } fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result>, DispatchError> { - use up_data_structs::mapping::TokenAddressMapping; - use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - let nft_id = TokenId(nft_by_id); - if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); } - - let owner = match collection.token_owner(nft_id) { - Some(owner) => match ::CrossTokenAddressMapping::address_to_token(&owner) { - Some((col, tok)) => { - let rmrk_collection = RmrkCore::rmrk_collection_id(col)?; - - RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0) - } - None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone()) - }, - None => return Ok(None) - }; - - Ok(Some(RmrkInstanceInfo { - owner: owner, - royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?, - metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?, - equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?, - pending: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)?, - })) + pallet_proxy_rmrk_core::rpc::nft_by_id::(collection_id, nft_by_id) } fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType}; - use pallet_common::CommonCollectionOperations; - - let cross_account_id = CrossAccountId::from_sub(account_id); - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) { - Ok(c) => c, - Err(_) => return Ok(Vec::new()), - }; - - let tokens = collection.account_tokens(cross_account_id) - .into_iter() - .filter(|token| { - let is_pending = RmrkCore::get_nft_property_decoded( - collection_id, - *token, - RmrkProperty::PendingNftAccept - ).unwrap_or(true); - - !is_pending - }) - .map(|token| token.0) - .collect(); - - Ok(tokens) + pallet_proxy_rmrk_core::rpc::account_tokens::(account_id, collection_id) } fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::RmrkProperty; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - let nft_id = TokenId(nft_id); - if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); } - - Ok( - pallet_nonfungible::TokenChildren::::iter_prefix((collection_id, nft_id)) - .filter_map(|((child_collection, child_token), _)| { - let is_pending = RmrkCore::get_nft_property_decoded( - child_collection, - child_token, - RmrkProperty::PendingNftAccept - ).ok()?; - - if is_pending { - return None; - } - - let rmrk_child_collection = RmrkCore::rmrk_collection_id( - child_collection - ).ok()?; - - Some(RmrkNftChild { - collection_id: rmrk_child_collection, - nft_id: child_token.0, - }) - }).collect() - ) + pallet_proxy_rmrk_core::rpc::nft_children::(collection_id, nft_id) } fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option>) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::misc::CollectionType; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { - return Ok(Vec::new()); - } - - let properties = RmrkCore::filter_user_properties( - collection_id, - /* token_id = */ None, - filter_keys, - |key, value| RmrkPropertyInfo { - key, - value - } - )?; - - Ok(properties) + pallet_proxy_rmrk_core::rpc::collection_properties::(collection_id, filter_keys) } fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option>) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::misc::NftType; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - let token_id = TokenId(nft_id); - - if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() { - return Ok(Vec::new()); - } - - let properties = RmrkCore::filter_user_properties( - collection_id, - Some(token_id), - filter_keys, - |key, value| RmrkPropertyInfo { - key, - value - } - )?; - - Ok(properties) + pallet_proxy_rmrk_core::rpc::nft_properties::(collection_id, nft_id, filter_keys) } fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}}; - use pallet_common::CommonCollectionOperations; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(Vec::new()) - }; - if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); } - - let nft_id = TokenId(nft_id); - if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); } - - let res_collection_id: Option = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?; - - let res_collection_id = match res_collection_id { - Some(id) => id, - None => return Ok(Vec::new()) - }; - - let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?; - - let resources = resource_collection - .collection_tokens() - .iter() - .filter_map(|res_id| Some(RmrkResourceInfo { - id: res_id.0, - pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).ok()?, - pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).ok()?, - resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).ok()? { - ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource { - src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?, - metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?, - license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?, - thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?, - }), - ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource { - parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).ok()?, - base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?, - src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?, - metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?, - license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?, - thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?, - }), - ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource { - base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?, - src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?, - metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?, - slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).ok()?, - license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?, - thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?, - }), - }, - })) - .collect(); - - Ok(resources) + pallet_proxy_rmrk_core::rpc::nft_resources::(collection_id, nft_id) } fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}}; - - let collection_id = match RmrkCore::unique_collection_id(collection_id) { - Ok(id) => id, - Err(_) => return Ok(None) - }; - if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(None); } - - let nft_id = TokenId(nft_id); - if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(None); } - - let priorities: Vec<_> = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?; - Ok( - priorities.into_iter() - .enumerate() - .find(|(_, id)| *id == resource_id) - .map(|(priority, _): (usize, RmrkResourceId)| priority as u32) - ) + pallet_proxy_rmrk_core::rpc::nft_resource_priority::(collection_id, nft_id, resource_id) } fn base(base_id: RmrkBaseId) -> Result>, DispatchError> { - use pallet_proxy_rmrk_core::{ - RmrkProperty, misc::{CollectionType}, - }; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - Ok(Some(RmrkBaseInfo { - issuer: collection.owner.clone(), - base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?, - symbol: RmrkCore::rebind(&collection.token_prefix)?, - })) + pallet_proxy_rmrk_equip::rpc::base::(base_id) } fn base_parts(base_id: RmrkBaseId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(Vec::new()), - }; - - let parts = collection.collection_tokens() - .into_iter() - .filter_map(|token_id| { - let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?; - - match nft_type { - NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart { - id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?, - src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?, - z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?, - })), - NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart { - id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?, - src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?, - z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?, - equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?, - })), - _ => None - } - }) - .collect(); - - Ok(parts) + pallet_proxy_rmrk_equip::rpc::base_parts::(base_id) } fn theme_names(base_id: RmrkBaseId) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{NftType, CollectionType}}; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(Vec::new()), - }; - - let theme_names = collection.collection_tokens() - .iter() - .filter_map(|token_id| { - let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).ok()?; - - match nft_type { - NftType::Theme => RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).ok(), - _ => None - } - }) - .collect(); - - Ok(theme_names) + pallet_proxy_rmrk_equip::rpc::theme_names::(base_id) } fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option>) -> Result, DispatchError> { - use pallet_proxy_rmrk_core::{ - RmrkProperty, - misc::{CollectionType, NftType} - }; - use pallet_common::CommonCollectionOperations; - - let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) { - Ok(c) => c, - Err(_) => return Ok(None), - }; - - let theme_info = collection.collection_tokens() - .into_iter() - .find_map(|token_id| { - RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?; - - let name: RmrkString = RmrkCore::get_nft_property_decoded( - collection_id, token_id, RmrkProperty::ThemeName - ).ok()?; - - if name == theme_name { - Some((name, token_id)) - } else { - None - } - }); - - let (name, theme_id) = match theme_info { - Some((name, theme_id)) => (name, theme_id), - None => return Ok(None) - }; - - let properties = RmrkCore::filter_user_properties( - collection_id, - Some(theme_id), - filter_keys, - |key, value| RmrkThemeProperty { - key, - value - } - )?; - - let inherit = RmrkCore::get_nft_property_decoded( - collection_id, - theme_id, - RmrkProperty::ThemeInherit - )?; - - let theme = RmrkTheme { - name, - properties, - inherit, - }; - - Ok(Some(theme)) + pallet_proxy_rmrk_equip::rpc::theme::(base_id, theme_name, filter_keys) } } } --- a/runtime/unique/Cargo.toml +++ b/runtime/unique/Cargo.toml @@ -16,7 +16,7 @@ targets = ['x86_64-unknown-linux-gnu'] [features] -default = ['std'] +default = ['std', 'unique-runtime'] runtime-benchmarks = [ 'hex-literal', 'frame-benchmarking', @@ -119,6 +119,7 @@ "orml-vesting/std", ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] +unique-runtime = [] ################################################################################ # Substrate Dependencies --- a/runtime/unique/src/lib.rs +++ b/runtime/unique/src/lib.rs @@ -74,9 +74,8 @@ CollectionStats, RpcCollection, mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping}, TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, - RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, - RmrkNftId, RmrkNftChild, RmrkPropertyKey, - RmrkResourceId, RmrkBaseId, + RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId, + RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId, }; // use pallet_contracts::weights::WeightInfo;