difftreelog
feat add all rmrk properties
in: master
4 files changed
pallets/rmrk-proxy/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, traits::ConstU32, dispatch::DispatchResult};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::DispatchError;22use up_data_structs::*;23use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations};24use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};25use pallet_evm::account::CrossAccountId;2627pub use pallet::*;2829pub mod misc;3031use misc::*;3233#[frame_support::pallet]34pub mod pallet {35 use super::*;36 use pallet_evm::account;3738 #[pallet::config]39 pub trait Config: frame_system::Config40 + pallet_common::Config41 + pallet_nonfungible::Config42 + account::Config {43 type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;44 }4546 #[pallet::pallet]47 #[pallet::generate_store(pub(super) trait Store)]48 pub struct Pallet<T>(_);4950 #[pallet::event]51 #[pallet::generate_deposit(pub(super) fn deposit_event)]52 pub enum Event<T: Config> {53 CollectionCreated {54 issuer: T::AccountId,55 collection_id: CollectionId,56 },57 CollectionDestroyed {58 issuer: T::AccountId,59 collection_id: CollectionId,60 },61 CollectionLocked {62 issuer: T::AccountId,63 collection_id: CollectionId,64 },65 }6667 #[pallet::error]68 pub enum Error<T> {69 /* Unique-specific events */70 CorruptedCollectionType,71 NotRmrkCollection,7273 /* RMRK compatible events */74 CollectionNotEmpty,75 NoAvailableCollectionId,76 CollectionUnknown,77 }7879 #[pallet::call]80 impl<T: Config> Pallet<T> {81 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]82 #[transactional]83 pub fn create_collection(84 origin: OriginFor<T>,85 metadata: PropertyValue,86 max: Option<u32>,87 symbol: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,88 ) -> DispatchResult {89 let sender = ensure_signed(origin)?;9091 let limits = max.map(|max| CollectionLimits {92 token_limit: Some(max),93 ..Default::default()94 });9596 let data = CreateCollectionData {97 limits,98 token_prefix: symbol,99 ..Default::default()100 };101102 let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);103104 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {105 return Err(<Error<T>>::NoAvailableCollectionId.into());106 }107108 let collection_id = collection_id_res?;109110 let collection = Self::get_nft_collection(collection_id)?.into_inner();111112 <PalletCommon<T>>::set_scoped_collection_properties(113 &collection,114 PropertyScope::Rmrk,115 [116 rmrk_property!(Metadata, metadata),117 rmrk_property!(CollectionType, CollectionType::Regular),118 ].into_iter()119 )?;120121 Self::deposit_event(Event::CollectionCreated { issuer: sender, collection_id });122123 Ok(())124 }125126 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]127 #[transactional]128 pub fn destroy_collection(129 origin: OriginFor<T>,130 collection_id: CollectionId,131 ) -> DispatchResult {132 let sender = ensure_signed(origin)?;133 let cross_sender = T::CrossAccountId::from_sub(sender.clone());134135 let collection = Self::get_nft_collection(collection_id)?;136137 Self::check_collection_type(collection_id, CollectionType::Regular)?;138139 ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);140141 <PalletNft<T>>::destroy_collection(collection, &cross_sender)?;142143 Self::deposit_event(Event::CollectionDestroyed { issuer: sender, collection_id });144145 Ok(())146 }147148 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]149 #[transactional]150 pub fn change_collection_issuer(151 origin: OriginFor<T>,152 collection_id: CollectionId,153 new_issuer: T::AccountId,154 ) -> DispatchResult {155 let sender = ensure_signed(origin)?;156157 Self::change_collection_owner(158 collection_id,159 CollectionType::Regular,160 sender,161 new_issuer162 )?;163164 Ok(())165 }166167 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]168 #[transactional]169 pub fn lock_collection(170 origin: OriginFor<T>,171 collection_id: CollectionId,172 ) -> DispatchResult {173 let sender = ensure_signed(origin)?;174 let cross_sender = T::CrossAccountId::from_sub(sender.clone());175176 let collection = Self::get_nft_collection(collection_id)?;177 collection.check_is_owner(&cross_sender)?;178179 let token_count = collection.total_supply();180181 let mut collection = collection.into_inner();182 collection.limits.token_limit = Some(token_count);183 collection.save()?;184185 Self::deposit_event(Event::CollectionLocked { issuer: sender, collection_id });186187 Ok(())188 }189 }190}191192impl<T: Config> Pallet<T> {193 fn change_collection_owner(194 collection_id: CollectionId,195 collection_type: CollectionType,196 sender: T::AccountId,197 new_owner: T::AccountId,198 ) -> DispatchResult {199 let mut collection = Self::get_nft_collection(collection_id)?.into_inner();200 collection.check_is_owner(&T::CrossAccountId::from_sub(sender))?;201202 Self::check_collection_type(collection_id, collection_type)?;203204 collection.owner = new_owner;205 collection.save()206 }207208 fn get_nft_collection(collection_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {209 let collection = <CollectionHandle<T>>::try_get(collection_id)210 .map_err(|_| <Error<T>>::CollectionUnknown)?211 .into_nft_collection()?;212213 Ok(collection)214 }215216 fn get_collection_type(collection_id: CollectionId) -> Result<CollectionType, DispatchError> {217 let collection_type: CollectionType = <PalletCommon<T>>::collection_properties(collection_id)218 .get(&rmrk_property!(CollectionType))219 .ok_or(<Error<T>>::NotRmrkCollection)?220 .try_into()221 .map_err(<Error<T>>::from)?;222223 Ok(collection_type)224 }225226 fn check_collection_type(collection_id: CollectionId, collection_type: CollectionType) -> DispatchResult {227 let actual_type = Self::get_collection_type(collection_id)?;228 ensure!(actual_type == collection_type, <CommonError<T>>::NoPermission);229230 Ok(())231 }232}1// 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, traits::ConstU32, dispatch::DispatchResult};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::DispatchError;22use up_data_structs::*;23use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations};24use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};25use pallet_evm::account::CrossAccountId;2627pub use pallet::*;2829pub mod misc;30pub mod property;3132use misc::*;33pub use property::*;3435#[frame_support::pallet]36pub mod pallet {37 use super::*;38 use pallet_evm::account;3940 #[pallet::config]41 pub trait Config: frame_system::Config42 + pallet_common::Config43 + pallet_nonfungible::Config44 + account::Config {45 type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;46 }4748 #[pallet::pallet]49 #[pallet::generate_store(pub(super) trait Store)]50 pub struct Pallet<T>(_);5152 #[pallet::event]53 #[pallet::generate_deposit(pub(super) fn deposit_event)]54 pub enum Event<T: Config> {55 CollectionCreated {56 issuer: T::AccountId,57 collection_id: CollectionId,58 },59 CollectionDestroyed {60 issuer: T::AccountId,61 collection_id: CollectionId,62 },63 CollectionLocked {64 issuer: T::AccountId,65 collection_id: CollectionId,66 },67 }6869 #[pallet::error]70 pub enum Error<T> {71 /* Unique-specific events */72 CorruptedCollectionType,73 NotRmrkCollection,74 RmrkPropertyIsTooLong,7576 /* RMRK compatible events */77 CollectionNotEmpty,78 NoAvailableCollectionId,79 CollectionUnknown,80 }8182 #[pallet::call]83 impl<T: Config> Pallet<T> {84 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]85 #[transactional]86 pub fn create_collection(87 origin: OriginFor<T>,88 metadata: PropertyValue,89 max: Option<u32>,90 symbol: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,91 ) -> DispatchResult {92 let sender = ensure_signed(origin)?;9394 let limits = max.map(|max| CollectionLimits {95 token_limit: Some(max),96 ..Default::default()97 });9899 let data = CreateCollectionData {100 limits,101 token_prefix: symbol,102 ..Default::default()103 };104105 let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);106107 if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {108 return Err(<Error<T>>::NoAvailableCollectionId.into());109 }110111 let collection_id = collection_id_res?;112113 let collection = Self::get_nft_collection(collection_id)?.into_inner();114115 <PalletCommon<T>>::set_scoped_collection_properties(116 &collection,117 PropertyScope::Rmrk,118 [119 rmrk_property!(Config=T, Metadata: metadata)?,120 rmrk_property!(Config=T, CollectionType: CollectionType::Regular)?,121 ].into_iter()122 )?;123124 Self::deposit_event(Event::CollectionCreated { issuer: sender, collection_id });125126 Ok(())127 }128129 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]130 #[transactional]131 pub fn destroy_collection(132 origin: OriginFor<T>,133 collection_id: CollectionId,134 ) -> DispatchResult {135 let sender = ensure_signed(origin)?;136 let cross_sender = T::CrossAccountId::from_sub(sender.clone());137138 let collection = Self::get_nft_collection(collection_id)?;139140 Self::check_collection_type(collection_id, CollectionType::Regular)?;141142 ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);143144 <PalletNft<T>>::destroy_collection(collection, &cross_sender)?;145146 Self::deposit_event(Event::CollectionDestroyed { issuer: sender, collection_id });147148 Ok(())149 }150151 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]152 #[transactional]153 pub fn change_collection_issuer(154 origin: OriginFor<T>,155 collection_id: CollectionId,156 new_issuer: T::AccountId,157 ) -> DispatchResult {158 let sender = ensure_signed(origin)?;159160 Self::change_collection_owner(161 collection_id,162 CollectionType::Regular,163 sender,164 new_issuer165 )?;166167 Ok(())168 }169170 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]171 #[transactional]172 pub fn lock_collection(173 origin: OriginFor<T>,174 collection_id: CollectionId,175 ) -> DispatchResult {176 let sender = ensure_signed(origin)?;177 let cross_sender = T::CrossAccountId::from_sub(sender.clone());178179 let collection = Self::get_nft_collection(collection_id)?;180 collection.check_is_owner(&cross_sender)?;181182 let token_count = collection.total_supply();183184 let mut collection = collection.into_inner();185 collection.limits.token_limit = Some(token_count);186 collection.save()?;187188 Self::deposit_event(Event::CollectionLocked { issuer: sender, collection_id });189190 Ok(())191 }192 }193}194195impl<T: Config> Pallet<T> {196 fn change_collection_owner(197 collection_id: CollectionId,198 collection_type: CollectionType,199 sender: T::AccountId,200 new_owner: T::AccountId,201 ) -> DispatchResult {202 let mut collection = Self::get_nft_collection(collection_id)?.into_inner();203 collection.check_is_owner(&T::CrossAccountId::from_sub(sender))?;204205 Self::check_collection_type(collection_id, collection_type)?;206207 collection.owner = new_owner;208 collection.save()209 }210211 fn get_nft_collection(collection_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {212 let collection = <CollectionHandle<T>>::try_get(collection_id)213 .map_err(|_| <Error<T>>::CollectionUnknown)?214 .into_nft_collection()?;215216 Ok(collection)217 }218219 fn get_collection_type(collection_id: CollectionId) -> Result<CollectionType, DispatchError> {220 let collection_type: CollectionType = <PalletCommon<T>>::collection_properties(collection_id)221 .get(&rmrk_property!(Config=T, CollectionType)?)222 .ok_or(<Error<T>>::NotRmrkCollection)?223 .try_into()224 .map_err(<Error<T>>::from)?;225226 Ok(collection_type)227 }228229 fn check_collection_type(collection_id: CollectionId, collection_type: CollectionType) -> DispatchResult {230 let actual_type = Self::get_collection_type(collection_id)?;231 ensure!(actual_type == collection_type, <CommonError<T>>::NoPermission);232233 Ok(())234 }235}pallets/rmrk-proxy/src/misc.rsdiffbeforeafterboth--- a/pallets/rmrk-proxy/src/misc.rs
+++ b/pallets/rmrk-proxy/src/misc.rs
@@ -1,31 +1,12 @@
use super::*;
use codec::{Encode, Decode};
-use frame_support::dispatch::Vec;
use pallet_nonfungible::NonfungibleHandle;
-
-#[macro_export]
-macro_rules! rmrk_property {
- ($key:ident, $value:expr) => {
- Property {
- key: rmrk_property!(@raw $key),
- value: $value.into()
- }
- };
- (@raw $key:ident) => {
- RmrkProperty::$key.to_key()
- };
-
- ($key:ident) => {
- PropertyScope::Rmrk.apply(rmrk_property!(@raw $key)).unwrap()
- };
-}
-
macro_rules! impl_rmrk_value {
($enum_name:path, decode_error: $error:ident) => {
- impl Into<PropertyValue> for $enum_name {
- fn into(self) -> PropertyValue {
- self.encode().try_into().unwrap()
+ impl From<$enum_name> for PropertyValue {
+ fn from(e: $enum_name) -> Self {
+ e.encode().try_into().unwrap()
}
}
@@ -64,26 +45,6 @@
match self.mode {
CollectionMode::NFT => Ok(NonfungibleHandle::cast(self)),
_ => Err(<Error<T>>::NotRmrkCollection)
- }
- }
-}
-
-pub enum RmrkProperty {
- Metadata,
- CollectionType,
-}
-
-impl RmrkProperty {
- pub fn to_key(self) -> PropertyKey {
- let key = |str_key: &str| {
- PropertyKey::try_from(
- str_key.bytes().collect::<Vec<_>>()
- ).unwrap()
- };
-
- match self {
- Self::Metadata => key("metadata"),
- Self::CollectionType => key("collection-type"),
}
}
}
pallets/rmrk-proxy/src/property.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/rmrk-proxy/src/property.rs
@@ -0,0 +1,92 @@
+use super::*;
+use core::convert::AsRef;
+
+pub enum RmrkProperty {
+ Metadata,
+ CollectionType,
+ Recipient,
+ Royalty,
+ Equipped,
+ Pending,
+ ResourceCollection,
+ ResourcePriorities,
+ PendingRemoval,
+ Parts,
+ Base,
+ Src,
+ Slot,
+ License,
+ Thumb,
+ EquippedNft,
+ BaseType,
+ // // RmrkPartId(/* Id type? */)
+ EquippableList,
+ ZIndex,
+ ThemeName,
+ ThemeProperty(RmrkString),
+ ThemeInherit,
+}
+
+impl RmrkProperty {
+ pub fn to_key<T: Config>(self) -> Result<PropertyKey, Error<T>> {
+ fn get_bytes<T: AsRef<[u8]>>(container: &T) -> &[u8] {
+ container.as_ref()
+ }
+
+ macro_rules! key {
+ ($($component:expr),+) => {
+ PropertyKey::try_from([$(key!(@ &$component)),+].concat())
+ .map_err(|_| <Error<T>>::RmrkPropertyIsTooLong)
+ };
+
+ (@ $key:expr) => {
+ get_bytes($key)
+ };
+ }
+
+ match self {
+ Self::Metadata => key!("metadata"),
+ Self::CollectionType => key!("collection-type"),
+ Self::Recipient => key!("recipient"),
+ Self::Royalty => key!("royalty"),
+ Self::Equipped => key!("equipped"),
+ Self::Pending => key!("pending"),
+ Self::ResourceCollection => key!("resource-collection"),
+ Self::ResourcePriorities => key!("resource-priorities"),
+ Self::PendingRemoval => key!("pending-removal"),
+ Self::Parts => key!("parts"),
+ Self::Base => key!("base"),
+ Self::Src => key!("src"),
+ Self::Slot => key!("slot"),
+ Self::License => key!("license"),
+ Self::Thumb => key!("thumb"),
+ Self::EquippedNft => key!("equipped-nft"),
+ Self::BaseType => key!("base-type"),
+ // RmrkPartId(/* Id type? */)
+ Self::EquippableList => key!("equippable-list"),
+ Self::ZIndex => key!("z-index"),
+ Self::ThemeName => key!("theme-name"),
+ Self::ThemeProperty(name) => key!("theme-property-", name),
+ Self::ThemeInherit => key!("theme-inherit"),
+ }
+ }
+}
+
+#[macro_export]
+macro_rules! rmrk_property {
+ (Config=$cfg:ty, $key:ident: $value:expr) => {
+ rmrk_property!(@$cfg, $key).map(|key| Property {
+ key,
+ value: $value.into()
+ })
+ };
+
+ (@$cfg:ty, $key:ident) => {
+ $crate::RmrkProperty::$key.to_key::<$cfg>()
+ };
+
+ (Config=$cfg:ty, $key:ident) => {
+ PropertyScope::Rmrk.apply(rmrk_property!(@$cfg, $key)?)
+ .map_err(|_| <Error<T>>::RmrkPropertyIsTooLong)
+ };
+}
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -924,4 +924,4 @@
pub type RmrkThemeName = RmrkRpcString;
pub type RmrkPropertyKey = RmrkRpcString;
-type RmrkString = BoundedVec<u8, RmrkStringLimit>;
+pub type RmrkString = BoundedVec<u8, RmrkStringLimit>;