1use core::marker::PhantomData;23use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};4use up_data_structs::{TokenId, CustomDataLimit, CreateItemExData};5use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};6use sp_runtime::DispatchError;7use sp_std::vec::Vec;89use crate::{10 AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,11 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,12};1314pub struct CommonWeights<T: Config>(PhantomData<T>);15impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {16 fn create_item() -> Weight {17 <SelfWeightOf<T>>::create_item()18 }1920 fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {21 match data {22 CreateItemExData::NFT(t) => <SelfWeightOf<T>>::create_multiple_items_ex(t.len() as u32),23 _ => 0,24 }25 }2627 fn create_multiple_items(amount: u32) -> Weight {28 <SelfWeightOf<T>>::create_multiple_items(amount)29 }3031 fn burn_item() -> Weight {32 <SelfWeightOf<T>>::burn_item()33 }3435 fn transfer() -> Weight {36 <SelfWeightOf<T>>::transfer()37 }3839 fn approve() -> Weight {40 <SelfWeightOf<T>>::approve()41 }4243 fn transfer_from() -> Weight {44 <SelfWeightOf<T>>::transfer_from()45 }4647 fn burn_from() -> Weight {48 <SelfWeightOf<T>>::burn_from()49 }5051 fn set_variable_metadata(bytes: u32) -> Weight {52 <SelfWeightOf<T>>::set_variable_metadata(bytes)53 }54}5556fn map_create_data<T: Config>(57 data: up_data_structs::CreateItemData,58 to: &T::CrossAccountId,59) -> Result<CreateItemData<T>, DispatchError> {60 match data {61 up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {62 const_data: data.const_data,63 variable_data: data.variable_data,64 owner: to.clone(),65 }),66 _ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),67 }68}6970impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {71 fn create_item(72 &self,73 sender: T::CrossAccountId,74 to: T::CrossAccountId,75 data: up_data_structs::CreateItemData,76 ) -> DispatchResultWithPostInfo {77 with_weight(78 <Pallet<T>>::create_item(self, &sender, map_create_data::<T>(data, &to)?),79 <CommonWeights<T>>::create_item(),80 )81 }8283 fn create_multiple_items(84 &self,85 sender: T::CrossAccountId,86 to: T::CrossAccountId,87 data: Vec<up_data_structs::CreateItemData>,88 ) -> DispatchResultWithPostInfo {89 let data = data90 .into_iter()91 .map(|d| map_create_data::<T>(d, &to))92 .collect::<Result<Vec<_>, DispatchError>>()?;9394 let amount = data.len();95 with_weight(96 <Pallet<T>>::create_multiple_items(self, &sender, data),97 <CommonWeights<T>>::create_multiple_items(amount as u32),98 )99 }100101 fn create_multiple_items_ex(102 &self,103 sender: <T>::CrossAccountId,104 data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,105 ) -> DispatchResultWithPostInfo {106 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);107 let data = match data {108 up_data_structs::CreateItemExData::NFT(nft) => nft,109 _ => fail!(Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken),110 };111112 with_weight(113 <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner()),114 weight,115 )116 }117118 fn burn_item(119 &self,120 sender: T::CrossAccountId,121 token: TokenId,122 amount: u128,123 ) -> DispatchResultWithPostInfo {124 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);125 if amount == 1 {126 with_weight(127 <Pallet<T>>::burn(self, &sender, token),128 <CommonWeights<T>>::burn_item(),129 )130 } else {131 Ok(().into())132 }133 }134135 fn transfer(136 &self,137 from: T::CrossAccountId,138 to: T::CrossAccountId,139 token: TokenId,140 amount: u128,141 ) -> DispatchResultWithPostInfo {142 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);143 if amount == 1 {144 with_weight(145 <Pallet<T>>::transfer(self, &from, &to, token),146 <CommonWeights<T>>::transfer(),147 )148 } else {149 Ok(().into())150 }151 }152153 fn approve(154 &self,155 sender: T::CrossAccountId,156 spender: T::CrossAccountId,157 token: TokenId,158 amount: u128,159 ) -> DispatchResultWithPostInfo {160 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);161162 with_weight(163 if amount == 1 {164 <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))165 } else {166 <Pallet<T>>::set_allowance(self, &sender, token, None)167 },168 <CommonWeights<T>>::approve(),169 )170 }171172 fn transfer_from(173 &self,174 sender: T::CrossAccountId,175 from: T::CrossAccountId,176 to: T::CrossAccountId,177 token: TokenId,178 amount: u128,179 ) -> DispatchResultWithPostInfo {180 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);181182 if amount == 1 {183 with_weight(184 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token),185 <CommonWeights<T>>::transfer_from(),186 )187 } else {188 Ok(().into())189 }190 }191192 fn burn_from(193 &self,194 sender: T::CrossAccountId,195 from: T::CrossAccountId,196 token: TokenId,197 amount: u128,198 ) -> DispatchResultWithPostInfo {199 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);200201 if amount == 1 {202 with_weight(203 <Pallet<T>>::burn_from(self, &sender, &from, token),204 <CommonWeights<T>>::burn_from(),205 )206 } else {207 Ok(().into())208 }209 }210211 fn set_variable_metadata(212 &self,213 sender: T::CrossAccountId,214 token: TokenId,215 data: BoundedVec<u8, CustomDataLimit>,216 ) -> DispatchResultWithPostInfo {217 let len = data.len();218 with_weight(219 <Pallet<T>>::set_variable_metadata(self, &sender, token, data),220 <CommonWeights<T>>::set_variable_metadata(len as u32),221 )222 }223224 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {225 <Owned<T>>::iter_prefix((self.id, account))226 .map(|(id, _)| id)227 .collect()228 }229230 fn token_exists(&self, token: TokenId) -> bool {231 <Pallet<T>>::token_exists(self, token)232 }233234 fn last_token_id(&self) -> TokenId {235 TokenId(<TokensMinted<T>>::get(self.id))236 }237238 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {239 <TokenData<T>>::get((self.id, token)).map(|t| t.owner)240 }241 fn const_metadata(&self, token: TokenId) -> Vec<u8> {242 <TokenData<T>>::get((self.id, token))243 .map(|t| t.const_data)244 .unwrap_or_default()245 .into_inner()246 }247 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {248 <TokenData<T>>::get((self.id, token))249 .map(|t| t.variable_data)250 .unwrap_or_default()251 .into_inner()252 }253254 fn collection_tokens(&self) -> u32 {255 <Pallet<T>>::total_supply(self)256 }257258 fn account_balance(&self, account: T::CrossAccountId) -> u32 {259 <AccountBalance<T>>::get((self.id, account))260 }261262 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {263 if <TokenData<T>>::get((self.id, token))264 .map(|a| a.owner == account)265 .unwrap_or(false)266 {267 1268 } else {269 0270 }271 }272273 fn allowance(274 &self,275 sender: T::CrossAccountId,276 spender: T::CrossAccountId,277 token: TokenId,278 ) -> u128 {279 if <TokenData<T>>::get((self.id, token))280 .map(|a| a.owner != sender)281 .unwrap_or(true)282 {283 0284 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {285 1286 } else {287 0288 }289 }290}