git.delta.rocks / unique-network / refs/commits / 3903c8aaf16e

difftreelog

source

pallets/proxy-rmrk-equip/src/lib.rs6.4 KiBsourcehistory
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, 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};24use pallet_rmrk_core::{25	Pallet as PalletCore,26	misc::{self, *},27	property::RmrkProperty::*,28};29use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};30use pallet_evm::account::CrossAccountId;3132pub use pallet::*;3334#[frame_support::pallet]35pub mod pallet {36	use super::*;3738	#[pallet::config]39	pub trait Config: frame_system::Config + pallet_rmrk_core::Config {40		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;41	}4243	#[pallet::storage]44	#[pallet::getter(fn internal_part_id)]45	pub type InernalPartId<T: Config> =46		StorageDoubleMap<_, Twox64Concat, CollectionId, Twox64Concat, RmrkPartId, TokenId>;4748	#[pallet::storage]49	#[pallet::getter(fn base_has_default_theme)]50	pub type BaseHasDefaultTheme<T: Config> =51		StorageMap<_, Twox64Concat, CollectionId, bool, ValueQuery>;5253	#[pallet::pallet]54	#[pallet::generate_store(pub(super) trait Store)]55	pub struct Pallet<T>(_);5657	#[pallet::event]58	#[pallet::generate_deposit(pub(super) fn deposit_event)]59	pub enum Event<T: Config> {60		BaseCreated {61			issuer: T::AccountId,62			base_id: RmrkBaseId,63		},64	}6566	#[pallet::error]67	pub enum Error<T> {68		PermissionError,69		NoAvailableBaseId,70		NoAvailablePartId,71		BaseDoesntExist,72		NeedsDefaultThemeFirst,73	}7475	#[pallet::call]76	impl<T: Config> Pallet<T> {77		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]78		#[transactional]79		pub fn create_base(80			origin: OriginFor<T>,81			base_type: RmrkString,82			symbol: RmrkString,83			parts: BoundedVec<RmrkPartType, RmrkPartsLimit>,84		) -> DispatchResult {85			let sender = ensure_signed(origin)?;86			let cross_sender = T::CrossAccountId::from_sub(sender.clone());8788			let data = CreateCollectionData {89				limits: None,90				token_prefix: symbol91					.into_inner()92					.try_into()93					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,94				..Default::default()95			};9697			let collection_id_res =98				<PalletNft<T>>::init_collection(cross_sender.clone(), data, true);99100			if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {101				return Err(<Error<T>>::NoAvailableBaseId.into());102			}103104			let collection_id = collection_id_res?;105106			<PalletCommon<T>>::set_scoped_collection_properties(107				collection_id,108				PropertyScope::Rmrk,109				[110					<PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,111					<PalletCore<T>>::rmrk_property(BaseType, &base_type)?,112				]113				.into_iter(),114			)?;115116			let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;117118			for part in parts {119				let part_id = part.id();120				let part_token_id = Self::create_part(&cross_sender, &collection, part)?;121122				<InernalPartId<T>>::insert(collection_id, part_id, part_token_id);123124				<PalletNft<T>>::set_scoped_token_property(125					collection_id,126					part_token_id,127					PropertyScope::Rmrk,128					<PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?,129				)?;130			}131132			Self::deposit_event(Event::BaseCreated {133				issuer: sender,134				base_id: collection_id.0,135			});136137			Ok(())138		}139140		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]141		#[transactional]142		pub fn theme_add(143			origin: OriginFor<T>,144			base_id: RmrkBaseId,145			theme: RmrkTheme,146		) -> DispatchResult {147			let sender = ensure_signed(origin)?;148149			let sender = T::CrossAccountId::from_sub(sender);150			let owner = &sender;151152			let collection_id: CollectionId = base_id.into();153154			let collection = <PalletCore<T>>::get_typed_nft_collection(155				collection_id,156				misc::CollectionType::Base,157			)158			.map_err(|_| <Error<T>>::BaseDoesntExist)?;159			collection.check_is_external()?;160161			if theme.name.as_slice() == b"default" {162				<BaseHasDefaultTheme<T>>::insert(collection_id, true);163			} else if !Self::base_has_default_theme(collection_id) {164				return Err(<Error<T>>::NeedsDefaultThemeFirst.into());165			}166167			let token_id = <PalletCore<T>>::create_nft(168				&sender,169				owner,170				&collection,171				[172					<PalletCore<T>>::rmrk_property(TokenType, &NftType::Theme)?,173					<PalletCore<T>>::rmrk_property(ThemeName, &theme.name)?,174					<PalletCore<T>>::rmrk_property(ThemeInherit, &theme.inherit)?,175				]176				.into_iter(),177			)178			.map_err(|_| <Error<T>>::PermissionError)?;179180			for property in theme.properties {181				<PalletNft<T>>::set_scoped_token_property(182					collection_id,183					token_id,184					PropertyScope::Rmrk,185					<PalletCore<T>>::rmrk_property(186						UserProperty(property.key.as_slice()),187						&property.value,188					)?,189				)?;190			}191192			Ok(())193		}194	}195}196197impl<T: Config> Pallet<T> {198	fn create_part(199		sender: &T::CrossAccountId,200		collection: &NonfungibleHandle<T>,201		part: RmrkPartType,202	) -> Result<TokenId, DispatchError> {203		let owner = sender;204205		let src = part.src();206		let z_index = part.z_index();207208		let nft_type = match part {209			RmrkPartType::FixedPart(_) => NftType::FixedPart,210			RmrkPartType::SlotPart(_) => NftType::SlotPart,211		};212213		let token_id = <PalletCore<T>>::create_nft(214			sender,215			owner,216			collection,217			[218				<PalletCore<T>>::rmrk_property(TokenType, &nft_type)?,219				<PalletCore<T>>::rmrk_property(Src, &src)?,220				<PalletCore<T>>::rmrk_property(ZIndex, &z_index)?,221			]222			.into_iter(),223		)224		.map_err(|err| match err {225			DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),226			err => err,227		})?;228229		if let RmrkPartType::SlotPart(part) = part {230			<PalletNft<T>>::set_scoped_token_property(231				collection.id,232				token_id,233				PropertyScope::Rmrk,234				<PalletCore<T>>::rmrk_property(EquippableList, &part.equippable)?,235			)?;236		}237238		Ok(token_id)239	}240}