git.delta.rocks / unique-network / refs/commits / 5d82f750c78d

difftreelog

feat(rmrk) refactor resources

Daniel Shiposha2022-06-15parent: #f9272dd.patch.diff
in: master

5 files changed

modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
154 NftTypeEncodeError,154 NftTypeEncodeError,
155 RmrkPropertyKeyIsTooLong,155 RmrkPropertyKeyIsTooLong,
156 RmrkPropertyValueIsTooLong,156 RmrkPropertyValueIsTooLong,
157 RmrkPropertyIsNotFound,
157 UnableToDecodeRmrkData,158 UnableToDecodeRmrkData,
158159
159 /* RMRK compatible events */160 /* RMRK compatible events */
169 CannotAcceptNonOwnedNft,170 CannotAcceptNonOwnedNft,
170 CannotRejectNonOwnedNft,171 CannotRejectNonOwnedNft,
171 ResourceNotPending,172 ResourceNotPending,
173 NoAvailableResourceId,
172 }174 }
173175
174 #[pallet::call]176 #[pallet::call]
381 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,383 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
382 Self::rmrk_property(Metadata, &metadata)?,384 Self::rmrk_property(Metadata, &metadata)?,
383 Self::rmrk_property(Equipped, &false)?,385 Self::rmrk_property(Equipped, &false)?,
384 Self::rmrk_property(ResourceCollection, &None::<CollectionId>)?,
385 Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,386 Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
387 Self::rmrk_property(NextResourceId, &(0 as RmrkResourceId))?,
386 ]388 ]
387 .into_iter(),389 .into_iter(),
388 )390 )
653 collection.check_is_external()?;655 collection.check_is_external()?;
654656
655 ensure!(657 ensure!(
658 <TokenData<T>>::get((collection_id, nft_id)).is_some(),
659 <Error<T>>::NoAvailableNftId
660 );
661
662 ensure!(
656 Self::get_nft_property_decoded(663 Self::get_nft_property_decoded(
657 collection_id,664 collection_id,
658 nft_id,665 nft_id,
686 origin: OriginFor<T>,693 origin: OriginFor<T>,
687 rmrk_collection_id: RmrkCollectionId,694 rmrk_collection_id: RmrkCollectionId,
688 rmrk_nft_id: RmrkNftId,695 rmrk_nft_id: RmrkNftId,
689 rmrk_resource_id: RmrkResourceId,696 resource_id: RmrkResourceId,
690 ) -> DispatchResult {697 ) -> DispatchResult {
691 let sender = ensure_signed(origin)?;698 let sender = ensure_signed(origin)?;
692 let cross_sender = T::CrossAccountId::from_sub(sender);699 let cross_sender = T::CrossAccountId::from_sub(sender);
698 collection.check_is_external()?;705 collection.check_is_external()?;
699706
700 let nft_id = rmrk_nft_id.into();707 let nft_id = rmrk_nft_id.into();
701 let resource_id = rmrk_resource_id.into();
702708
703 let budget = budget::Value::new(NESTING_BUDGET);709 let budget = budget::Value::new(NESTING_BUDGET);
704710
705 let nft_owner =711 let nft_owner =
706 <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)712 <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)
707 .map_err(|_| <Error<T>>::ResourceDoesntExist)?;713 .map_err(|_| <Error<T>>::ResourceDoesntExist)?;
708714
709 let resource_collection_id: Option<CollectionId> =715 Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {
710 Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)716 ensure!(res.pending, <Error<T>>::ResourceNotPending);
711 .map_err(|_| <Error<T>>::ResourceDoesntExist)?;717 ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);
712718
713 let resource_collection_id =719 res.pending = false;
714 resource_collection_id.ok_or(<Error<T>>::ResourceDoesntExist)?;
715720
716 let is_pending: bool = Self::get_nft_property_decoded(721 Ok(())
717 resource_collection_id,
718 resource_id,
719 PendingResourceAccept,
720 )
721 .map_err(|_| <Error<T>>::ResourceDoesntExist)?;722 })?;
722723
723 ensure!(is_pending, <Error<T>>::ResourceNotPending);
724
725 ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);
726
727 <PalletNft<T>>::set_scoped_token_property(
728 resource_collection_id,
729 rmrk_resource_id.into(),
730 PropertyScope::Rmrk,
731 Self::rmrk_property(PendingResourceAccept, &false)?,
732 )?;
733
734 Self::deposit_event(Event::<T>::ResourceAccepted {724 Self::deposit_event(Event::<T>::ResourceAccepted {
735 nft_id: rmrk_nft_id,725 nft_id: rmrk_nft_id,
736 resource_id: rmrk_resource_id,726 resource_id,
737 });727 });
738728
739 Ok(())729 Ok(())
746 origin: OriginFor<T>,736 origin: OriginFor<T>,
747 rmrk_collection_id: RmrkCollectionId,737 rmrk_collection_id: RmrkCollectionId,
748 rmrk_nft_id: RmrkNftId,738 rmrk_nft_id: RmrkNftId,
749 rmrk_resource_id: RmrkResourceId,739 resource_id: RmrkResourceId,
750 ) -> DispatchResult {740 ) -> DispatchResult {
751 let sender = ensure_signed(origin)?;741 let sender = ensure_signed(origin)?;
752 let cross_sender = T::CrossAccountId::from_sub(sender);742 let cross_sender = T::CrossAccountId::from_sub(sender);
758 collection.check_is_external()?;748 collection.check_is_external()?;
759749
760 let nft_id = rmrk_nft_id.into();750 let nft_id = rmrk_nft_id.into();
761 let resource_id = rmrk_resource_id.into();
762751
763 let budget = budget::Value::new(NESTING_BUDGET);752 let budget = budget::Value::new(NESTING_BUDGET);
764753
768757
769 ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);758 ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);
770759
771 let resource_collection_id: Option<CollectionId> =760 let resource_id_key = Self::rmrk_property_key(ResourceId(resource_id))?;
772 Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)
773 .map_err(|_| <Error<T>>::ResourceDoesntExist)?;
774761
775 let resource_collection_id =762 let resource_info = <PalletNft<T>>::token_sys_property((
776 resource_collection_id.ok_or(<Error<T>>::ResourceDoesntExist)?;763 collection_id,
764 nft_id,
765 PropertyScope::Rmrk,
766 resource_id_key.clone(),
767 ))
768 .ok_or(<Error<T>>::ResourceDoesntExist)?;
777769
778 let is_pending: bool = Self::get_nft_property_decoded(770 let resource_info: RmrkResourceInfo = Self::decode_property(&resource_info)?;
779 resource_collection_id,
780 resource_id,
781 PendingResourceRemoval,
782 )
783 .map_err(|_| <Error<T>>::ResourceDoesntExist)?;
784771
785 ensure!(is_pending, <Error<T>>::ResourceNotPending);772 ensure!(
773 resource_info.pending_removal,
774 <Error<T>>::ResourceNotPending
775 );
786776
787 let resource_collection = Self::get_typed_nft_collection(777 <PalletNft<T>>::remove_token_sys_property(
788 resource_collection_id,778 collection_id,
789 misc::CollectionType::Resource,779 nft_id,
780 PropertyScope::Rmrk,
781 resource_id_key,
790 )?;782 );
791783
792 let resource_data = <TokenData<T>>::get((resource_collection_id, resource_id))
793 .ok_or(<Error<T>>::ResourceDoesntExist)?;
794
795 let resource_owner = resource_data.owner;
796
797 <PalletNft<T>>::burn(
798 &resource_collection,
799 &resource_owner,
800 rmrk_resource_id.into(),
801 )
802 .map_err(Self::map_unique_err_to_proxy)?;
803
804 Self::deposit_event(Event::<T>::ResourceRemovalAccepted {784 Self::deposit_event(Event::<T>::ResourceRemovalAccepted {
805 nft_id: rmrk_nft_id,785 nft_id: rmrk_nft_id,
806 resource_id: rmrk_resource_id,786 resource_id,
807 });787 });
808788
809 Ok(())789 Ok(())
1014 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;994 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
1015 collection.check_is_external()?;995 collection.check_is_external()?;
1016996
1017 Self::resource_remove(sender, collection_id, nft_id.into(), resource_id.into())?;997 Self::resource_remove(sender, collection_id, nft_id.into(), resource_id)?;
1018998
1019 Self::deposit_event(Event::ResourceRemoval {999 Self::deposit_event(Event::ResourceRemoval {
1020 nft_id,1000 nft_id,
1043 ) -> Result<Property, DispatchError> {1023 ) -> Result<Property, DispatchError> {
1044 let key = rmrk_key.to_key::<T>()?;1024 let key = rmrk_key.to_key::<T>()?;
10451025
1026 let value = Self::encode_property(value)?;
1027
1028 let property = Property { key, value };
1029
1030 Ok(property)
1031 }
1032
1033 pub fn encode_property<E: Encode, S: Get<u32>>(
1034 value: &E,
1035 ) -> Result<BoundedBytes<S>, DispatchError> {
1046 let value = value1036 let value = value
1047 .encode()1037 .encode()
1048 .try_into()1038 .try_into()
1049 .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;1039 .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;
10501040
1051 let property = Property { key, value };1041 Ok(value)
1052
1053 Ok(property)
1054 }1042 }
10551043
1056 pub fn decode_property<D: Decode>(vec: PropertyValue) -> Result<D, DispatchError> {1044 pub fn decode_property<D: Decode, S: Get<u32>>(
1045 vec: &BoundedBytes<S>,
1046 ) -> Result<D, DispatchError> {
1057 vec.decode()1047 vec.decode()
1058 .map_err(|_| <Error<T>>::UnableToDecodeRmrkData.into())1048 .map_err(|_| <Error<T>>::UnableToDecodeRmrkData.into())
1059 }1049 }
1153 )1143 )
1154 }1144 }
11551145
1156 fn resource_add(1146 fn acquire_next_resource_id(
1157 sender: T::AccountId,
1158 collection_id: CollectionId,1147 collection_id: CollectionId,
1159 nft_id: TokenId,1148 nft_id: TokenId,
1160 resource: RmrkResourceTypes,
1161 ) -> Result<RmrkResourceId, DispatchError> {1149 ) -> Result<RmrkResourceId, DispatchError> {
1162 match resource {1150 let resource_id: RmrkResourceId =
1163 RmrkResourceTypes::Basic(resource) => Self::resource_add_helper(
1164 sender,1151 Self::get_nft_property_decoded(collection_id, nft_id, NextResourceId)?;
1165 collection_id,1152
1166 nft_id,
1167 [
1168 Self::rmrk_property(TokenType, &NftType::Resource)?,
1169 Self::rmrk_property(ResourceType, &misc::ResourceType::Basic)?,
1170 Self::rmrk_property(Src, &resource.src)?,
1171 Self::rmrk_property(Metadata, &resource.metadata)?,1153 let next_id = resource_id
1172 Self::rmrk_property(License, &resource.license)?,
1173 Self::rmrk_property(Thumb, &resource.thumb)?,
1174 ]
1175 .into_iter(),
1176 ),
1177 RmrkResourceTypes::Composable(resource) => Self::resource_add_helper(
1178 sender,1154 .checked_add(1)
1179 collection_id,
1180 nft_id.into(),
1181 [1155 .ok_or(<Error<T>>::NoAvailableResourceId)?;
1182 Self::rmrk_property(TokenType, &NftType::Resource)?,1156
1183 Self::rmrk_property(ResourceType, &misc::ResourceType::Composable)?,
1184 Self::rmrk_property(Parts, &resource.parts)?,
1185 Self::rmrk_property(Base, &resource.base)?,
1186 Self::rmrk_property(Src, &resource.src)?,
1187 Self::rmrk_property(Metadata, &resource.metadata)?,
1188 Self::rmrk_property(License, &resource.license)?,1157 <PalletNft<T>>::set_scoped_token_property(
1189 Self::rmrk_property(Thumb, &resource.thumb)?,
1190 ]
1191 .into_iter(),
1192 ),
1193 RmrkResourceTypes::Slot(resource) => Self::resource_add_helper(
1194 sender,1158 collection_id,
1195 collection_id,
1196 nft_id.into(),1159 nft_id,
1197 [1160 PropertyScope::Rmrk,
1198 Self::rmrk_property(TokenType, &NftType::Resource)?,
1199 Self::rmrk_property(ResourceType, &misc::ResourceType::Slot)?,1161 Self::rmrk_property(NextResourceId, &next_id)?,
1200 Self::rmrk_property(Base, &resource.base)?,1162 )?;
1201 Self::rmrk_property(Src, &resource.src)?,1163
1202 Self::rmrk_property(Metadata, &resource.metadata)?,1164 Ok(resource_id)
1203 Self::rmrk_property(Slot, &resource.slot)?,
1204 Self::rmrk_property(License, &resource.license)?,
1205 Self::rmrk_property(Thumb, &resource.thumb)?,
1206 ]
1207 .into_iter(),
1208 ),
1209 }
1210 }1165 }
12111166
1212 fn resource_add_helper(1167 fn resource_add(
1213 sender: T::AccountId,1168 sender: T::AccountId,
1214 collection_id: CollectionId,1169 collection_id: CollectionId,
1215 token_id: TokenId,1170 nft_id: TokenId,
1216 resource_properties: impl Iterator<Item = Property>,1171 resource: RmrkResourceTypes,
1217 ) -> Result<RmrkResourceId, DispatchError> {1172 ) -> Result<RmrkResourceId, DispatchError> {
1218 let collection =1173 let collection =
1219 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1174 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
1222 let sender = T::CrossAccountId::from_sub(sender);1177 let sender = T::CrossAccountId::from_sub(sender);
1223 let budget = budget::Value::new(NESTING_BUDGET);1178 let budget = budget::Value::new(NESTING_BUDGET);
12241179
1225 let nft_owner = <PalletStructure<T>>::find_topmost_owner(collection_id, token_id, &budget)1180 let nft_owner = <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)
1226 .map_err(Self::map_unique_err_to_proxy)?;1181 .map_err(Self::map_unique_err_to_proxy)?;
12271182
1228 let pending = sender != nft_owner;1183 let pending = sender != nft_owner;
12291184
1230 let resource_collection_id: Option<CollectionId> =1185 let id = Self::acquire_next_resource_id(collection_id, nft_id)?;
1231 Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;
12321186
1233 let resource_collection_id = match resource_collection_id {1187 let resource_info = RmrkResourceInfo {
1234 Some(id) => id,1188 id,
1235 None => {1189 resource,
1236 let resource_collection_id = Self::init_collection(
1237 sender.clone(),
1238 CreateCollectionData {1190 pending,
1239 ..Default::default()
1240 },
1241 [Self::rmrk_property(1191 pending_removal: false,
1242 CollectionType,
1243 &misc::CollectionType::Resource,
1244 )?]
1245 .into_iter(),
1246 )?;
1247
1248 <PalletNft<T>>::set_scoped_token_property(
1249 collection_id,
1250 token_id,
1251 PropertyScope::Rmrk,
1252 Self::rmrk_property(ResourceCollection, &Some(resource_collection_id))?,
1253 )?;
1254
1255 resource_collection_id
1256 }
1257 };1192 };
12581193
1259 let resource_collection =1194 <PalletNft<T>>::try_mutate_token_sys_property(
1260 Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;1195 collection_id,
1196 nft_id,
1197 PropertyScope::Rmrk,
1198 Self::rmrk_property_key(ResourceId(id))?,
1199 |value| -> DispatchResult {
1200 *value = Some(Self::encode_property(&resource_info)?);
12611201
1262 // todo probably add extra connections to bases, slots, etc., when RMRK starts to use them1202 Ok(())
1203 },
1204 )?;
12631205
1264 let resource_id = Self::create_nft(1206 Ok(id)
1265 &sender,
1266 &nft_owner,
1267 &resource_collection,
1268 resource_properties.chain(
1269 [
1270 Self::rmrk_property(PendingResourceAccept, &pending)?,
1271 Self::rmrk_property(PendingResourceRemoval, &false)?,
1272 ]
1273 .into_iter(),
1274 ),
1275 )
1276 .map_err(|err| match err {
1277 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
1278 err => Self::map_unique_err_to_proxy(err),
1279 })?;
1280
1281 Ok(resource_id.0)
1282 }1207 }
12831208
1284 fn resource_remove(1209 fn resource_remove(
1285 sender: T::AccountId,1210 sender: T::AccountId,
1286 collection_id: CollectionId,1211 collection_id: CollectionId,
1287 nft_id: TokenId,1212 nft_id: TokenId,
1288 resource_id: TokenId,1213 resource_id: RmrkResourceId,
1289 ) -> DispatchResult {1214 ) -> DispatchResult {
1290 let collection =1215 let collection =
1291 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1216 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
1292 ensure!(collection.owner == sender, Error::<T>::NoPermission);1217 ensure!(collection.owner == sender, Error::<T>::NoPermission);
12931218
1294 let resource_collection_id: Option<CollectionId> =1219 let resource_id_key = Self::rmrk_property_key(ResourceId(resource_id))?;
1295 Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)?;1220 let scope = PropertyScope::Rmrk;
12961221
1297 let resource_collection_id =
1298 resource_collection_id.ok_or(Error::<T>::ResourceDoesntExist)?;
1299
1300 let resource_collection =
1301 Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;
1302 ensure!(1222 ensure!(
1303 <PalletNft<T>>::token_exists(&resource_collection, resource_id),1223 <PalletNft<T>>::token_sys_property((
1224 collection_id,
1225 nft_id,
1226 scope,
1227 resource_id_key.clone()
1228 ))
1229 .is_some(),
1304 Error::<T>::ResourceDoesntExist1230 <Error<T>>::ResourceDoesntExist
1305 );1231 );
13061232
1307 let budget = up_data_structs::budget::Value::new(NESTING_BUDGET);1233 let budget = up_data_structs::budget::Value::new(NESTING_BUDGET);
13101236
1311 let sender = T::CrossAccountId::from_sub(sender);1237 let sender = T::CrossAccountId::from_sub(sender);
1312 if topmost_owner == sender {1238 if topmost_owner == sender {
1313 <PalletNft<T>>::burn(&resource_collection, &sender, resource_id)1239 <PalletNft<T>>::remove_token_sys_property(
1314 .map_err(Self::map_unique_err_to_proxy)?;
1315 } else {
1316 <PalletNft<T>>::set_scoped_token_property(
1317 resource_collection_id,1240 collection_id,
1318 resource_id,1241 nft_id,
1319 PropertyScope::Rmrk,1242 PropertyScope::Rmrk,
1320 Self::rmrk_property(PendingResourceRemoval, &true)?,1243 Self::rmrk_property_key(ResourceId(resource_id))?,
1244 );
1245 } else {
1246 Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {
1247 res.pending_removal = true;
1248
1249 Ok(())
1321 )?;1250 })?;
1322 }1251 }
13231252
1324 Ok(())1253 Ok(())
1254 }
1255
1256 fn try_mutate_resource_info(
1257 collection_id: CollectionId,
1258 nft_id: TokenId,
1259 resource_id: RmrkResourceId,
1260 f: impl FnOnce(&mut RmrkResourceInfo) -> DispatchResult,
1261 ) -> DispatchResult {
1262 <PalletNft<T>>::try_mutate_token_sys_property(
1263 collection_id,
1264 nft_id,
1265 PropertyScope::Rmrk,
1266 Self::rmrk_property_key(ResourceId(resource_id))?,
1267 |value| match value {
1268 Some(value) => {
1269 let mut resource_info: RmrkResourceInfo = Self::decode_property(value)?;
1270
1271 f(&mut resource_info)?;
1272
1273 *value = Self::encode_property(&resource_info)?;
1274
1275 Ok(())
1276 }
1277 None => Err(<Error<T>>::ResourceDoesntExist.into()),
1278 },
1279 )
1325 }1280 }
13261281
1327 fn change_collection_owner(1282 fn change_collection_owner(
1397 collection_id: CollectionId,1352 collection_id: CollectionId,
1398 key: RmrkProperty,1353 key: RmrkProperty,
1399 ) -> Result<V, DispatchError> {1354 ) -> Result<V, DispatchError> {
1400 Self::decode_property(Self::get_collection_property(collection_id, key)?)1355 Self::decode_property(&Self::get_collection_property(collection_id, key)?)
1401 }1356 }
14021357
1403 pub fn get_collection_type(1358 pub fn get_collection_type(
1450 ) -> Result<PropertyValue, DispatchError> {1405 ) -> Result<PropertyValue, DispatchError> {
1451 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))1406 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))
1452 .get(&Self::rmrk_property_key(key)?)1407 .get(&Self::rmrk_property_key(key)?)
1453 .ok_or(<Error<T>>::NoAvailableNftId)? // todo replace with better error?1408 .ok_or(<Error<T>>::RmrkPropertyIsNotFound)?
1454 .clone();1409 .clone();
14551410
1456 Ok(nft_property)1411 Ok(nft_property)
1461 nft_id: TokenId,1416 nft_id: TokenId,
1462 key: RmrkProperty,1417 key: RmrkProperty,
1463 ) -> Result<V, DispatchError> {1418 ) -> Result<V, DispatchError> {
1464 Self::decode_property(Self::get_nft_property(collection_id, nft_id, key)?)1419 Self::decode_property(&Self::get_nft_property(collection_id, nft_id, key)?)
1465 }1420 }
14661421
1467 pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {1422 pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
modifiedpallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth
--- 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,
 }
modifiedpallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth
--- 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"),
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -75,9 +75,8 @@
 	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,
+	RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceId,
+	RmrkBaseId, RmrkFixedPart, RmrkSlotPart, RmrkString,
 };
 
 // use pallet_contracts::weights::WeightInfo;
@@ -1501,8 +1500,8 @@
 		}
 
 		fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
-			use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};
-			use pallet_common::CommonCollectionOperations;
+			use pallet_proxy_rmrk_core::misc::{CollectionType, NftType};
+			use up_data_structs::PropertyScope;
 
 			let collection_id = match RmrkCore::unique_collection_id(collection_id) {
 				Ok(id) => id,
@@ -1513,48 +1512,13 @@
 			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<CollectionId> = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;
+			let resources = <pallet_nonfungible::Pallet<Runtime>>::iterate_token_sys_properties(
+				collection_id, nft_id, PropertyScope::Rmrk
+			).filter_map(|(_, value)| {
+				let resource_info: RmrkResourceInfo = RmrkCore::decode_property(&value).ok()?;
 
-			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();
+				Some(resource_info)
+			}).collect();
 
 			Ok(resources)
 		}
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -75,9 +75,8 @@
 	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,
+	RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceId,
+	RmrkBaseId, RmrkFixedPart, RmrkSlotPart, RmrkString,
 };
 
 // use pallet_contracts::weights::WeightInfo;
@@ -1501,8 +1500,8 @@
 		}
 
 		fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
-			use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};
-			use pallet_common::CommonCollectionOperations;
+			use pallet_proxy_rmrk_core::misc::{CollectionType, NftType};
+			use up_data_structs::PropertyScope;
 
 			let collection_id = match RmrkCore::unique_collection_id(collection_id) {
 				Ok(id) => id,
@@ -1513,48 +1512,13 @@
 			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<CollectionId> = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;
+			let resources = <pallet_nonfungible::Pallet<Runtime>>::iterate_token_sys_properties(
+				collection_id, nft_id, PropertyScope::Rmrk
+			).filter_map(|(_, value)| {
+				let resource_info: RmrkResourceInfo = RmrkCore::decode_property(&value).ok()?;
 
-			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();
+				Some(resource_info)
+			}).collect();
 
 			Ok(resources)
 		}