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
--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -1,6 +1,5 @@
 use super::*;
-use codec::{Encode, Decode};
-use derivative::Derivative;
+use codec::{Encode, Decode, Error};
 
 #[macro_export]
 macro_rules! map_common_err_to_proxy {
@@ -15,30 +14,30 @@
     };
 }
 
-pub trait RmrkDecode<T: Decode + Default, S> {
-	fn decode_or_default(&self) -> T;
+// Utilize the RmrkCore pallet for access to Runtime errors.
+pub trait RmrkDecode<T: Decode, S> {
+	fn decode(&self) -> Result<T, Error>;
 }
 
-// todo fail if unwrap doesn't work
-impl<T: Decode + Default, S> RmrkDecode<T, S> for BoundedVec<u8, S> {
-	fn decode_or_default(&self) -> T {
+impl<T: Decode, S> RmrkDecode<T, S> for BoundedVec<u8, S> {
+	fn decode(&self) -> Result<T, Error> {
 		let mut value = self.as_slice();
 
-		T::decode(&mut value).unwrap_or_default()
+		T::decode(&mut value)
 	}
 }
 
+// Utilize the RmrkCore pallet for access to Runtime errors.
 pub trait RmrkRebind<T, S> {
-	fn rebind(&self) -> BoundedVec<u8, S>;
+	fn rebind(&self) -> Result<BoundedVec<u8, S>, Error>;
 }
 
-// todo fail if unwrap doesn't work
 impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T>
 where
 	BoundedVec<u8, S>: TryFrom<Vec<u8>>,
 {
-	fn rebind(&self) -> BoundedVec<u8, S> {
-		BoundedVec::<u8, S>::try_from(self.clone().into_inner()).unwrap_or_default()
+	fn rebind(&self) -> Result<BoundedVec<u8, S>, Error> {
+		BoundedVec::<u8, S>::try_from(self.clone().into_inner()).map_err(|_| "BoundedVec exceeds its limit".into())
 	}
 }
 
@@ -49,11 +48,8 @@
 	Base,
 }
 
-// todo remove default?
-#[derive(Encode, Decode, PartialEq, Eq, Derivative)]
-#[derivative(Default(bound = ""))]
+#[derive(Encode, Decode, PartialEq, Eq)]
 pub enum NftType {
-	#[derivative(Default)]
 	Regular,
 	Resource,
 	FixedPart,
@@ -61,11 +57,8 @@
 	Theme,
 }
 
-// todo remove default?
-#[derive(Encode, Decode, PartialEq, Eq, Derivative)]
-#[derivative(Default(bound = ""))]
+#[derive(Encode, Decode, PartialEq, Eq)]
 pub enum ResourceType {
-	#[derivative(Default)]
 	Basic,
 	Composable,
 	Slot,
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -144,7 +144,7 @@
                 }
 
                 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
-                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode, RmrkRebind}};
+                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType}};
 
                     let collection_id = RmrkCore::unique_collection_id(collection_id)?;
                     let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
@@ -157,9 +157,9 @@
 
                     Ok(Some(RmrkCollectionInfo {
                         issuer: collection.owner.clone(),
-                        metadata: RmrkCore::get_collection_property(collection_id, RmrkProperty::Metadata)?.decode_or_default(),
+                        metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,
                         max: collection.limits.token_limit,
-                        symbol: collection.token_prefix.rebind(),
+                        symbol: RmrkCore::rebind(&collection.token_prefix)?,
                         nfts_count
                     }))
                 }
@@ -185,9 +185,9 @@
 
                     Ok(Some(RmrkInstanceInfo {
                         owner: owner,
-                        royalty: RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?.decode_or_default(),
-                        metadata: RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::Metadata)?.decode_or_default(),
-                        equipped: RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::Equipped)?.decode_or_default(),
+                        royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,
+                        metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,
+                        equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,
                         pending: allowance.is_some(),
                     }))
                 }
@@ -281,8 +281,7 @@
                     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: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)?
-                        .decode_or_default();
+                    let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;
                     let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;
 
                     let resources = resource_collection
@@ -290,32 +289,31 @@
                         .iter()
                         .filter_map(|(res_id)| Some(RmrkResourceInfo {
                             id: res_id.0,
-                            pending: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap().decode_or_default(),
-                            pending_removal: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap().decode_or_default(),
-                            resource: match RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap().decode_or_default() {
+                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),
+                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),
+                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {
                                 ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {
-                                    src: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Src).unwrap().decode_or_default(),
-                                    metadata: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap().decode_or_default(),
-                                    license: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::License).unwrap().decode_or_default(),
-                                    thumb: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap().decode_or_default(),
+                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
+                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
+                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
+                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
                                 }),
                                 ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {
-                                    parts: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Parts).unwrap().decode_or_default(),
-                                    base: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Base).unwrap().decode_or_default(),
-                                    src: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Src).unwrap().decode_or_default(),
-                                    metadata: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap().decode_or_default(),
-                                    license: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::License).unwrap().decode_or_default(),
-                                    thumb: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap().decode_or_default(),
+                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),
+                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
+                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
+                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
+                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
+                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
                                 }),
                                 ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {
-                                    base: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Base).unwrap().decode_or_default(),
-                                    src: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Src).unwrap().decode_or_default(),
-                                    metadata: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap().decode_or_default(),
-                                    slot: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Slot).unwrap().decode_or_default(),
-                                    license: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::License).unwrap().decode_or_default(),
-                                    thumb: RmrkCore::get_nft_property(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap().decode_or_default(),
+                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
+                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
+                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
+                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),
+                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
+                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
                                 }),
-                                // todo refactor :|
                             },
                         }))
                         .collect();
@@ -332,28 +330,26 @@
                     let nft_id = TokenId(nft_id);
                     if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }
 
-                    /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)
-                        .unwrap()
-                        .decode_or_default();
+                    /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)
+                        .unwrap();
                     if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }
 
                     let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))
                         .filter_map(|(resource_id, properties)| Some((
                             resource_id, // ResourceId property
-                            RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap().decode_or_default(),
+                            RmrkCore::get_nft_property_decoded(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap(),
                         )))
                         .collect()
                         .sort_by_key(|(_, index)| *index)
                         .into_iter().map(|(resource_id, _)| resource_id)*/
-                    let priorities = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourcePriorities)?.decode_or_default();
-                    // todo let it simply be default here after removing default from decode
+                    let priorities = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;
 
                     Ok(priorities)
                 }
 
                 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
                     use pallet_proxy_rmrk_core::{
-                        RmrkProperty, misc::{CollectionType, RmrkDecode, RmrkRebind},
+                        RmrkProperty, misc::{CollectionType},
                     };
 
                     let collection_id = RmrkCore::unique_collection_id(base_id)?;
@@ -364,8 +360,8 @@
 
                     Ok(Some(RmrkBaseInfo {
                         issuer: collection.owner.clone(),
-                        base_type: RmrkCore::get_collection_property(collection_id, RmrkProperty::BaseType)?.decode_or_default(),
-                        symbol: collection.token_prefix.rebind(),
+                        base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,
+                        symbol: RmrkCore::rebind(&collection.token_prefix)?,
                     }))
                 }
 
@@ -382,15 +378,15 @@
 
                             match nft_type {
                                 NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {
-                                    id: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?.decode_or_default(),
-                                    src: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::Src).ok()?.decode_or_default(),
-                                    z: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ZIndex).ok()?.decode_or_default(),
+                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,
+                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,
+                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,
                                 })),
                                 NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {
-                                    id: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?.decode_or_default(),
-                                    src: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::Src).ok()?.decode_or_default(),
-                                    z: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ZIndex).ok()?.decode_or_default(),
-                                    equippable: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::EquippableList).ok()?.decode_or_default(),
+                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,
+                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,
+                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,
+                                    equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,
                                 })),
                                 _ => None
                             }
@@ -415,7 +411,7 @@
 
                             match nft_type {
                                 Theme => Some(
-                                    RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::ThemeName).unwrap().decode_or_default()
+                                    RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()
                                 ),
                                 _ => None
                             }
@@ -441,9 +437,9 @@
                         .find_map(|token_id| {
                             RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;
 
-                            let name: RmrkString = RmrkCore::get_nft_property(
+                            let name: RmrkString = RmrkCore::get_nft_property_decoded(
                                 collection_id, token_id, RmrkProperty::ThemeName
-                            ).ok()?.decode_or_default();
+                            ).ok()?;
 
                             if name == theme_name {
                                 Some((name, token_id))
@@ -467,11 +463,11 @@
                         }
                     )?;
 
-                    let inherit = RmrkCore::get_nft_property(
+                    let inherit = RmrkCore::get_nft_property_decoded(
                         collection_id,
                         theme_id,
                         RmrkProperty::ThemeInherit
-                    )?.decode_or_default();
+                    )?;
 
                     let theme = RmrkTheme {
                         name,