difftreelog
refactor iterate rmrk props, add rmrk proxy set_propertty
in: master
5 files changed
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth24use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations};24use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations};25use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};25use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};26use pallet_evm::account::CrossAccountId;26use pallet_evm::account::CrossAccountId;27use core::convert::AsRef;272828pub use pallet::*;29pub use pallet::*;293085 owner: T::AccountId,86 owner: T::AccountId,86 nft_id: RmrkNftId,87 nft_id: RmrkNftId,87 },88 },89 PropertySet {90 collection_id: RmrkCollectionId,91 maybe_nft_id: Option<RmrkNftId>,92 key: RmrkKeyString,93 value: RmrkValueString,94 },88 }95 }899690 #[pallet::error]97 #[pallet::error]291 collection_id: RmrkCollectionId,298 collection_id: RmrkCollectionId,292 nft_id: RmrkNftId,299 nft_id: RmrkNftId,293 ) -> DispatchResult {300 ) -> DispatchResult {294 let sender = ensure_signed(origin.clone())?;301 let sender = ensure_signed(origin)?;295 let cross_sender = T::CrossAccountId::from_sub(sender.clone());302 let cross_sender = T::CrossAccountId::from_sub(sender.clone());296303297 Self::destroy_nft(304 Self::destroy_nft(306 Ok(())313 Ok(())307 }314 }315316 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]317 #[transactional]318 pub fn set_property(319 origin: OriginFor<T>,320 #[pallet::compact] rmrk_collection_id: RmrkCollectionId,321 maybe_nft_id: Option<RmrkNftId>,322 key: RmrkKeyString,323 value: RmrkValueString,324 ) -> DispatchResult {325 let sender = ensure_signed(origin)?;326 let sender = T::CrossAccountId::from_sub(sender);327328 let collection_id: CollectionId = rmrk_collection_id.into();329330 match maybe_nft_id {331 Some(nft_id) => {332 let token_id: TokenId = nft_id.into();333334 Self::ensure_nft_owner(collection_id, token_id, &sender)?;335 Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;336337 <PalletNft<T>>::set_scoped_token_property(338 collection_id,339 token_id,340 PropertyScope::Rmrk,341 Self::rmrk_property(UserProperty(key.as_slice()), &value)?342 )?;343 },344 None => {345 let collection = Self::get_typed_nft_collection(346 collection_id,347 misc::CollectionType::Regular348 )?;349350 Self::check_collection_owner(&collection, &sender)?;351352 <PalletCommon<T>>::set_scoped_collection_property(353 collection_id,354 PropertyScope::Rmrk,355 Self::rmrk_property(UserProperty(key.as_slice()), &value)?356 )?;357 }358 }359360 Self::deposit_event(361 Event::PropertySet {362 collection_id: rmrk_collection_id,363 maybe_nft_id,364 key,365 value366 }367 );368369 Ok(())370 }308 }371 }309}372}310373477540478 pub fn ensure_nft_type(collection_id: CollectionId, token_id: TokenId, nft_type: NftType) -> DispatchResult {541 pub fn ensure_nft_type(collection_id: CollectionId, token_id: TokenId, nft_type: NftType) -> DispatchResult {479 let actual_type = Self::get_nft_type(collection_id, token_id)?;542 let actual_type = Self::get_nft_type(collection_id, token_id)?;480 ensure!(actual_type == nft_type, <CommonError<T>>::NoPermission);543 ensure!(actual_type == nft_type, <Error<T>>::NoPermission);481544482 Ok(())545 Ok(())483 }546 }547548 pub fn ensure_nft_owner(549 collection_id: CollectionId,550 token_id: TokenId,551 possible_owner: &T::CrossAccountId552 ) -> DispatchResult {553 let token_data = <TokenData<T>>::get((collection_id, token_id))554 .ok_or(<Error<T>>::NoAvailableNftId)?;555556 ensure!(token_data.owner == *possible_owner, <Error<T>>::NoPermission);557558 Ok(())559 }484560485 pub fn filter_theme_properties(561 pub fn filter_user_properties<Key, Value, R, Mapper>(486 collection_id: CollectionId,562 collection_id: CollectionId,487 token_id: TokenId,563 token_id: Option<TokenId>,488 filter_keys: Option<Vec<RmrkPropertyKey>>564 filter_keys: Option<Vec<RmrkPropertyKey>>,565 mapper: Mapper,489 ) -> Result<Vec<RmrkThemeProperty>, DispatchError> {566 ) -> Result<Vec<R>, DispatchError>567 where568 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,569 Value: Decode + Default,570 Mapper: Fn(Key, Value) -> R571 {490 filter_keys.map(|keys| {572 filter_keys.map(|keys| {491 let properties = keys.into_iter()573 let properties = keys.into_iter()492 .filter_map(|key| {574 .filter_map(|key| {493 let key: RmrkString = key.try_into().ok()?;575 let key: Key = key.try_into().ok()?;494576495 let value = Self::get_nft_property(577 let value = match token_id {578 Some(token_id) => Self::get_nft_property(496 collection_id,579 collection_id,497 token_id,580 token_id,498 ThemeProperty(&key)581 UserProperty(key.as_ref())499 ).ok()?.decode_or_default();582 ),500583 None => Self::get_collection_property(501 let property = RmrkThemeProperty {584 collection_id,585 UserProperty(key.as_ref())586 )587 }.ok()?.decode_or_default();588502 key,589 Some(mapper(key, value))503 value504 };505506 Some(property)507 })590 })508 .collect();591 .collect();509592510 Ok(properties)593 Ok(properties)511 }).unwrap_or_else(|| {594 }).unwrap_or_else(|| {512 let properties = Self::iterate_theme_properties(collection_id, token_id)?595 let properties = Self::iterate_user_properties(collection_id, token_id, mapper)?513 .collect();596 .collect();514597515 Ok(properties)598 Ok(properties)516 })599 })517 }600 }518601519 pub fn iterate_theme_properties(602 pub fn iterate_user_properties<Key, Value, R, Mapper>(520 collection_id: CollectionId,603 collection_id: CollectionId,521 token_id: TokenId604 token_id: Option<TokenId>,605 mapper: Mapper,522 ) -> Result<impl Iterator<Item=RmrkThemeProperty>, DispatchError> {606 ) -> Result<impl Iterator<Item=R>, DispatchError>607 where608 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,609 Value: Decode + Default,610 Mapper: Fn(Key, Value) -> R611 {523 let key_prefix = Self::rmrk_property_key(ThemeProperty(&RmrkString::default()))?;612 let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;613614 let properties = match token_id {615 Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),616 None => <PalletCommon<T>>::collection_properties(collection_id)617 };524618525 let properties = <PalletNft<T>>::token_properties((collection_id, token_id))619 let properties = properties526 .into_iter()620 .into_iter()527 .filter_map(move |(key, value)| {621 .filter_map(move |(key, value)| {528 let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;622 let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;529623530 let key: RmrkString = key.to_vec().try_into().ok()?;624 let key: Key = key.to_vec().try_into().ok()?;531 let value: RmrkString = value.decode_or_default();625 let value: Value = value.decode_or_default();532626533 let property = RmrkThemeProperty {534 key,627 Some(mapper(key, value))535 value536 };537538 Some(property)539 });628 });540629541 Ok(properties)630 Ok(properties)pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth23 EquippableList,23 EquippableList,24 ZIndex,24 ZIndex,25 ThemeName,25 ThemeName,26 ThemeInherit,26 ThemeProperty(&'r RmrkString),27 UserProperty(&'r [u8]),27 ThemeInherit,28}28}292930impl<'r> RmrkProperty<'r> {30impl<'r> RmrkProperty<'r> {66 Self::EquippableList => key!("equippable-list"),66 Self::EquippableList => key!("equippable-list"),67 Self::ZIndex => key!("z-index"),67 Self::ZIndex => key!("z-index"),68 Self::ThemeName => key!("theme-name"),68 Self::ThemeName => key!("theme-name"),69 Self::ThemeProperty(name) => key!("theme-property-", name),70 Self::ThemeInherit => key!("theme-inherit"),69 Self::ThemeInherit => key!("theme-inherit"),70 Self::UserProperty(name) => key!("userprop-", name),71 }71 }72 }72 }73}73}pallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth185 token_id,185 token_id,186 PropertyScope::Rmrk,186 PropertyScope::Rmrk,187 <PalletCore<T>>::rmrk_property(187 <PalletCore<T>>::rmrk_property(188 ThemeProperty(&property.key),188 UserProperty(property.key.as_slice()),189 &property.value189 &property.value190 )?190 )?191 )?;191 )?;primitives/data-structs/src/lib.rsdiffbeforeafterboth934 RmrkString,934 RmrkString,935 BoundedVec<RmrkPartId, RmrkPartsLimit>,935 BoundedVec<RmrkPartId, RmrkPartsLimit>,936>;936>;937pub type RmrkPropertyInfo =937pub type RmrkKeyString = BoundedVec<u8, RmrkKeyLimit>;938 PropertyInfo<BoundedVec<u8, RmrkKeyLimit>, BoundedVec<u8, RmrkValueLimit>>;938pub type RmrkValueString = BoundedVec<u8, RmrkValueLimit>;939pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;939pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;940pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;940pub type RmrkPartType =941pub type RmrkPartType =941 PartType<RmrkString, BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>>;942 PartType<RmrkString, BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>>;runtime/common/src/runtime_apis.rsdiffbeforeafterboth232 }232 }233233234 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {234 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {235 use pallet_proxy_rmrk_core::misc::RmrkDecode;235 use pallet_proxy_rmrk_core::misc::CollectionType;236236237 let collection_id = CollectionId(collection_id);237 let collection_id = CollectionId(collection_id);238 if !RmrkCore::collection_exists(collection_id) { return Ok(Vec::new()); }238 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {239 return Ok(Vec::new());240 }239241240 let properties = Common::collection_properties(collection_id);242 let properties = RmrkCore::filter_user_properties(241243 collection_id,242 // todo repeated code244 /* token_id = */ None,243 return Ok(match filter_keys {245 filter_keys,244 Some(keys) => {245 let keys = Common::bytes_keys_to_property_keys(keys)?;246 let properties = keys247 .into_iter()248 .filter_map(|key| {249 properties.get(&key).map(|value| RmrkPropertyInfo {250 key: key.decode_or_default(),251 value: value.decode_or_default(),252 })253 })254 .collect();255256 properties257 }258 None => {259 properties260 .into_iter()261 .filter_map(|(key, value)| Some(RmrkPropertyInfo {246 |key, value| RmrkPropertyInfo {262 key: key.decode_or_default(),247 key,263 value: value.decode_or_default(),248 value264 }))249 }250 )?;251265 .collect()252 Ok(properties)266 }267 });268 }253 }269254270 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {255 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {271 use frame_support::BoundedVec;272 use pallet_proxy_rmrk_core::misc::RmrkDecode;256 use pallet_proxy_rmrk_core::misc::NftType;273257274 let collection_id = CollectionId(collection_id);258 let collection_id = CollectionId(collection_id);275 let token_id = TokenId(nft_id);259 let token_id = TokenId(nft_id);260276 if !RmrkCore::nft_exists(collection_id, token_id) { return Ok(Vec::new()); }261 if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {262 return Ok(Vec::new());263 }277264278 let properties = Nonfungible::token_properties((collection_id, token_id));265 let properties = RmrkCore::filter_user_properties(279 // todo look into this usage of pallet_nonfungible266 collection_id,280281 // todo displace to a function? redundant code piece with collection props282 return Ok(match filter_keys {283 Some(keys) => {267 Some(token_id),284 let keys = Common::bytes_keys_to_property_keys(keys)?;285 let properties = keys286 .into_iter()287 .filter_map(|key| {288 properties.get(&key).map(|value| RmrkPropertyInfo {289 key: key.decode_or_default(),290 value: value.decode_or_default(),268 filter_keys,291 })292 })293 .collect();294295 properties296 }297 None => {298 properties299 .into_iter()300 .filter_map(|(key, value)| Some(RmrkPropertyInfo {269 |key, value| RmrkPropertyInfo {301 key: key.decode_or_default(),270 key,302 value: value.decode_or_default(),271 value303 }))272 }273 )?;274304 .collect()275 Ok(properties)305 }306 });307 }276 }308277309 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {278 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {436 None => return Ok(None)405 None => return Ok(None)437 };406 };438407439 let properties = RmrkCore::filter_theme_properties(collection_id, theme_id, filter_keys)?;408 let properties = RmrkCore::filter_user_properties(409 collection_id,410 Some(theme_id),411 filter_keys,412 |key, value| RmrkThemeProperty {413 key,414 value415 }416 )?;440417441 let inherit = RmrkCore::get_nft_property(418 let inherit = RmrkCore::get_nft_property(