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::{26 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,27 weights::WeightInfo as _,28};29use pallet_structure::Error as StructureError;30use sp_runtime::{DispatchError};31use sp_std::{vec::Vec, vec};3233use crate::{34 AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle,35 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,36};3738macro_rules! max_weight_of {39 ($($method:ident ($($args:tt)*)),*) => {40 041 $(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_item() -> Weight {50 <SelfWeightOf<T>>::create_item()51 }5253 fn create_multiple_items(data: &[CreateItemData]) -> Weight {54 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32)55 }5657 fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {58 match call {59 CreateItemExData::RefungibleMultipleOwners(i) => {60 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)61 }62 CreateItemExData::RefungibleMultipleItems(i) => {63 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)64 }65 _ => 0,66 }67 }6869 fn burn_item() -> Weight {70 max_weight_of!(burn_item_partial(), burn_item_fully())71 }7273 fn set_collection_properties(amount: u32) -> Weight {74 <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)75 }7677 fn delete_collection_properties(amount: u32) -> Weight {78 <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)79 }8081 fn set_token_properties(amount: u32) -> Weight {82 <SelfWeightOf<T>>::set_token_properties(amount)83 }8485 fn delete_token_properties(amount: u32) -> Weight {86 <SelfWeightOf<T>>::delete_token_properties(amount)87 }8889 fn set_token_property_permissions(amount: u32) -> Weight {90 <SelfWeightOf<T>>::set_token_property_permissions(amount)91 }9293 fn transfer() -> Weight {94 max_weight_of!(95 transfer_normal(),96 transfer_creating(),97 transfer_removing(),98 transfer_creating_removing()99 )100 }101102 fn approve() -> Weight {103 <SelfWeightOf<T>>::approve()104 }105106 fn transfer_from() -> Weight {107 max_weight_of!(108 transfer_from_normal(),109 transfer_from_creating(),110 transfer_from_removing(),111 transfer_from_creating_removing()112 )113 }114115 fn burn_from() -> Weight {116 <SelfWeightOf<T>>::burn_from()117 }118119 fn burn_recursively_self_raw() -> Weight {120 121 Self::burn_item() + T::DbWeight::get().reads(1)122 }123 fn burn_recursively_breadth_raw(_amount: u32) -> Weight {124 125 0126 }127}128129fn map_create_data<T: Config>(130 data: up_data_structs::CreateItemData,131 to: &T::CrossAccountId,132) -> Result<CreateRefungibleExData<T::CrossAccountId>, DispatchError> {133 match data {134 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {135 const_data: data.const_data,136 users: {137 let mut out = BTreeMap::new();138 out.insert(to.clone(), data.pieces);139 out.try_into().expect("limit > 0")140 },141 properties: data.properties,142 }),143 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),144 }145}146147148149impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {150 fn create_item(151 &self,152 sender: T::CrossAccountId,153 to: T::CrossAccountId,154 data: up_data_structs::CreateItemData,155 nesting_budget: &dyn Budget,156 ) -> DispatchResultWithPostInfo {157 with_weight(158 <Pallet<T>>::create_item(159 self,160 &sender,161 map_create_data::<T>(data, &to)?,162 nesting_budget,163 ),164 <CommonWeights<T>>::create_item(),165 )166 }167168 fn create_multiple_items(169 &self,170 sender: T::CrossAccountId,171 to: T::CrossAccountId,172 data: Vec<up_data_structs::CreateItemData>,173 nesting_budget: &dyn Budget,174 ) -> DispatchResultWithPostInfo {175 let weight = <CommonWeights<T>>::create_multiple_items(&data);176 let data = data177 .into_iter()178 .map(|d| map_create_data::<T>(d, &to))179 .collect::<Result<Vec<_>, DispatchError>>()?;180181 with_weight(182 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),183 weight,184 )185 }186187 fn create_multiple_items_ex(188 &self,189 sender: <T>::CrossAccountId,190 data: CreateItemExData<T::CrossAccountId>,191 nesting_budget: &dyn Budget,192 ) -> DispatchResultWithPostInfo {193 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);194 let data = match data {195 CreateItemExData::RefungibleMultipleOwners(r) => vec![r],196 CreateItemExData::RefungibleMultipleItems(r)197 if r.iter().all(|i| i.users.len() == 1) =>198 {199 r.into_inner()200 }201 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),202 };203204 with_weight(205 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),206 weight,207 )208 }209210 fn burn_item(211 &self,212 sender: T::CrossAccountId,213 token: TokenId,214 amount: u128,215 ) -> DispatchResultWithPostInfo {216 with_weight(217 <Pallet<T>>::burn(self, &sender, token, amount),218 <CommonWeights<T>>::burn_item(),219 )220 }221222 fn burn_item_recursively(223 &self,224 sender: T::CrossAccountId,225 token: TokenId,226 self_budget: &dyn Budget,227 _breadth_budget: &dyn Budget,228 ) -> DispatchResultWithPostInfo {229 ensure!(self_budget.consume(), <StructureError<T>>::DepthLimit,);230 with_weight(231 <Pallet<T>>::burn(232 self,233 &sender,234 token,235 <Balance<T>>::get((self.id, token, &sender)),236 ),237 <CommonWeights<T>>::burn_recursively_self_raw(),238 )239 }240241 fn transfer(242 &self,243 from: T::CrossAccountId,244 to: T::CrossAccountId,245 token: TokenId,246 amount: u128,247 nesting_budget: &dyn Budget,248 ) -> DispatchResultWithPostInfo {249 with_weight(250 <Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),251 <CommonWeights<T>>::transfer(),252 )253 }254255 fn approve(256 &self,257 sender: T::CrossAccountId,258 spender: T::CrossAccountId,259 token: TokenId,260 amount: u128,261 ) -> DispatchResultWithPostInfo {262 with_weight(263 <Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),264 <CommonWeights<T>>::approve(),265 )266 }267268 fn transfer_from(269 &self,270 sender: T::CrossAccountId,271 from: T::CrossAccountId,272 to: T::CrossAccountId,273 token: TokenId,274 amount: u128,275 nesting_budget: &dyn Budget,276 ) -> DispatchResultWithPostInfo {277 with_weight(278 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),279 <CommonWeights<T>>::transfer_from(),280 )281 }282283 fn burn_from(284 &self,285 sender: T::CrossAccountId,286 from: T::CrossAccountId,287 token: TokenId,288 amount: u128,289 nesting_budget: &dyn Budget,290 ) -> DispatchResultWithPostInfo {291 with_weight(292 <Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),293 <CommonWeights<T>>::burn_from(),294 )295 }296297 fn set_collection_properties(298 &self,299 sender: T::CrossAccountId,300 properties: Vec<Property>,301 ) -> DispatchResultWithPostInfo {302 let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);303304 with_weight(305 <Pallet<T>>::set_collection_properties(self, &sender, properties),306 weight,307 )308 }309310 fn delete_collection_properties(311 &self,312 sender: &T::CrossAccountId,313 property_keys: Vec<PropertyKey>,314 ) -> DispatchResultWithPostInfo {315 let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);316317 with_weight(318 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),319 weight,320 )321 }322323 fn set_token_properties(324 &self,325 sender: T::CrossAccountId,326 token_id: TokenId,327 properties: Vec<Property>,328 nesting_budget: &dyn Budget,329 ) -> DispatchResultWithPostInfo {330 let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);331332 with_weight(333 <Pallet<T>>::set_token_properties(334 self,335 &sender,336 token_id,337 properties.into_iter(),338 false,339 nesting_budget,340 ),341 weight,342 )343 }344345 fn set_token_property_permissions(346 &self,347 sender: &T::CrossAccountId,348 property_permissions: Vec<PropertyKeyPermission>,349 ) -> DispatchResultWithPostInfo {350 let weight =351 <CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);352353 with_weight(354 <Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),355 weight,356 )357 }358359 fn delete_token_properties(360 &self,361 sender: T::CrossAccountId,362 token_id: TokenId,363 property_keys: Vec<PropertyKey>,364 nesting_budget: &dyn Budget,365 ) -> DispatchResultWithPostInfo {366 let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);367368 with_weight(369 <Pallet<T>>::delete_token_properties(370 self,371 &sender,372 token_id,373 property_keys.into_iter(),374 nesting_budget,375 ),376 weight,377 )378 }379380 fn check_nesting(381 &self,382 _sender: <T>::CrossAccountId,383 _from: (CollectionId, TokenId),384 _under: TokenId,385 _nesting_budget: &dyn Budget,386 ) -> sp_runtime::DispatchResult {387 fail!(<Error<T>>::RefungibleDisallowsNesting)388 }389390 fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}391392 fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}393394 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {395 <Owned<T>>::iter_prefix((self.id, account))396 .map(|(id, _)| id)397 .collect()398 }399400 fn collection_tokens(&self) -> Vec<TokenId> {401 <TokenData<T>>::iter_prefix((self.id,))402 .map(|(id, _)| id)403 .collect()404 }405406 fn token_exists(&self, token: TokenId) -> bool {407 <Pallet<T>>::token_exists(self, token)408 }409410 fn last_token_id(&self) -> TokenId {411 TokenId(<TokensMinted<T>>::get(self.id))412 }413414 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {415 <Pallet<T>>::token_owner(self.id, token)416 }417418 fn token_property(&self, _token_id: TokenId, _key: &PropertyKey) -> Option<PropertyValue> {419 None420 }421422 fn token_properties(423 &self,424 _token_id: TokenId,425 _keys: Option<Vec<PropertyKey>>,426 ) -> Vec<Property> {427 Vec::new()428 }429430 fn total_supply(&self) -> u32 {431 <Pallet<T>>::total_supply(self)432 }433434 fn account_balance(&self, account: T::CrossAccountId) -> u32 {435 <AccountBalance<T>>::get((self.id, account))436 }437438 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {439 <Balance<T>>::get((self.id, token, account))440 }441442 fn allowance(443 &self,444 sender: T::CrossAccountId,445 spender: T::CrossAccountId,446 token: TokenId,447 ) -> u128 {448 <Allowance<T>>::get((self.id, token, sender, spender))449 }450451 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {452 Some(self)453 }454455 fn total_pieces(&self, token: TokenId) -> Option<u128> {456 <Pallet<T>>::total_pieces(self.id, token)457 }458}459460impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {461 fn repartition(462 &self,463 owner: &T::CrossAccountId,464 token: TokenId,465 amount: u128,466 ) -> DispatchResultWithPostInfo {467 with_weight(468 <Pallet<T>>::repartition(self, owner, token, amount),469 <SelfWeightOf<T>>::repartition_item(),470 )471 }472}