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

difftreelog

refactor iterate rmrk props, add rmrk proxy set_propertty

Daniel Shiposha2022-05-25parent: #aab4f30.patch.diff
in: master

5 files changed

modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
24use 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;
2728
28pub use pallet::*;29pub use pallet::*;
2930
85 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 }
8996
90 #[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());
296303
297 Self::destroy_nft(304 Self::destroy_nft(
306 Ok(())313 Ok(())
307 }314 }
315
316 #[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);
327
328 let collection_id: CollectionId = rmrk_collection_id.into();
329
330 match maybe_nft_id {
331 Some(nft_id) => {
332 let token_id: TokenId = nft_id.into();
333
334 Self::ensure_nft_owner(collection_id, token_id, &sender)?;
335 Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
336
337 <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::Regular
348 )?;
349
350 Self::check_collection_owner(&collection, &sender)?;
351
352 <PalletCommon<T>>::set_scoped_collection_property(
353 collection_id,
354 PropertyScope::Rmrk,
355 Self::rmrk_property(UserProperty(key.as_slice()), &value)?
356 )?;
357 }
358 }
359
360 Self::deposit_event(
361 Event::PropertySet {
362 collection_id: rmrk_collection_id,
363 maybe_nft_id,
364 key,
365 value
366 }
367 );
368
369 Ok(())
370 }
308 }371 }
309}372}
310373
477540
478 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);
481544
482 Ok(())545 Ok(())
483 }546 }
547
548 pub fn ensure_nft_owner(
549 collection_id: CollectionId,
550 token_id: TokenId,
551 possible_owner: &T::CrossAccountId
552 ) -> DispatchResult {
553 let token_data = <TokenData<T>>::get((collection_id, token_id))
554 .ok_or(<Error<T>>::NoAvailableNftId)?;
555
556 ensure!(token_data.owner == *possible_owner, <Error<T>>::NoPermission);
557
558 Ok(())
559 }
484560
485 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 where
568 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
569 Value: Decode + Default,
570 Mapper: Fn(Key, Value) -> R
571 {
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()?;
494576
495 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();
588
502 key,589 Some(mapper(key, value))
503 value
504 };
505
506 Some(property)
507 })590 })
508 .collect();591 .collect();
509592
510 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();
514597
515 Ok(properties)598 Ok(properties)
516 })599 })
517 }600 }
518601
519 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 where
608 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
609 Value: Decode + Default,
610 Mapper: Fn(Key, Value) -> R
611 {
523 let key_prefix = Self::rmrk_property_key(ThemeProperty(&RmrkString::default()))?;612 let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;
613
614 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 };
524618
525 let properties = <PalletNft<T>>::token_properties((collection_id, token_id))619 let properties = properties
526 .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())?;
529623
530 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();
532626
533 let property = RmrkThemeProperty {
534 key,627 Some(mapper(key, value))
535 value
536 };
537
538 Some(property)
539 });628 });
540629
541 Ok(properties)630 Ok(properties)
modifiedpallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth
23 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}
2929
30impl<'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}
modifiedpallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth
185 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.value
190 )?190 )?
191 )?;191 )?;
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
934 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>>;
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
232 }232 }
233233
234 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;
236236
237 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 }
239241
240 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 = keys
247 .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();
255
256 properties
257 }
258 None => {
259 properties
260 .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 value
264 }))249 }
250 )?;
251
265 .collect()252 Ok(properties)
266 }
267 });
268 }253 }
269254
270 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;
273257
274 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);
260
276 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 }
277264
278 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,
280
281 // todo displace to a function? redundant code piece with collection props
282 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 = keys
286 .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();
294
295 properties
296 }
297 None => {
298 properties
299 .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 value
303 }))272 }
273 )?;
274
304 .collect()275 Ok(properties)
305 }
306 });
307 }276 }
308277
309 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 };
438407
439 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 value
415 }
416 )?;
440417
441 let inherit = RmrkCore::get_nft_property(418 let inherit = RmrkCore::get_nft_property(