git.delta.rocks / unique-network / refs/commits / 47c39a449fef

difftreelog

source

pallets/nonfungible/src/common.rs11.8 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/>.1617use core::marker::PhantomData;1819use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};20use up_data_structs::{21	TokenId, CreateItemExData, CollectionId, budget::Budget, Property, PropertyKey,22	PropertyKeyPermission, PropertyValue,23};24use pallet_common::{25	CommonCollectionOperations, CommonWeightInfo, with_weight, weights::WeightInfo as _,26};27use sp_runtime::DispatchError;28use sp_std::vec::Vec;2930use crate::{31	AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,32	SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,33};3435pub struct CommonWeights<T: Config>(PhantomData<T>);36impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {37	fn create_item() -> Weight {38		<SelfWeightOf<T>>::create_item()39	}4041	fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {42		match data {43			CreateItemExData::NFT(t) => {44				<SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32)45					+ t.iter()46						.map(|t| {47							if t.properties.len() > 0 {48								Self::set_token_properties(t.properties.len() as u32)49							} else {50								051							}52						})53						.sum::<u64>()54			}55			_ => 0,56		}57	}5859	fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {60		<SelfWeightOf<T>>::create_multiple_items(data.len() as u32)61			+ data62				.iter()63				.filter_map(|t| match t {64					up_data_structs::CreateItemData::NFT(n) if n.properties.len() > 0 => {65						Some(Self::set_token_properties(n.properties.len() as u32))66					}67					_ => None,68				})69				.sum::<u64>()70	}7172	fn burn_item() -> Weight {73		<SelfWeightOf<T>>::burn_item()74	}7576	fn set_collection_properties(amount: u32) -> Weight {77		<pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)78	}7980	fn delete_collection_properties(amount: u32) -> Weight {81		<pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)82	}8384	fn set_token_properties(amount: u32) -> Weight {85		<SelfWeightOf<T>>::set_token_properties(amount)86	}8788	fn delete_token_properties(amount: u32) -> Weight {89		<SelfWeightOf<T>>::delete_token_properties(amount)90	}9192	fn set_token_property_permissions(amount: u32) -> Weight {93		<SelfWeightOf<T>>::set_token_property_permissions(amount)94	}9596	fn transfer() -> Weight {97		<SelfWeightOf<T>>::transfer()98	}99100	fn approve() -> Weight {101		<SelfWeightOf<T>>::approve()102	}103104	fn transfer_from() -> Weight {105		<SelfWeightOf<T>>::transfer_from()106	}107108	fn burn_from() -> Weight {109		<SelfWeightOf<T>>::burn_from()110	}111112	fn burn_recursively_self_raw() -> Weight {113		<SelfWeightOf<T>>::burn_recursively_self_raw()114	}115116	fn burn_recursively_breadth_raw(amount: u32) -> Weight {117		<SelfWeightOf<T>>::burn_recursively_breadth_plus_self_plus_self_per_each_raw(amount)118			.saturating_sub(Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1))119	}120}121122fn map_create_data<T: Config>(123	data: up_data_structs::CreateItemData,124	to: &T::CrossAccountId,125) -> Result<CreateItemData<T>, DispatchError> {126	match data {127		up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {128			properties: data.properties,129			owner: to.clone(),130		}),131		_ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),132	}133}134135impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {136	fn create_item(137		&self,138		sender: T::CrossAccountId,139		to: T::CrossAccountId,140		data: up_data_structs::CreateItemData,141		nesting_budget: &dyn Budget,142	) -> DispatchResultWithPostInfo {143		with_weight(144			<Pallet<T>>::create_item(145				self,146				&sender,147				map_create_data::<T>(data, &to)?,148				nesting_budget,149			),150			<CommonWeights<T>>::create_item(),151		)152	}153154	fn create_multiple_items(155		&self,156		sender: T::CrossAccountId,157		to: T::CrossAccountId,158		data: Vec<up_data_structs::CreateItemData>,159		nesting_budget: &dyn Budget,160	) -> DispatchResultWithPostInfo {161		let weight = <CommonWeights<T>>::create_multiple_items(&data);162		let data = data163			.into_iter()164			.map(|d| map_create_data::<T>(d, &to))165			.collect::<Result<Vec<_>, DispatchError>>()?;166167		with_weight(168			<Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),169			weight,170		)171	}172173	fn create_multiple_items_ex(174		&self,175		sender: <T>::CrossAccountId,176		data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,177		nesting_budget: &dyn Budget,178	) -> DispatchResultWithPostInfo {179		let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);180		let data = match data {181			up_data_structs::CreateItemExData::NFT(nft) => nft,182			_ => fail!(Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken),183		};184185		with_weight(186			<Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),187			weight,188		)189	}190191	fn set_collection_properties(192		&self,193		sender: T::CrossAccountId,194		properties: Vec<Property>,195	) -> DispatchResultWithPostInfo {196		let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);197198		with_weight(199			<Pallet<T>>::set_collection_properties(self, &sender, properties),200			weight,201		)202	}203204	fn delete_collection_properties(205		&self,206		sender: &T::CrossAccountId,207		property_keys: Vec<PropertyKey>,208	) -> DispatchResultWithPostInfo {209		let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);210211		with_weight(212			<Pallet<T>>::delete_collection_properties(self, sender, property_keys),213			weight,214		)215	}216217	fn set_token_properties(218		&self,219		sender: T::CrossAccountId,220		token_id: TokenId,221		properties: Vec<Property>,222	) -> DispatchResultWithPostInfo {223		let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);224225		with_weight(226			<Pallet<T>>::set_token_properties(self, &sender, token_id, properties, false),227			weight,228		)229	}230231	fn delete_token_properties(232		&self,233		sender: T::CrossAccountId,234		token_id: TokenId,235		property_keys: Vec<PropertyKey>,236	) -> DispatchResultWithPostInfo {237		let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);238239		with_weight(240			<Pallet<T>>::delete_token_properties(self, &sender, token_id, property_keys),241			weight,242		)243	}244245	fn set_token_property_permissions(246		&self,247		sender: &T::CrossAccountId,248		property_permissions: Vec<PropertyKeyPermission>,249	) -> DispatchResultWithPostInfo {250		let weight =251			<CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);252253		with_weight(254			<Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),255			weight,256		)257	}258259	fn burn_item(260		&self,261		sender: T::CrossAccountId,262		token: TokenId,263		amount: u128,264	) -> DispatchResultWithPostInfo {265		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);266		if amount == 1 {267			with_weight(268				<Pallet<T>>::burn(self, &sender, token),269				<CommonWeights<T>>::burn_item(),270			)271		} else {272			Ok(().into())273		}274	}275276	fn burn_item_recursively(277		&self,278		sender: T::CrossAccountId,279		token: TokenId,280		self_budget: &dyn Budget,281		breadth_budget: &dyn Budget,282	) -> DispatchResultWithPostInfo {283		<Pallet<T>>::burn_recursively(self, &sender, token, self_budget, breadth_budget)284	}285286	fn transfer(287		&self,288		from: T::CrossAccountId,289		to: T::CrossAccountId,290		token: TokenId,291		amount: u128,292		nesting_budget: &dyn Budget,293	) -> DispatchResultWithPostInfo {294		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);295		if amount == 1 {296			with_weight(297				<Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),298				<CommonWeights<T>>::transfer(),299			)300		} else {301			Ok(().into())302		}303	}304305	fn approve(306		&self,307		sender: T::CrossAccountId,308		spender: T::CrossAccountId,309		token: TokenId,310		amount: u128,311	) -> DispatchResultWithPostInfo {312		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);313314		with_weight(315			if amount == 1 {316				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))317			} else {318				<Pallet<T>>::set_allowance(self, &sender, token, None)319			},320			<CommonWeights<T>>::approve(),321		)322	}323324	fn transfer_from(325		&self,326		sender: T::CrossAccountId,327		from: T::CrossAccountId,328		to: T::CrossAccountId,329		token: TokenId,330		amount: u128,331		nesting_budget: &dyn Budget,332	) -> DispatchResultWithPostInfo {333		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);334335		if amount == 1 {336			with_weight(337				<Pallet<T>>::transfer_from(self, &sender, &from, &to, token, nesting_budget),338				<CommonWeights<T>>::transfer_from(),339			)340		} else {341			Ok(().into())342		}343	}344345	fn burn_from(346		&self,347		sender: T::CrossAccountId,348		from: T::CrossAccountId,349		token: TokenId,350		amount: u128,351		nesting_budget: &dyn Budget,352	) -> DispatchResultWithPostInfo {353		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);354355		if amount == 1 {356			with_weight(357				<Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),358				<CommonWeights<T>>::burn_from(),359			)360		} else {361			Ok(().into())362		}363	}364365	fn check_nesting(366		&self,367		sender: T::CrossAccountId,368		from: (CollectionId, TokenId),369		under: TokenId,370		budget: &dyn Budget,371	) -> sp_runtime::DispatchResult {372		<Pallet<T>>::check_nesting(self, sender, from, under, budget)373	}374375	fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId)) {376		<Pallet<T>>::nest((self.id, under), to_nest);377	}378379	fn unnest(&self, under: TokenId, to_unnest: (CollectionId, TokenId)) {380		<Pallet<T>>::unnest((self.id, under), to_unnest);381	}382383	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {384		<Owned<T>>::iter_prefix((self.id, account))385			.map(|(id, _)| id)386			.collect()387	}388389	fn collection_tokens(&self) -> Vec<TokenId> {390		<TokenData<T>>::iter_prefix((self.id,))391			.map(|(id, _)| id)392			.collect()393	}394395	fn token_exists(&self, token: TokenId) -> bool {396		<Pallet<T>>::token_exists(self, token)397	}398399	fn last_token_id(&self) -> TokenId {400		TokenId(<TokensMinted<T>>::get(self.id))401	}402403	fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {404		<TokenData<T>>::get((self.id, token)).map(|t| t.owner)405	}406407	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {408		<Pallet<T>>::token_properties((self.id, token_id))409			.get(key)410			.cloned()411	}412413	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {414		let properties = <Pallet<T>>::token_properties((self.id, token_id));415416		keys.map(|keys| {417			keys.into_iter()418				.filter_map(|key| {419					properties.get(&key).map(|value| Property {420						key,421						value: value.clone(),422					})423				})424				.collect()425		})426		.unwrap_or_else(|| {427			properties428				.into_iter()429				.map(|(key, value)| Property { key, value })430				.collect()431		})432	}433434	fn total_supply(&self) -> u32 {435		<Pallet<T>>::total_supply(self)436	}437438	fn account_balance(&self, account: T::CrossAccountId) -> u32 {439		<AccountBalance<T>>::get((self.id, account))440	}441442	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {443		if <TokenData<T>>::get((self.id, token))444			.map(|a| a.owner == account)445			.unwrap_or(false)446		{447			1448		} else {449			0450		}451	}452453	fn allowance(454		&self,455		sender: T::CrossAccountId,456		spender: T::CrossAccountId,457		token: TokenId,458	) -> u128 {459		if <TokenData<T>>::get((self.id, token))460			.map(|a| a.owner != sender)461			.unwrap_or(true)462		{463			0464		} else if <Allowance<T>>::get((self.id, token)) == Some(spender) {465			1466		} else {467			0468		}469	}470}