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

difftreelog

source

pallets/refungible/src/common.rs14.7 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, fail, weights::Weight};20use pallet_common::{21	weights::WeightInfo as _, with_weight, write_token_properties_total_weight,22	CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions,23};24use pallet_structure::Pallet as PalletStructure;25use sp_runtime::DispatchError;26use sp_std::{collections::btree_map::BTreeMap, vec, vec::Vec};27use up_data_structs::{28	budget::Budget, CollectionId, CreateItemExData, CreateRefungibleExMultipleOwners,29	CreateRefungibleExSingleOwner, Property, PropertyKey, PropertyKeyPermission, PropertyValue,30	TokenId, TokenOwnerError,31};3233use crate::{34	weights::WeightInfo, AccountBalance, Allowance, Balance, Config, CreateItemData, Error, Owned,35	Pallet, RefungibleHandle, SelfWeightOf, TokenProperties, TokensMinted, TotalSupply,36};3738macro_rules! max_weight_of {39	($($method:ident ($($args:tt)*)),*) => {40		Weight::zero()41		$(42			.max(<SelfWeightOf<T>>::$method($($args)*))43		)*44	};45}4647pub struct CommonWeights<T: Config>(PhantomData<T>);48impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {49	fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {50		<SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(51			write_token_properties_total_weight::<T, _>(52				data.iter().map(|data| match data {53					up_data_structs::CreateItemData::ReFungible(rft_data) => {54						rft_data.properties.len() as u3255					}56					_ => 0,57				}),58				<SelfWeightOf<T>>::write_token_properties,59			),60		)61	}6263	fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {64		match call {65			CreateItemExData::RefungibleMultipleOwners(i) => {66				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)67					.saturating_add(write_token_properties_total_weight::<T, _>(68						[i.properties.len() as u32].into_iter(),69						<SelfWeightOf<T>>::write_token_properties,70					))71			}72			CreateItemExData::RefungibleMultipleItems(i) => {73				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)74					.saturating_add(write_token_properties_total_weight::<T, _>(75						i.iter().map(|d| d.properties.len() as u32),76						<SelfWeightOf<T>>::write_token_properties,77					))78			}79			_ => Weight::zero(),80		}81	}8283	fn burn_item() -> Weight {84		max_weight_of!(burn_item_partial(), burn_item_fully())85	}8687	fn set_collection_properties(amount: u32) -> Weight {88		<pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)89	}9091	fn set_token_properties(amount: u32) -> Weight {92		write_token_properties_total_weight::<T, _>([amount].into_iter(), |amount| {93			<SelfWeightOf<T>>::load_token_properties()94				+ <SelfWeightOf<T>>::write_token_properties(amount)95		})96	}9798	fn set_token_property_permissions(amount: u32) -> Weight {99		<SelfWeightOf<T>>::set_token_property_permissions(amount)100	}101102	fn transfer() -> Weight {103		max_weight_of!(104			transfer_normal(),105			transfer_creating(),106			transfer_removing(),107			transfer_creating_removing()108		)109	}110111	fn approve() -> Weight {112		<SelfWeightOf<T>>::approve()113	}114115	fn approve_from() -> Weight {116		<SelfWeightOf<T>>::approve_from()117	}118119	fn transfer_from() -> Weight {120		max_weight_of!(121			transfer_from_normal(),122			transfer_from_creating(),123			transfer_from_removing(),124			transfer_from_creating_removing()125		)126	}127128	fn burn_from() -> Weight {129		<SelfWeightOf<T>>::burn_from()130	}131132	fn set_allowance_for_all() -> Weight {133		<SelfWeightOf<T>>::set_allowance_for_all()134	}135136	fn force_repair_item() -> Weight {137		<SelfWeightOf<T>>::repair_item()138	}139}140141fn map_create_data<T: Config>(142	data: up_data_structs::CreateItemData,143	to: &T::CrossAccountId,144) -> Result<CreateItemData<T>, DispatchError> {145	match data {146		up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData::<T> {147			users: {148				let mut out = BTreeMap::new();149				out.insert(to.clone(), data.pieces);150				out.try_into().expect("limit > 0")151			},152			properties: data.properties,153		}),154		_ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),155	}156}157158/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete159/// methods and adds weight info.160impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {161	fn create_item(162		&self,163		sender: T::CrossAccountId,164		to: T::CrossAccountId,165		data: up_data_structs::CreateItemData,166		nesting_budget: &dyn Budget,167	) -> DispatchResultWithPostInfo {168		let weight = <CommonWeights<T>>::create_item(&data);169		with_weight(170			<Pallet<T>>::create_item(171				self,172				&sender,173				map_create_data::<T>(data, &to)?,174				nesting_budget,175			),176			weight,177		)178	}179180	fn create_multiple_items(181		&self,182		sender: T::CrossAccountId,183		to: T::CrossAccountId,184		data: Vec<up_data_structs::CreateItemData>,185		nesting_budget: &dyn Budget,186	) -> DispatchResultWithPostInfo {187		let weight = <CommonWeights<T>>::create_multiple_items(&data);188		let data = data189			.into_iter()190			.map(|d| map_create_data::<T>(d, &to))191			.collect::<Result<Vec<_>, DispatchError>>()?;192193		with_weight(194			<Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),195			weight,196		)197	}198199	fn create_multiple_items_ex(200		&self,201		sender: <T>::CrossAccountId,202		data: CreateItemExData<T::CrossAccountId>,203		nesting_budget: &dyn Budget,204	) -> DispatchResultWithPostInfo {205		let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);206		let data = match data {207			CreateItemExData::RefungibleMultipleOwners(CreateRefungibleExMultipleOwners {208				users,209				properties,210			}) => vec![CreateItemData::<T> { users, properties }],211			CreateItemExData::RefungibleMultipleItems(r) => r212				.into_inner()213				.into_iter()214				.map(215					|CreateRefungibleExSingleOwner {216					     user,217					     pieces,218					     properties,219					 }| CreateItemData::<T> {220						users: BTreeMap::from([(user, pieces)])221							.try_into()222							.expect("limit >= 1"),223						properties,224					},225				)226				.collect(),227			_ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),228		};229230		with_weight(231			<Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),232			weight,233		)234	}235236	fn burn_item(237		&self,238		sender: T::CrossAccountId,239		token: TokenId,240		amount: u128,241	) -> DispatchResultWithPostInfo {242		with_weight(243			<Pallet<T>>::burn(self, &sender, token, amount),244			<CommonWeights<T>>::burn_item(),245		)246	}247248	fn transfer(249		&self,250		from: T::CrossAccountId,251		to: T::CrossAccountId,252		token: TokenId,253		amount: u128,254		nesting_budget: &dyn Budget,255	) -> DispatchResultWithPostInfo {256		with_weight(257			<Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),258			<CommonWeights<T>>::transfer(),259		)260	}261262	fn approve(263		&self,264		sender: T::CrossAccountId,265		spender: T::CrossAccountId,266		token: TokenId,267		amount: u128,268	) -> DispatchResultWithPostInfo {269		with_weight(270			<Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),271			<CommonWeights<T>>::approve(),272		)273	}274275	fn approve_from(276		&self,277		sender: T::CrossAccountId,278		from: T::CrossAccountId,279		to: T::CrossAccountId,280		token_id: TokenId,281		amount: u128,282	) -> DispatchResultWithPostInfo {283		with_weight(284			<Pallet<T>>::set_allowance_from(self, &sender, &from, &to, token_id, amount),285			<CommonWeights<T>>::approve_from(),286		)287	}288289	fn transfer_from(290		&self,291		sender: T::CrossAccountId,292		from: T::CrossAccountId,293		to: T::CrossAccountId,294		token: TokenId,295		amount: u128,296		nesting_budget: &dyn Budget,297	) -> DispatchResultWithPostInfo {298		with_weight(299			<Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),300			<CommonWeights<T>>::transfer_from(),301		)302	}303304	fn burn_from(305		&self,306		sender: T::CrossAccountId,307		from: T::CrossAccountId,308		token: TokenId,309		amount: u128,310		nesting_budget: &dyn Budget,311	) -> DispatchResultWithPostInfo {312		with_weight(313			<Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),314			<CommonWeights<T>>::burn_from(),315		)316	}317318	fn set_collection_properties(319		&self,320		sender: T::CrossAccountId,321		properties: Vec<Property>,322	) -> DispatchResultWithPostInfo {323		let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);324325		with_weight(326			<Pallet<T>>::set_collection_properties(self, &sender, properties),327			weight,328		)329	}330331	fn delete_collection_properties(332		&self,333		sender: &T::CrossAccountId,334		property_keys: Vec<PropertyKey>,335	) -> DispatchResultWithPostInfo {336		let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);337338		with_weight(339			<Pallet<T>>::delete_collection_properties(self, sender, property_keys),340			weight,341		)342	}343344	fn set_token_properties(345		&self,346		sender: T::CrossAccountId,347		token_id: TokenId,348		properties: Vec<Property>,349		nesting_budget: &dyn Budget,350	) -> DispatchResultWithPostInfo {351		let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);352353		with_weight(354			<Pallet<T>>::set_token_properties(355				self,356				&sender,357				token_id,358				properties.into_iter(),359				nesting_budget,360			),361			weight,362		)363	}364365	fn set_token_property_permissions(366		&self,367		sender: &T::CrossAccountId,368		property_permissions: Vec<PropertyKeyPermission>,369	) -> DispatchResultWithPostInfo {370		let weight =371			<CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);372373		with_weight(374			<Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),375			weight,376		)377	}378379	fn delete_token_properties(380		&self,381		sender: T::CrossAccountId,382		token_id: TokenId,383		property_keys: Vec<PropertyKey>,384		nesting_budget: &dyn Budget,385	) -> DispatchResultWithPostInfo {386		let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);387388		with_weight(389			<Pallet<T>>::delete_token_properties(390				self,391				&sender,392				token_id,393				property_keys.into_iter(),394				nesting_budget,395			),396			weight,397		)398	}399400	fn get_token_properties_raw(401		&self,402		token_id: TokenId,403	) -> Option<up_data_structs::TokenProperties> {404		<TokenProperties<T>>::get((self.id, token_id))405	}406407	fn set_token_properties_raw(&self, token_id: TokenId, map: up_data_structs::TokenProperties) {408		<TokenProperties<T>>::insert((self.id, token_id), map)409	}410411	fn check_nesting(412		&self,413		_sender: <T>::CrossAccountId,414		_from: (CollectionId, TokenId),415		_under: TokenId,416		_nesting_budget: &dyn Budget,417	) -> sp_runtime::DispatchResult {418		fail!(<Error<T>>::RefungibleDisallowsNesting)419	}420421	fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}422423	fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}424425	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {426		<Owned<T>>::iter_prefix((self.id, account))427			.map(|(id, _)| id)428			.collect()429	}430431	fn collection_tokens(&self) -> Vec<TokenId> {432		<TotalSupply<T>>::iter_prefix((self.id,))433			.map(|(id, _)| id)434			.collect()435	}436437	fn token_exists(&self, token: TokenId) -> bool {438		<Pallet<T>>::token_exists(self, token)439	}440441	fn last_token_id(&self) -> TokenId {442		TokenId(<TokensMinted<T>>::get(self.id))443	}444445	fn token_owner(&self, token: TokenId) -> Result<T::CrossAccountId, TokenOwnerError> {446		<Pallet<T>>::token_owner(self.id, token)447	}448449	fn check_token_indirect_owner(450		&self,451		token: TokenId,452		maybe_owner: &T::CrossAccountId,453		nesting_budget: &dyn Budget,454	) -> Result<bool, DispatchError> {455		let balance = self.balance(maybe_owner.clone(), token);456		let total_pieces: u128 = <Pallet<T>>::total_pieces(self.id, token).unwrap_or(u128::MAX);457		if balance != total_pieces {458			return Ok(false);459		}460461		<PalletStructure<T>>::check_indirectly_owned(462			maybe_owner.clone(),463			self.id,464			token,465			None,466			nesting_budget,467		)468	}469470	/// Returns 10 token in no particular order.471	fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {472		<Pallet<T>>::token_owners(self.id, token).unwrap_or_default()473	}474475	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {476		<Pallet<T>>::token_properties((self.id, token_id))?477			.get(key)478			.cloned()479	}480481	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {482		let Some(properties) = <Pallet<T>>::token_properties((self.id, token_id)) else {483			return vec![];484		};485486		keys.map(|keys| {487			keys.into_iter()488				.filter_map(|key| {489					properties.get(&key).map(|value| Property {490						key,491						value: value.clone(),492					})493				})494				.collect()495		})496		.unwrap_or_else(|| {497			properties498				.into_iter()499				.map(|(key, value)| Property { key, value })500				.collect()501		})502	}503504	fn total_supply(&self) -> u32 {505		<Pallet<T>>::total_supply(self)506	}507508	fn account_balance(&self, account: T::CrossAccountId) -> u32 {509		<AccountBalance<T>>::get((self.id, account))510	}511512	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {513		<Balance<T>>::get((self.id, token, account))514	}515516	fn allowance(517		&self,518		sender: T::CrossAccountId,519		spender: T::CrossAccountId,520		token: TokenId,521	) -> u128 {522		<Allowance<T>>::get((self.id, token, sender, spender))523	}524525	fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {526		Some(self)527	}528529	fn total_pieces(&self, token: TokenId) -> Option<u128> {530		<Pallet<T>>::total_pieces(self.id, token)531	}532533	fn set_allowance_for_all(534		&self,535		owner: T::CrossAccountId,536		operator: T::CrossAccountId,537		approve: bool,538	) -> DispatchResultWithPostInfo {539		with_weight(540			<Pallet<T>>::set_allowance_for_all(self, &owner, &operator, approve),541			<CommonWeights<T>>::set_allowance_for_all(),542		)543	}544545	fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {546		<Pallet<T>>::allowance_for_all(self, &owner, &operator)547	}548549	fn repair_item(&self, token: TokenId) -> DispatchResultWithPostInfo {550		with_weight(551			<Pallet<T>>::repair_item(self, token),552			<CommonWeights<T>>::force_repair_item(),553		)554	}555}556557impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {558	fn repartition(559		&self,560		owner: &T::CrossAccountId,561		token: TokenId,562		amount: u128,563	) -> DispatchResultWithPostInfo {564		with_weight(565			<Pallet<T>>::repartition(self, owner, token, amount),566			<SelfWeightOf<T>>::repartition_item(),567		)568	}569}