git.delta.rocks / unique-network / refs/commits / d2735a42ddb8

difftreelog

source

pallets/proxy-rmrk-equip/src/lib.rs6.3 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 = <PalletNft<T>>::init_collection(cross_sender.clone(), data);9899			if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {100				return Err(<Error<T>>::NoAvailableBaseId.into());101			}102103			let collection_id = collection_id_res?;104105			<PalletCommon<T>>::set_scoped_collection_properties(106				collection_id,107				PropertyScope::Rmrk,108				[109					<PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,110					<PalletCore<T>>::rmrk_property(BaseType, &base_type)?,111				]112				.into_iter(),113			)?;114115			let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;116117			for part in parts {118				let part_id = part.id();119				let part_token_id = Self::create_part(&cross_sender, &collection, part)?;120121				<InernalPartId<T>>::insert(collection_id, part_id, part_token_id);122123				<PalletNft<T>>::set_scoped_token_property(124					collection_id,125					part_token_id,126					PropertyScope::Rmrk,127					<PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?,128				)?;129			}130131			Self::deposit_event(Event::BaseCreated {132				issuer: sender,133				base_id: collection_id.0,134			});135136			Ok(())137		}138139		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]140		#[transactional]141		pub fn theme_add(142			origin: OriginFor<T>,143			base_id: RmrkBaseId,144			theme: RmrkTheme,145		) -> DispatchResult {146			let sender = ensure_signed(origin)?;147148			let sender = T::CrossAccountId::from_sub(sender);149			let owner = &sender;150151			let collection_id: CollectionId = base_id.into();152153			let collection = <PalletCore<T>>::get_typed_nft_collection(154				collection_id,155				misc::CollectionType::Base,156			)157			.map_err(|_| <Error<T>>::BaseDoesntExist)?;158159			if theme.name.as_slice() == b"default" {160				<BaseHasDefaultTheme<T>>::insert(collection_id, true);161			} else if !Self::base_has_default_theme(collection_id) {162				return Err(<Error<T>>::NeedsDefaultThemeFirst.into());163			}164165			let token_id = <PalletCore<T>>::create_nft(166				&sender,167				owner,168				&collection,169				NftType::Theme,170				[171					<PalletCore<T>>::rmrk_property(ThemeName, &theme.name)?,172					<PalletCore<T>>::rmrk_property(ThemeInherit, &theme.inherit)?,173				]174				.into_iter(),175			)176			.map_err(|_| <Error<T>>::PermissionError)?;177178			for property in theme.properties {179				<PalletNft<T>>::set_scoped_token_property(180					collection_id,181					token_id,182					PropertyScope::Rmrk,183					<PalletCore<T>>::rmrk_property(184						UserProperty(property.key.as_slice()),185						&property.value,186					)?,187				)?;188			}189190			Ok(())191		}192	}193}194195impl<T: Config> Pallet<T> {196	fn create_part(197		sender: &T::CrossAccountId,198		collection: &NonfungibleHandle<T>,199		part: RmrkPartType,200	) -> Result<TokenId, DispatchError> {201		let owner = sender;202203		let src = part.src();204		let z_index = part.z_index();205206		let nft_type = match part {207			RmrkPartType::FixedPart(_) => NftType::FixedPart,208			RmrkPartType::SlotPart(_) => NftType::SlotPart,209		};210211		let token_id = <PalletCore<T>>::create_nft(212			sender,213			owner,214			collection,215			nft_type,216			[217				<PalletCore<T>>::rmrk_property(Src, &src)?,218				<PalletCore<T>>::rmrk_property(ZIndex, &z_index)?,219			]220			.into_iter(),221		)222		.map_err(|err| match err {223			DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),224			err => err,225		})?;226227		if let RmrkPartType::SlotPart(part) = part {228			<PalletNft<T>>::set_scoped_token_property(229				collection.id,230				token_id,231				PropertyScope::Rmrk,232				<PalletCore<T>>::rmrk_property(EquippableList, &part.equippable)?,233			)?;234		}235236		Ok(token_id)237	}238}