1234567891011121314151617use core::marker::PhantomData;1819use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};20use up_data_structs::{21 TokenId, CustomDataLimit, CreateItemExData, CollectionId, budget::Budget, Property, PropertyKeyPermission,22};23use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};24use sp_runtime::DispatchError;25use sp_std::vec::Vec;2627use crate::{28 AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,29 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,30};3132pub struct CommonWeights<T: Config>(PhantomData<T>);33impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {34 fn create_item() -> Weight {35 <SelfWeightOf<T>>::create_item()36 }3738 fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {39 match data {40 CreateItemExData::NFT(t) => <SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32),41 _ => 0,42 }43 }4445 fn create_multiple_items(amount: u32) -> Weight {46 <SelfWeightOf<T>>::create_multiple_items(amount)47 }4849 fn burn_item() -> Weight {50 <SelfWeightOf<T>>::burn_item()51 }5253 fn set_collection_properties(amount: u32) -> Weight {54 <SelfWeightOf<T>>::set_collection_properties(amount)55 }5657 fn set_token_properties(amount: u32) -> Weight {58 <SelfWeightOf<T>>::set_token_properties(amount)59 }6061 fn set_property_permissions(amount: u32) -> Weight {62 <SelfWeightOf<T>>::set_property_permissions(amount)63 }6465 fn transfer() -> Weight {66 <SelfWeightOf<T>>::transfer()67 }6869 fn approve() -> Weight {70 <SelfWeightOf<T>>::approve()71 }7273 fn transfer_from() -> Weight {74 <SelfWeightOf<T>>::transfer_from()75 }7677 fn burn_from() -> Weight {78 <SelfWeightOf<T>>::burn_from()79 }8081 fn set_variable_metadata(bytes: u32) -> Weight {82 <SelfWeightOf<T>>::set_variable_metadata(bytes)83 }84}8586fn map_create_data<T: Config>(87 data: up_data_structs::CreateItemData,88 to: &T::CrossAccountId,89) -> Result<CreateItemData<T>, DispatchError> {90 match data {91 up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {92 const_data: data.const_data,93 variable_data: data.variable_data,94 owner: to.clone(),95 }),96 _ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),97 }98}99100impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {101 fn create_item(102 &self,103 sender: T::CrossAccountId,104 to: T::CrossAccountId,105 data: up_data_structs::CreateItemData,106 nesting_budget: &dyn Budget,107 ) -> DispatchResultWithPostInfo {108 with_weight(109 <Pallet<T>>::create_item(110 self,111 &sender,112 map_create_data::<T>(data, &to)?,113 nesting_budget,114 ),115 <CommonWeights<T>>::create_item(),116 )117 }118119 fn create_multiple_items(120 &self,121 sender: T::CrossAccountId,122 to: T::CrossAccountId,123 data: Vec<up_data_structs::CreateItemData>,124 nesting_budget: &dyn Budget,125 ) -> DispatchResultWithPostInfo {126 let data = data127 .into_iter()128 .map(|d| map_create_data::<T>(d, &to))129 .collect::<Result<Vec<_>, DispatchError>>()?;130131 let amount = data.len();132 with_weight(133 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),134 <CommonWeights<T>>::create_multiple_items(amount as u32),135 )136 }137138 fn create_multiple_items_ex(139 &self,140 sender: <T>::CrossAccountId,141 data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,142 nesting_budget: &dyn Budget,143 ) -> DispatchResultWithPostInfo {144 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);145 let data = match data {146 up_data_structs::CreateItemExData::NFT(nft) => nft,147 _ => fail!(Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken),148 };149150 with_weight(151 <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),152 weight,153 )154 }155156 fn set_collection_properties(157 &self,158 sender: T::CrossAccountId,159 properties: Vec<Property>,160 ) -> DispatchResultWithPostInfo {161 let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);162163 with_weight(164 <Pallet<T>>::set_collection_properties(self, &sender, properties),165 weight166 )167 }168169 fn set_token_properties(170 &self,171 sender: T::CrossAccountId,172 token_id: TokenId,173 properties: Vec<Property>,174 ) -> DispatchResultWithPostInfo {175 let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);176177 with_weight(178 <Pallet<T>>::set_token_properties(self, &sender, token_id, properties),179 weight180 )181 }182183 fn set_property_permissions(184 &self,185 sender: &T::CrossAccountId,186 property_permissions: Vec<PropertyKeyPermission>,187 ) -> DispatchResultWithPostInfo {188 let weight = <CommonWeights<T>>::set_property_permissions(property_permissions.len() as u32);189190 with_weight(191 <Pallet<T>>::set_property_permissions(self, sender, property_permissions),192 weight193 )194 }195196 fn burn_item(197 &self,198 sender: T::CrossAccountId,199 token: TokenId,200 amount: u128,201 ) -> DispatchResultWithPostInfo {202 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);203 if amount == 1 {204 with_weight(205 <Pallet<T>>::burn(self, &sender, token),206 <CommonWeights<T>>::burn_item(),207 )208 } else {209 Ok(().into())210 }211 }212213 fn transfer(214 &self,215 from: T::CrossAccountId,216 to: T::CrossAccountId,217 token: TokenId,218 amount: u128,219 nesting_budget: &dyn Budget,220 ) -> DispatchResultWithPostInfo {221 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);222 if amount == 1 {223 with_weight(224 <Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),225 <CommonWeights<T>>::transfer(),226 )227 } else {228 Ok(().into())229 }230 }231232 fn approve(233 &self,234 sender: T::CrossAccountId,235 spender: T::CrossAccountId,236 token: TokenId,237 amount: u128,238 ) -> DispatchResultWithPostInfo {239 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);240241 with_weight(242 if amount == 1 {243 <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))244 } else {245 <Pallet<T>>::set_allowance(self, &sender, token, None)246 },247 <CommonWeights<T>>::approve(),248 )249 }250251 fn transfer_from(252 &self,253 sender: T::CrossAccountId,254 from: T::CrossAccountId,255 to: T::CrossAccountId,256 token: TokenId,257 amount: u128,258 nesting_budget: &dyn Budget,259 ) -> DispatchResultWithPostInfo {260 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);261262 if amount == 1 {263 with_weight(264 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, nesting_budget),265 <CommonWeights<T>>::transfer_from(),266 )267 } else {268 Ok(().into())269 }270 }271272 fn burn_from(273 &self,274 sender: T::CrossAccountId,275 from: T::CrossAccountId,276 token: TokenId,277 amount: u128,278 nesting_budget: &dyn Budget,279 ) -> DispatchResultWithPostInfo {280 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);281282 if amount == 1 {283 with_weight(284 <Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),285 <CommonWeights<T>>::burn_from(),286 )287 } else {288 Ok(().into())289 }290 }291292 fn set_variable_metadata(293 &self,294 sender: T::CrossAccountId,295 token: TokenId,296 data: BoundedVec<u8, CustomDataLimit>,297 ) -> DispatchResultWithPostInfo {298 let len = data.len();299 with_weight(300 <Pallet<T>>::set_variable_metadata(self, &sender, token, data),301 <CommonWeights<T>>::set_variable_metadata(len as u32),302 )303 }304305 fn check_nesting(306 &self,307 sender: T::CrossAccountId,308 from: (CollectionId, TokenId),309 under: TokenId,310 budget: &dyn Budget,311 ) -> sp_runtime::DispatchResult {312 <Pallet<T>>::check_nesting(self, sender, from, under, budget)313 }314315 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {316 <Owned<T>>::iter_prefix((self.id, account))317 .map(|(id, _)| id)318 .collect()319 }320321 fn collection_tokens(&self) -> Vec<TokenId> {322 <TokenData<T>>::iter_prefix((self.id,))323 .map(|(id, _)| id)324 .collect()325 }326327 fn token_exists(&self, token: TokenId) -> bool {328 <Pallet<T>>::token_exists(self, token)329 }330331 fn last_token_id(&self) -> TokenId {332 TokenId(<TokensMinted<T>>::get(self.id))333 }334335 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {336 <TokenData<T>>::get((self.id, token)).map(|t| t.owner)337 }338 fn const_metadata(&self, token: TokenId) -> Vec<u8> {339 <TokenData<T>>::get((self.id, token))340 .map(|t| t.const_data)341 .unwrap_or_default()342 .into_inner()343 }344 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {345 <TokenData<T>>::get((self.id, token))346 .map(|t| t.variable_data)347 .unwrap_or_default()348 .into_inner()349 }350351 fn total_supply(&self) -> u32 {352 <Pallet<T>>::total_supply(self)353 }354355 fn account_balance(&self, account: T::CrossAccountId) -> u32 {356 <AccountBalance<T>>::get((self.id, account))357 }358359 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {360 if <TokenData<T>>::get((self.id, token))361 .map(|a| a.owner == account)362 .unwrap_or(false)363 {364 1365 } else {366 0367 }368 }369370 fn allowance(371 &self,372 sender: T::CrossAccountId,373 spender: T::CrossAccountId,374 token: TokenId,375 ) -> u128 {376 if <TokenData<T>>::get((self.id, token))377 .map(|a| a.owner != sender)378 .unwrap_or(true)379 {380 0381 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {382 1383 } else {384 0385 }386 }387}