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

difftreelog

refactor(rmrk-proxy) better decoding

Fahrrader2022-06-02parent: #71b4dea.patch.diff
in: master

3 files changed

modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
111 CorruptedCollectionType,111 CorruptedCollectionType,
112 NftTypeEncodeError,112 NftTypeEncodeError,
113 RmrkPropertyKeyIsTooLong,113 RmrkPropertyKeyIsTooLong,
114 RmrkPropertyValueIsTooLong, // todo utilize that in RPCs114 RmrkPropertyValueIsTooLong,
115115
116 /* RMRK compatible events */116 /* RMRK compatible events */
117 CollectionNotEmpty,117 CollectionNotEmpty,
518 Ok(scoped_key)518 Ok(scoped_key)
519 }519 }
520520
521 pub fn rmrk_property<E: Encode>(521 pub fn rmrk_property<E: Encode>( // todo think about renaming this
522 rmrk_key: RmrkProperty,522 rmrk_key: RmrkProperty,
523 value: &E,523 value: &E,
524 ) -> Result<Property, DispatchError> {524 ) -> Result<Property, DispatchError> {
534 Ok(property)534 Ok(property)
535 }535 }
536
537 pub fn decode_property<D: Decode>(
538 vec: PropertyValue,
539 ) -> Result<D, DispatchError> {
540 vec.decode().map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())
541 }
542
543 pub fn rebind<L, S>(
544 vec: &BoundedVec<u8, L>,
545 ) -> Result<BoundedVec<u8, S>, DispatchError>
546 where
547 BoundedVec<u8, S>: TryFrom<Vec<u8>>
548 {
549 vec.rebind().map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())
550 }
536551
537 fn init_collection(552 fn init_collection(
538 sender: T::CrossAccountId,553 sender: T::CrossAccountId,
619 )?;634 )?;
620635
621 let resource_collection_id: CollectionId =636 let resource_collection_id: CollectionId =
622 Self::get_nft_property(collection_id, token_id, ResourceCollection)?637 Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;
623 .decode_or_default();
624 let resource_collection =638 let resource_collection =
625 Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;639 Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;
626640
709 Ok(collection_property)723 Ok(collection_property)
710 }724 }
725
726 pub fn get_collection_property_decoded<V: Decode>(
727 collection_id: CollectionId,
728 key: RmrkProperty,
729 ) -> Result<V, DispatchError> {
730 Self::decode_property(
731 Self::get_collection_property(collection_id, key)?
732 )
733 }
711734
712 pub fn get_collection_type(735 pub fn get_collection_type(
713 collection_id: CollectionId,736 collection_id: CollectionId,
714 ) -> Result<misc::CollectionType, DispatchError> {737 ) -> Result<misc::CollectionType, DispatchError> {
715 let value = Self::get_collection_property(collection_id, CollectionType)?;738 Self::get_collection_property_decoded(collection_id, CollectionType)
716
717 let mut value = value.as_slice();
718
719 misc::CollectionType::decode(&mut value)
720 .map_err(|_| <Error<T>>::CorruptedCollectionType.into())739 .map_err(|_| <Error<T>>::CorruptedCollectionType.into())
721 }740 }
722741
723 pub fn ensure_collection_type(742 pub fn ensure_collection_type(
749 ) -> Result<PropertyValue, DispatchError> {768 ) -> Result<PropertyValue, DispatchError> {
750 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))769 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))
751 .get(&Self::rmrk_property_key(key)?)770 .get(&Self::rmrk_property_key(key)?)
752 .ok_or(<Error<T>>::NoAvailableNftId)? // todo replace with better error771 .ok_or(<Error<T>>::NoAvailableNftId)? // todo replace with better error?
753 .clone();772 .clone();
754773
755 Ok(nft_property)774 Ok(nft_property)
756 }775 }
776
777 pub fn get_nft_property_decoded<V: Decode>(
778 collection_id: CollectionId,
779 nft_id: TokenId,
780 key: RmrkProperty,
781 ) -> Result<V, DispatchError> {
782 Self::decode_property(
783 Self::get_nft_property(collection_id, nft_id, key)?
784 )
785 }
757786
758 pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {787 pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
759 <TokenData<T>>::contains_key((collection_id, nft_id))788 <TokenData<T>>::contains_key((collection_id, nft_id))
763 collection_id: CollectionId,792 collection_id: CollectionId,
764 token_id: TokenId,793 token_id: TokenId,
765 ) -> Result<NftType, DispatchError> {794 ) -> Result<NftType, DispatchError> {
766 Ok(Self::get_nft_property(collection_id, token_id, TokenType)?.decode_or_default())795 Self::get_nft_property_decoded(collection_id, token_id, TokenType)
767 // todo throw error796 .map_err(|_| <Error<T>>::NftTypeEncodeError.into())
768 // NftTypeEncodeError?
769 }797 }
770798
771 pub fn ensure_nft_type(799 pub fn ensure_nft_type(
814 let key: Key = key.try_into().ok()?;842 let key: Key = key.try_into().ok()?;
815843
816 let value = match token_id {844 let value = match token_id {
817 Some(token_id) => Self::get_nft_property(845 Some(token_id) => Self::get_nft_property_decoded(
818 collection_id,846 collection_id,
819 token_id,847 token_id,
820 UserProperty(key.as_ref()),848 UserProperty(key.as_ref()),
821 ),849 ),
822 None => Self::get_collection_property(850 None => Self::get_collection_property_decoded(
823 collection_id,851 collection_id,
824 UserProperty(key.as_ref()),852 UserProperty(key.as_ref()),
825 ),853 ),
826 }854 }
827 .ok()?
828 .decode_or_default();855 .ok()?;
829856
830 Some(mapper(key, value))857 Some(mapper(key, value))
831 })858 })
862 let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;889 let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;
863890
864 let key: Key = key.to_vec().try_into().ok()?;891 let key: Key = key.to_vec().try_into().ok()?;
865 let value: Value = value.decode_or_default();892 let value: Value = value.decode().ok()?;
866893
867 Some(mapper(key, value))894 Some(mapper(key, value))
868 });895 });
modifiedpallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth
1use super::*;1use super::*;
2use codec::{Encode, Decode};2use codec::{Encode, Decode, Error};
3use derivative::Derivative;
43
5#[macro_export]4#[macro_export]
6macro_rules! map_common_err_to_proxy {5macro_rules! map_common_err_to_proxy {
15 };14 };
16}15}
1716
17// Utilize the RmrkCore pallet for access to Runtime errors.
18pub trait RmrkDecode<T: Decode + Default, S> {18pub trait RmrkDecode<T: Decode, S> {
19 fn decode_or_default(&self) -> T;19 fn decode(&self) -> Result<T, Error>;
20}20}
2121
22// todo fail if unwrap doesn't work
23impl<T: Decode + Default, S> RmrkDecode<T, S> for BoundedVec<u8, S> {22impl<T: Decode, S> RmrkDecode<T, S> for BoundedVec<u8, S> {
24 fn decode_or_default(&self) -> T {23 fn decode(&self) -> Result<T, Error> {
25 let mut value = self.as_slice();24 let mut value = self.as_slice();
2625
27 T::decode(&mut value).unwrap_or_default()26 T::decode(&mut value)
28 }27 }
29}28}
3029
30// Utilize the RmrkCore pallet for access to Runtime errors.
31pub trait RmrkRebind<T, S> {31pub trait RmrkRebind<T, S> {
32 fn rebind(&self) -> BoundedVec<u8, S>;32 fn rebind(&self) -> Result<BoundedVec<u8, S>, Error>;
33}33}
3434
35// todo fail if unwrap doesn't work
36impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T>35impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T>
37where36where
38 BoundedVec<u8, S>: TryFrom<Vec<u8>>,37 BoundedVec<u8, S>: TryFrom<Vec<u8>>,
39{38{
40 fn rebind(&self) -> BoundedVec<u8, S> {39 fn rebind(&self) -> Result<BoundedVec<u8, S>, Error> {
41 BoundedVec::<u8, S>::try_from(self.clone().into_inner()).unwrap_or_default()40 BoundedVec::<u8, S>::try_from(self.clone().into_inner()).map_err(|_| "BoundedVec exceeds its limit".into())
42 }41 }
43}42}
4443
49 Base,48 Base,
50}49}
5150
52// todo remove default?
53#[derive(Encode, Decode, PartialEq, Eq, Derivative)]51#[derive(Encode, Decode, PartialEq, Eq)]
54#[derivative(Default(bound = ""))]
55pub enum NftType {52pub enum NftType {
56 #[derivative(Default)]
57 Regular,53 Regular,
58 Resource,54 Resource,
59 FixedPart,55 FixedPart,
60 SlotPart,56 SlotPart,
61 Theme,57 Theme,
62}58}
6359
64// todo remove default?
65#[derive(Encode, Decode, PartialEq, Eq, Derivative)]60#[derive(Encode, Decode, PartialEq, Eq)]
66#[derivative(Default(bound = ""))]
67pub enum ResourceType {61pub enum ResourceType {
68 #[derivative(Default)]
69 Basic,62 Basic,
70 Composable,63 Composable,
71 Slot,64 Slot,
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
144 }144 }
145145
146 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {146 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
147 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode, RmrkRebind}};147 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType}};
148148
149 let collection_id = RmrkCore::unique_collection_id(collection_id)?;149 let collection_id = RmrkCore::unique_collection_id(collection_id)?;
150 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {150 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
157157
158 Ok(Some(RmrkCollectionInfo {158 Ok(Some(RmrkCollectionInfo {
159 issuer: collection.owner.clone(),159 issuer: collection.owner.clone(),
160 metadata: RmrkCore::get_collection_property(collection_id, RmrkProperty::Metadata)?.decode_or_default(),160 metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,
161 max: collection.limits.token_limit,161 max: collection.limits.token_limit,
162 symbol: collection.token_prefix.rebind(),162 symbol: RmrkCore::rebind(&collection.token_prefix)?,
163 nfts_count163 nfts_count
164 }))164 }))
165 }165 }
185185
186 Ok(Some(RmrkInstanceInfo {186 Ok(Some(RmrkInstanceInfo {
187 owner: owner,187 owner: owner,
188 royalty: RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?.decode_or_default(),188 royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,
189 metadata: RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::Metadata)?.decode_or_default(),189 metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,
190 equipped: RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::Equipped)?.decode_or_default(),190 equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,
191 pending: allowance.is_some(),191 pending: allowance.is_some(),
192 }))192 }))
193 }193 }
281 let nft_id = TokenId(nft_id);281 let nft_id = TokenId(nft_id);
282 if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }282 if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }
283283
284 let res_collection_id: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)?284 let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;
285 .decode_or_default();
286 let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;285 let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;
287286
288 let resources = resource_collection287 let resources = resource_collection
289 .collection_tokens()288 .collection_tokens()
290 .iter()289 .iter()
291 .filter_map(|(res_id)| Some(RmrkResourceInfo {290 .filter_map(|(res_id)| Some(RmrkResourceInfo {
292 id: res_id.0,291 id: res_id.0,
293 pending: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap().decode_or_default(),292 pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),
294 pending_removal: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap().decode_or_default(),293 pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),
295 resource: match RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap().decode_or_default() {294 resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {
296 ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {295 ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {
297 src: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Src).unwrap().decode_or_default(),296 src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
298 metadata: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap().decode_or_default(),297 metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
299 license: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::License).unwrap().decode_or_default(),298 license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
300 thumb: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap().decode_or_default(),299 thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
301 }),300 }),
302 ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {301 ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {
303 parts: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Parts).unwrap().decode_or_default(),302 parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),
304 base: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Base).unwrap().decode_or_default(),303 base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
305 src: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Src).unwrap().decode_or_default(),304 src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
306 metadata: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap().decode_or_default(),305 metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
307 license: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::License).unwrap().decode_or_default(),306 license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
308 thumb: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap().decode_or_default(),307 thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
309 }),308 }),
310 ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {309 ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {
311 base: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Base).unwrap().decode_or_default(),310 base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
312 src: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Src).unwrap().decode_or_default(),311 src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
313 metadata: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap().decode_or_default(),312 metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
314 slot: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Slot).unwrap().decode_or_default(),313 slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),
315 license: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::License).unwrap().decode_or_default(),314 license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
316 thumb: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap().decode_or_default(),315 thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
317 }),316 }),
318 // todo refactor :|
319 },317 },
320 }))318 }))
321 .collect();319 .collect();
332 let nft_id = TokenId(nft_id);330 let nft_id = TokenId(nft_id);
333 if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }331 if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }
334332
335 /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)333 /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)
336 .unwrap()334 .unwrap();
337 .decode_or_default();335 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }
338 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }336
339337 let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))
340 let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))338 .filter_map(|(resource_id, properties)| Some((
341 .filter_map(|(resource_id, properties)| Some((339 resource_id, // ResourceId property
342 resource_id, // ResourceId property340 RmrkCore::get_nft_property_decoded(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap(),
343 RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap().decode_or_default(),341 )))
344 )))342 .collect()
345 .collect()343 .sort_by_key(|(_, index)| *index)
346 .sort_by_key(|(_, index)| *index)344 .into_iter().map(|(resource_id, _)| resource_id)*/
347 .into_iter().map(|(resource_id, _)| resource_id)*/
348 let priorities = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourcePriorities)?.decode_or_default();345 let priorities = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;
349 // todo let it simply be default here after removing default from decode
350346
351 Ok(priorities)347 Ok(priorities)
352 }348 }
353349
354 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {350 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
355 use pallet_proxy_rmrk_core::{351 use pallet_proxy_rmrk_core::{
356 RmrkProperty, misc::{CollectionType, RmrkDecode, RmrkRebind},352 RmrkProperty, misc::{CollectionType},
357 };353 };
358354
359 let collection_id = RmrkCore::unique_collection_id(base_id)?;355 let collection_id = RmrkCore::unique_collection_id(base_id)?;
364360
365 Ok(Some(RmrkBaseInfo {361 Ok(Some(RmrkBaseInfo {
366 issuer: collection.owner.clone(),362 issuer: collection.owner.clone(),
367 base_type: RmrkCore::get_collection_property(collection_id, RmrkProperty::BaseType)?.decode_or_default(),363 base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,
368 symbol: collection.token_prefix.rebind(),364 symbol: RmrkCore::rebind(&collection.token_prefix)?,
369 }))365 }))
370 }366 }
371367
382378
383 match nft_type {379 match nft_type {
384 NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {380 NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {
385 id: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?.decode_or_default(),381 id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,
386 src: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::Src).ok()?.decode_or_default(),382 src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,
387 z: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ZIndex).ok()?.decode_or_default(),383 z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,
388 })),384 })),
389 NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {385 NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {
390 id: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?.decode_or_default(),386 id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,
391 src: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::Src).ok()?.decode_or_default(),387 src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,
392 z: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ZIndex).ok()?.decode_or_default(),388 z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,
393 equippable: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::EquippableList).ok()?.decode_or_default(),389 equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,
394 })),390 })),
395 _ => None391 _ => None
396 }392 }
415411
416 match nft_type {412 match nft_type {
417 Theme => Some(413 Theme => Some(
418 RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::ThemeName).unwrap().decode_or_default()414 RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()
419 ),415 ),
420 _ => None416 _ => None
421 }417 }
441 .find_map(|token_id| {437 .find_map(|token_id| {
442 RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;438 RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;
443439
444 let name: RmrkString = RmrkCore::get_nft_property(440 let name: RmrkString = RmrkCore::get_nft_property_decoded(
445 collection_id, token_id, RmrkProperty::ThemeName441 collection_id, token_id, RmrkProperty::ThemeName
446 ).ok()?.decode_or_default();442 ).ok()?;
447443
448 if name == theme_name {444 if name == theme_name {
449 Some((name, token_id))445 Some((name, token_id))
467 }463 }
468 )?;464 )?;
469465
470 let inherit = RmrkCore::get_nft_property(466 let inherit = RmrkCore::get_nft_property_decoded(
471 collection_id,467 collection_id,
472 theme_id,468 theme_id,
473 RmrkProperty::ThemeInherit469 RmrkProperty::ThemeInherit
474 )?.decode_or_default();470 )?;
475471
476 let theme = RmrkTheme {472 let theme = RmrkTheme {
477 name,473 name,