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

difftreelog

source

pallets/refungible/src/common.rs14.9 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		mint_with_props_weight::<T>(51			<SelfWeightOf<T>>::create_multiple_items(data.len() as u32),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		)59	}6061	fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {62		match call {63			CreateItemExData::RefungibleMultipleOwners(i) => mint_with_props_weight::<T>(64				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32),65				[i.properties.len() as u32].into_iter(),66			),67			CreateItemExData::RefungibleMultipleItems(i) => mint_with_props_weight::<T>(68				<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32),69				i.iter().map(|d| d.properties.len() as u32),70			),71			_ => Weight::zero(),72		}73	}7475	fn burn_item() -> Weight {76		max_weight_of!(burn_item_partial(), burn_item_fully())77	}7879	fn set_collection_properties(amount: u32) -> Weight {80		<pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)81	}8283	fn set_token_properties(amount: u32) -> Weight {84		write_token_properties_total_weight::<T, _>([amount].into_iter(), |amount| {85			<SelfWeightOf<T>>::load_token_properties()86				.saturating_add(<SelfWeightOf<T>>::write_token_properties(amount))87		})88	}8990	fn set_token_property_permissions(amount: u32) -> Weight {91		<SelfWeightOf<T>>::set_token_property_permissions(amount)92	}9394	fn transfer() -> Weight {95		max_weight_of!(96			transfer_normal(),97			transfer_creating(),98			transfer_removing(),99			transfer_creating_removing()100		)101	}102103	fn approve() -> Weight {104		<SelfWeightOf<T>>::approve()105	}106107	fn approve_from() -> Weight {108		<SelfWeightOf<T>>::approve_from()109	}110111	fn transfer_from() -> Weight {112		max_weight_of!(113			transfer_from_normal(),114			transfer_from_creating(),115			transfer_from_removing(),116			transfer_from_creating_removing()117		)118	}119120	fn burn_from() -> Weight {121		<SelfWeightOf<T>>::burn_from()122	}123124	fn set_allowance_for_all() -> Weight {125		<SelfWeightOf<T>>::set_allowance_for_all()126	}127128	fn force_repair_item() -> Weight {129		<SelfWeightOf<T>>::repair_item()130	}131}132133/// Weight of minting tokens with properties134/// * `create_no_data_weight` -- the weight of minting without properties135/// * `token_properties_nums` -- number of properties of each token136#[inline]137pub(crate) fn mint_with_props_weight<T: Config>(138	create_no_data_weight: Weight,139	token_properties_nums: impl Iterator<Item = u32> + Clone,140) -> Weight {141	create_no_data_weight.saturating_add(write_token_properties_total_weight::<T, _>(142		token_properties_nums,143		<SelfWeightOf<T>>::write_token_properties,144	))145}146147fn map_create_data<T: Config>(148	data: up_data_structs::CreateItemData,149	to: &T::CrossAccountId,150) -> Result<CreateItemData<T>, DispatchError> {151	match data {152		up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData::<T> {153			users: {154				let mut out = BTreeMap::new();155				out.insert(to.clone(), data.pieces);156				out.try_into().expect("limit > 0")157			},158			properties: data.properties,159		}),160		_ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),161	}162}163164/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete165/// methods and adds weight info.166impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {167	fn create_item(168		&self,169		sender: T::CrossAccountId,170		to: T::CrossAccountId,171		data: up_data_structs::CreateItemData,172		nesting_budget: &dyn Budget,173	) -> DispatchResultWithPostInfo {174		let weight = <CommonWeights<T>>::create_item(&data);175		with_weight(176			<Pallet<T>>::create_item(177				self,178				&sender,179				map_create_data::<T>(data, &to)?,180				nesting_budget,181			),182			weight,183		)184	}185186	fn create_multiple_items(187		&self,188		sender: T::CrossAccountId,189		to: T::CrossAccountId,190		data: Vec<up_data_structs::CreateItemData>,191		nesting_budget: &dyn Budget,192	) -> DispatchResultWithPostInfo {193		let weight = <CommonWeights<T>>::create_multiple_items(&data);194		let data = data195			.into_iter()196			.map(|d| map_create_data::<T>(d, &to))197			.collect::<Result<Vec<_>, DispatchError>>()?;198199		with_weight(200			<Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),201			weight,202		)203	}204205	fn create_multiple_items_ex(206		&self,207		sender: <T>::CrossAccountId,208		data: CreateItemExData<T::CrossAccountId>,209		nesting_budget: &dyn Budget,210	) -> DispatchResultWithPostInfo {211		let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);212		let data = match data {213			CreateItemExData::RefungibleMultipleOwners(CreateRefungibleExMultipleOwners {214				users,215				properties,216			}) => vec![CreateItemData::<T> { users, properties }],217			CreateItemExData::RefungibleMultipleItems(r) => r218				.into_inner()219				.into_iter()220				.map(221					|CreateRefungibleExSingleOwner {222					     user,223					     pieces,224					     properties,225					 }| CreateItemData::<T> {226						users: BTreeMap::from([(user, pieces)])227							.try_into()228							.expect("limit >= 1"),229						properties,230					},231				)232				.collect(),233			_ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),234		};235236		with_weight(237			<Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),238			weight,239		)240	}241242	fn burn_item(243		&self,244		sender: T::CrossAccountId,245		token: TokenId,246		amount: u128,247	) -> DispatchResultWithPostInfo {248		with_weight(249			<Pallet<T>>::burn(self, &sender, token, amount),250			<CommonWeights<T>>::burn_item(),251		)252	}253254	fn transfer(255		&self,256		from: T::CrossAccountId,257		to: T::CrossAccountId,258		token: TokenId,259		amount: u128,260		nesting_budget: &dyn Budget,261	) -> DispatchResultWithPostInfo {262		with_weight(263			<Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),264			<CommonWeights<T>>::transfer(),265		)266	}267268	fn approve(269		&self,270		sender: T::CrossAccountId,271		spender: T::CrossAccountId,272		token: TokenId,273		amount: u128,274	) -> DispatchResultWithPostInfo {275		with_weight(276			<Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),277			<CommonWeights<T>>::approve(),278		)279	}280281	fn approve_from(282		&self,283		sender: T::CrossAccountId,284		from: T::CrossAccountId,285		to: T::CrossAccountId,286		token_id: TokenId,287		amount: u128,288	) -> DispatchResultWithPostInfo {289		with_weight(290			<Pallet<T>>::set_allowance_from(self, &sender, &from, &to, token_id, amount),291			<CommonWeights<T>>::approve_from(),292		)293	}294295	fn transfer_from(296		&self,297		sender: T::CrossAccountId,298		from: T::CrossAccountId,299		to: T::CrossAccountId,300		token: TokenId,301		amount: u128,302		nesting_budget: &dyn Budget,303	) -> DispatchResultWithPostInfo {304		with_weight(305			<Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),306			<CommonWeights<T>>::transfer_from(),307		)308	}309310	fn burn_from(311		&self,312		sender: T::CrossAccountId,313		from: T::CrossAccountId,314		token: TokenId,315		amount: u128,316		nesting_budget: &dyn Budget,317	) -> DispatchResultWithPostInfo {318		with_weight(319			<Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),320			<CommonWeights<T>>::burn_from(),321		)322	}323324	fn set_collection_properties(325		&self,326		sender: T::CrossAccountId,327		properties: Vec<Property>,328	) -> DispatchResultWithPostInfo {329		let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);330331		with_weight(332			<Pallet<T>>::set_collection_properties(self, &sender, properties),333			weight,334		)335	}336337	fn delete_collection_properties(338		&self,339		sender: &T::CrossAccountId,340		property_keys: Vec<PropertyKey>,341	) -> DispatchResultWithPostInfo {342		let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);343344		with_weight(345			<Pallet<T>>::delete_collection_properties(self, sender, property_keys),346			weight,347		)348	}349350	fn set_token_properties(351		&self,352		sender: T::CrossAccountId,353		token_id: TokenId,354		properties: Vec<Property>,355		nesting_budget: &dyn Budget,356	) -> DispatchResultWithPostInfo {357		let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);358359		with_weight(360			<Pallet<T>>::set_token_properties(361				self,362				&sender,363				token_id,364				properties.into_iter(),365				nesting_budget,366			),367			weight,368		)369	}370371	fn set_token_property_permissions(372		&self,373		sender: &T::CrossAccountId,374		property_permissions: Vec<PropertyKeyPermission>,375	) -> DispatchResultWithPostInfo {376		let weight =377			<CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);378379		with_weight(380			<Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),381			weight,382		)383	}384385	fn delete_token_properties(386		&self,387		sender: T::CrossAccountId,388		token_id: TokenId,389		property_keys: Vec<PropertyKey>,390		nesting_budget: &dyn Budget,391	) -> DispatchResultWithPostInfo {392		let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);393394		with_weight(395			<Pallet<T>>::delete_token_properties(396				self,397				&sender,398				token_id,399				property_keys.into_iter(),400				nesting_budget,401			),402			weight,403		)404	}405406	fn get_token_properties_raw(407		&self,408		token_id: TokenId,409	) -> Option<up_data_structs::TokenProperties> {410		<TokenProperties<T>>::get((self.id, token_id))411	}412413	fn set_token_properties_raw(&self, token_id: TokenId, map: up_data_structs::TokenProperties) {414		<TokenProperties<T>>::insert((self.id, token_id), map)415	}416417	fn check_nesting(418		&self,419		_sender: &<T>::CrossAccountId,420		_from: (CollectionId, TokenId),421		_under: TokenId,422		_nesting_budget: &dyn Budget,423	) -> sp_runtime::DispatchResult {424		fail!(<Error<T>>::RefungibleDisallowsNesting)425	}426427	fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}428429	fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}430431	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {432		<Owned<T>>::iter_prefix((self.id, account))433			.map(|(id, _)| id)434			.collect()435	}436437	fn collection_tokens(&self) -> Vec<TokenId> {438		<TotalSupply<T>>::iter_prefix((self.id,))439			.map(|(id, _)| id)440			.collect()441	}442443	fn token_exists(&self, token: TokenId) -> bool {444		<Pallet<T>>::token_exists(self, token)445	}446447	fn last_token_id(&self) -> TokenId {448		TokenId(<TokensMinted<T>>::get(self.id))449	}450451	fn token_owner(&self, token: TokenId) -> Result<T::CrossAccountId, TokenOwnerError> {452		<Pallet<T>>::token_owner(self.id, token)453	}454455	fn check_token_indirect_owner(456		&self,457		token: TokenId,458		maybe_owner: &T::CrossAccountId,459		nesting_budget: &dyn Budget,460	) -> Result<bool, DispatchError> {461		let balance = self.balance(maybe_owner.clone(), token);462		let total_pieces: u128 = <Pallet<T>>::total_pieces(self.id, token).unwrap_or(u128::MAX);463		if balance != total_pieces {464			return Ok(false);465		}466467		<PalletStructure<T>>::check_indirectly_owned(468			maybe_owner.clone(),469			self.id,470			token,471			None,472			nesting_budget,473		)474	}475476	/// Returns 10 token in no particular order.477	fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {478		<Pallet<T>>::token_owners(self.id, token).unwrap_or_default()479	}480481	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {482		<Pallet<T>>::token_properties((self.id, token_id))?483			.get(key)484			.cloned()485	}486487	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {488		let Some(properties) = <Pallet<T>>::token_properties((self.id, token_id)) else {489			return vec![];490		};491492		keys.map(|keys| {493			keys.into_iter()494				.filter_map(|key| {495					properties.get(&key).map(|value| Property {496						key,497						value: value.clone(),498					})499				})500				.collect()501		})502		.unwrap_or_else(|| {503			properties504				.into_iter()505				.map(|(key, value)| Property { key, value })506				.collect()507		})508	}509510	fn total_supply(&self) -> u32 {511		<Pallet<T>>::total_supply(self)512	}513514	fn account_balance(&self, account: T::CrossAccountId) -> u32 {515		<AccountBalance<T>>::get((self.id, account))516	}517518	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {519		<Balance<T>>::get((self.id, token, account))520	}521522	fn allowance(523		&self,524		sender: T::CrossAccountId,525		spender: T::CrossAccountId,526		token: TokenId,527	) -> u128 {528		<Allowance<T>>::get((self.id, token, sender, spender))529	}530531	fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {532		Some(self)533	}534535	fn total_pieces(&self, token: TokenId) -> Option<u128> {536		<Pallet<T>>::total_pieces(self.id, token)537	}538539	fn set_allowance_for_all(540		&self,541		owner: T::CrossAccountId,542		operator: T::CrossAccountId,543		approve: bool,544	) -> DispatchResultWithPostInfo {545		with_weight(546			<Pallet<T>>::set_allowance_for_all(self, &owner, &operator, approve),547			<CommonWeights<T>>::set_allowance_for_all(),548		)549	}550551	fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {552		<Pallet<T>>::allowance_for_all(self, &owner, &operator)553	}554555	fn repair_item(&self, token: TokenId) -> DispatchResultWithPostInfo {556		with_weight(557			<Pallet<T>>::repair_item(self, token),558			<CommonWeights<T>>::force_repair_item(),559		)560	}561}562563impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {564	fn repartition(565		&self,566		owner: &T::CrossAccountId,567		token: TokenId,568		amount: u128,569	) -> DispatchResultWithPostInfo {570		with_weight(571			<Pallet<T>>::repartition(self, owner, token, amount),572			<SelfWeightOf<T>>::repartition_item(),573		)574	}575}