git.delta.rocks / unique-network / refs/commits / a74fad685f6e

difftreelog

feat(rmrk) add associated bases property

Daniel Shiposha2022-06-30parent: #51e15a0.patch.diff
in: master

2 files changed

modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
--- 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<PendingChild>;
+type PendingChildrenSet = BTreeSet<PendingChild>;
+
+type BasesMap = BTreeMap<RmrkBaseId, u32>;
 
 #[frame_support::pallet]
 pub mod pallet {
@@ -398,7 +400,8 @@
 					Self::rmrk_property(Equipped, &false)?,
 					Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::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::<T>::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),
 			)?;
 
+			<PalletNft<T>>::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 {
 		<PalletNft<T>>::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!(
-			<PalletNft<T>>::token_aux_property((
-				collection_id,
-				nft_id,
-				scope,
-				resource_id_key.clone()
-			))
-			.is_some(),
-			<Error<T>>::ResourceDoesntExist
-		);
+		let resource = <PalletNft<T>>::token_aux_property((
+			collection_id,
+			nft_id,
+			scope,
+			resource_id_key.clone()
+		)).ok_or(<Error<T>>::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 {
+		<PalletNft<T>>::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,
modifiedpallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth
34 ResourceId(RmrkResourceId),34 ResourceId(RmrkResourceId),
35 PendingNftAccept,35 PendingNftAccept,
36 PendingChildren,36 PendingChildren,
37 AssociatedBases,
37 Parts,38 Parts,
38 Base,39 Base,
39 Src,40 Src,
77 Self::ResourceId(id) => key!(RESOURCE_ID_PREFIX, id.to_le_bytes()),78 Self::ResourceId(id) => key!(RESOURCE_ID_PREFIX, id.to_le_bytes()),
78 Self::PendingNftAccept => key!("pending-nft-accept"),79 Self::PendingNftAccept => key!("pending-nft-accept"),
79 Self::PendingChildren => key!("pending-children"),80 Self::PendingChildren => key!("pending-children"),
81 Self::AssociatedBases => key!("assoc-bases"),
80 Self::Parts => key!("parts"),82 Self::Parts => key!("parts"),
81 Self::Base => key!("base"),83 Self::Base => key!("base"),
82 Self::Src => key!("src"),84 Self::Src => key!("src"),