git.delta.rocks / unique-network / refs/commits / 91e514bdbb72

difftreelog

source

pallets/nonfungible/src/common.rs14.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/>.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, RefungibleExtensions, with_weight,26	weights::WeightInfo as _,27};28use sp_runtime::DispatchError;29use sp_std::{vec::Vec, vec};3031use crate::{32	AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,33	SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,34};3536pub struct CommonWeights<T: Config>(PhantomData<T>);37impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {38	fn create_item() -> Weight {39		<SelfWeightOf<T>>::create_item()40	}4142	fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {43		match data {44			CreateItemExData::NFT(t) => {45				<SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32)46					+ t.iter()47						.filter_map(|t| {48							if t.properties.len() > 0 {49								Some(Self::set_token_properties(t.properties.len() as u32))50							} else {51								None52							}53						})54						.fold(Weight::zero(), |a, b| a.saturating_add(b))55			}56			_ => Weight::zero(),57		}58	}5960	fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {61		<SelfWeightOf<T>>::create_multiple_items(data.len() as u32)62			+ data63				.iter()64				.filter_map(|t| match t {65					up_data_structs::CreateItemData::NFT(n) if n.properties.len() > 0 => {66						Some(Self::set_token_properties(n.properties.len() as u32))67					}68					_ => None,69				})70				.fold(Weight::zero(), |a, b| a.saturating_add(b))71	}7273	fn burn_item() -> Weight {74		<SelfWeightOf<T>>::burn_item()75	}7677	fn set_collection_properties(amount: u32) -> Weight {78		<pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)79	}8081	fn delete_collection_properties(amount: u32) -> Weight {82		<pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)83	}8485	fn set_token_properties(amount: u32) -> Weight {86		<SelfWeightOf<T>>::set_token_properties(amount)87	}8889	fn delete_token_properties(amount: u32) -> Weight {90		<SelfWeightOf<T>>::delete_token_properties(amount)91	}9293	fn set_token_property_permissions(amount: u32) -> Weight {94		<SelfWeightOf<T>>::set_token_property_permissions(amount)95	}9697	fn transfer() -> Weight {98		<SelfWeightOf<T>>::transfer()99	}100101	fn approve() -> Weight {102		<SelfWeightOf<T>>::approve()103	}104105	fn approve_from() -> Weight {106		<SelfWeightOf<T>>::approve_from()107	}108109	fn transfer_from() -> Weight {110		<SelfWeightOf<T>>::transfer_from()111	}112113	fn burn_from() -> Weight {114		<SelfWeightOf<T>>::burn_from()115	}116117	fn burn_recursively_self_raw() -> Weight {118		<SelfWeightOf<T>>::burn_recursively_self_raw()119	}120121	fn burn_recursively_breadth_raw(amount: u32) -> Weight {122		<SelfWeightOf<T>>::burn_recursively_breadth_plus_self_plus_self_per_each_raw(amount)123			.saturating_sub(Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1))124	}125126	fn token_owner() -> Weight {127		<SelfWeightOf<T>>::token_owner()128	}129130	fn set_allowance_for_all() -> Weight {131		<SelfWeightOf<T>>::set_allowance_for_all()132	}133134	fn force_repair_item() -> Weight {135		<SelfWeightOf<T>>::repair_item()136	}137}138139fn map_create_data<T: Config>(140	data: up_data_structs::CreateItemData,141	to: &T::CrossAccountId,142) -> Result<CreateItemData<T>, DispatchError> {143	match data {144		up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {145			properties: data.properties,146			owner: to.clone(),147		}),148		_ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),149	}150}151152/// Implementation of `CommonCollectionOperations` for `NonfungibleHandle`. It wraps Nonfungible Pallete153/// methods and adds weight info.154impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {155	fn create_item(156		&self,157		sender: T::CrossAccountId,158		to: T::CrossAccountId,159		data: up_data_structs::CreateItemData,160		nesting_budget: &dyn Budget,161	) -> DispatchResultWithPostInfo {162		with_weight(163			<Pallet<T>>::create_item(164				self,165				&sender,166				map_create_data::<T>(data, &to)?,167				nesting_budget,168			),169			<CommonWeights<T>>::create_item(),170		)171	}172173	fn create_multiple_items(174		&self,175		sender: T::CrossAccountId,176		to: T::CrossAccountId,177		data: Vec<up_data_structs::CreateItemData>,178		nesting_budget: &dyn Budget,179	) -> DispatchResultWithPostInfo {180		let weight = <CommonWeights<T>>::create_multiple_items(&data);181		let data = data182			.into_iter()183			.map(|d| map_create_data::<T>(d, &to))184			.collect::<Result<Vec<_>, DispatchError>>()?;185186		with_weight(187			<Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),188			weight,189		)190	}191192	fn create_multiple_items_ex(193		&self,194		sender: <T>::CrossAccountId,195		data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,196		nesting_budget: &dyn Budget,197	) -> DispatchResultWithPostInfo {198		let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);199		let data = match data {200			up_data_structs::CreateItemExData::NFT(nft) => nft,201			_ => fail!(Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken),202		};203204		with_weight(205			<Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),206			weight,207		)208	}209210	fn set_collection_properties(211		&self,212		sender: T::CrossAccountId,213		properties: Vec<Property>,214	) -> DispatchResultWithPostInfo {215		let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);216217		with_weight(218			<Pallet<T>>::set_collection_properties(self, &sender, properties),219			weight,220		)221	}222223	fn delete_collection_properties(224		&self,225		sender: &T::CrossAccountId,226		property_keys: Vec<PropertyKey>,227	) -> DispatchResultWithPostInfo {228		let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);229230		with_weight(231			<Pallet<T>>::delete_collection_properties(self, sender, property_keys),232			weight,233		)234	}235236	fn set_token_properties(237		&self,238		sender: T::CrossAccountId,239		token_id: TokenId,240		properties: Vec<Property>,241		nesting_budget: &dyn Budget,242	) -> DispatchResultWithPostInfo {243		let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);244245		with_weight(246			<Pallet<T>>::set_token_properties(247				self,248				&sender,249				token_id,250				properties.into_iter(),251				false,252				nesting_budget,253			),254			weight,255		)256	}257258	fn delete_token_properties(259		&self,260		sender: T::CrossAccountId,261		token_id: TokenId,262		property_keys: Vec<PropertyKey>,263		nesting_budget: &dyn Budget,264	) -> DispatchResultWithPostInfo {265		let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);266267		with_weight(268			<Pallet<T>>::delete_token_properties(269				self,270				&sender,271				token_id,272				property_keys.into_iter(),273				nesting_budget,274			),275			weight,276		)277	}278279	fn set_token_property_permissions(280		&self,281		sender: &T::CrossAccountId,282		property_permissions: Vec<PropertyKeyPermission>,283	) -> DispatchResultWithPostInfo {284		let weight =285			<CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);286287		with_weight(288			<Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),289			weight,290		)291	}292293	fn burn_item(294		&self,295		sender: T::CrossAccountId,296		token: TokenId,297		amount: u128,298	) -> DispatchResultWithPostInfo {299		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);300		if amount == 1 {301			with_weight(302				<Pallet<T>>::burn(self, &sender, token),303				<CommonWeights<T>>::burn_item(),304			)305		} else {306			<Pallet<T>>::check_token_immediate_ownership(self, token, &sender)?;307			Ok(().into())308		}309	}310311	fn burn_item_recursively(312		&self,313		sender: T::CrossAccountId,314		token: TokenId,315		self_budget: &dyn Budget,316		breadth_budget: &dyn Budget,317	) -> DispatchResultWithPostInfo {318		<Pallet<T>>::burn_recursively(self, &sender, token, self_budget, breadth_budget)319	}320321	fn transfer(322		&self,323		from: T::CrossAccountId,324		to: T::CrossAccountId,325		token: TokenId,326		amount: u128,327		nesting_budget: &dyn Budget,328	) -> DispatchResultWithPostInfo {329		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);330		if amount == 1 {331			with_weight(332				<Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),333				<CommonWeights<T>>::transfer(),334			)335		} else {336			<Pallet<T>>::check_token_immediate_ownership(self, token, &from)?;337			Ok(().into())338		}339	}340341	fn approve(342		&self,343		sender: T::CrossAccountId,344		spender: T::CrossAccountId,345		token: TokenId,346		amount: u128,347	) -> DispatchResultWithPostInfo {348		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);349350		with_weight(351			if amount == 1 {352				<Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))353			} else {354				<Pallet<T>>::set_allowance(self, &sender, token, None)355			},356			<CommonWeights<T>>::approve(),357		)358	}359360	fn approve_from(361		&self,362		sender: T::CrossAccountId,363		from: T::CrossAccountId,364		to: T::CrossAccountId,365		token: TokenId,366		amount: u128,367	) -> DispatchResultWithPostInfo {368		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);369370		with_weight(371			if amount == 1 {372				<Pallet<T>>::set_allowance_from(self, &sender, &from, token, Some(&to))373			} else {374				<Pallet<T>>::set_allowance_from(self, &sender, &from, token, None)375			},376			<CommonWeights<T>>::approve_from(),377		)378	}379380	fn transfer_from(381		&self,382		sender: T::CrossAccountId,383		from: T::CrossAccountId,384		to: T::CrossAccountId,385		token: TokenId,386		amount: u128,387		nesting_budget: &dyn Budget,388	) -> DispatchResultWithPostInfo {389		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);390391		if amount == 1 {392			with_weight(393				<Pallet<T>>::transfer_from(self, &sender, &from, &to, token, nesting_budget),394				<CommonWeights<T>>::transfer_from(),395			)396		} else {397			<Pallet<T>>::check_allowed(self, &sender, &from, token, nesting_budget)?;398399			Ok(().into())400		}401	}402403	fn burn_from(404		&self,405		sender: T::CrossAccountId,406		from: T::CrossAccountId,407		token: TokenId,408		amount: u128,409		nesting_budget: &dyn Budget,410	) -> DispatchResultWithPostInfo {411		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);412413		if amount == 1 {414			with_weight(415				<Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),416				<CommonWeights<T>>::burn_from(),417			)418		} else {419			<Pallet<T>>::check_allowed(self, &sender, &from, token, nesting_budget)?;420421			Ok(().into())422		}423	}424425	fn check_nesting(426		&self,427		sender: T::CrossAccountId,428		from: (CollectionId, TokenId),429		under: TokenId,430		nesting_budget: &dyn Budget,431	) -> sp_runtime::DispatchResult {432		<Pallet<T>>::check_nesting(self, sender, from, under, nesting_budget)433	}434435	fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId)) {436		<Pallet<T>>::nest((self.id, under), to_nest);437	}438439	fn unnest(&self, under: TokenId, to_unnest: (CollectionId, TokenId)) {440		<Pallet<T>>::unnest((self.id, under), to_unnest);441	}442443	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {444		<Owned<T>>::iter_prefix((self.id, account))445			.map(|(id, _)| id)446			.collect()447	}448449	fn collection_tokens(&self) -> Vec<TokenId> {450		<TokenData<T>>::iter_prefix((self.id,))451			.map(|(id, _)| id)452			.collect()453	}454455	fn token_exists(&self, token: TokenId) -> bool {456		<Pallet<T>>::token_exists(self, token)457	}458459	fn last_token_id(&self) -> TokenId {460		TokenId(<TokensMinted<T>>::get(self.id))461	}462463	fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {464		<TokenData<T>>::get((self.id, token)).map(|t| t.owner)465	}466467	/// Returns token owners.468	fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {469		self.token_owner(token).map_or_else(|| vec![], |t| vec![t])470	}471472	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {473		<Pallet<T>>::token_properties((self.id, token_id))474			.get(key)475			.cloned()476	}477478	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {479		let properties = <Pallet<T>>::token_properties((self.id, token_id));480481		keys.map(|keys| {482			keys.into_iter()483				.filter_map(|key| {484					properties.get(&key).map(|value| Property {485						key,486						value: value.clone(),487					})488				})489				.collect()490		})491		.unwrap_or_else(|| {492			properties493				.into_iter()494				.map(|(key, value)| Property { key, value })495				.collect()496		})497	}498499	fn total_supply(&self) -> u32 {500		<Pallet<T>>::total_supply(self)501	}502503	fn account_balance(&self, account: T::CrossAccountId) -> u32 {504		<AccountBalance<T>>::get((self.id, account))505	}506507	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {508		if <TokenData<T>>::get((self.id, token))509			.map(|a| a.owner == account)510			.unwrap_or(false)511		{512			1513		} else {514			0515		}516	}517518	fn allowance(519		&self,520		sender: T::CrossAccountId,521		spender: T::CrossAccountId,522		token: TokenId,523	) -> u128 {524		if <TokenData<T>>::get((self.id, token))525			.map(|a| a.owner != sender)526			.unwrap_or(true)527		{528			0529		} else if <Allowance<T>>::get((self.id, token)) == Some(spender) {530			1531		} else {532			0533		}534	}535536	fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {537		None538	}539540	fn total_pieces(&self, token: TokenId) -> Option<u128> {541		if <TokenData<T>>::contains_key((self.id, token)) {542			Some(1)543		} else {544			None545		}546	}547548	fn set_allowance_for_all(549		&self,550		owner: T::CrossAccountId,551		operator: T::CrossAccountId,552		approve: bool,553	) -> DispatchResultWithPostInfo {554		with_weight(555			<Pallet<T>>::set_allowance_for_all(self, &owner, &operator, approve),556			<CommonWeights<T>>::set_allowance_for_all(),557		)558	}559560	fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {561		<Pallet<T>>::allowance_for_all(self, &owner, &operator)562	}563564	fn repair_item(&self, token: TokenId) -> DispatchResultWithPostInfo {565		with_weight(566			<Pallet<T>>::repair_item(self, token),567			<CommonWeights<T>>::force_repair_item(),568		)569	}570}