From a74fad685f6e3fc7eda84a23da638e697cd5c9a8 Mon Sep 17 00:00:00 2001 From: Daniel Shiposha Date: Thu, 30 Jun 2022 09:56:53 +0000 Subject: [PATCH] feat(rmrk): add associated bases property --- --- a/pallets/proxy-rmrk-core/src/lib.rs +++ b/pallets/proxy-rmrk-core/src/lib.rs @@ -24,7 +24,7 @@ }; use frame_system::{pallet_prelude::*, ensure_signed}; use sp_runtime::{DispatchError, Permill, traits::StaticLookup}; -use sp_std::{vec::Vec, collections::btree_set::BTreeSet}; +use sp_std::{vec::Vec, collections::{btree_set::BTreeSet, btree_map::BTreeMap}}; use up_data_structs::{*, mapping::TokenAddressMapping}; use pallet_common::{ Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations, @@ -55,7 +55,9 @@ type PendingTarget = (CollectionId, TokenId); type PendingChild = (RmrkCollectionId, RmrkNftId); -type PendingChildrenMap = BTreeSet; +type PendingChildrenSet = BTreeSet; + +type BasesMap = BTreeMap; #[frame_support::pallet] pub mod pallet { @@ -398,7 +400,8 @@ Self::rmrk_property(Equipped, &false)?, Self::rmrk_property(ResourcePriorities, &>::new())?, Self::rmrk_property(NextResourceId, &(0 as RmrkResourceId))?, - Self::rmrk_property(PendingChildren, &PendingChildrenMap::new())?, + Self::rmrk_property(PendingChildren, &PendingChildrenSet::new())?, + Self::rmrk_property(AssociatedBases, &BasesMap::new())?, ] .into_iter(), ) @@ -816,6 +819,12 @@ resource_id_key, ); + if let RmrkResourceTypes::Composable(resource) = resource_info.resource { + let base_id = resource.base; + + Self::remove_associated_base_id(collection_id, nft_id, base_id)?; + } + Self::deposit_event(Event::::ResourceRemovalAccepted { nft_id: rmrk_nft_id, resource_id, @@ -969,6 +978,8 @@ Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?; collection.check_is_external()?; + let base_id = resource.base; + let resource_id = Self::resource_add( sender, collection_id, @@ -976,6 +987,24 @@ RmrkResourceTypes::Composable(resource), )?; + >::try_mutate_token_aux_property( + collection_id, + nft_id.into(), + PropertyScope::Rmrk, + Self::rmrk_property_key(AssociatedBases)?, + |value| -> DispatchResult { + let mut bases: BasesMap = match value { + Some(value) => Self::decode_property(value)?, + None => BasesMap::new() + }; + + *bases.entry(base_id).or_insert(0) += 1; + + *value = Some(Self::encode_property(&bases)?); + Ok(()) + } + )?; + Self::deposit_event(Event::ResourceAdded { nft_id, resource_id, @@ -1198,7 +1227,7 @@ fn mutate_pending_child( (target_collection_id, target_nft_id): (CollectionId, TokenId), - f: impl FnOnce(&mut PendingChildrenMap), + f: impl FnOnce(&mut PendingChildrenSet), ) -> DispatchResult { >::try_mutate_token_aux_property( target_collection_id, @@ -1208,7 +1237,7 @@ |pending_children| -> DispatchResult { let mut map = match pending_children { Some(map) => Self::decode_property(map)?, - None => PendingChildrenMap::new(), + None => PendingChildrenSet::new(), }; f(&mut map); @@ -1230,7 +1259,7 @@ let pending_children = match property { Some(map) => Self::decode_property(&map)?, - None => PendingChildrenMap::new(), + None => PendingChildrenSet::new(), }; Ok(pending_children.into_iter()) @@ -1312,16 +1341,14 @@ let resource_id_key = Self::rmrk_property_key(ResourceId(resource_id))?; let scope = PropertyScope::Rmrk; - ensure!( - >::token_aux_property(( - collection_id, - nft_id, - scope, - resource_id_key.clone() - )) - .is_some(), - >::ResourceDoesntExist - ); + let resource = >::token_aux_property(( + collection_id, + nft_id, + scope, + resource_id_key.clone() + )).ok_or(>::ResourceDoesntExist)?; + + let resource_info: RmrkResourceInfo = Self::decode_property(&resource)?; let budget = up_data_structs::budget::Value::new(NESTING_BUDGET); let topmost_owner = @@ -1335,6 +1362,12 @@ PropertyScope::Rmrk, Self::rmrk_property_key(ResourceId(resource_id))?, ); + + if let RmrkResourceTypes::Composable(resource) = resource_info.resource { + let base_id = resource.base; + + Self::remove_associated_base_id(collection_id, nft_id, base_id)?; + } } else { Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| { res.pending_removal = true; @@ -1346,6 +1379,36 @@ Ok(()) } + fn remove_associated_base_id( + collection_id: CollectionId, + nft_id: TokenId, + base_id: RmrkBaseId, + ) -> DispatchResult { + >::try_mutate_token_aux_property( + collection_id, + nft_id, + PropertyScope::Rmrk, + Self::rmrk_property_key(AssociatedBases)?, + |value| -> DispatchResult { + let mut bases: BasesMap = match value { + Some(value) => Self::decode_property(value)?, + None => BasesMap::new() + }; + + let remaining = bases.get(&base_id); + + if let Some(remaining) = remaining { + if let Some(0) | None = remaining.checked_sub(1) { + bases.remove(&base_id); + } + } + + *value = Some(Self::encode_property(&bases)?); + Ok(()) + } + ) + } + fn try_mutate_resource_info( collection_id: CollectionId, nft_id: TokenId, --- a/pallets/proxy-rmrk-core/src/property.rs +++ b/pallets/proxy-rmrk-core/src/property.rs @@ -34,6 +34,7 @@ ResourceId(RmrkResourceId), PendingNftAccept, PendingChildren, + AssociatedBases, Parts, Base, Src, @@ -77,6 +78,7 @@ Self::ResourceId(id) => key!(RESOURCE_ID_PREFIX, id.to_le_bytes()), Self::PendingNftAccept => key!("pending-nft-accept"), Self::PendingChildren => key!("pending-children"), + Self::AssociatedBases => key!("assoc-bases"), Self::Parts => key!("parts"), Self::Base => key!("base"), Self::Src => key!("src"), -- gitstuff