difftreelog
feat implement theme RMRK RPC
in: master
7 files changed
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -443,7 +443,7 @@
<TokenData<T>>::get((collection_id, token_id))
.unwrap()
.rmrk_nft_type()
- .ok_or(<Error<T>>::NoAvailableNftId.into())
+ .ok_or_else(|| <Error<T>>::NoAvailableNftId.into())
}
pub fn ensure_nft_type(collection_id: CollectionId, token_id: TokenId, nft_type: NftType) -> DispatchResult {
@@ -453,6 +453,65 @@
Ok(())
}
+ pub fn filter_theme_properties(
+ collection_id: CollectionId,
+ token_id: TokenId,
+ filter_keys: Option<Vec<RmrkPropertyKey>>
+ ) -> Result<Vec<RmrkThemeProperty>, DispatchError> {
+ filter_keys.map(|keys| {
+ let properties = keys.into_iter()
+ .filter_map(|key| {
+ let key: RmrkString = key.try_into().ok()?;
+
+ let value = Self::get_nft_property(
+ collection_id,
+ token_id,
+ RmrkProperty::ThemeProperty(&key)
+ ).ok()?.decode_or_default();
+
+ let property = RmrkThemeProperty {
+ key,
+ value
+ };
+
+ Some(property)
+ })
+ .collect();
+
+ Ok(properties)
+ }).unwrap_or_else(|| {
+ let properties = Self::iterate_theme_properties(collection_id, token_id)?
+ .collect();
+
+ Ok(properties)
+ })
+ }
+
+ pub fn iterate_theme_properties(
+ collection_id: CollectionId,
+ token_id: TokenId
+ ) -> Result<impl Iterator<Item=RmrkThemeProperty>, DispatchError> {
+ let key_prefix = rmrk_property!(Config=T, key: ThemeProperty(&RmrkString::default()))?;
+
+ let properties = <PalletNft<T>>::token_properties((collection_id, token_id))
+ .into_iter()
+ .filter_map(move |(key, value)| {
+ let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;
+
+ let key: RmrkString = key.to_vec().try_into().ok()?;
+ let value: RmrkString = value.decode_or_default();
+
+ let property = RmrkThemeProperty {
+ key,
+ value
+ };
+
+ Some(property)
+ });
+
+ Ok(properties)
+ }
+
pub fn get_typed_nft_collection(
collection_id: CollectionId,
collection_type: CollectionType
pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/property.rs
+++ b/pallets/proxy-rmrk-core/src/property.rs
@@ -1,7 +1,7 @@
use super::*;
use core::convert::AsRef;
-pub enum RmrkProperty {
+pub enum RmrkProperty<'r> {
Metadata,
CollectionType,
RoyaltyInfo,
@@ -23,11 +23,11 @@
EquippableList,
ZIndex,
ThemeName,
- ThemeProperty(RmrkString),
+ ThemeProperty(&'r RmrkString),
ThemeInherit,
}
-impl RmrkProperty {
+impl<'r> RmrkProperty<'r> {
pub fn to_key<T: Config>(self) -> Result<PropertyKey, Error<T>> {
fn get_bytes<T: AsRef<[u8]>>(container: &T) -> &[u8] {
container.as_ref()
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -775,6 +775,10 @@
self.0.iter()
}
+ pub fn into_iter(self) -> impl Iterator<Item = (PropertyKey, Value)> {
+ self.0.into_iter()
+ }
+
fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {
if key.is_empty() {
return Err(PropertiesError::EmptyPropertyKey);
@@ -848,6 +852,10 @@
pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &PropertyValue)> {
self.map.iter()
}
+
+ pub fn into_iter(self) -> impl Iterator<Item = (PropertyKey, PropertyValue)> {
+ self.map.into_iter()
+ }
}
impl TrySetProperty for Properties {
@@ -936,7 +944,8 @@
pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;
pub type RmrkPartType =
PartType<RmrkString, BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>>;
-pub type RmrkTheme = Theme<RmrkString, Vec<ThemeProperty<RmrkString>>>;
+pub type RmrkThemeProperty = ThemeProperty<RmrkString>;
+pub type RmrkTheme = Theme<RmrkString, Vec<RmrkThemeProperty>>;
pub type RmrkRpcString = Vec<u8>;
pub type RmrkThemeName = RmrkRpcString;
runtime/common/src/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -184,7 +184,7 @@
},
None => return Ok(None)
};
-
+
let allowance = pallet_nonfungible::Allowance::<Runtime>::get((collection_id, nft_id));
Ok(Some(RmrkInstanceInfo {
@@ -317,7 +317,7 @@
if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Resource).is_err() { return Ok(Vec::new()); }
Ok(Vec::new(/*[RmrkResourceInfo {
-
+
}]*/))
}
@@ -379,16 +379,18 @@
fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
use frame_support::BoundedVec;
- use pallet_proxy_rmrk_core::{RmrkProperty, misc::{RmrkNft, RmrkDecode}};
+ use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkNft, RmrkDecode}};
let collection_id = CollectionId(base_id);
- // todo make sure this is theme
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {
+ return Ok(Vec::new());
+ }
- let theme_names = (dispatch_unique_runtime!(collection_id.collection_tokens()) as Result<Vec<TokenId>, DispatchError>)?
+ let theme_names = (dispatch_unique_runtime!(collection_id.collection_tokens()))?
.iter()
.filter_map(|token_id| {
let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();
-
+
match nft_type {
Theme => Some(
RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::ThemeName).unwrap().decode_or_default()
@@ -396,47 +398,59 @@
_ => None
}
})
- .collect::<Vec<RmrkThemeName>>();
+ .collect();
Ok(theme_names)
}
fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
use frame_support::BoundedVec;
+ use pallet_proxy_rmrk_core::{
+ RmrkProperty,
+ misc::{CollectionType, NftType, RmrkNft, RmrkDecode}
+ };
let collection_id = CollectionId(base_id);
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {
+ return Ok(None);
+ }
- // todo one theme. filter collection tokens according to theme name, should result in one
- // (is it possible to search with iter_prefix for part of a struct that satisfies?..)
- // filter properties according to filter_keys and load them into resulting theme.properties
- let themes = (dispatch_unique_runtime!(collection_id.collection_tokens()) as Result<Vec<TokenId>, DispatchError>)?
- .iter()
- .filter_map(|token_id| {
- let properties = Nonfungible::token_properties((collection_id, token_id));
+ let theme_info = (dispatch_unique_runtime!(collection_id.collection_tokens()))?
+ .into_iter()
+ .find_map(|token_id| {
+ RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;
+
+ let name: RmrkString = RmrkCore::get_nft_property(
+ collection_id, token_id, RmrkProperty::ThemeName
+ ).ok()?.decode_or_default();
- // todo ping properties for "rmrk:nft-type"
- // if none, skip, None
- // ugh gonna go through ALL properties, searching for matches for "rmrk:theme-property-<key>"
- let nft_type = "theme";
- match nft_type {
- "theme" => Some(RmrkTheme {
- name: BoundedVec::try_from(
- <pallet_nonfungible::TokenData<Runtime>>::get((collection_id, token_id))
- .map(|t| t.const_data)
- .unwrap_or_default()
- .into_inner()
- ).unwrap(),
- // todo? (dispatch_unique_runtime!(collection_id.const_metadata(token_id)) as Result<Vec<u8>, DispatchError>)?,
- properties: Vec::new(), // pain in the ass
- inherit: false, // "rmrk:theme-inherit"
- }),
- _ => None
+ if name == theme_name {
+ Some((name, token_id))
+ } else {
+ None
}
- })
- .collect::<Vec<_>>();
+ });
+
+ let (name, theme_id) = match theme_info {
+ Some((name, theme_id)) => (name, theme_id),
+ None => return Ok(None)
+ };
- // todo
- Ok(Some(themes[0].clone()))
+ let properties = RmrkCore::filter_theme_properties(collection_id, theme_id, filter_keys)?;
+
+ let inherit = RmrkCore::get_nft_property(
+ collection_id,
+ theme_id,
+ RmrkProperty::ThemeInherit
+ )?.decode_or_default();
+
+ let theme = RmrkTheme {
+ name,
+ properties,
+ inherit,
+ };
+
+ Ok(Some(theme))
}
}
runtime/opal/src/lib.rsdiffbeforeafterboth--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -1149,7 +1149,7 @@
let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
let dispatch = collection.as_dyn();
- Ok(dispatch.$method($($name),*))
+ Ok::<_, DispatchError>(dispatch.$method($($name),*))
}};
}
runtime/quartz/src/lib.rsdiffbeforeafterboth--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -1122,7 +1122,7 @@
let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
let dispatch = collection.as_dyn();
- Ok(dispatch.$method($($name),*))
+ Ok::<_, DispatchError>(dispatch.$method($($name),*))
}};
}
runtime/unique/src/lib.rsdiffbeforeafterboth1127 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1127 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1128 let dispatch = collection.as_dyn();1128 let dispatch = collection.as_dyn();112911291130 Ok(dispatch.$method($($name),*))1130 Ok::<_, DispatchError>(dispatch.$method($($name),*))1131 }};1131 }};1132}1132}11331133