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,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_property() -> Weight {54 <SelfWeightOf<T>>::set_property()55 }5657 fn transfer() -> Weight {58 <SelfWeightOf<T>>::transfer()59 }6061 fn approve() -> Weight {62 <SelfWeightOf<T>>::approve()63 }6465 fn transfer_from() -> Weight {66 <SelfWeightOf<T>>::transfer_from()67 }6869 fn burn_from() -> Weight {70 <SelfWeightOf<T>>::burn_from()71 }7273 fn set_variable_metadata(bytes: u32) -> Weight {74 <SelfWeightOf<T>>::set_variable_metadata(bytes)75 }76}7778fn map_create_data<T: Config>(79 data: up_data_structs::CreateItemData,80 to: &T::CrossAccountId,81) -> Result<CreateItemData<T>, DispatchError> {82 match data {83 up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {84 const_data: data.const_data,85 variable_data: data.variable_data,86 owner: to.clone(),87 }),88 _ => fail!(<Error<T>>::NotNonfungibleDataUsedToMintFungibleCollectionToken),89 }90}9192impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {93 fn create_item(94 &self,95 sender: T::CrossAccountId,96 to: T::CrossAccountId,97 data: up_data_structs::CreateItemData,98 nesting_budget: &dyn Budget,99 ) -> DispatchResultWithPostInfo {100 with_weight(101 <Pallet<T>>::create_item(102 self,103 &sender,104 map_create_data::<T>(data, &to)?,105 nesting_budget,106 ),107 <CommonWeights<T>>::create_item(),108 )109 }110111 fn create_multiple_items(112 &self,113 sender: T::CrossAccountId,114 to: T::CrossAccountId,115 data: Vec<up_data_structs::CreateItemData>,116 nesting_budget: &dyn Budget,117 ) -> DispatchResultWithPostInfo {118 let data = data119 .into_iter()120 .map(|d| map_create_data::<T>(d, &to))121 .collect::<Result<Vec<_>, DispatchError>>()?;122123 let amount = data.len();124 with_weight(125 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),126 <CommonWeights<T>>::create_multiple_items(amount as u32),127 )128 }129130 fn create_multiple_items_ex(131 &self,132 sender: <T>::CrossAccountId,133 data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,134 nesting_budget: &dyn Budget,135 ) -> DispatchResultWithPostInfo {136 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);137 let data = match data {138 up_data_structs::CreateItemExData::NFT(nft) => nft,139 _ => fail!(Error::<T>::NotNonfungibleDataUsedToMintFungibleCollectionToken),140 };141142 with_weight(143 <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner(), nesting_budget),144 weight,145 )146 }147148 fn burn_item(149 &self,150 sender: T::CrossAccountId,151 token: TokenId,152 amount: u128,153 ) -> DispatchResultWithPostInfo {154 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);155 if amount == 1 {156 with_weight(157 <Pallet<T>>::burn(self, &sender, token),158 <CommonWeights<T>>::burn_item(),159 )160 } else {161 Ok(().into())162 }163 }164165 fn transfer(166 &self,167 from: T::CrossAccountId,168 to: T::CrossAccountId,169 token: TokenId,170 amount: u128,171 nesting_budget: &dyn Budget,172 ) -> DispatchResultWithPostInfo {173 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);174 if amount == 1 {175 with_weight(176 <Pallet<T>>::transfer(self, &from, &to, token, nesting_budget),177 <CommonWeights<T>>::transfer(),178 )179 } else {180 Ok(().into())181 }182 }183184 fn approve(185 &self,186 sender: T::CrossAccountId,187 spender: T::CrossAccountId,188 token: TokenId,189 amount: u128,190 ) -> DispatchResultWithPostInfo {191 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);192193 with_weight(194 if amount == 1 {195 <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))196 } else {197 <Pallet<T>>::set_allowance(self, &sender, token, None)198 },199 <CommonWeights<T>>::approve(),200 )201 }202203 fn transfer_from(204 &self,205 sender: T::CrossAccountId,206 from: T::CrossAccountId,207 to: T::CrossAccountId,208 token: TokenId,209 amount: u128,210 nesting_budget: &dyn Budget,211 ) -> DispatchResultWithPostInfo {212 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);213214 if amount == 1 {215 with_weight(216 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, nesting_budget),217 <CommonWeights<T>>::transfer_from(),218 )219 } else {220 Ok(().into())221 }222 }223224 fn burn_from(225 &self,226 sender: T::CrossAccountId,227 from: T::CrossAccountId,228 token: TokenId,229 amount: u128,230 nesting_budget: &dyn Budget,231 ) -> DispatchResultWithPostInfo {232 ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);233234 if amount == 1 {235 with_weight(236 <Pallet<T>>::burn_from(self, &sender, &from, token, nesting_budget),237 <CommonWeights<T>>::burn_from(),238 )239 } else {240 Ok(().into())241 }242 }243244 fn change_collection_property(245 &self,246 sender: T::CrossAccountId,247 property: Property,248 ) -> DispatchResultWithPostInfo {249 250 with_weight(251 252 Ok(()),253 <CommonWeights<T>>::set_property(),254 )255 }256257 fn change_token_property(258 &self,259 sender: T::CrossAccountId,260 token_id: TokenId,261 property: Property,262 ) -> DispatchResultWithPostInfo {263 with_weight(264 265 Ok(()),266 <CommonWeights<T>>::set_property(),267 )268 }269270 fn set_variable_metadata(271 &self,272 sender: T::CrossAccountId,273 token: TokenId,274 data: BoundedVec<u8, CustomDataLimit>,275 ) -> DispatchResultWithPostInfo {276 let len = data.len();277 with_weight(278 <Pallet<T>>::set_variable_metadata(self, &sender, token, data),279 <CommonWeights<T>>::set_variable_metadata(len as u32),280 )281 }282283 fn check_nesting(284 &self,285 sender: T::CrossAccountId,286 from: (CollectionId, TokenId),287 under: TokenId,288 budget: &dyn Budget,289 ) -> sp_runtime::DispatchResult {290 <Pallet<T>>::check_nesting(self, sender, from, under, budget)291 }292293 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {294 <Owned<T>>::iter_prefix((self.id, account))295 .map(|(id, _)| id)296 .collect()297 }298299 fn collection_tokens(&self) -> Vec<TokenId> {300 <TokenData<T>>::iter_prefix((self.id,))301 .map(|(id, _)| id)302 .collect()303 }304305 fn token_exists(&self, token: TokenId) -> bool {306 <Pallet<T>>::token_exists(self, token)307 }308309 fn last_token_id(&self) -> TokenId {310 TokenId(<TokensMinted<T>>::get(self.id))311 }312313 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {314 <TokenData<T>>::get((self.id, token)).map(|t| t.owner)315 }316 fn const_metadata(&self, token: TokenId) -> Vec<u8> {317 <TokenData<T>>::get((self.id, token))318 .map(|t| t.const_data)319 .unwrap_or_default()320 .into_inner()321 }322 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {323 <TokenData<T>>::get((self.id, token))324 .map(|t| t.variable_data)325 .unwrap_or_default()326 .into_inner()327 }328329 fn total_supply(&self) -> u32 {330 <Pallet<T>>::total_supply(self)331 }332333 fn account_balance(&self, account: T::CrossAccountId) -> u32 {334 <AccountBalance<T>>::get((self.id, account))335 }336337 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {338 if <TokenData<T>>::get((self.id, token))339 .map(|a| a.owner == account)340 .unwrap_or(false)341 {342 1343 } else {344 0345 }346 }347348 fn allowance(349 &self,350 sender: T::CrossAccountId,351 spender: T::CrossAccountId,352 token: TokenId,353 ) -> u128 {354 if <TokenData<T>>::get((self.id, token))355 .map(|a| a.owner != sender)356 .unwrap_or(true)357 {358 0359 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {360 1361 } else {362 0363 }364 }365}