1234567891011121314151617use core::marker::PhantomData;1819use sp_std::collections::btree_map::BTreeMap;20use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight, BoundedVec};21use up_data_structs::{22 CollectionId, TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData,23 budget::Budget, Property,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 change_collection_properties(amount: u32) -> Weight {70 <SelfWeightOf<T>>::change_collection_properties(amount)71 }7273 fn change_token_properties(amount: u32) -> Weight {74 <SelfWeightOf<T>>::change_token_properties(amount)75 }7677 fn transfer() -> Weight {78 max_weight_of!(79 transfer_normal(),80 transfer_creating(),81 transfer_removing(),82 transfer_creating_removing()83 )84 }8586 fn approve() -> Weight {87 <SelfWeightOf<T>>::approve()88 }8990 fn transfer_from() -> Weight {91 max_weight_of!(92 transfer_from_normal(),93 transfer_from_creating(),94 transfer_from_removing(),95 transfer_from_creating_removing()96 )97 }9899 fn burn_from() -> Weight {100 <SelfWeightOf<T>>::burn_from()101 }102103 fn set_variable_metadata(bytes: u32) -> Weight {104 <SelfWeightOf<T>>::set_variable_metadata(bytes)105 }106}107108fn map_create_data<T: Config>(109 data: up_data_structs::CreateItemData,110 to: &T::CrossAccountId,111) -> Result<CreateRefungibleExData<T::CrossAccountId>, DispatchError> {112 match data {113 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {114 const_data: data.const_data,115 variable_data: data.variable_data,116 users: {117 let mut out = BTreeMap::new();118 out.insert(to.clone(), data.pieces);119 out.try_into().expect("limit > 0")120 },121 }),122 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),123 }124}125126impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {127 fn create_item(128 &self,129 sender: T::CrossAccountId,130 to: T::CrossAccountId,131 data: up_data_structs::CreateItemData,132 nesting_budget: &dyn Budget,133 ) -> DispatchResultWithPostInfo {134 with_weight(135 <Pallet<T>>::create_item(136 self,137 &sender,138 map_create_data::<T>(data, &to)?,139 nesting_budget,140 ),141 <CommonWeights<T>>::create_item(),142 )143 }144145 fn create_multiple_items(146 &self,147 sender: T::CrossAccountId,148 to: T::CrossAccountId,149 data: Vec<up_data_structs::CreateItemData>,150 nesting_budget: &dyn Budget,151 ) -> DispatchResultWithPostInfo {152 let data = data153 .into_iter()154 .map(|d| map_create_data::<T>(d, &to))155 .collect::<Result<Vec<_>, DispatchError>>()?;156157 let amount = data.len();158 with_weight(159 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),160 <CommonWeights<T>>::create_multiple_items(amount as u32),161 )162 }163164 fn create_multiple_items_ex(165 &self,166 sender: <T>::CrossAccountId,167 data: CreateItemExData<T::CrossAccountId>,168 nesting_budget: &dyn Budget,169 ) -> DispatchResultWithPostInfo {170 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);171 let data = match data {172 CreateItemExData::RefungibleMultipleOwners(r) => vec![r],173 CreateItemExData::RefungibleMultipleItems(r)174 if r.iter().all(|i| i.users.len() == 1) =>175 {176 r.into_inner()177 }178 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),179 };180181 with_weight(182 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),183 weight,184 )185 }186187 fn burn_item(188 &self,189 sender: T::CrossAccountId,190 token: TokenId,191 amount: u128,192 ) -> DispatchResultWithPostInfo {193 with_weight(194 <Pallet<T>>::burn(self, &sender, token, amount),195 <CommonWeights<T>>::burn_item(),196 )197 }198199 fn transfer(200 &self,201 from: T::CrossAccountId,202 to: T::CrossAccountId,203 token: TokenId,204 amount: u128,205 nesting_budget: &dyn Budget,206 ) -> DispatchResultWithPostInfo {207 with_weight(208 <Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),209 <CommonWeights<T>>::transfer(),210 )211 }212213 fn approve(214 &self,215 sender: T::CrossAccountId,216 spender: T::CrossAccountId,217 token: TokenId,218 amount: u128,219 ) -> DispatchResultWithPostInfo {220 with_weight(221 <Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),222 <CommonWeights<T>>::approve(),223 )224 }225226 fn transfer_from(227 &self,228 sender: T::CrossAccountId,229 from: T::CrossAccountId,230 to: T::CrossAccountId,231 token: TokenId,232 amount: u128,233 nesting_budget: &dyn Budget,234 ) -> DispatchResultWithPostInfo {235 with_weight(236 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),237 <CommonWeights<T>>::transfer_from(),238 )239 }240241 fn burn_from(242 &self,243 sender: T::CrossAccountId,244 from: T::CrossAccountId,245 token: TokenId,246 amount: u128,247 nesting_budget: &dyn Budget,248 ) -> DispatchResultWithPostInfo {249 with_weight(250 <Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),251 <CommonWeights<T>>::burn_from(),252 )253 }254255 fn change_collection_properties(256 &self,257 _sender: T::CrossAccountId,258 _property: Vec<Property>,259 ) -> DispatchResultWithPostInfo {260 fail!(<Error<T>>::PropertiesNotAllowed)261 }262263 fn change_token_properties(264 &self,265 _sender: T::CrossAccountId,266 _token_id: TokenId,267 _property: Vec<Property>,268 ) -> DispatchResultWithPostInfo {269 fail!(<Error<T>>::PropertiesNotAllowed)270 }271272 fn set_variable_metadata(273 &self,274 sender: T::CrossAccountId,275 token: TokenId,276 data: BoundedVec<u8, CustomDataLimit>,277 ) -> DispatchResultWithPostInfo {278 let len = data.len();279 with_weight(280 <Pallet<T>>::set_variable_metadata(self, &sender, token, data),281 <CommonWeights<T>>::set_variable_metadata(len as u32),282 )283 }284285 fn check_nesting(286 &self,287 _sender: <T>::CrossAccountId,288 _from: (CollectionId, TokenId),289 _under: TokenId,290 _budget: &dyn Budget,291 ) -> sp_runtime::DispatchResult {292 fail!(<Error<T>>::RefungibleDisallowsNesting)293 }294295 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {296 <Owned<T>>::iter_prefix((self.id, account))297 .map(|(id, _)| id)298 .collect()299 }300301 fn collection_tokens(&self) -> Vec<TokenId> {302 <TokenData<T>>::iter_prefix((self.id,))303 .map(|(id, _)| id)304 .collect()305 }306307 fn token_exists(&self, token: TokenId) -> bool {308 <Pallet<T>>::token_exists(self, token)309 }310311 fn last_token_id(&self) -> TokenId {312 TokenId(<TokensMinted<T>>::get(self.id))313 }314315 fn token_owner(&self, _token: TokenId) -> Option<T::CrossAccountId> {316 None317 }318 fn const_metadata(&self, token: TokenId) -> Vec<u8> {319 <TokenData<T>>::get((self.id, token))320 .const_data321 .into_inner()322 }323 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {324 <TokenData<T>>::get((self.id, token))325 .variable_data326 .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 <Balance<T>>::get((self.id, token, account))339 }340341 fn allowance(342 &self,343 sender: T::CrossAccountId,344 spender: T::CrossAccountId,345 token: TokenId,346 ) -> u128 {347 <Allowance<T>>::get((self.id, token, sender, spender))348 }349}