git.delta.rocks / unique-network / refs/commits / 764dfd599fff

difftreelog

source

pallets/proxy-rmrk-equip/src/lib.rs7.6 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::{Pallet as PalletCore, misc::{self, *}, property::RmrkProperty::*};25use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};26use pallet_evm::account::CrossAccountId;2728pub use pallet::*;2930#[frame_support::pallet]31pub mod pallet {32    use super::*;3334	#[pallet::config]35	pub trait Config: frame_system::Config36                    + pallet_rmrk_core::Config {37		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;38	}3940    #[pallet::storage]41	#[pallet::getter(fn internal_part_id)]42	pub type InernalPartId<T: Config> = StorageDoubleMap<43        _,44        Twox64Concat,45        CollectionId,46        Twox64Concat,47        RmrkPartId,48        TokenId49    >;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    >;6061    #[pallet::pallet]62	#[pallet::generate_store(pub(super) trait Store)]63	pub struct Pallet<T>(_);6465	#[pallet::event]66	#[pallet::generate_deposit(pub(super) fn deposit_event)]67	pub enum Event<T: Config> {68        BaseCreated {69			issuer: T::AccountId,70			base_id: RmrkBaseId,71		},72    }7374    #[pallet::error]75	pub enum Error<T> {76        PermissionError,77        NoAvailableBaseId,78        NoAvailablePartId,79        BaseDoesntExist,80        NeedsDefaultThemeFirst,81    }8283    #[pallet::call]84	impl<T: Config> Pallet<T> {85        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]86        #[transactional]87		pub fn create_base(88			origin: OriginFor<T>,89			base_type: RmrkString,90			symbol: RmrkString,91			parts: BoundedVec<RmrkPartType, RmrkPartsLimit>,92		) -> DispatchResult {93            let sender = ensure_signed(origin)?;94            let cross_sender = T::CrossAccountId::from_sub(sender.clone());9596            let data = CreateCollectionData {97                limits: None,98                token_prefix: symbol.into_inner()99                    .try_into()100                    .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,101                ..Default::default()102            };103104            let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);105106            if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {107                return Err(<Error<T>>::NoAvailableBaseId.into());108            }109110            let collection_id = collection_id_res?;111112            <PalletCommon<T>>::set_scoped_collection_properties(113                collection_id,114                PropertyScope::Rmrk,115                [116                    <PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,117                    <PalletCore<T>>::rmrk_property(BaseType, &base_type)?,118                ].into_iter()119            )?;120121            let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;122123            for part in parts {124                let part_id = part.id();125                let part_token_id = Self::create_part(126                    &cross_sender,127                    &collection,128                    part129                )?;130131                <InernalPartId<T>>::insert(collection_id, part_id, part_token_id);132133                <PalletNft<T>>::set_scoped_token_property(134                    collection_id,135                    part_token_id,136                    PropertyScope::Rmrk,137                    <PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?138                )?;139            }140141            Self::deposit_event(Event::BaseCreated { issuer: sender, base_id: collection_id.0 });142143            Ok(())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                        UserProperty(property.key.as_slice()),189                        &property.value190                    )?191                )?;192            }193194            Ok(())195        }196    }197}198199impl<T: Config> Pallet<T> {200    fn create_part(201        sender: &T::CrossAccountId,202        collection: &NonfungibleHandle<T>,203        part: RmrkPartType204    ) -> Result<TokenId, DispatchError> {205        let owner = sender;206207        let src = part.src();208        let z_index = part.z_index();209210        let nft_type = match part {211            RmrkPartType::FixedPart(_) => NftType::FixedPart,212            RmrkPartType::SlotPart(_) => NftType::SlotPart,213        };214215        let token_id = <PalletCore<T>>::create_nft(216            sender,217            owner,218            collection,219            nft_type,220            [221                <PalletCore<T>>::rmrk_property(Src, &src)?,222                <PalletCore<T>>::rmrk_property(ZIndex, &z_index)?223            ].into_iter()224        ).map_err(|err| match err {225            DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),226            err => err227        })?;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}