1234567891011121314151617use core::marker::PhantomData;1819use sp_std::collections::btree_map::BTreeMap;20use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};21use up_data_structs::{22 CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,23 PropertyKey, PropertyKeyPermission,24};25use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};26use sp_runtime::DispatchError;27use sp_std::{vec::Vec, vec};2829use crate::{30 AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle,31 SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted,32};3334macro_rules! max_weight_of {35 ($($method:ident ($($args:tt)*)),*) => {36 037 $(38 .max(<SelfWeightOf<T>>::$method($($args)*))39 )*40 };41}4243pub struct CommonWeights<T: Config>(PhantomData<T>);44impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {45 fn create_item() -> Weight {46 <SelfWeightOf<T>>::create_item()47 }4849 fn create_multiple_items(amount: u32) -> Weight {50 <SelfWeightOf<T>>::create_multiple_items(amount)51 }5253 fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {54 match call {55 CreateItemExData::RefungibleMultipleOwners(i) => {56 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)57 }58 CreateItemExData::RefungibleMultipleItems(i) => {59 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)60 }61 _ => 0,62 }63 }6465 fn burn_item() -> Weight {66 max_weight_of!(burn_item_partial(), burn_item_fully())67 }6869 fn set_collection_properties(amount: u32) -> Weight {70 <SelfWeightOf<T>>::set_collection_properties(amount)71 }7273 fn delete_collection_properties(amount: u32) -> Weight {74 <SelfWeightOf<T>>::delete_collection_properties(amount)75 }7677 fn set_token_properties(amount: u32) -> Weight {78 <SelfWeightOf<T>>::set_token_properties(amount)79 }8081 fn delete_token_properties(amount: u32) -> Weight {82 <SelfWeightOf<T>>::delete_token_properties(amount)83 }8485 fn set_property_permissions(amount: u32) -> Weight {86 <SelfWeightOf<T>>::set_property_permissions(amount)87 }8889 fn transfer() -> Weight {90 max_weight_of!(91 transfer_normal(),92 transfer_creating(),93 transfer_removing(),94 transfer_creating_removing()95 )96 }9798 fn approve() -> Weight {99 <SelfWeightOf<T>>::approve()100 }101102 fn transfer_from() -> Weight {103 max_weight_of!(104 transfer_from_normal(),105 transfer_from_creating(),106 transfer_from_removing(),107 transfer_from_creating_removing()108 )109 }110111 fn burn_from() -> Weight {112 <SelfWeightOf<T>>::burn_from()113 }114}115116fn map_create_data<T: Config>(117 data: up_data_structs::CreateItemData,118 to: &T::CrossAccountId,119) -> Result<CreateRefungibleExData<T::CrossAccountId>, DispatchError> {120 match data {121 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {122 const_data: data.const_data,123 users: {124 let mut out = BTreeMap::new();125 out.insert(to.clone(), data.pieces);126 out.try_into().expect("limit > 0")127 },128 }),129 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),130 }131}132133impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {134 fn create_item(135 &self,136 sender: T::CrossAccountId,137 to: T::CrossAccountId,138 data: up_data_structs::CreateItemData,139 nesting_budget: &dyn Budget,140 ) -> DispatchResultWithPostInfo {141 with_weight(142 <Pallet<T>>::create_item(143 self,144 &sender,145 map_create_data::<T>(data, &to)?,146 nesting_budget,147 ),148 <CommonWeights<T>>::create_item(),149 )150 }151152 fn create_multiple_items(153 &self,154 sender: T::CrossAccountId,155 to: T::CrossAccountId,156 data: Vec<up_data_structs::CreateItemData>,157 nesting_budget: &dyn Budget,158 ) -> DispatchResultWithPostInfo {159 let data = data160 .into_iter()161 .map(|d| map_create_data::<T>(d, &to))162 .collect::<Result<Vec<_>, DispatchError>>()?;163164 let amount = data.len();165 with_weight(166 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),167 <CommonWeights<T>>::create_multiple_items(amount as u32),168 )169 }170171 fn create_multiple_items_ex(172 &self,173 sender: <T>::CrossAccountId,174 data: CreateItemExData<T::CrossAccountId>,175 nesting_budget: &dyn Budget,176 ) -> DispatchResultWithPostInfo {177 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);178 let data = match data {179 CreateItemExData::RefungibleMultipleOwners(r) => vec![r],180 CreateItemExData::RefungibleMultipleItems(r)181 if r.iter().all(|i| i.users.len() == 1) =>182 {183 r.into_inner()184 }185 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),186 };187188 with_weight(189 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),190 weight,191 )192 }193194 fn burn_item(195 &self,196 sender: T::CrossAccountId,197 token: TokenId,198 amount: u128,199 ) -> DispatchResultWithPostInfo {200 with_weight(201 <Pallet<T>>::burn(self, &sender, token, amount),202 <CommonWeights<T>>::burn_item(),203 )204 }205206 fn transfer(207 &self,208 from: T::CrossAccountId,209 to: T::CrossAccountId,210 token: TokenId,211 amount: u128,212 nesting_budget: &dyn Budget,213 ) -> DispatchResultWithPostInfo {214 with_weight(215 <Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),216 <CommonWeights<T>>::transfer(),217 )218 }219220 fn approve(221 &self,222 sender: T::CrossAccountId,223 spender: T::CrossAccountId,224 token: TokenId,225 amount: u128,226 ) -> DispatchResultWithPostInfo {227 with_weight(228 <Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),229 <CommonWeights<T>>::approve(),230 )231 }232233 fn transfer_from(234 &self,235 sender: T::CrossAccountId,236 from: T::CrossAccountId,237 to: T::CrossAccountId,238 token: TokenId,239 amount: u128,240 nesting_budget: &dyn Budget,241 ) -> DispatchResultWithPostInfo {242 with_weight(243 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),244 <CommonWeights<T>>::transfer_from(),245 )246 }247248 fn burn_from(249 &self,250 sender: T::CrossAccountId,251 from: T::CrossAccountId,252 token: TokenId,253 amount: u128,254 nesting_budget: &dyn Budget,255 ) -> DispatchResultWithPostInfo {256 with_weight(257 <Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),258 <CommonWeights<T>>::burn_from(),259 )260 }261262 fn set_collection_properties(263 &self,264 _sender: T::CrossAccountId,265 _property: Vec<Property>,266 ) -> DispatchResultWithPostInfo {267 fail!(<Error<T>>::SettingPropertiesNotAllowed)268 }269270 fn delete_collection_properties(271 &self,272 _sender: &T::CrossAccountId,273 _property_keys: Vec<PropertyKey>,274 ) -> DispatchResultWithPostInfo {275 fail!(<Error<T>>::SettingPropertiesNotAllowed)276 }277278 fn set_token_properties(279 &self,280 _sender: T::CrossAccountId,281 _token_id: TokenId,282 _property: Vec<Property>,283 ) -> DispatchResultWithPostInfo {284 fail!(<Error<T>>::SettingPropertiesNotAllowed)285 }286287 fn set_property_permissions(288 &self,289 _sender: &T::CrossAccountId,290 _property_permissions: Vec<PropertyKeyPermission>,291 ) -> DispatchResultWithPostInfo {292 fail!(<Error<T>>::SettingPropertiesNotAllowed)293 }294295 fn delete_token_properties(296 &self,297 _sender: T::CrossAccountId,298 _token_id: TokenId,299 _property_keys: Vec<PropertyKey>,300 ) -> DispatchResultWithPostInfo {301 fail!(<Error<T>>::SettingPropertiesNotAllowed)302 }303304 fn check_nesting(305 &self,306 _sender: <T>::CrossAccountId,307 _from: (CollectionId, TokenId),308 _under: TokenId,309 _budget: &dyn Budget,310 ) -> sp_runtime::DispatchResult {311 fail!(<Error<T>>::RefungibleDisallowsNesting)312 }313314 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {315 <Owned<T>>::iter_prefix((self.id, account))316 .map(|(id, _)| id)317 .collect()318 }319320 fn collection_tokens(&self) -> Vec<TokenId> {321 <TokenData<T>>::iter_prefix((self.id,))322 .map(|(id, _)| id)323 .collect()324 }325326 fn token_exists(&self, token: TokenId) -> bool {327 <Pallet<T>>::token_exists(self, token)328 }329330 fn last_token_id(&self) -> TokenId {331 TokenId(<TokensMinted<T>>::get(self.id))332 }333334 fn token_owner(&self, _token: TokenId) -> Option<T::CrossAccountId> {335 None336 }337 fn const_metadata(&self, token: TokenId) -> Vec<u8> {338 <TokenData<T>>::get((self.id, token))339 .const_data340 .into_inner()341 }342343 fn token_properties(344 &self,345 _token_id: TokenId,346 _keys: Option<Vec<PropertyKey>>,347 ) -> Vec<Property> {348 Vec::new()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 <Balance<T>>::get((self.id, token, account))361 }362363 fn allowance(364 &self,365 sender: T::CrossAccountId,366 spender: T::CrossAccountId,367 token: TokenId,368 ) -> u128 {369 <Allowance<T>>::get((self.id, token, sender, spender))370 }371}