1234567891011121314151617use 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,23};24use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};25use sp_runtime::DispatchError;26use sp_std::vec::Vec;2728use crate::{29 AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,30 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,31};3233pub struct CommonWeights<T: Config>(PhantomData<T>);34impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {35 fn create_item() -> Weight {36 <SelfWeightOf<T>>::create_item()37 }3839 fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {40 match data {41 CreateItemExData::NFT(t) => <SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32),42 _ => 0,43 }44 }4546 fn create_multiple_items(amount: u32) -> Weight {47 <SelfWeightOf<T>>::create_multiple_items(amount)48 }4950 fn burn_item() -> Weight {51 <SelfWeightOf<T>>::burn_item()52 }5354 fn set_collection_properties(amount: u32) -> Weight {55 <SelfWeightOf<T>>::set_collection_properties(amount)56 }5758 fn delete_collection_properties(amount: u32) -> Weight {59 <SelfWeightOf<T>>::delete_collection_properties(amount)60 }6162 fn set_token_properties(amount: u32) -> Weight {63 <SelfWeightOf<T>>::set_token_properties(amount)64 }6566 fn delete_token_properties(amount: u32) -> Weight {67 <SelfWeightOf<T>>::delete_token_properties(amount)68 }6970 fn set_property_permissions(amount: u32) -> Weight {71 <SelfWeightOf<T>>::set_property_permissions(amount)72 }7374 fn transfer() -> Weight {75 <SelfWeightOf<T>>::transfer()76 }7778 fn approve() -> Weight {79 <SelfWeightOf<T>>::approve()80 }8182 fn transfer_from() -> Weight {83 <SelfWeightOf<T>>::transfer_from()84 }8586 fn burn_from() -> Weight {87 <SelfWeightOf<T>>::burn_from()88 }89}9091fn map_create_data<T: Config>(92 data: up_data_structs::CreateItemData,93 to: &T::CrossAccountId,94) -> Result<CreateItemData<T>, DispatchError> {95 match data {96 up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {97 const_data: data.const_data,98 properties: data.properties,99 owner: to.clone(),100 }),101 _ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),102 }103}104105impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {106 fn create_item(107 &self,108 sender: T::CrossAccountId,109 to: T::CrossAccountId,110 data: up_data_structs::CreateItemData,111 nesting_budget: &dyn Budget,112 ) -> DispatchResultWithPostInfo {113 with_weight(114 <Pallet<T>>::create_item(115 self,116 &sender,117 map_create_data::<T>(data, &to)?,118 nesting_budget,119 ),120 <CommonWeights<T>>::create_item(),121 )122 }123124 fn create_multiple_items(125 &self,126 sender: T::CrossAccountId,127 to: T::CrossAccountId,128 data: Vec<up_data_structs::CreateItemData>,129 nesting_budget: &dyn Budget,130 ) -> DispatchResultWithPostInfo {131 let data = data132 .into_iter()133 .map(|d| map_create_data::<T>(d, &to))134 .collect::<Result<Vec<_>, DispatchError>>()?;135136 let amount = data.len();137 with_weight(138 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),139 <CommonWeights<T>>::create_multiple_items(amount as u32),140 )141 }142143 fn create_multiple_items_ex(144 &self,145 sender: <T>::CrossAccountId,146 data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,147 nesting_budget: &dyn Budget,148 ) -> DispatchResultWithPostInfo {149 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);150 let data = match data {151 up_data_structs::CreateItemExData::NFT(nft) => nft,152 _ => fail!(Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken),153 };154155 with_weight(156 <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),157 weight,158 )159 }160161 fn set_collection_properties(162 &self,163 sender: T::CrossAccountId,164 properties: Vec<Property>,165 ) -> DispatchResultWithPostInfo {166 let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);167168 with_weight(169 <Pallet<T>>::set_collection_properties(self, &sender, properties),170 weight,171 )172 }173174 fn delete_collection_properties(175 &self,176 sender: &T::CrossAccountId,177 property_keys: Vec<PropertyKey>,178 ) -> DispatchResultWithPostInfo {179 let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);180181 with_weight(182 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),183 weight,184 )185 }186187 fn set_token_properties(188 &self,189 sender: T::CrossAccountId,190 token_id: TokenId,191 properties: Vec<Property>,192 ) -> DispatchResultWithPostInfo {193 let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);194195 with_weight(196 <Pallet<T>>::set_token_properties(self, &sender, token_id, properties),197 weight,198 )199 }200201 fn delete_token_properties(202 &self,203 sender: T::CrossAccountId,204 token_id: TokenId,205 property_keys: Vec<PropertyKey>,206 ) -> DispatchResultWithPostInfo {207 let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);208209 with_weight(210 <Pallet<T>>::delete_token_properties(self, &sender, token_id, property_keys),211 weight,212 )213 }214215 fn set_property_permissions(216 &self,217 sender: &T::CrossAccountId,218 property_permissions: Vec<PropertyKeyPermission>,219 ) -> DispatchResultWithPostInfo {220 let weight =221 <CommonWeights<T>>::set_property_permissions(property_permissions.len() as u32);222223 with_weight(224 <Pallet<T>>::set_property_permissions(self, sender, property_permissions),225 weight,226 )227 }228229 fn burn_item(230 &self,231 sender: T::CrossAccountId,232 token: TokenId,233 amount: u128,234 ) -> DispatchResultWithPostInfo {235 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);236 if amount == 1 {237 with_weight(238 <Pallet<T>>::burn(self, &sender, token),239 <CommonWeights<T>>::burn_item(),240 )241 } else {242 Ok(().into())243 }244 }245246 fn transfer(247 &self,248 from: T::CrossAccountId,249 to: T::CrossAccountId,250 token: TokenId,251 amount: u128,252 nesting_budget: &dyn Budget,253 ) -> DispatchResultWithPostInfo {254 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);255 if amount == 1 {256 with_weight(257 <Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),258 <CommonWeights<T>>::transfer(),259 )260 } else {261 Ok(().into())262 }263 }264265 fn approve(266 &self,267 sender: T::CrossAccountId,268 spender: T::CrossAccountId,269 token: TokenId,270 amount: u128,271 ) -> DispatchResultWithPostInfo {272 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);273274 with_weight(275 if amount == 1 {276 <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))277 } else {278 <Pallet<T>>::set_allowance(self, &sender, token, None)279 },280 <CommonWeights<T>>::approve(),281 )282 }283284 fn transfer_from(285 &self,286 sender: T::CrossAccountId,287 from: T::CrossAccountId,288 to: T::CrossAccountId,289 token: TokenId,290 amount: u128,291 nesting_budget: &dyn Budget,292 ) -> DispatchResultWithPostInfo {293 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);294295 if amount == 1 {296 with_weight(297 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, nesting_budget),298 <CommonWeights<T>>::transfer_from(),299 )300 } else {301 Ok(().into())302 }303 }304305 fn burn_from(306 &self,307 sender: T::CrossAccountId,308 from: T::CrossAccountId,309 token: TokenId,310 amount: u128,311 nesting_budget: &dyn Budget,312 ) -> DispatchResultWithPostInfo {313 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);314315 if amount == 1 {316 with_weight(317 <Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),318 <CommonWeights<T>>::burn_from(),319 )320 } else {321 Ok(().into())322 }323 }324325 fn check_nesting(326 &self,327 sender: T::CrossAccountId,328 from: (CollectionId, TokenId),329 under: TokenId,330 budget: &dyn Budget,331 ) -> sp_runtime::DispatchResult {332 <Pallet<T>>::check_nesting(self, sender, from, under, budget)333 }334335 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {336 <Owned<T>>::iter_prefix((self.id, account))337 .map(|(id, _)| id)338 .collect()339 }340341 fn collection_tokens(&self) -> Vec<TokenId> {342 <TokenData<T>>::iter_prefix((self.id,))343 .map(|(id, _)| id)344 .collect()345 }346347 fn token_exists(&self, token: TokenId) -> bool {348 <Pallet<T>>::token_exists(self, token)349 }350351 fn last_token_id(&self) -> TokenId {352 TokenId(<TokensMinted<T>>::get(self.id))353 }354355 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {356 <TokenData<T>>::get((self.id, token)).map(|t| t.owner)357 }358 fn const_metadata(&self, token: TokenId) -> Vec<u8> {359 <TokenData<T>>::get((self.id, token))360 .map(|t| t.const_data)361 .unwrap_or_default()362 .into_inner()363 }364365 fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {366 let properties = <Pallet<T>>::token_properties((self.id, token_id));367368 keys.map(|keys| {369 keys.into_iter()370 .filter_map(|key| {371 properties.get(&key).map(|value| Property {372 key,373 value: value.clone(),374 })375 })376 .collect()377 })378 .unwrap_or_else(|| {379 properties380 .iter()381 .map(|(key, value)| Property {382 key: key.clone(),383 value: value.clone(),384 })385 .collect()386 })387 }388389 fn total_supply(&self) -> u32 {390 <Pallet<T>>::total_supply(self)391 }392393 fn account_balance(&self, account: T::CrossAccountId) -> u32 {394 <AccountBalance<T>>::get((self.id, account))395 }396397 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {398 if <TokenData<T>>::get((self.id, token))399 .map(|a| a.owner == account)400 .unwrap_or(false)401 {402 1403 } else {404 0405 }406 }407408 fn allowance(409 &self,410 sender: T::CrossAccountId,411 spender: T::CrossAccountId,412 token: TokenId,413 ) -> u128 {414 if <TokenData<T>>::get((self.id, token))415 .map(|a| a.owner != sender)416 .unwrap_or(true)417 {418 0419 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {420 1421 } else {422 0423 }424 }425}