From da5e7f48f1a389b7eaeb9e5b497c23155fa8ba68 Mon Sep 17 00:00:00 2001 From: Daniel Shiposha Date: Mon, 20 Jun 2022 14:21:57 +0000 Subject: [PATCH] feat(rmrk): add equippable extrinsic --- --- a/pallets/proxy-rmrk-core/src/lib.rs +++ b/pallets/proxy-rmrk-core/src/lib.rs @@ -1298,7 +1298,7 @@ collection.save() } - fn check_collection_owner( + pub fn check_collection_owner( collection: &NonfungibleHandle, account: &T::CrossAccountId, ) -> DispatchResult { @@ -1363,7 +1363,11 @@ collection_id: CollectionId, ) -> Result { Self::get_collection_property_decoded(collection_id, CollectionType) - .map_err(|_| >::CorruptedCollectionType.into()) + .map_err(|err| if err != >::CollectionUnknown.into() { + >::CorruptedCollectionType.into() + } else { + err + }) } pub fn ensure_collection_type( --- a/pallets/proxy-rmrk-equip/src/lib.rs +++ b/pallets/proxy-rmrk-equip/src/lib.rs @@ -23,6 +23,7 @@ use pallet_common::{Pallet as PalletCommon, Error as CommonError}; use pallet_rmrk_core::{ Pallet as PalletCore, + Error as CoreError, misc::{self, *}, property::RmrkProperty::*, }; @@ -70,6 +71,10 @@ issuer: T::AccountId, base_id: RmrkBaseId, }, + EquippablesUpdated { + base_id: RmrkBaseId, + slot_id: RmrkSlotId, + }, } #[pallet::error] @@ -79,6 +84,8 @@ NoAvailablePartId, BaseDoesntExist, NeedsDefaultThemeFirst, + PartDoesntExist, + NoEquippableOnFixedPart, } #[pallet::call] @@ -182,12 +189,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); @@ -222,6 +224,53 @@ 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(()) + } } } @@ -268,4 +317,16 @@ Ok(token_id) } + + 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) + } } --- a/pallets/proxy-rmrk-equip/src/weights.rs +++ b/pallets/proxy-rmrk-equip/src/weights.rs @@ -3,7 +3,7 @@ //! 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-16, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-06-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: @@ -35,6 +35,7 @@ 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. @@ -53,13 +54,13 @@ // Storage: Nonfungible Owned (r:0 w:1) // Storage: RmrkEquip InernalPartId (r:0 w:1) fn create_base(b: u32, ) -> Weight { - (43_216_000 as Weight) + (44_632_000 as Weight) // Standard Error: 10_000 - .saturating_add((16_253_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((16_912_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(9 as Weight)) - .saturating_add(T::DbWeight::get().writes((3 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) @@ -70,12 +71,21 @@ // Storage: Nonfungible TokenData (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:1) fn theme_add(b: u32, ) -> Weight { - (39_467_000 as Weight) - // Standard Error: 15_000 - .saturating_add((2_332_000 as Weight).saturating_mul(b as Weight)) + (39_525_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_494_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_371_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 @@ -93,13 +103,13 @@ // Storage: Nonfungible Owned (r:0 w:1) // Storage: RmrkEquip InernalPartId (r:0 w:1) fn create_base(b: u32, ) -> Weight { - (43_216_000 as Weight) + (44_632_000 as Weight) // Standard Error: 10_000 - .saturating_add((16_253_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((16_912_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(9 as Weight)) - .saturating_add(RocksDbWeight::get().writes((3 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) @@ -110,10 +120,19 @@ // Storage: Nonfungible TokenData (r:0 w:1) // Storage: Nonfungible Owned (r:0 w:1) fn theme_add(b: u32, ) -> Weight { - (39_467_000 as Weight) - // Standard Error: 15_000 - .saturating_add((2_332_000 as Weight).saturating_mul(b as Weight)) + (39_525_000 as Weight) + // Standard Error: 12_000 + .saturating_add((2_494_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_371_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; @@ -987,8 +987,9 @@ 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>; -- gitstuff