1use core::marker::PhantomData;23use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};4use nft_data_structs::TokenId;5use pallet_common::{6 CommonCollectionOperations, CommonWeightInfo, account::CrossAccountId, with_weight,7};8use sp_runtime::DispatchError;9use sp_std::vec::Vec;1011use crate::{12 AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,13 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,14};1516pub struct CommonWeights<T: Config>(PhantomData<T>);17impl<T: Config> CommonWeightInfo for CommonWeights<T> {18 fn create_item() -> Weight {19 <SelfWeightOf<T>>::create_item()20 }2122 fn create_multiple_items(amount: u32) -> Weight {23 <SelfWeightOf<T>>::create_multiple_items(amount)24 }2526 fn burn_item() -> Weight {27 <SelfWeightOf<T>>::burn_item()28 }2930 fn transfer() -> Weight {31 <SelfWeightOf<T>>::transfer()32 }3334 fn approve() -> Weight {35 <SelfWeightOf<T>>::approve()36 }3738 fn transfer_from() -> Weight {39 <SelfWeightOf<T>>::transfer_from()40 }4142 fn burn_from() -> Weight {43 044 }4546 fn set_variable_metadata(bytes: u32) -> Weight {47 <SelfWeightOf<T>>::set_variable_metadata(bytes)48 }49}5051fn map_create_data<T: Config>(52 data: nft_data_structs::CreateItemData,53 to: &T::CrossAccountId,54) -> Result<CreateItemData<T>, DispatchError> {55 match data {56 nft_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData {57 const_data: data.const_data,58 variable_data: data.variable_data,59 owner: to.clone(),60 }),61 _ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),62 }63}6465impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {66 fn create_item(67 &self,68 sender: T::CrossAccountId,69 to: T::CrossAccountId,70 data: nft_data_structs::CreateItemData,71 ) -> DispatchResultWithPostInfo {72 with_weight(73 <Pallet<T>>::create_item(self, &sender, map_create_data(data, &to)?),74 <CommonWeights<T>>::create_item(),75 )76 }7778 fn create_multiple_items(79 &self,80 sender: T::CrossAccountId,81 to: T::CrossAccountId,82 data: Vec<nft_data_structs::CreateItemData>,83 ) -> DispatchResultWithPostInfo {84 let data = data85 .into_iter()86 .map(|d| map_create_data::<T>(d, &to))87 .collect::<Result<Vec<_>, DispatchError>>()?;8889 let amount = data.len();90 with_weight(91 <Pallet<T>>::create_multiple_items(self, &sender, data),92 <CommonWeights<T>>::create_multiple_items(amount as u32),93 )94 }9596 fn burn_item(97 &self,98 sender: T::CrossAccountId,99 token: TokenId,100 amount: u128,101 ) -> DispatchResultWithPostInfo {102 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);103 if amount == 1 {104 with_weight(105 <Pallet<T>>::burn(&self, &sender, token),106 <CommonWeights<T>>::burn_item(),107 )108 } else {109 Ok(().into())110 }111 }112113 fn transfer(114 &self,115 from: T::CrossAccountId,116 to: T::CrossAccountId,117 token: TokenId,118 amount: u128,119 ) -> DispatchResultWithPostInfo {120 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);121 if amount == 1 {122 with_weight(123 <Pallet<T>>::transfer(&self, &from, &to, token),124 <CommonWeights<T>>::transfer(),125 )126 } else {127 Ok(().into())128 }129 }130131 fn approve(132 &self,133 sender: T::CrossAccountId,134 spender: T::CrossAccountId,135 token: TokenId,136 amount: u128,137 ) -> DispatchResultWithPostInfo {138 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);139140 with_weight(141 if amount == 1 {142 <Pallet<T>>::set_allowance(&self, &sender, token, Some(&spender))143 } else {144 <Pallet<T>>::set_allowance(&self, &sender, token, None)145 },146 <CommonWeights<T>>::approve(),147 )148 }149150 fn transfer_from(151 &self,152 sender: T::CrossAccountId,153 from: T::CrossAccountId,154 to: T::CrossAccountId,155 token: TokenId,156 amount: u128,157 ) -> DispatchResultWithPostInfo {158 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);159160 if amount == 1 {161 with_weight(162 <Pallet<T>>::transfer_from(&self, &sender, &from, &to, token),163 <CommonWeights<T>>::transfer_from(),164 )165 } else {166 Ok(().into())167 }168 }169170 fn burn_from(171 &self,172 sender: T::CrossAccountId,173 from: T::CrossAccountId,174 token: TokenId,175 amount: u128,176 ) -> DispatchResultWithPostInfo {177 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);178179 if amount == 1 {180 with_weight(181 <Pallet<T>>::burn_from(&self, &sender, &from, token),182 <CommonWeights<T>>::burn_from(),183 )184 } else {185 Ok(().into())186 }187 }188189 fn set_variable_metadata(190 &self,191 sender: T::CrossAccountId,192 token: TokenId,193 data: Vec<u8>,194 ) -> DispatchResultWithPostInfo {195 let len = data.len();196 with_weight(197 <Pallet<T>>::set_variable_metadata(&self, &sender, token, data),198 <CommonWeights<T>>::set_variable_metadata(len as u32),199 )200 }201202 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {203 <Owned<T>>::iter_prefix((self.id, account.as_sub()))204 .map(|(id, _)| id)205 .collect()206 }207208 fn token_exists(&self, token: TokenId) -> bool {209 <Pallet<T>>::token_exists(self, token)210 }211212 fn last_token_id(&self) -> TokenId {213 TokenId(<TokensMinted<T>>::get(self.id))214 }215216 fn token_owner(&self, token: TokenId) -> T::CrossAccountId {217 <TokenData<T>>::get((self.id, token))218 .map(|t| t.owner)219 .unwrap_or_default()220 }221 fn const_metadata(&self, token: TokenId) -> Vec<u8> {222 <TokenData<T>>::get((self.id, token))223 .map(|t| t.const_data.clone())224 .unwrap_or_default()225 }226 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {227 <TokenData<T>>::get((self.id, token))228 .map(|t| t.variable_data.clone())229 .unwrap_or_default()230 }231232 fn collection_tokens(&self) -> u32 {233 <Pallet<T>>::total_supply(self)234 }235236 fn account_balance(&self, account: T::CrossAccountId) -> u32 {237 <AccountBalance<T>>::get((self.id, account.as_sub()))238 }239240 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {241 if <TokenData<T>>::get((self.id, token))242 .map(|a| a.owner == account)243 .unwrap_or(false)244 {245 1246 } else {247 0248 }249 }250251 fn allowance(252 &self,253 sender: T::CrossAccountId,254 spender: T::CrossAccountId,255 token: TokenId,256 ) -> u128 {257 if <TokenData<T>>::get((self.id, token))258 .map(|a| a.owner == sender)259 .unwrap_or(false)260 {261 0262 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {263 1264 } else {265 0266 }267 }268}