difftreelog
refactor rmrk proxy, add add_theme rmrk proxy
in: master
8 files changed
client/rpc/src/lib.rsdiffbeforeafterboth30// RMRK30// RMRK31use rmrk_rpc::RmrkApi as RmrkRuntimeApi;31use rmrk_rpc::RmrkApi as RmrkRuntimeApi;32use up_data_structs::{32use up_data_structs::{33 RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkPropertyKey,33 RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName,34 RmrkResourceId,34 RmrkResourceId,35};35};3636248 fn collection_properties(248 fn collection_properties(249 &self,249 &self,250 collection_id: RmrkCollectionId,250 collection_id: RmrkCollectionId,251 filter_keys: Option<Vec<RmrkPropertyKey>>, //String251 filter_keys: Option<Vec<String>>,252 at: Option<BlockHash>,252 at: Option<BlockHash>,253 ) -> Result<Vec<PropertyInfo>>;253 ) -> Result<Vec<PropertyInfo>>;254254258 &self,258 &self,259 collection_id: RmrkCollectionId,259 collection_id: RmrkCollectionId,260 nft_id: RmrkNftId,260 nft_id: RmrkNftId,261 filter_keys: Option<Vec<RmrkPropertyKey>>,261 filter_keys: Option<Vec<String>>,262 at: Option<BlockHash>,262 at: Option<BlockHash>,263 ) -> Result<Vec<PropertyInfo>>;263 ) -> Result<Vec<PropertyInfo>>;264264299 fn theme(299 fn theme(300 &self,300 &self,301 base_id: RmrkBaseId,301 base_id: RmrkBaseId,302 theme_name: RmrkThemeName, // String302 theme_name: String,303 filter_keys: Option<Vec<RmrkPropertyKey>>,303 filter_keys: Option<Vec<String>>,304 at: Option<BlockHash>,304 at: Option<BlockHash>,305 ) -> Result<Option<Theme>>;305 ) -> Result<Option<Theme>>;306 }306 }523 pass_method!(account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Vec<RmrkNftId>, rmrk_api);523 pass_method!(account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Vec<RmrkNftId>, rmrk_api);524 pass_method!(nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<RmrkNftChild>, rmrk_api);524 pass_method!(nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<RmrkNftChild>, rmrk_api);525 pass_method!(525 pass_method!(526 collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Vec<PropertyInfo>,526 collection_properties(527 collection_id: RmrkCollectionId,528529 #[map(|keys| string_keys_to_bytes_keys(keys))]530 filter_keys: Option<Vec<String>>531 ) -> Vec<PropertyInfo>,527 rmrk_api532 rmrk_api528 );533 );529 pass_method!(534 pass_method!(530 nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Vec<PropertyInfo>,535 nft_properties(536 collection_id: RmrkCollectionId,537 nft_id: RmrkNftId,538539 #[map(|keys| string_keys_to_bytes_keys(keys))]540 filter_keys: Option<Vec<String>>541 ) -> Vec<PropertyInfo>,531 rmrk_api542 rmrk_api532 );543 );535 pass_method!(base(base_id: RmrkBaseId) -> Option<BaseInfo>, rmrk_api);546 pass_method!(base(base_id: RmrkBaseId) -> Option<BaseInfo>, rmrk_api);536 pass_method!(base_parts(base_id: RmrkBaseId) -> Vec<PartType>, rmrk_api);547 pass_method!(base_parts(base_id: RmrkBaseId) -> Vec<PartType>, rmrk_api);537 pass_method!(theme_names(base_id: RmrkBaseId) -> Vec<RmrkThemeName>, rmrk_api);548 pass_method!(theme_names(base_id: RmrkBaseId) -> Vec<RmrkThemeName>, rmrk_api);538 pass_method!(theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Option<Theme>, rmrk_api);549 pass_method!(550 theme(551 base_id: RmrkBaseId,552553 #[map(|n| n.into_bytes())]554 theme_name: String,555556 #[map(|keys| string_keys_to_bytes_keys(keys))]557 filter_keys: Option<Vec<String>>558 ) -> Option<Theme>, rmrk_api);539}559}540560pallets/common/src/lib.rsdiffbeforeafterboth795 }795 }796796797 pub fn set_scoped_collection_property(797 pub fn set_scoped_collection_property(798 collection: &CollectionHandle<T>,798 collection_id: CollectionId,799 scope: PropertyScope,799 scope: PropertyScope,800 property: Property,800 property: Property,801 ) -> DispatchResult {801 ) -> DispatchResult {802 CollectionProperties::<T>::try_mutate(collection.id, |properties| {802 CollectionProperties::<T>::try_mutate(collection_id, |properties| {803 properties.try_scoped_set(scope, property.key, property.value)803 properties.try_scoped_set(scope, property.key, property.value)804 })804 })805 .map_err(<Error<T>>::from)?;805 .map_err(<Error<T>>::from)?;806806807 Ok(())807 Ok(())808 }808 }809809810 #[transactional]811 pub fn set_scoped_collection_properties(810 pub fn set_scoped_collection_properties(812 collection: &CollectionHandle<T>,811 collection_id: CollectionId,813 scope: PropertyScope,812 scope: PropertyScope,814 properties: impl Iterator<Item = Property>,813 properties: impl Iterator<Item = Property>,815 ) -> DispatchResult {814 ) -> DispatchResult {816 CollectionProperties::<T>::try_mutate(collection.id, |stored_properties| {815 CollectionProperties::<T>::try_mutate(collection_id, |stored_properties| {817 stored_properties.try_scoped_set_from_iter(scope, properties)816 stored_properties.try_scoped_set_from_iter(scope, properties)818 })817 })819 .map_err(<Error<T>>::from)?;818 .map_err(<Error<T>>::from)?;pallets/nonfungible/src/lib.rsdiffbeforeafterboth195 }195 }196196197 pub fn set_scoped_token_property(197 pub fn set_scoped_token_property(198 collection: &CollectionHandle<T>,198 collection_id: CollectionId,199 token_id: TokenId,199 token_id: TokenId,200 scope: PropertyScope,200 scope: PropertyScope,201 property: Property,201 property: Property,202 ) -> DispatchResult {202 ) -> DispatchResult {203 TokenProperties::<T>::try_mutate((collection.id, token_id), |properties| {203 TokenProperties::<T>::try_mutate((collection_id, token_id), |properties| {204 properties.try_scoped_set(scope, property.key, property.value)204 properties.try_scoped_set(scope, property.key, property.value)205 })205 })206 .map_err(<CommonError<T>>::from)?;206 .map_err(<CommonError<T>>::from)?;209 }209 }210210211 pub fn set_scoped_token_properties(211 pub fn set_scoped_token_properties(212 collection: &CollectionHandle<T>,212 collection_id: CollectionId,213 token_id: TokenId,213 token_id: TokenId,214 scope: PropertyScope,214 scope: PropertyScope,215 properties: impl Iterator<Item=Property>,215 properties: impl Iterator<Item=Property>,216 ) -> DispatchResult {216 ) -> DispatchResult {217 TokenProperties::<T>::try_mutate((collection.id, token_id), |stored_properties| {217 TokenProperties::<T>::try_mutate((collection_id, token_id), |stored_properties| {218 stored_properties.try_scoped_set_from_iter(scope, properties)218 stored_properties.try_scoped_set_from_iter(scope, properties)219 })219 })220 .map_err(<CommonError<T>>::from)?;220 .map_err(<CommonError<T>>::from)?;221221222 Ok(())222 Ok(())223 }223 }224224225 pub fn current_token_id(collection: &CollectionHandle<T>) -> TokenId {225 pub fn current_token_id(collection_id: CollectionId) -> TokenId {226 TokenId(<TokensMinted<T>>::get(collection.id))226 TokenId(<TokensMinted<T>>::get(collection_id))227 }227 }228}228}229229pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth33use misc::*;33use misc::*;34pub use property::*;34pub use property::*;3536use RmrkProperty::*;353736#[frame_support::pallet]38#[frame_support::pallet]37pub mod pallet {39pub mod pallet {136138137 let collection_id = collection_id_res?;139 let collection_id = collection_id_res?;138139 let collection = Self::get_nft_collection(collection_id)?.into_inner();140140141 <PalletCommon<T>>::set_scoped_collection_properties(141 <PalletCommon<T>>::set_scoped_collection_properties(142 &collection,142 collection_id,143 PropertyScope::Rmrk,143 PropertyScope::Rmrk,144 [144 [145 rmrk_property!(Config=T, Metadata: metadata)?,145 Self::rmrk_property(Metadata, &metadata)?,146 rmrk_property!(Config=T, CollectionType: CollectionType::Regular)?,146 Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,147 ].into_iter()147 ].into_iter()148 )?;148 )?;149149168168169 let unique_collection_id = collection_id.into();169 let unique_collection_id = collection_id.into();170170171 let collection = Self::get_typed_nft_collection(unique_collection_id, CollectionType::Regular)?;171 let collection = Self::get_typed_nft_collection(unique_collection_id, misc::CollectionType::Regular)?;172172173 ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);173 ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);174174193193194 Self::change_collection_owner(194 Self::change_collection_owner(195 collection_id.into(),195 collection_id.into(),196 CollectionType::Regular,196 misc::CollectionType::Regular,197 sender.clone(),197 sender.clone(),198 new_issuer.clone()198 new_issuer.clone()199 )?;199 )?;218218219 let collection = Self::get_typed_nft_collection(219 let collection = Self::get_typed_nft_collection(220 collection_id.into(),220 collection_id.into(),221 CollectionType::Regular221 misc::CollectionType::Regular222 )?;222 )?;223223224 Self::check_collection_owner(&collection, &cross_sender)?;224 Self::check_collection_owner(&collection, &cross_sender)?;253 amount253 amount254 });254 });255256 let collection = Self::get_typed_nft_collection(257 collection_id.into(),258 misc::CollectionType::Regular,259 )?;255260256 let nft_id = Self::create_nft(261 let nft_id = Self::create_nft(257 &sender,262 &sender,258 &cross_owner,263 &cross_owner,259 collection_id.into(),260 CollectionType::Regular,264 &collection,261 NftType::Regular,265 NftType::Regular,262 [266 [263 rmrk_property!(Config=T, RoyaltyInfo: royalty_info)?,267 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,264 rmrk_property!(Config=T, Metadata: metadata)?,268 Self::rmrk_property(Metadata, &metadata)?,265 rmrk_property!(Config=T, Equipped: false)?,269 Self::rmrk_property(Equipped, &false)?,266 rmrk_property!(Config=T, ResourceCollection: None::<CollectionId>)?,270 Self::rmrk_property(ResourceCollection, &None::<CollectionId>)?,267 rmrk_property!(Config=T, ResourcePriorities: <Vec<u8>>::new())?,271 Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,268 ].into_iter()272 ].into_iter()269 )?;273 ).map_err(|err| match err {274 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),275 err => Self::map_common_err_to_proxy(err)276 })?;270277271 Self::deposit_event(Event::NftMinted {278 Self::deposit_event(Event::NftMinted {272 owner,279 owner,290 Self::destroy_nft(297 Self::destroy_nft(291 cross_sender,298 cross_sender,292 collection_id.into(),299 collection_id.into(),293 CollectionType::Regular,300 misc::CollectionType::Regular,294 nft_id.into()301 nft_id.into()295 )?;302 )?;296303302}309}303310304impl<T: Config> Pallet<T> {311impl<T: Config> Pallet<T> {312 pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {313 let key = rmrk_key.to_key::<T>()?;314315 let scoped_key = PropertyScope::Rmrk.apply(key)316 .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;317318 Ok(scoped_key)319 }320321 pub fn rmrk_property<E: Encode>(rmrk_key: RmrkProperty, value: &E) -> Result<Property, DispatchError> {322 let key = rmrk_key.to_key::<T>()?;323324 let value = value.encode()325 .try_into()326 .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;327328 let property = Property {329 key,330 value,331 };332333 Ok(property)334 }335305 pub fn create_nft(336 pub fn create_nft(306 sender: &T::CrossAccountId,337 sender: &T::CrossAccountId,307 owner: &T::CrossAccountId,338 owner: &T::CrossAccountId,308 collection_id: CollectionId,339 collection: &NonfungibleHandle<T>,309 collection_type: CollectionType,310 nft_type: NftType,340 nft_type: NftType,311 properties: impl Iterator<Item=Property>341 properties: impl Iterator<Item=Property>312 ) -> Result<TokenId, DispatchError> {342 ) -> Result<TokenId, DispatchError> {313 let collection = Self::get_typed_nft_collection(314 collection_id,315 collection_type316 )?;317318 let data = CreateNftExData {343 let data = CreateNftExData {319 const_data: nft_type.encode()344 const_data: nft_type.encode()326 let budget = budget::Value::new(2);351 let budget = budget::Value::new(2);327352328 <PalletNft<T>>::create_item(353 <PalletNft<T>>::create_item(329 &collection,354 collection,330 sender,355 sender,331 data,356 data,332 &budget,357 &budget,333 ).map_err(Self::map_common_err_to_proxy)?;358 )?;334359335 let nft_id = <PalletNft<T>>::current_token_id(&collection);360 let nft_id = <PalletNft<T>>::current_token_id(collection.id);336361337 <PalletNft<T>>::set_scoped_token_properties(362 <PalletNft<T>>::set_scoped_token_properties(338 &collection,363 collection.id,339 nft_id,364 nft_id,340 PropertyScope::Rmrk,365 PropertyScope::Rmrk,341 properties366 properties347 fn destroy_nft(372 fn destroy_nft(348 sender: T::CrossAccountId,373 sender: T::CrossAccountId,349 collection_id: CollectionId,374 collection_id: CollectionId,350 collection_type: CollectionType,375 collection_type: misc::CollectionType,351 token_id: TokenId376 token_id: TokenId352 ) -> DispatchResult {377 ) -> DispatchResult {353 let collection = Self::get_typed_nft_collection(378 let collection = Self::get_typed_nft_collection(363388364 fn change_collection_owner(389 fn change_collection_owner(365 collection_id: CollectionId,390 collection_id: CollectionId,366 collection_type: CollectionType,391 collection_type: misc::CollectionType,367 sender: T::AccountId,392 sender: T::AccountId,368 new_owner: T::AccountId,393 new_owner: T::AccountId,369 ) -> DispatchResult {394 ) -> DispatchResult {391 pub fn get_nft_collection(collection_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {416 pub fn get_nft_collection(collection_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {392 let collection = <CollectionHandle<T>>::try_get(collection_id)417 let collection = <CollectionHandle<T>>::try_get(collection_id)393 .map_err(|_| <Error<T>>::CollectionUnknown)?418 .map_err(|_| <Error<T>>::CollectionUnknown)?;394 .into_nft_collection()?;419395420 match collection.mode {396 Ok(collection)421 CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),422 _ => Err(<Error<T>>::CollectionUnknown.into())423 }397 }424 }398425399 // should this even be here, might displace it to common/nonfungible -- but they did not need it, only rmrk does426 // should this even be here, might displace it to common/nonfungible -- but they did not need it, only rmrk does407434408 pub fn get_collection_property(collection_id: CollectionId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {435 pub fn get_collection_property(collection_id: CollectionId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {409 let collection_property = <PalletCommon<T>>::collection_properties(collection_id)436 let collection_property = <PalletCommon<T>>::collection_properties(collection_id)410 .get(&rmrk_property!(Config=T, key)?)437 .get(&Self::rmrk_property_key(key)?)411 .ok_or(<Error<T>>::CollectionUnknown)?438 .ok_or(<Error<T>>::CollectionUnknown)?412 .clone();439 .clone();413440414 Ok(collection_property)441 Ok(collection_property)415 }442 }416443417 pub fn get_collection_type(collection_id: CollectionId) -> Result<CollectionType, DispatchError> {444 pub fn get_collection_type(collection_id: CollectionId) -> Result<misc::CollectionType, DispatchError> {418 let value = Self::get_collection_property(collection_id, RmrkProperty::CollectionType)?;445 let value = Self::get_collection_property(collection_id, CollectionType)?;446419 let collection_type: CollectionType = (&value)447 let mut value = value.as_slice();420 .try_into()448449 misc::CollectionType::decode(&mut value)421 .map_err(<Error<T>>::from)?;450 .map_err(|_| <Error<T>>::CorruptedCollectionType.into())422423 Ok(collection_type)424 }451 }425452426 pub fn ensure_collection_type(collection_id: CollectionId, collection_type: CollectionType) -> DispatchResult {453 pub fn ensure_collection_type(collection_id: CollectionId, collection_type: misc::CollectionType) -> DispatchResult {427 let actual_type = Self::get_collection_type(collection_id)?;454 let actual_type = Self::get_collection_type(collection_id)?;428 ensure!(actual_type == collection_type, <CommonError<T>>::NoPermission);455 ensure!(actual_type == collection_type, <CommonError<T>>::NoPermission);429456432459433 pub fn get_nft_property(collection_id: CollectionId, nft_id: TokenId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {460 pub fn get_nft_property(collection_id: CollectionId, nft_id: TokenId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {434 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))461 let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))435 .get(&rmrk_property!(Config=T, key)?)462 .get(&Self::rmrk_property_key(key)?)436 .ok_or(<Error<T>>::NoAvailableNftId)?463 .ok_or(<Error<T>>::NoAvailableNftId)?437 .clone();464 .clone();438465439 Ok(nft_property)466 Ok(nft_property)440 }467 }441468442 pub fn get_nft_type(collection_id: CollectionId, token_id: TokenId) -> Result<NftType, DispatchError> {469 pub fn get_nft_type(collection_id: CollectionId, token_id: TokenId) -> Result<NftType, DispatchError> {470 let token_data = <TokenData<T>>::get((collection_id, token_id))471 .ok_or(<Error<T>>::NoAvailableNftId)?;472473 let mut const_data = token_data.const_data.as_slice();474443 <TokenData<T>>::get((collection_id, token_id))475 NftType::decode(&mut const_data).map_err(|_| <Error<T>>::NoAvailableNftId.into())444 .unwrap()445 .rmrk_nft_type()446 .ok_or_else(|| <Error<T>>::NoAvailableNftId.into())447 }476 }448477449 pub fn ensure_nft_type(collection_id: CollectionId, token_id: TokenId, nft_type: NftType) -> DispatchResult {478 pub fn ensure_nft_type(collection_id: CollectionId, token_id: TokenId, nft_type: NftType) -> DispatchResult {466 let value = Self::get_nft_property(495 let value = Self::get_nft_property(467 collection_id,496 collection_id,468 token_id,497 token_id,469 RmrkProperty::ThemeProperty(&key)498 ThemeProperty(&key)470 ).ok()?.decode_or_default();499 ).ok()?.decode_or_default();471500472 let property = RmrkThemeProperty {501 let property = RmrkThemeProperty {491 collection_id: CollectionId,520 collection_id: CollectionId,492 token_id: TokenId521 token_id: TokenId493 ) -> Result<impl Iterator<Item=RmrkThemeProperty>, DispatchError> {522 ) -> Result<impl Iterator<Item=RmrkThemeProperty>, DispatchError> {494 let key_prefix = rmrk_property!(Config=T, key: ThemeProperty(&RmrkString::default()))?;523 let key_prefix = Self::rmrk_property_key(ThemeProperty(&RmrkString::default()))?;495524496 let properties = <PalletNft<T>>::token_properties((collection_id, token_id))525 let properties = <PalletNft<T>>::token_properties((collection_id, token_id))497 .into_iter()526 .into_iter()514543515 pub fn get_typed_nft_collection(544 pub fn get_typed_nft_collection(516 collection_id: CollectionId,545 collection_id: CollectionId,517 collection_type: CollectionType546 collection_type: misc::CollectionType518 ) -> Result<NonfungibleHandle<T>, DispatchError> {547 ) -> Result<NonfungibleHandle<T>, DispatchError> {519 Self::ensure_collection_type(collection_id, collection_type)?;548 Self::ensure_collection_type(collection_id, collection_type)?;520549pallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth1use super::*;1use super::*;2use codec::{Encode, Decode};2use codec::{Encode, Decode};3use pallet_nonfungible::{NonfungibleHandle, ItemData};45macro_rules! impl_rmrk_value {6 ($enum_name:path, decode_error: $error:ident) => {7 impl TryFrom<&PropertyValue> for $enum_name {8 type Error = MiscError;910 fn try_from(value: &PropertyValue) -> Result<Self, Self::Error> {11 let mut value = value.as_slice();1213 <$enum_name>::decode(&mut value)14 .map_err(|_| MiscError::$error)15 }16 }1718 };19}20321#[macro_export]4#[macro_export]22macro_rules! map_common_err_to_proxy {5macro_rules! map_common_err_to_proxy {31 };14 };32}15}3334pub enum MiscError {35 RmrkPropertyValueIsTooLong,36 CorruptedCollectionType,37}3839impl<T: Config> From<MiscError> for Error<T> {40 fn from(error: MiscError) -> Self {41 match error {42 MiscError::RmrkPropertyValueIsTooLong => Self::RmrkPropertyValueIsTooLong,43 MiscError::CorruptedCollectionType => Self::CorruptedCollectionType,44 }45 }46}4748pub trait IntoNftCollection<T: Config> {49 fn into_nft_collection(self) -> Result<NonfungibleHandle<T>, Error<T>>;50}5152impl<T: Config> IntoNftCollection<T> for CollectionHandle<T> {53 fn into_nft_collection(self) -> Result<NonfungibleHandle<T>, Error<T>> {54 match self.mode {55 CollectionMode::NFT => Ok(NonfungibleHandle::cast(self)),56 _ => Err(<Error<T>>::CollectionUnknown)57 }58 }59}6061pub trait IntoPropertyValue {62 fn into_property_value(self) -> Result<PropertyValue, MiscError>;63}6465impl<T: Encode> IntoPropertyValue for T {66 fn into_property_value(self) -> Result<PropertyValue, MiscError> {67 self.encode()68 .try_into()69 .map_err(|_| MiscError::RmrkPropertyValueIsTooLong)70 }71}7273pub trait RmrkNft {74 fn rmrk_nft_type(&self) -> Option<NftType>;75}7677impl<CrossAccountId> RmrkNft for ItemData<CrossAccountId> {78 fn rmrk_nft_type(&self) -> Option<NftType> {79 let mut value = self.const_data.as_slice();8081 NftType::decode(&mut value).ok()82 }83}841685pub trait RmrkDecode<T: Decode + Default, S> {17pub trait RmrkDecode<T: Decode + Default, S> {86 fn decode_or_default(&self) -> T;18 fn decode_or_default(&self) -> T;122 Theme54 Theme123}55}124125impl_rmrk_value!(CollectionType, decode_error: CorruptedCollectionType);12656pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth72 }72 }73}73}7475#[macro_export]76macro_rules! rmrk_property {77 (Config=$cfg:ty, key: $key:ident $(($key_ext:expr))?) => {78 rmrk_property!(Config=$cfg, $crate::RmrkProperty::$key $(($key_ext))?)79 };8081 (Config=$cfg:ty, $key:ident $(($key_ext:expr))?: $value:expr) => {{82 let key = rmrk_property!(@$cfg, $crate::RmrkProperty::$key $(($key_ext))?)?;8384 let value = $value.into_property_value()85 .map_err(<$crate::Error<$cfg>>::from)?;8687 Ok::<_, $crate::Error<$cfg>>(Property {88 key,89 value,90 })91 }};9293 (@$cfg:ty, $key_enum:expr) => {94 $key_enum.to_key::<$cfg>()95 };9697 (Config=$cfg:ty, $key_enum:expr) => {98 PropertyScope::Rmrk.apply(rmrk_property!(@$cfg, $key_enum)?)99 .map_err(|_| <$crate::Error<$cfg>>::RmrkPropertyKeyIsTooLong)100 };101}10274pallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth20use frame_system::{pallet_prelude::*, ensure_signed};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::DispatchError;21use sp_runtime::DispatchError;22use up_data_structs::*;22use up_data_structs::*;23use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle};23use pallet_common::{Pallet as PalletCommon, Error as CommonError};24use pallet_rmrk_core::{Pallet as PalletCore, rmrk_property, misc::*};24use pallet_rmrk_core::{Pallet as PalletCore, misc::{self, *}, property::RmrkProperty::*};25use pallet_nonfungible::{Pallet as PalletNft};25use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};26use pallet_evm::account::CrossAccountId;26use pallet_evm::account::CrossAccountId;272728pub use pallet::*;28pub use pallet::*;48 TokenId48 TokenId49 >;49 >;5051 #[pallet::storage]52 #[pallet::getter(fn base_has_default_theme)]53 pub type BaseHasDefaultTheme<T: Config> = StorageMap<54 _,55 Twox64Concat,56 CollectionId,57 bool,58 ValueQuery59 >;506051 #[pallet::pallet]61 #[pallet::pallet]52 #[pallet::generate_store(pub(super) trait Store)]62 #[pallet::generate_store(pub(super) trait Store)]637364 #[pallet::error]74 #[pallet::error]65 pub enum Error<T> {75 pub enum Error<T> {76 PermissionError,66 NoAvailableBaseId,77 NoAvailableBaseId,78 NoAvailablePartId,79 BaseDoesntExist,80 NeedsDefaultThemeFirst,67 }81 }688269 #[pallet::call]83 #[pallet::call]9510996 let collection_id = collection_id_res?;110 let collection_id = collection_id_res?;9798 let collection = <PalletCore<T>>::get_nft_collection(collection_id)?.into_inner();99111100 <PalletCommon<T>>::set_scoped_collection_properties(112 <PalletCommon<T>>::set_scoped_collection_properties(101 &collection,113 collection_id,102 PropertyScope::Rmrk,114 PropertyScope::Rmrk,103 [115 [104 rmrk_property!(Config=T, CollectionType: CollectionType::Base)?,116 <PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,105 rmrk_property!(Config=T, BaseType: base_type)?,117 <PalletCore<T>>::rmrk_property(BaseType, &base_type)?,106 ].into_iter()118 ].into_iter()107 )?;119 )?;120121 let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;108122109 for part in parts {123 for part in parts {110 let part_id = part.id();124 let part_id = part.id();117 <InernalPartId<T>>::insert(collection_id, part_id, part_token_id);131 <InernalPartId<T>>::insert(collection_id, part_id, part_token_id);118132119 <PalletNft<T>>::set_scoped_token_property(133 <PalletNft<T>>::set_scoped_token_property(120 &collection,134 collection_id,121 part_token_id,135 part_token_id,122 PropertyScope::Rmrk,136 PropertyScope::Rmrk,123 rmrk_property!(Config=T, ExternalPartId: part_id)?137 <PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?124 )?;138 )?;125 }139 }126140129 Ok(())143 Ok(())130 }144 }145146 #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]147 #[transactional]148 pub fn theme_add(149 origin: OriginFor<T>,150 base_id: RmrkBaseId,151 theme: RmrkTheme,152 ) -> DispatchResult {153 let sender = ensure_signed(origin)?;154155 let sender = T::CrossAccountId::from_sub(sender);156 let owner = &sender;157158 let collection_id: CollectionId = base_id.into();159160 let collection = <PalletCore<T>>::get_typed_nft_collection(161 collection_id,162 misc::CollectionType::Base163 ).map_err(|_| <Error<T>>::BaseDoesntExist)?;164165 if theme.name.as_slice() == b"default" {166 <BaseHasDefaultTheme<T>>::insert(collection_id, true);167 } else if !Self::base_has_default_theme(collection_id) {168 return Err(<Error<T>>::NeedsDefaultThemeFirst.into());169 }170171 let token_id = <PalletCore<T>>::create_nft(172 &sender,173 owner,174 &collection,175 NftType::Theme,176 [177 <PalletCore<T>>::rmrk_property(ThemeName, &theme.name)?,178 <PalletCore<T>>::rmrk_property(ThemeInherit, &theme.inherit)?179 ].into_iter()180 ).map_err(|_| <Error<T>>::PermissionError)?;181182 for property in theme.properties {183 <PalletNft<T>>::set_scoped_token_property(184 collection_id,185 token_id,186 PropertyScope::Rmrk,187 <PalletCore<T>>::rmrk_property(188 ThemeProperty(&property.key),189 &property.value190 )?191 )?;192 }193194 Ok(())195 }131 }196 }132}197}133198134impl<T: Config> Pallet<T> {199impl<T: Config> Pallet<T> {135 fn create_part(200 fn create_part(136 sender: &T::CrossAccountId,201 sender: &T::CrossAccountId,137 collection: &CollectionHandle<T>,202 collection: &NonfungibleHandle<T>,138 part: RmrkPartType203 part: RmrkPartType139 ) -> Result<TokenId, DispatchError> {204 ) -> Result<TokenId, DispatchError> {140 let owner = sender;205 let owner = sender;150 let token_id = <PalletCore<T>>::create_nft(215 let token_id = <PalletCore<T>>::create_nft(151 sender,216 sender,152 owner,217 owner,153 collection.id,218 collection,154 CollectionType::Base,155 nft_type,219 nft_type,156 [220 [157 rmrk_property!(Config=T, Src: src)?,221 <PalletCore<T>>::rmrk_property(Src, &src)?,158 rmrk_property!(Config=T, ZIndex: z_index)?222 <PalletCore<T>>::rmrk_property(ZIndex, &z_index)?159 ].into_iter()223 ].into_iter()160 )?;224 ).map_err(|err| match err {225 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),226 err => err227 })?;161228162 if let RmrkPartType::SlotPart(part) = part {229 if let RmrkPartType::SlotPart(part) = part {163 <PalletNft<T>>::set_scoped_token_property(230 <PalletNft<T>>::set_scoped_token_property(164 collection,231 collection.id,165 token_id,232 token_id,166 PropertyScope::Rmrk,233 PropertyScope::Rmrk,167 rmrk_property!(Config=T, EquippableList: part.equippable)?234 <PalletCore<T>>::rmrk_property(EquippableList, &part.equippable)?168 )?;235 )?;169 }236 }170237runtime/common/src/runtime_apis.rsdiffbeforeafterboth347347348 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {348 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {349 use frame_support::BoundedVec;349 use frame_support::BoundedVec;350 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkNft, RmrkDecode}};350 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};351351352 let collection_id = CollectionId(base_id);352 let collection_id = CollectionId(base_id);353 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }353 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }379379380 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {380 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {381 use frame_support::BoundedVec;381 use frame_support::BoundedVec;382 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkNft, RmrkDecode}};382 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode}};383383384 let collection_id = CollectionId(base_id);384 let collection_id = CollectionId(base_id);385 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {385 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {407 use frame_support::BoundedVec;407 use frame_support::BoundedVec;408 use pallet_proxy_rmrk_core::{408 use pallet_proxy_rmrk_core::{409 RmrkProperty,409 RmrkProperty,410 misc::{CollectionType, NftType, RmrkNft, RmrkDecode}410 misc::{CollectionType, NftType, RmrkDecode}411 };411 };412412413 let collection_id = CollectionId(base_id);413 let collection_id = CollectionId(base_id);