1234567891011121314151617use core::marker::PhantomData;1819use sp_std::collections::btree_map::BTreeMap;20use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};21use up_data_structs::{22 CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,23 PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData,24};25use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};26use pallet_structure::Error as StructureError;27use sp_runtime::DispatchError;28use sp_std::{vec::Vec, vec};2930use crate::{31 AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle,32 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,33};3435macro_rules! max_weight_of {36 ($($method:ident ($($args:tt)*)),*) => {37 038 $(39 .max(<SelfWeightOf<T>>::$method($($args)*))40 )*41 };42}4344pub struct CommonWeights<T: Config>(PhantomData<T>);45impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {46 fn create_item() -> Weight {47 <SelfWeightOf<T>>::create_item()48 }4950 fn create_multiple_items(data: &[CreateItemData]) -> Weight {51 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32)52 }5354 fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {55 match call {56 CreateItemExData::RefungibleMultipleOwners(i) => {57 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)58 }59 CreateItemExData::RefungibleMultipleItems(i) => {60 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)61 }62 _ => 0,63 }64 }6566 fn burn_item() -> Weight {67 max_weight_of!(burn_item_partial(), burn_item_fully())68 }6970 fn set_collection_properties(_amount: u32) -> Weight {71 72 073 }7475 fn delete_collection_properties(_amount: u32) -> Weight {76 77 078 }7980 fn set_token_properties(amount: u32) -> Weight {81 <SelfWeightOf<T>>::set_token_properties(amount)82 }8384 fn delete_token_properties(amount: u32) -> Weight {85 <SelfWeightOf<T>>::delete_token_properties(amount)86 }8788 fn set_property_permissions(amount: u32) -> Weight {89 <SelfWeightOf<T>>::set_property_permissions(amount)90 }9192 fn transfer() -> Weight {93 max_weight_of!(94 transfer_normal(),95 transfer_creating(),96 transfer_removing(),97 transfer_creating_removing()98 )99 }100101 fn approve() -> Weight {102 <SelfWeightOf<T>>::approve()103 }104105 fn transfer_from() -> Weight {106 max_weight_of!(107 transfer_from_normal(),108 transfer_from_creating(),109 transfer_from_removing(),110 transfer_from_creating_removing()111 )112 }113114 fn burn_from() -> Weight {115 <SelfWeightOf<T>>::burn_from()116 }117118 fn burn_recursively_self_raw() -> Weight {119 120 Self::burn_item() + T::DbWeight::get().reads(1)121 }122 fn burn_recursively_breadth_raw(_amount: u32) -> Weight {123 124 0125 }126}127128fn map_create_data<T: Config>(129 data: up_data_structs::CreateItemData,130 to: &T::CrossAccountId,131) -> Result<CreateRefungibleExData<T::CrossAccountId>, DispatchError> {132 match data {133 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {134 const_data: data.const_data,135 users: {136 let mut out = BTreeMap::new();137 out.insert(to.clone(), data.pieces);138 out.try_into().expect("limit > 0")139 },140 }),141 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),142 }143}144145impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {146 fn create_item(147 &self,148 sender: T::CrossAccountId,149 to: T::CrossAccountId,150 data: up_data_structs::CreateItemData,151 nesting_budget: &dyn Budget,152 ) -> DispatchResultWithPostInfo {153 with_weight(154 <Pallet<T>>::create_item(155 self,156 &sender,157 map_create_data::<T>(data, &to)?,158 nesting_budget,159 ),160 <CommonWeights<T>>::create_item(),161 )162 }163164 fn create_multiple_items(165 &self,166 sender: T::CrossAccountId,167 to: T::CrossAccountId,168 data: Vec<up_data_structs::CreateItemData>,169 nesting_budget: &dyn Budget,170 ) -> DispatchResultWithPostInfo {171 let weight = <CommonWeights<T>>::create_multiple_items(&data);172 let data = data173 .into_iter()174 .map(|d| map_create_data::<T>(d, &to))175 .collect::<Result<Vec<_>, DispatchError>>()?;176177 with_weight(178 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),179 weight,180 )181 }182183 fn create_multiple_items_ex(184 &self,185 sender: <T>::CrossAccountId,186 data: CreateItemExData<T::CrossAccountId>,187 nesting_budget: &dyn Budget,188 ) -> DispatchResultWithPostInfo {189 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);190 let data = match data {191 CreateItemExData::RefungibleMultipleOwners(r) => vec![r],192 CreateItemExData::RefungibleMultipleItems(r)193 if r.iter().all(|i| i.users.len() == 1) =>194 {195 r.into_inner()196 }197 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),198 };199200 with_weight(201 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),202 weight,203 )204 }205206 fn burn_item(207 &self,208 sender: T::CrossAccountId,209 token: TokenId,210 amount: u128,211 ) -> DispatchResultWithPostInfo {212 with_weight(213 <Pallet<T>>::burn(self, &sender, token, amount),214 <CommonWeights<T>>::burn_item(),215 )216 }217218 fn burn_item_recursively(219 &self,220 sender: T::CrossAccountId,221 token: TokenId,222 self_budget: &dyn Budget,223 _breadth_budget: &dyn Budget,224 ) -> DispatchResultWithPostInfo {225 ensure!(self_budget.consume(), <StructureError<T>>::DepthLimit,);226 with_weight(227 <Pallet<T>>::burn(228 self,229 &sender,230 token,231 <Balance<T>>::get((self.id, token, &sender)),232 ),233 <CommonWeights<T>>::burn_recursively_self_raw(),234 )235 }236237 fn transfer(238 &self,239 from: T::CrossAccountId,240 to: T::CrossAccountId,241 token: TokenId,242 amount: u128,243 nesting_budget: &dyn Budget,244 ) -> DispatchResultWithPostInfo {245 with_weight(246 <Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),247 <CommonWeights<T>>::transfer(),248 )249 }250251 fn approve(252 &self,253 sender: T::CrossAccountId,254 spender: T::CrossAccountId,255 token: TokenId,256 amount: u128,257 _nesting_budget: &dyn Budget,258 ) -> DispatchResultWithPostInfo {259 with_weight(260 <Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),261 <CommonWeights<T>>::approve(),262 )263 }264265 fn transfer_from(266 &self,267 sender: T::CrossAccountId,268 from: T::CrossAccountId,269 to: T::CrossAccountId,270 token: TokenId,271 amount: u128,272 nesting_budget: &dyn Budget,273 ) -> DispatchResultWithPostInfo {274 with_weight(275 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),276 <CommonWeights<T>>::transfer_from(),277 )278 }279280 fn burn_from(281 &self,282 sender: T::CrossAccountId,283 from: T::CrossAccountId,284 token: TokenId,285 amount: u128,286 nesting_budget: &dyn Budget,287 ) -> DispatchResultWithPostInfo {288 with_weight(289 <Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),290 <CommonWeights<T>>::burn_from(),291 )292 }293294 fn set_collection_properties(295 &self,296 _sender: T::CrossAccountId,297 _property: Vec<Property>,298 ) -> DispatchResultWithPostInfo {299 fail!(<Error<T>>::SettingPropertiesNotAllowed)300 }301302 fn delete_collection_properties(303 &self,304 _sender: &T::CrossAccountId,305 _property_keys: Vec<PropertyKey>,306 ) -> DispatchResultWithPostInfo {307 fail!(<Error<T>>::SettingPropertiesNotAllowed)308 }309310 fn set_token_properties(311 &self,312 _sender: T::CrossAccountId,313 _token_id: TokenId,314 _property: Vec<Property>,315 ) -> DispatchResultWithPostInfo {316 fail!(<Error<T>>::SettingPropertiesNotAllowed)317 }318319 fn set_property_permissions(320 &self,321 _sender: &T::CrossAccountId,322 _property_permissions: Vec<PropertyKeyPermission>,323 ) -> DispatchResultWithPostInfo {324 fail!(<Error<T>>::SettingPropertiesNotAllowed)325 }326327 fn delete_token_properties(328 &self,329 _sender: T::CrossAccountId,330 _token_id: TokenId,331 _property_keys: Vec<PropertyKey>,332 ) -> DispatchResultWithPostInfo {333 fail!(<Error<T>>::SettingPropertiesNotAllowed)334 }335336 fn check_nesting(337 &self,338 _sender: <T>::CrossAccountId,339 _from: (CollectionId, TokenId),340 _under: TokenId,341 _budget: &dyn Budget,342 ) -> sp_runtime::DispatchResult {343 fail!(<Error<T>>::RefungibleDisallowsNesting)344 }345346 fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}347348 fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}349350 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {351 <Owned<T>>::iter_prefix((self.id, account))352 .map(|(id, _)| id)353 .collect()354 }355356 fn collection_tokens(&self) -> Vec<TokenId> {357 <TokenData<T>>::iter_prefix((self.id,))358 .map(|(id, _)| id)359 .collect()360 }361362 fn token_exists(&self, token: TokenId) -> bool {363 <Pallet<T>>::token_exists(self, token)364 }365366 fn last_token_id(&self) -> TokenId {367 TokenId(<TokensMinted<T>>::get(self.id))368 }369370 fn token_owner(&self, _token: TokenId) -> Option<T::CrossAccountId> {371 None372 }373374 fn token_property(&self, _token_id: TokenId, _key: &PropertyKey) -> Option<PropertyValue> {375 None376 }377378 fn token_properties(379 &self,380 _token_id: TokenId,381 _keys: Option<Vec<PropertyKey>>,382 ) -> Vec<Property> {383 Vec::new()384 }385386 fn total_supply(&self) -> u32 {387 <Pallet<T>>::total_supply(self)388 }389390 fn account_balance(&self, account: T::CrossAccountId) -> u32 {391 <AccountBalance<T>>::get((self.id, account))392 }393394 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {395 <Balance<T>>::get((self.id, token, account))396 }397398 fn allowance(399 &self,400 sender: T::CrossAccountId,401 spender: T::CrossAccountId,402 token: TokenId,403 ) -> u128 {404 <Allowance<T>>::get((self.id, token, sender, spender))405 }406}