difftreelog
style(rmrk-proxy) cargo fmt
in: master
2 files changed
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use frame_support::{pallet_prelude::*, transactional, BoundedVec, dispatch::DispatchResult};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::{DispatchError, Permill, traits::StaticLookup};22use sp_std::vec::Vec;23use up_data_structs::*;24use pallet_common::{25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,26};27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};28use pallet_structure::Pallet as PalletStructure;29use pallet_evm::account::CrossAccountId;30use core::convert::AsRef;3132pub use pallet::*;3334pub mod misc;35pub mod property;3637use misc::*;38pub use property::*;3940use RmrkProperty::*;4142#[frame_support::pallet]43pub mod pallet {44 use super::*;45 use pallet_evm::account;4647 #[pallet::config]48 pub trait Config:49 frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config50 {51 type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;52 }5354 #[pallet::storage]55 #[pallet::getter(fn collection_index)]56 pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;5758 #[pallet::storage]59 #[pallet::getter(fn collection_index_map)]60 pub type CollectionIndexMap<T: Config> =61 StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;6263 #[pallet::pallet]64 #[pallet::generate_store(pub(super) trait Store)]65 pub struct Pallet<T>(_);6667 #[pallet::event]68 #[pallet::generate_deposit(pub(super) fn deposit_event)]69 pub enum Event<T: Config> {70 CollectionCreated {71 issuer: T::AccountId,72 collection_id: RmrkCollectionId,73 },74 CollectionDestroyed {75 issuer: T::AccountId,76 collection_id: RmrkCollectionId,77 },78 IssuerChanged {79 old_issuer: T::AccountId,80 new_issuer: T::AccountId,81 collection_id: RmrkCollectionId,82 },83 CollectionLocked {84 issuer: T::AccountId,85 collection_id: RmrkCollectionId,86 },87 NftMinted {88 owner: T::AccountId,89 collection_id: RmrkCollectionId,90 nft_id: RmrkNftId,91 },92 NFTBurned {93 owner: T::AccountId,94 nft_id: RmrkNftId,95 },96 PropertySet {97 collection_id: RmrkCollectionId,98 maybe_nft_id: Option<RmrkNftId>,99 key: RmrkKeyString,100 value: RmrkValueString,101 },102 ResourceAdded {103 nft_id: RmrkNftId,104 resource_id: RmrkResourceId,105 },106 }107108 #[pallet::error]109 pub enum Error<T> {110 /* Unique-specific events */111 CorruptedCollectionType,112 NftTypeEncodeError,113 RmrkPropertyKeyIsTooLong,114 RmrkPropertyValueIsTooLong,115116 /* RMRK compatible events */117 CollectionNotEmpty,118 NoAvailableCollectionId,119 NoAvailableNftId,120 CollectionUnknown,121 NoPermission,122 CollectionFullOrLocked,123 // todo add resource errors?124 }125126 #[pallet::call]127 impl<T: Config> Pallet<T> {128 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]129 #[transactional]130 pub fn create_collection(131 origin: OriginFor<T>,132 metadata: RmrkString,133 max: Option<u32>,134 symbol: RmrkCollectionSymbol,135 ) -> DispatchResult {136 let sender = ensure_signed(origin)?;137138 let limits = CollectionLimits {139 owner_can_transfer: Some(false),140 token_limit: max,141 ..Default::default()142 };143144 let data = CreateCollectionData {145 limits: Some(limits),146 token_prefix: symbol147 .into_inner()148 .try_into()149 .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,150 ..Default::default()151 };152153 <CollectionIndex<T>>::mutate(|n| *n += 1);154155 let unique_collection_id = Self::init_collection(156 T::CrossAccountId::from_sub(sender.clone()),157 data,158 [159 Self::rmrk_property(Metadata, &metadata)?,160 Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,161 ]162 .into_iter(),163 )?; //collection_id_res?;164 let rmrk_collection_id = <CollectionIndex<T>>::get();165166 <CollectionIndexMap<T>>::insert(rmrk_collection_id, unique_collection_id);167168 Self::deposit_event(Event::CollectionCreated {169 issuer: sender,170 collection_id: rmrk_collection_id,171 });172173 Ok(())174 }175176 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]177 #[transactional]178 pub fn destroy_collection(179 origin: OriginFor<T>,180 collection_id: RmrkCollectionId,181 ) -> DispatchResult {182 let sender = ensure_signed(origin)?;183 let cross_sender = T::CrossAccountId::from_sub(sender.clone());184185 let collection = Self::get_typed_nft_collection(186 Self::unique_collection_id(collection_id)?,187 misc::CollectionType::Regular,188 )?;189190 ensure!(191 collection.total_supply() == 0,192 <Error<T>>::CollectionNotEmpty193 );194195 <PalletNft<T>>::destroy_collection(collection, &cross_sender)196 .map_err(Self::map_common_err_to_proxy)?;197198 Self::deposit_event(Event::CollectionDestroyed {199 issuer: sender,200 collection_id,201 });202203 Ok(())204 }205206 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]207 #[transactional]208 pub fn change_collection_issuer(209 origin: OriginFor<T>,210 collection_id: RmrkCollectionId,211 new_issuer: <T::Lookup as StaticLookup>::Source,212 ) -> DispatchResult {213 let sender = ensure_signed(origin)?;214215 let new_issuer = T::Lookup::lookup(new_issuer)?;216217 Self::change_collection_owner(218 Self::unique_collection_id(collection_id)?,219 misc::CollectionType::Regular,220 sender.clone(),221 new_issuer.clone(),222 )?;223224 Self::deposit_event(Event::IssuerChanged {225 old_issuer: sender,226 new_issuer,227 collection_id,228 });229230 Ok(())231 }232233 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]234 #[transactional]235 pub fn lock_collection(236 origin: OriginFor<T>,237 collection_id: RmrkCollectionId,238 ) -> DispatchResult {239 let sender = ensure_signed(origin)?;240 let cross_sender = T::CrossAccountId::from_sub(sender.clone());241242 let collection = Self::get_typed_nft_collection(243 Self::unique_collection_id(collection_id)?,244 misc::CollectionType::Regular,245 )?;246247 Self::check_collection_owner(&collection, &cross_sender)?;248249 let token_count = collection.total_supply();250251 let mut collection = collection.into_inner();252 collection.limits.token_limit = Some(token_count);253 collection.save()?;254255 Self::deposit_event(Event::CollectionLocked {256 issuer: sender,257 collection_id,258 });259260 Ok(())261 }262263 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]264 #[transactional]265 pub fn mint_nft(266 origin: OriginFor<T>,267 owner: T::AccountId,268 collection_id: RmrkCollectionId,269 recipient: Option<T::AccountId>,270 royalty_amount: Option<Permill>,271 metadata: RmrkString,272 ) -> DispatchResult {273 let sender = ensure_signed(origin)?;274 let sender = T::CrossAccountId::from_sub(sender);275 let cross_owner = T::CrossAccountId::from_sub(owner.clone());276277 let royalty_info = royalty_amount.map(|amount| rmrk::RoyaltyInfo {278 recipient: recipient.unwrap_or_else(|| owner.clone()),279 amount,280 });281282 let collection = Self::get_typed_nft_collection(283 Self::unique_collection_id(collection_id)?,284 misc::CollectionType::Regular,285 )?;286287 let nft_id = Self::create_nft(288 &sender,289 &cross_owner,290 &collection,291 [292 Self::rmrk_property(TokenType, &NftType::Regular)?,293 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,294 Self::rmrk_property(Metadata, &metadata)?,295 Self::rmrk_property(Equipped, &false)?,296 Self::rmrk_property(297 ResourceCollection,298 &Self::init_collection(299 sender.clone(),300 CreateCollectionData {301 ..Default::default()302 },303 [Self::rmrk_property(304 CollectionType,305 &misc::CollectionType::Resource,306 )?]307 .into_iter(),308 )?,309 )?, // todo possibly add limits to the collection if rmrk warrants them310 Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?, // todo create resource priorities?311 ]312 .into_iter(),313 )314 .map_err(|err| match err {315 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),316 err => Self::map_common_err_to_proxy(err),317 })?;318319 Self::deposit_event(Event::NftMinted {320 owner,321 collection_id,322 nft_id: nft_id.0,323 });324325 Ok(())326 }327328 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]329 #[transactional]330 pub fn burn_nft(331 origin: OriginFor<T>,332 collection_id: RmrkCollectionId,333 nft_id: RmrkNftId,334 ) -> DispatchResult {335 let sender = ensure_signed(origin)?;336 let cross_sender = T::CrossAccountId::from_sub(sender.clone());337338 Self::destroy_nft(339 cross_sender,340 Self::unique_collection_id(collection_id)?,341 misc::CollectionType::Regular,342 nft_id.into(),343 )?;344345 Self::deposit_event(Event::NFTBurned {346 owner: sender,347 nft_id,348 });349350 Ok(())351 }352353 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]354 #[transactional]355 pub fn set_property(356 origin: OriginFor<T>,357 #[pallet::compact] rmrk_collection_id: RmrkCollectionId,358 maybe_nft_id: Option<RmrkNftId>,359 key: RmrkKeyString,360 value: RmrkValueString,361 ) -> DispatchResult {362 let sender = ensure_signed(origin)?;363 let sender = T::CrossAccountId::from_sub(sender);364365 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;366367 match maybe_nft_id {368 Some(nft_id) => {369 let token_id: TokenId = nft_id.into();370371 Self::ensure_nft_owner(collection_id, token_id, &sender)?;372 Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;373374 <PalletNft<T>>::set_scoped_token_property(375 collection_id,376 token_id,377 PropertyScope::Rmrk,378 Self::rmrk_property(UserProperty(key.as_slice()), &value)?,379 )?;380 }381 None => {382 let collection = Self::get_typed_nft_collection(383 collection_id,384 misc::CollectionType::Regular,385 )?;386387 Self::check_collection_owner(&collection, &sender)?;388389 <PalletCommon<T>>::set_scoped_collection_property(390 collection_id,391 PropertyScope::Rmrk,392 Self::rmrk_property(UserProperty(key.as_slice()), &value)?,393 )?;394 }395 }396397 Self::deposit_event(Event::PropertySet {398 collection_id: rmrk_collection_id,399 maybe_nft_id,400 key,401 value,402 });403404 Ok(())405 }406407 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]408 #[transactional]409 pub fn add_basic_resource(410 origin: OriginFor<T>,411 collection_id: RmrkCollectionId,412 nft_id: RmrkNftId,413 resource: RmrkBasicResource,414 ) -> DispatchResult {415 let sender = ensure_signed(origin.clone())?;416417 let resource_id = Self::resource_add(418 sender,419 Self::unique_collection_id(collection_id)?,420 nft_id.into(),421 [422 Self::rmrk_property(TokenType, &NftType::Resource)?,423 Self::rmrk_property(ResourceType, &misc::ResourceType::Basic)?,424 Self::rmrk_property(Src, &resource.src)?,425 Self::rmrk_property(Metadata, &resource.metadata)?,426 Self::rmrk_property(License, &resource.license)?,427 Self::rmrk_property(Thumb, &resource.thumb)?,428 ]429 .into_iter(),430 )?;431432 Self::deposit_event(Event::ResourceAdded {433 nft_id,434 resource_id,435 });436 Ok(())437 }438439 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]440 #[transactional]441 pub fn add_composable_resource(442 origin: OriginFor<T>,443 collection_id: RmrkCollectionId,444 nft_id: RmrkNftId,445 _resource_id: RmrkBoundedResource,446 resource: RmrkComposableResource,447 ) -> DispatchResult {448 let sender = ensure_signed(origin.clone())?;449450 let resource_id = Self::resource_add(451 sender,452 Self::unique_collection_id(collection_id)?,453 nft_id.into(),454 [455 Self::rmrk_property(TokenType, &NftType::Resource)?,456 Self::rmrk_property(ResourceType, &misc::ResourceType::Composable)?,457 Self::rmrk_property(Parts, &resource.parts)?,458 Self::rmrk_property(Base, &resource.base)?,459 Self::rmrk_property(Src, &resource.src)?,460 Self::rmrk_property(Metadata, &resource.metadata)?,461 Self::rmrk_property(License, &resource.license)?,462 Self::rmrk_property(Thumb, &resource.thumb)?,463 ]464 .into_iter(),465 )?;466467 Self::deposit_event(Event::ResourceAdded {468 nft_id,469 resource_id,470 });471 Ok(())472 }473474 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]475 #[transactional]476 pub fn add_slot_resource(477 origin: OriginFor<T>,478 collection_id: RmrkCollectionId,479 nft_id: RmrkNftId,480 resource: RmrkSlotResource,481 ) -> DispatchResult {482 let sender = ensure_signed(origin.clone())?;483484 let resource_id = Self::resource_add(485 sender,486 Self::unique_collection_id(collection_id)?,487 nft_id.into(),488 [489 Self::rmrk_property(TokenType, &NftType::Resource)?,490 Self::rmrk_property(ResourceType, &misc::ResourceType::Slot)?,491 Self::rmrk_property(Base, &resource.base)?,492 Self::rmrk_property(Src, &resource.src)?,493 Self::rmrk_property(Metadata, &resource.metadata)?,494 Self::rmrk_property(Slot, &resource.slot)?,495 Self::rmrk_property(License, &resource.license)?,496 Self::rmrk_property(Thumb, &resource.thumb)?,497 ]498 .into_iter(),499 )?;500501 Self::deposit_event(Event::ResourceAdded {502 nft_id,503 resource_id,504 });505 Ok(())506 }507 }508}509510impl<T: Config> Pallet<T> {511 pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {512 let key = rmrk_key.to_key::<T>()?;513514 let scoped_key = PropertyScope::Rmrk515 .apply(key)516 .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;517518 Ok(scoped_key)519 }520521 pub fn rmrk_property<E: Encode>( // todo think about renaming this522 rmrk_key: RmrkProperty,523 value: &E,524 ) -> Result<Property, DispatchError> {525 let key = rmrk_key.to_key::<T>()?;526527 let value = value528 .encode()529 .try_into()530 .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;531532 let property = Property { key, value };533534 Ok(property)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 }542543 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 }551552 fn init_collection(553 sender: T::CrossAccountId,554 data: CreateCollectionData<T::AccountId>,555 properties: impl Iterator<Item = Property>,556 ) -> Result<CollectionId, DispatchError> {557 let collection_id = <PalletNft<T>>::init_collection(sender, data);558559 if let Err(DispatchError::Arithmetic(_)) = &collection_id {560 return Err(<Error<T>>::NoAvailableCollectionId.into());561 }562563 <PalletCommon<T>>::set_scoped_collection_properties(564 collection_id?,565 PropertyScope::Rmrk,566 properties,567 )?;568569 collection_id570 }571572 pub fn create_nft(573 sender: &T::CrossAccountId,574 owner: &T::CrossAccountId,575 collection: &NonfungibleHandle<T>,576 properties: impl Iterator<Item = Property>,577 ) -> Result<TokenId, DispatchError> {578 let data = CreateNftExData {579 properties: BoundedVec::default(),580 owner: owner.clone(),581 };582583 let budget = budget::Value::new(2);584585 <PalletNft<T>>::create_item(collection, sender, data, &budget)?;586587 let nft_id = <PalletNft<T>>::current_token_id(collection.id);588589 <PalletNft<T>>::set_scoped_token_properties(590 collection.id,591 nft_id,592 PropertyScope::Rmrk,593 properties,594 )?;595596 Ok(nft_id)597 }598599 fn destroy_nft(600 sender: T::CrossAccountId,601 collection_id: CollectionId,602 collection_type: misc::CollectionType,603 token_id: TokenId,604 ) -> DispatchResult {605 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;606607 <PalletNft<T>>::burn(&collection, &sender, token_id)608 .map_err(Self::map_common_err_to_proxy)?;609610 Ok(())611 }612613 fn resource_add(614 sender: T::AccountId,615 collection_id: CollectionId,616 token_id: TokenId,617 resource_properties: impl Iterator<Item = Property>,618 ) -> Result<RmrkResourceId, DispatchError> {619 let collection =620 Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;621 ensure!(collection.owner == sender, Error::<T>::NoPermission);622623 // Check NFT lock status // todo depends on market, maybe later624 //ensure!(!Pallet::<T>::is_locked(collection_id, nft_id), pallet_uniques::Error::<T>::Locked);625626 let sender = T::CrossAccountId::from_sub(sender);627 let budget = budget::Value::new(10);628 let pending = <PalletStructure<T>>::check_indirectly_owned(629 sender.clone(),630 collection_id,631 token_id,632 None,633 &budget,634 )?;635636 let resource_collection_id: CollectionId =637 Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;638 let resource_collection =639 Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;640641 // todo probably add extra connections to bases, slots, etc., when RMRK starts to use them642643 let resource_id = Self::create_nft(644 &sender, // todo owner of the nft?645 &sender,646 &resource_collection,647 resource_properties.chain(648 [649 Self::rmrk_property(PendingResourceAccept, &pending)?,650 Self::rmrk_property(PendingResourceRemoval, &false)?,651 ]652 .into_iter(),653 ),654 )655 .map_err(|err| match err {656 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),657 err => Self::map_common_err_to_proxy(err),658 })?;659660 Ok(resource_id.0)661 }662663 fn change_collection_owner(664 collection_id: CollectionId,665 collection_type: misc::CollectionType,666 sender: T::AccountId,667 new_owner: T::AccountId,668 ) -> DispatchResult {669 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;670 Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;671672 let mut collection = collection.into_inner();673674 collection.owner = new_owner;675 collection.save()676 }677678 fn check_collection_owner(679 collection: &NonfungibleHandle<T>,680 account: &T::CrossAccountId,681 ) -> DispatchResult {682 collection683 .check_is_owner(account)684 .map_err(Self::map_common_err_to_proxy)685 }686687 pub fn last_collection_idx() -> RmrkCollectionId {688 <CollectionIndex<T>>::get()689 }690691 pub fn unique_collection_id(692 rmrk_collection_id: RmrkCollectionId,693 ) -> Result<CollectionId, DispatchError> {694 <CollectionIndexMap<T>>::try_get(rmrk_collection_id)695 .map_err(|_| <Error<T>>::CollectionUnknown.into())696 }697698 pub fn get_nft_collection(699 collection_id: CollectionId,700 ) -> Result<NonfungibleHandle<T>, DispatchError> {701 let collection = <CollectionHandle<T>>::try_get(collection_id)702 .map_err(|_| <Error<T>>::CollectionUnknown)?;703704 match collection.mode {705 CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),706 _ => Err(<Error<T>>::CollectionUnknown.into()),707 }708 }709710 pub fn collection_exists(collection_id: CollectionId) -> bool {711 <CollectionHandle<T>>::try_get(collection_id).is_ok()712 }713714 pub fn get_collection_property(715 collection_id: CollectionId,716 key: RmrkProperty,717 ) -> Result<PropertyValue, DispatchError> {718 let collection_property = <PalletCommon<T>>::collection_properties(collection_id)719 .get(&Self::rmrk_property_key(key)?)720 .ok_or(<Error<T>>::CollectionUnknown)?721 .clone();722723 Ok(collection_property)724 }725726 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 }734735 pub fn get_collection_type(736 collection_id: CollectionId,737 ) -> Result<misc::CollectionType, DispatchError> {738 Self::get_collection_property_decoded(collection_id, CollectionType)739 .map_err(|_| <Error<T>>::CorruptedCollectionType.into())740 }741742 pub fn ensure_collection_type(743 collection_id: CollectionId,744 collection_type: misc::CollectionType,745 ) -> DispatchResult {746 let actual_type = Self::get_collection_type(collection_id)?;747 ensure!(748 actual_type == collection_type,749 <CommonError<T>>::NoPermission750 );751752 Ok(())753 }754755 pub fn get_typed_nft_collection(756 collection_id: CollectionId,757 collection_type: misc::CollectionType,758 ) -> Result<NonfungibleHandle<T>, DispatchError> {759 Self::ensure_collection_type(collection_id, collection_type)?;760761 Self::get_nft_collection(collection_id)762 }763764 pub fn get_nft_property(765 collection_id: CollectionId,766 nft_id: TokenId,767 key: RmrkProperty,768 ) -> Result<PropertyValue, DispatchError> {769 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))770 .get(&Self::rmrk_property_key(key)?)771 .ok_or(<Error<T>>::NoAvailableNftId)? // todo replace with better error?772 .clone();773774 Ok(nft_property)775 }776777 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 }786787 pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {788 <TokenData<T>>::contains_key((collection_id, nft_id))789 }790791 pub fn get_nft_type(792 collection_id: CollectionId,793 token_id: TokenId,794 ) -> Result<NftType, DispatchError> {795 Self::get_nft_property_decoded(collection_id, token_id, TokenType)796 .map_err(|_| <Error<T>>::NftTypeEncodeError.into())797 }798799 pub fn ensure_nft_type(800 collection_id: CollectionId,801 token_id: TokenId,802 nft_type: NftType,803 ) -> DispatchResult {804 let actual_type = Self::get_nft_type(collection_id, token_id)?;805 ensure!(actual_type == nft_type, <Error<T>>::NoPermission);806807 Ok(())808 }809810 pub fn ensure_nft_owner(811 collection_id: CollectionId,812 token_id: TokenId,813 possible_owner: &T::CrossAccountId,814 ) -> DispatchResult {815 let token_data =816 <TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;817818 ensure!(819 token_data.owner == *possible_owner,820 <Error<T>>::NoPermission821 );822823 Ok(())824 }825826 pub fn filter_user_properties<Key, Value, R, Mapper>(827 collection_id: CollectionId,828 token_id: Option<TokenId>,829 filter_keys: Option<Vec<RmrkPropertyKey>>,830 mapper: Mapper,831 ) -> Result<Vec<R>, DispatchError>832 where833 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,834 Value: Decode + Default,835 Mapper: Fn(Key, Value) -> R,836 {837 filter_keys838 .map(|keys| {839 let properties = keys840 .into_iter()841 .filter_map(|key| {842 let key: Key = key.try_into().ok()?;843844 let value = match token_id {845 Some(token_id) => Self::get_nft_property_decoded(846 collection_id,847 token_id,848 UserProperty(key.as_ref()),849 ),850 None => Self::get_collection_property_decoded(851 collection_id,852 UserProperty(key.as_ref()),853 ),854 }855 .ok()?;856857 Some(mapper(key, value))858 })859 .collect();860861 Ok(properties)862 })863 .unwrap_or_else(|| {864 let properties =865 Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();866867 Ok(properties)868 })869 }870871 pub fn iterate_user_properties<Key, Value, R, Mapper>(872 collection_id: CollectionId,873 token_id: Option<TokenId>,874 mapper: Mapper,875 ) -> Result<impl Iterator<Item = R>, DispatchError>876 where877 Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,878 Value: Decode + Default,879 Mapper: Fn(Key, Value) -> R,880 {881 let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;882883 let properties = match token_id {884 Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),885 None => <PalletCommon<T>>::collection_properties(collection_id),886 };887888 let properties = properties.into_iter().filter_map(move |(key, value)| {889 let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;890891 let key: Key = key.to_vec().try_into().ok()?;892 let value: Value = value.decode().ok()?;893894 Some(mapper(key, value))895 });896897 Ok(properties)898 }899900 fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {901 map_common_err_to_proxy! {902 match err {903 NoPermission => NoPermission,904 CollectionTokenLimitExceeded => CollectionFullOrLocked,905 PublicMintingNotAllowed => NoPermission,906 TokenNotFound => NoAvailableNftId907 }908 }909 }910}pallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -37,7 +37,8 @@
BoundedVec<u8, S>: TryFrom<Vec<u8>>,
{
fn rebind(&self) -> Result<BoundedVec<u8, S>, Error> {
- BoundedVec::<u8, S>::try_from(self.clone().into_inner()).map_err(|_| "BoundedVec exceeds its limit".into())
+ BoundedVec::<u8, S>::try_from(self.clone().into_inner())
+ .map_err(|_| "BoundedVec exceeds its limit".into())
}
}