difftreelog
fix use OptionQuery for TokenProperties
in: master
9 files changed
pallets/balances-adapter/src/common.rsdiffbeforeafterboth--- a/pallets/balances-adapter/src/common.rs
+++ b/pallets/balances-adapter/src/common.rs
@@ -172,18 +172,16 @@
fail!(<pallet_common::Error<T>>::UnsupportedOperation);
}
- fn get_token_properties_map(&self, _token_id: TokenId) -> up_data_structs::TokenProperties {
+ fn get_token_properties_raw(
+ &self,
+ _token_id: TokenId,
+ ) -> Option<up_data_structs::TokenProperties> {
// No token properties are defined on fungibles
- up_data_structs::TokenProperties::new()
+ None
}
- fn set_token_properties_map(&self, _token_id: TokenId, _map: up_data_structs::TokenProperties) {
- // No token properties are defined on fungibles
- }
-
- fn properties_exist(&self, _token: TokenId) -> bool {
+ fn set_token_properties_raw(&self, _token_id: TokenId, _map: up_data_structs::TokenProperties) {
// No token properties are defined on fungibles
- false
}
fn set_token_property_permissions(
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -2098,18 +2098,13 @@
/// Get token properties raw map.
///
/// * `token_id` - The token which properties are needed.
- fn get_token_properties_map(&self, token_id: TokenId) -> TokenProperties;
+ fn get_token_properties_raw(&self, token_id: TokenId) -> Option<TokenProperties>;
/// Set token properties raw map.
///
/// * `token_id` - The token for which the properties are being set.
/// * `map` - The raw map containing the token's properties.
- fn set_token_properties_map(&self, token_id: TokenId, map: TokenProperties);
-
- /// Whether the given token has properties.
- ///
- /// * `token_id` - The token in question.
- fn properties_exist(&self, token: TokenId) -> bool;
+ fn set_token_properties_raw(&self, token_id: TokenId, map: TokenProperties);
/// Set token property permissions.
///
@@ -2590,7 +2585,7 @@
<PalletEvm<T>>::deposit_log(log);
self.collection
- .set_token_properties_map(token_id, stored_properties.into_inner());
+ .set_token_properties_raw(token_id, stored_properties.into_inner());
}
Ok(())
@@ -2624,7 +2619,7 @@
true
},
get_properties: |token_id| {
- debug_assert!(!collection.properties_exist(token_id));
+ debug_assert!(collection.get_token_properties_raw(token_id).is_none());
TokenProperties::new()
},
_phantom: PhantomData,
@@ -2686,7 +2681,11 @@
is_collection_admin: LazyValue::new(|| collection.is_owner_or_admin(sender)),
property_permissions: LazyValue::new(|| <Pallet<T>>::property_permissions(collection.id)),
check_token_exist: |token_id| collection.token_exists(token_id),
- get_properties: |token_id| collection.get_token_properties_map(token_id),
+ get_properties: |token_id| {
+ collection
+ .get_token_properties_raw(token_id)
+ .unwrap_or_default()
+ },
_phantom: PhantomData,
}
}
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -364,18 +364,16 @@
fail!(<Error<T>>::SettingPropertiesNotAllowed)
}
- fn get_token_properties_map(&self, _token_id: TokenId) -> up_data_structs::TokenProperties {
+ fn get_token_properties_raw(
+ &self,
+ _token_id: TokenId,
+ ) -> Option<up_data_structs::TokenProperties> {
// No token properties are defined on fungibles
- up_data_structs::TokenProperties::new()
+ None
}
- fn set_token_properties_map(&self, _token_id: TokenId, _map: up_data_structs::TokenProperties) {
- // No token properties are defined on fungibles
- }
-
- fn properties_exist(&self, _token: TokenId) -> bool {
+ fn set_token_properties_raw(&self, _token_id: TokenId, _map: up_data_structs::TokenProperties) {
// No token properties are defined on fungibles
- false
}
fn check_nesting(
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -265,12 +265,15 @@
)
}
- fn get_token_properties_map(&self, token_id: TokenId) -> up_data_structs::TokenProperties {
+ fn get_token_properties_raw(
+ &self,
+ token_id: TokenId,
+ ) -> Option<up_data_structs::TokenProperties> {
<TokenProperties<T>>::get((self.id, token_id))
}
- fn set_token_properties_map(&self, token_id: TokenId, map: up_data_structs::TokenProperties) {
- <TokenProperties<T>>::set((self.id, token_id), map)
+ fn set_token_properties_raw(&self, token_id: TokenId, map: up_data_structs::TokenProperties) {
+ <TokenProperties<T>>::insert((self.id, token_id), map)
}
fn set_token_property_permissions(
@@ -287,10 +290,6 @@
)
}
- fn properties_exist(&self, token: TokenId) -> bool {
- <TokenProperties<T>>::contains_key((self.id, token))
- }
-
fn burn_item(
&self,
sender: T::CrossAccountId,
@@ -482,13 +481,15 @@
}
fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {
- <Pallet<T>>::token_properties((self.id, token_id))
+ <Pallet<T>>::token_properties((self.id, token_id))?
.get(key)
.cloned()
}
fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {
- let properties = <Pallet<T>>::token_properties((self.id, token_id));
+ let Some(properties) = <Pallet<T>>::token_properties((self.id, token_id)) else {
+ return vec![];
+ };
keys.map(|keys| {
keys.into_iter()
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -272,7 +272,8 @@
.try_into()
.map_err(|_| "key too long")?;
- let props = <TokenProperties<T>>::get((self.id, token_id));
+ let props =
+ <TokenProperties<T>>::get((self.id, token_id)).ok_or("Token properties not found")?;
let prop = props.get(&key).ok_or("key not found")?;
Ok(prop.to_vec().into())
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -102,8 +102,8 @@
use up_data_structs::{
AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData,
mapping::TokenAddressMapping, budget::Budget, Property, PropertyKey, PropertyValue,
- PropertyKeyPermission, PropertyScope, TrySetProperty, TokenChild, AuxPropertyValue,
- PropertiesPermissionMap, TokenProperties as TokenPropertiesT,
+ PropertyKeyPermission, PropertyScope, TokenChild, AuxPropertyValue, PropertiesPermissionMap,
+ TokenProperties as TokenPropertiesT,
};
use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
use pallet_common::{
@@ -201,7 +201,7 @@
pub type TokenProperties<T: Config> = StorageNMap<
Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
Value = TokenPropertiesT,
- QueryKind = ValueQuery,
+ QueryKind = OptionQuery,
>;
/// Custom data of a token that is serialized to bytes,
@@ -340,40 +340,8 @@
/// - `token`: Token ID.
pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {
<TokenData<T>>::contains_key((collection.id, token))
- }
-
- /// Set the token property with the scope.
- ///
- /// - `property`: Contains key-value pair.
- pub fn set_scoped_token_property(
- collection_id: CollectionId,
- token_id: TokenId,
- scope: PropertyScope,
- property: Property,
- ) -> DispatchResult {
- TokenProperties::<T>::try_mutate((collection_id, token_id), |properties| {
- properties.try_scoped_set(scope, property.key, property.value)
- })
- .map_err(<CommonError<T>>::from)?;
-
- Ok(())
}
- /// Batch operation to set multiple properties with the same scope.
- pub fn set_scoped_token_properties(
- collection_id: CollectionId,
- token_id: TokenId,
- scope: PropertyScope,
- properties: impl Iterator<Item = Property>,
- ) -> DispatchResult {
- TokenProperties::<T>::try_mutate((collection_id, token_id), |stored_properties| {
- stored_properties.try_scoped_set_from_iter(scope, properties)
- })
- .map_err(<CommonError<T>>::from)?;
-
- Ok(())
- }
-
/// Add or edit auxiliary data for the property.
///
/// - `f`: function that adds or edits auxiliary data.
@@ -1394,7 +1362,9 @@
pub fn repair_item(collection: &NonfungibleHandle<T>, token: TokenId) -> DispatchResult {
<TokenProperties<T>>::mutate((collection.id, token), |properties| {
- properties.recompute_consumed_space();
+ if let Some(properties) = properties {
+ properties.recompute_consumed_space();
+ }
});
Ok(())
pallets/refungible/src/common.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use core::marker::PhantomData;1819use sp_std::collections::btree_map::BTreeMap;20use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};21use up_data_structs::{22 CollectionId, TokenId, CreateItemExData, budget::Budget, Property, PropertyKey, PropertyValue,23 PropertyKeyPermission, CreateRefungibleExMultipleOwners, CreateRefungibleExSingleOwner,24 TokenOwnerError,25};26use pallet_common::{27 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,28 weights::WeightInfo as _, init_token_properties_delta,29};30use pallet_structure::{Pallet as PalletStructure, Error as StructureError};31use sp_runtime::{DispatchError};32use sp_std::{vec::Vec, vec};3334use crate::{35 AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle,36 SelfWeightOf, weights::WeightInfo, TokensMinted, TotalSupply, CreateItemData, TokenProperties,37};3839macro_rules! max_weight_of {40 ($($method:ident ($($args:tt)*)),*) => {41 Weight::zero()42 $(43 .max(<SelfWeightOf<T>>::$method($($args)*))44 )*45 };46}4748pub struct CommonWeights<T: Config>(PhantomData<T>);49impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {50 fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {51 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(52 init_token_properties_delta::<T, _>(53 data.iter().map(|data| match data {54 up_data_structs::CreateItemData::ReFungible(rft_data) => {55 rft_data.properties.len() as u3256 }57 _ => 0,58 }),59 <SelfWeightOf<T>>::init_token_properties,60 ),61 )62 }6364 fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {65 match call {66 CreateItemExData::RefungibleMultipleOwners(i) => {67 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)68 .saturating_add(init_token_properties_delta::<T, _>(69 [i.properties.len() as u32].into_iter(),70 <SelfWeightOf<T>>::init_token_properties,71 ))72 }73 CreateItemExData::RefungibleMultipleItems(i) => {74 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)75 .saturating_add(init_token_properties_delta::<T, _>(76 i.iter().map(|d| d.properties.len() as u32),77 <SelfWeightOf<T>>::init_token_properties,78 ))79 }80 _ => Weight::zero(),81 }82 }8384 fn burn_item() -> Weight {85 max_weight_of!(burn_item_partial(), burn_item_fully())86 }8788 fn set_collection_properties(amount: u32) -> Weight {89 <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)90 }9192 fn delete_collection_properties(amount: u32) -> Weight {93 <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)94 }9596 fn set_token_properties(amount: u32) -> Weight {97 <SelfWeightOf<T>>::set_token_properties(amount)98 }99100 fn delete_token_properties(amount: u32) -> Weight {101 <SelfWeightOf<T>>::delete_token_properties(amount)102 }103104 fn set_token_property_permissions(amount: u32) -> Weight {105 <SelfWeightOf<T>>::set_token_property_permissions(amount)106 }107108 fn transfer() -> Weight {109 max_weight_of!(110 transfer_normal(),111 transfer_creating(),112 transfer_removing(),113 transfer_creating_removing()114 )115 }116117 fn approve() -> Weight {118 <SelfWeightOf<T>>::approve()119 }120121 fn approve_from() -> Weight {122 <SelfWeightOf<T>>::approve_from()123 }124125 fn transfer_from() -> Weight {126 max_weight_of!(127 transfer_from_normal(),128 transfer_from_creating(),129 transfer_from_removing(),130 transfer_from_creating_removing()131 )132 }133134 fn burn_from() -> Weight {135 <SelfWeightOf<T>>::burn_from()136 }137138 fn burn_recursively_self_raw() -> Weight {139 // Read to get total balance140 Self::burn_item() + T::DbWeight::get().reads(1)141 }142 fn burn_recursively_breadth_raw(_amount: u32) -> Weight {143 // Refungible token can't have children144 Weight::zero()145 }146147 fn token_owner() -> Weight {148 <SelfWeightOf<T>>::token_owner()149 }150151 fn set_allowance_for_all() -> Weight {152 <SelfWeightOf<T>>::set_allowance_for_all()153 }154155 fn force_repair_item() -> Weight {156 <SelfWeightOf<T>>::repair_item()157 }158}159160fn map_create_data<T: Config>(161 data: up_data_structs::CreateItemData,162 to: &T::CrossAccountId,163) -> Result<CreateItemData<T>, DispatchError> {164 match data {165 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData::<T> {166 users: {167 let mut out = BTreeMap::new();168 out.insert(to.clone(), data.pieces);169 out.try_into().expect("limit > 0")170 },171 properties: data.properties,172 }),173 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),174 }175}176177/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete178/// methods and adds weight info.179impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {180 fn create_item(181 &self,182 sender: T::CrossAccountId,183 to: T::CrossAccountId,184 data: up_data_structs::CreateItemData,185 nesting_budget: &dyn Budget,186 ) -> DispatchResultWithPostInfo {187 let weight = <CommonWeights<T>>::create_item(&data);188 with_weight(189 <Pallet<T>>::create_item(190 self,191 &sender,192 map_create_data::<T>(data, &to)?,193 nesting_budget,194 ),195 weight,196 )197 }198199 fn create_multiple_items(200 &self,201 sender: T::CrossAccountId,202 to: T::CrossAccountId,203 data: Vec<up_data_structs::CreateItemData>,204 nesting_budget: &dyn Budget,205 ) -> DispatchResultWithPostInfo {206 let weight = <CommonWeights<T>>::create_multiple_items(&data);207 let data = data208 .into_iter()209 .map(|d| map_create_data::<T>(d, &to))210 .collect::<Result<Vec<_>, DispatchError>>()?;211212 with_weight(213 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),214 weight,215 )216 }217218 fn create_multiple_items_ex(219 &self,220 sender: <T>::CrossAccountId,221 data: CreateItemExData<T::CrossAccountId>,222 nesting_budget: &dyn Budget,223 ) -> DispatchResultWithPostInfo {224 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);225 let data = match data {226 CreateItemExData::RefungibleMultipleOwners(CreateRefungibleExMultipleOwners {227 users,228 properties,229 }) => vec![CreateItemData::<T> { users, properties }],230 CreateItemExData::RefungibleMultipleItems(r) => r231 .into_inner()232 .into_iter()233 .map(234 |CreateRefungibleExSingleOwner {235 user,236 pieces,237 properties,238 }| CreateItemData::<T> {239 users: BTreeMap::from([(user, pieces)])240 .try_into()241 .expect("limit >= 1"),242 properties,243 },244 )245 .collect(),246 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),247 };248249 with_weight(250 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),251 weight,252 )253 }254255 fn burn_item(256 &self,257 sender: T::CrossAccountId,258 token: TokenId,259 amount: u128,260 ) -> DispatchResultWithPostInfo {261 with_weight(262 <Pallet<T>>::burn(self, &sender, token, amount),263 <CommonWeights<T>>::burn_item(),264 )265 }266267 fn burn_item_recursively(268 &self,269 sender: T::CrossAccountId,270 token: TokenId,271 self_budget: &dyn Budget,272 _breadth_budget: &dyn Budget,273 ) -> DispatchResultWithPostInfo {274 ensure!(self_budget.consume(), <StructureError<T>>::DepthLimit,);275 with_weight(276 <Pallet<T>>::burn(277 self,278 &sender,279 token,280 <Balance<T>>::get((self.id, token, &sender)),281 ),282 <CommonWeights<T>>::burn_recursively_self_raw(),283 )284 }285286 fn transfer(287 &self,288 from: T::CrossAccountId,289 to: T::CrossAccountId,290 token: TokenId,291 amount: u128,292 nesting_budget: &dyn Budget,293 ) -> DispatchResultWithPostInfo {294 with_weight(295 <Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),296 <CommonWeights<T>>::transfer(),297 )298 }299300 fn approve(301 &self,302 sender: T::CrossAccountId,303 spender: T::CrossAccountId,304 token: TokenId,305 amount: u128,306 ) -> DispatchResultWithPostInfo {307 with_weight(308 <Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),309 <CommonWeights<T>>::approve(),310 )311 }312313 fn approve_from(314 &self,315 sender: T::CrossAccountId,316 from: T::CrossAccountId,317 to: T::CrossAccountId,318 token_id: TokenId,319 amount: u128,320 ) -> DispatchResultWithPostInfo {321 with_weight(322 <Pallet<T>>::set_allowance_from(self, &sender, &from, &to, token_id, amount),323 <CommonWeights<T>>::approve_from(),324 )325 }326327 fn transfer_from(328 &self,329 sender: T::CrossAccountId,330 from: T::CrossAccountId,331 to: T::CrossAccountId,332 token: TokenId,333 amount: u128,334 nesting_budget: &dyn Budget,335 ) -> DispatchResultWithPostInfo {336 with_weight(337 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),338 <CommonWeights<T>>::transfer_from(),339 )340 }341342 fn burn_from(343 &self,344 sender: T::CrossAccountId,345 from: T::CrossAccountId,346 token: TokenId,347 amount: u128,348 nesting_budget: &dyn Budget,349 ) -> DispatchResultWithPostInfo {350 with_weight(351 <Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),352 <CommonWeights<T>>::burn_from(),353 )354 }355356 fn set_collection_properties(357 &self,358 sender: T::CrossAccountId,359 properties: Vec<Property>,360 ) -> DispatchResultWithPostInfo {361 let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);362363 with_weight(364 <Pallet<T>>::set_collection_properties(self, &sender, properties),365 weight,366 )367 }368369 fn delete_collection_properties(370 &self,371 sender: &T::CrossAccountId,372 property_keys: Vec<PropertyKey>,373 ) -> DispatchResultWithPostInfo {374 let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);375376 with_weight(377 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),378 weight,379 )380 }381382 fn set_token_properties(383 &self,384 sender: T::CrossAccountId,385 token_id: TokenId,386 properties: Vec<Property>,387 nesting_budget: &dyn Budget,388 ) -> DispatchResultWithPostInfo {389 let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);390391 with_weight(392 <Pallet<T>>::set_token_properties(393 self,394 &sender,395 token_id,396 properties.into_iter(),397 nesting_budget,398 ),399 weight,400 )401 }402403 fn set_token_property_permissions(404 &self,405 sender: &T::CrossAccountId,406 property_permissions: Vec<PropertyKeyPermission>,407 ) -> DispatchResultWithPostInfo {408 let weight =409 <CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);410411 with_weight(412 <Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),413 weight,414 )415 }416417 fn delete_token_properties(418 &self,419 sender: T::CrossAccountId,420 token_id: TokenId,421 property_keys: Vec<PropertyKey>,422 nesting_budget: &dyn Budget,423 ) -> DispatchResultWithPostInfo {424 let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);425426 with_weight(427 <Pallet<T>>::delete_token_properties(428 self,429 &sender,430 token_id,431 property_keys.into_iter(),432 nesting_budget,433 ),434 weight,435 )436 }437438 fn get_token_properties_map(&self, token_id: TokenId) -> up_data_structs::TokenProperties {439 <TokenProperties<T>>::get((self.id, token_id))440 }441442 fn set_token_properties_map(&self, token_id: TokenId, map: up_data_structs::TokenProperties) {443 <TokenProperties<T>>::set((self.id, token_id), map)444 }445446 fn properties_exist(&self, token: TokenId) -> bool {447 <TokenProperties<T>>::contains_key((self.id, token))448 }449450 fn check_nesting(451 &self,452 _sender: <T>::CrossAccountId,453 _from: (CollectionId, TokenId),454 _under: TokenId,455 _nesting_budget: &dyn Budget,456 ) -> sp_runtime::DispatchResult {457 fail!(<Error<T>>::RefungibleDisallowsNesting)458 }459460 fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}461462 fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}463464 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {465 <Owned<T>>::iter_prefix((self.id, account))466 .map(|(id, _)| id)467 .collect()468 }469470 fn collection_tokens(&self) -> Vec<TokenId> {471 <TotalSupply<T>>::iter_prefix((self.id,))472 .map(|(id, _)| id)473 .collect()474 }475476 fn token_exists(&self, token: TokenId) -> bool {477 <Pallet<T>>::token_exists(self, token)478 }479480 fn last_token_id(&self) -> TokenId {481 TokenId(<TokensMinted<T>>::get(self.id))482 }483484 fn token_owner(&self, token: TokenId) -> Result<T::CrossAccountId, TokenOwnerError> {485 <Pallet<T>>::token_owner(self.id, token)486 }487488 fn check_token_indirect_owner(489 &self,490 token: TokenId,491 maybe_owner: &T::CrossAccountId,492 nesting_budget: &dyn Budget,493 ) -> Result<bool, DispatchError> {494 let balance = self.balance(maybe_owner.clone(), token);495 let total_pieces: u128 = <Pallet<T>>::total_pieces(self.id, token).unwrap_or(u128::MAX);496 if balance != total_pieces {497 return Ok(false);498 }499500 let is_bundle_owner = <PalletStructure<T>>::check_indirectly_owned(501 maybe_owner.clone(),502 self.id,503 token,504 None,505 nesting_budget,506 )?;507508 Ok(is_bundle_owner)509 }510511 /// Returns 10 token in no particular order.512 fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {513 <Pallet<T>>::token_owners(self.id, token).unwrap_or_default()514 }515516 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {517 <Pallet<T>>::token_properties((self.id, token_id))518 .get(key)519 .cloned()520 }521522 fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {523 let properties = <Pallet<T>>::token_properties((self.id, token_id));524525 keys.map(|keys| {526 keys.into_iter()527 .filter_map(|key| {528 properties.get(&key).map(|value| Property {529 key,530 value: value.clone(),531 })532 })533 .collect()534 })535 .unwrap_or_else(|| {536 properties537 .into_iter()538 .map(|(key, value)| Property { key, value })539 .collect()540 })541 }542543 fn total_supply(&self) -> u32 {544 <Pallet<T>>::total_supply(self)545 }546547 fn account_balance(&self, account: T::CrossAccountId) -> u32 {548 <AccountBalance<T>>::get((self.id, account))549 }550551 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {552 <Balance<T>>::get((self.id, token, account))553 }554555 fn allowance(556 &self,557 sender: T::CrossAccountId,558 spender: T::CrossAccountId,559 token: TokenId,560 ) -> u128 {561 <Allowance<T>>::get((self.id, token, sender, spender))562 }563564 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {565 Some(self)566 }567568 fn total_pieces(&self, token: TokenId) -> Option<u128> {569 <Pallet<T>>::total_pieces(self.id, token)570 }571572 fn set_allowance_for_all(573 &self,574 owner: T::CrossAccountId,575 operator: T::CrossAccountId,576 approve: bool,577 ) -> DispatchResultWithPostInfo {578 with_weight(579 <Pallet<T>>::set_allowance_for_all(self, &owner, &operator, approve),580 <CommonWeights<T>>::set_allowance_for_all(),581 )582 }583584 fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {585 <Pallet<T>>::allowance_for_all(self, &owner, &operator)586 }587588 fn repair_item(&self, token: TokenId) -> DispatchResultWithPostInfo {589 with_weight(590 <Pallet<T>>::repair_item(self, token),591 <CommonWeights<T>>::force_repair_item(),592 )593 }594}595596impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {597 fn repartition(598 &self,599 owner: &T::CrossAccountId,600 token: TokenId,601 amount: u128,602 ) -> DispatchResultWithPostInfo {603 with_weight(604 <Pallet<T>>::repartition(self, owner, token, amount),605 <SelfWeightOf<T>>::repartition_item(),606 )607 }608}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use core::marker::PhantomData;1819use sp_std::collections::btree_map::BTreeMap;20use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};21use up_data_structs::{22 CollectionId, TokenId, CreateItemExData, budget::Budget, Property, PropertyKey, PropertyValue,23 PropertyKeyPermission, CreateRefungibleExMultipleOwners, CreateRefungibleExSingleOwner,24 TokenOwnerError,25};26use pallet_common::{27 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,28 weights::WeightInfo as _, init_token_properties_delta,29};30use pallet_structure::{Pallet as PalletStructure, Error as StructureError};31use sp_runtime::{DispatchError};32use sp_std::{vec::Vec, vec};3334use crate::{35 AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle,36 SelfWeightOf, weights::WeightInfo, TokensMinted, TotalSupply, CreateItemData, TokenProperties,37};3839macro_rules! max_weight_of {40 ($($method:ident ($($args:tt)*)),*) => {41 Weight::zero()42 $(43 .max(<SelfWeightOf<T>>::$method($($args)*))44 )*45 };46}4748pub struct CommonWeights<T: Config>(PhantomData<T>);49impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {50 fn create_multiple_items(data: &[up_data_structs::CreateItemData]) -> Weight {51 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(52 init_token_properties_delta::<T, _>(53 data.iter().map(|data| match data {54 up_data_structs::CreateItemData::ReFungible(rft_data) => {55 rft_data.properties.len() as u3256 }57 _ => 0,58 }),59 <SelfWeightOf<T>>::init_token_properties,60 ),61 )62 }6364 fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {65 match call {66 CreateItemExData::RefungibleMultipleOwners(i) => {67 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)68 .saturating_add(init_token_properties_delta::<T, _>(69 [i.properties.len() as u32].into_iter(),70 <SelfWeightOf<T>>::init_token_properties,71 ))72 }73 CreateItemExData::RefungibleMultipleItems(i) => {74 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)75 .saturating_add(init_token_properties_delta::<T, _>(76 i.iter().map(|d| d.properties.len() as u32),77 <SelfWeightOf<T>>::init_token_properties,78 ))79 }80 _ => Weight::zero(),81 }82 }8384 fn burn_item() -> Weight {85 max_weight_of!(burn_item_partial(), burn_item_fully())86 }8788 fn set_collection_properties(amount: u32) -> Weight {89 <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)90 }9192 fn delete_collection_properties(amount: u32) -> Weight {93 <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)94 }9596 fn set_token_properties(amount: u32) -> Weight {97 <SelfWeightOf<T>>::set_token_properties(amount)98 }99100 fn delete_token_properties(amount: u32) -> Weight {101 <SelfWeightOf<T>>::delete_token_properties(amount)102 }103104 fn set_token_property_permissions(amount: u32) -> Weight {105 <SelfWeightOf<T>>::set_token_property_permissions(amount)106 }107108 fn transfer() -> Weight {109 max_weight_of!(110 transfer_normal(),111 transfer_creating(),112 transfer_removing(),113 transfer_creating_removing()114 )115 }116117 fn approve() -> Weight {118 <SelfWeightOf<T>>::approve()119 }120121 fn approve_from() -> Weight {122 <SelfWeightOf<T>>::approve_from()123 }124125 fn transfer_from() -> Weight {126 max_weight_of!(127 transfer_from_normal(),128 transfer_from_creating(),129 transfer_from_removing(),130 transfer_from_creating_removing()131 )132 }133134 fn burn_from() -> Weight {135 <SelfWeightOf<T>>::burn_from()136 }137138 fn burn_recursively_self_raw() -> Weight {139 // Read to get total balance140 Self::burn_item() + T::DbWeight::get().reads(1)141 }142 fn burn_recursively_breadth_raw(_amount: u32) -> Weight {143 // Refungible token can't have children144 Weight::zero()145 }146147 fn token_owner() -> Weight {148 <SelfWeightOf<T>>::token_owner()149 }150151 fn set_allowance_for_all() -> Weight {152 <SelfWeightOf<T>>::set_allowance_for_all()153 }154155 fn force_repair_item() -> Weight {156 <SelfWeightOf<T>>::repair_item()157 }158}159160fn map_create_data<T: Config>(161 data: up_data_structs::CreateItemData,162 to: &T::CrossAccountId,163) -> Result<CreateItemData<T>, DispatchError> {164 match data {165 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData::<T> {166 users: {167 let mut out = BTreeMap::new();168 out.insert(to.clone(), data.pieces);169 out.try_into().expect("limit > 0")170 },171 properties: data.properties,172 }),173 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),174 }175}176177/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete178/// methods and adds weight info.179impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {180 fn create_item(181 &self,182 sender: T::CrossAccountId,183 to: T::CrossAccountId,184 data: up_data_structs::CreateItemData,185 nesting_budget: &dyn Budget,186 ) -> DispatchResultWithPostInfo {187 let weight = <CommonWeights<T>>::create_item(&data);188 with_weight(189 <Pallet<T>>::create_item(190 self,191 &sender,192 map_create_data::<T>(data, &to)?,193 nesting_budget,194 ),195 weight,196 )197 }198199 fn create_multiple_items(200 &self,201 sender: T::CrossAccountId,202 to: T::CrossAccountId,203 data: Vec<up_data_structs::CreateItemData>,204 nesting_budget: &dyn Budget,205 ) -> DispatchResultWithPostInfo {206 let weight = <CommonWeights<T>>::create_multiple_items(&data);207 let data = data208 .into_iter()209 .map(|d| map_create_data::<T>(d, &to))210 .collect::<Result<Vec<_>, DispatchError>>()?;211212 with_weight(213 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),214 weight,215 )216 }217218 fn create_multiple_items_ex(219 &self,220 sender: <T>::CrossAccountId,221 data: CreateItemExData<T::CrossAccountId>,222 nesting_budget: &dyn Budget,223 ) -> DispatchResultWithPostInfo {224 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);225 let data = match data {226 CreateItemExData::RefungibleMultipleOwners(CreateRefungibleExMultipleOwners {227 users,228 properties,229 }) => vec![CreateItemData::<T> { users, properties }],230 CreateItemExData::RefungibleMultipleItems(r) => r231 .into_inner()232 .into_iter()233 .map(234 |CreateRefungibleExSingleOwner {235 user,236 pieces,237 properties,238 }| CreateItemData::<T> {239 users: BTreeMap::from([(user, pieces)])240 .try_into()241 .expect("limit >= 1"),242 properties,243 },244 )245 .collect(),246 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),247 };248249 with_weight(250 <Pallet<T>>::create_multiple_items(self, &sender, data, nesting_budget),251 weight,252 )253 }254255 fn burn_item(256 &self,257 sender: T::CrossAccountId,258 token: TokenId,259 amount: u128,260 ) -> DispatchResultWithPostInfo {261 with_weight(262 <Pallet<T>>::burn(self, &sender, token, amount),263 <CommonWeights<T>>::burn_item(),264 )265 }266267 fn burn_item_recursively(268 &self,269 sender: T::CrossAccountId,270 token: TokenId,271 self_budget: &dyn Budget,272 _breadth_budget: &dyn Budget,273 ) -> DispatchResultWithPostInfo {274 ensure!(self_budget.consume(), <StructureError<T>>::DepthLimit,);275 with_weight(276 <Pallet<T>>::burn(277 self,278 &sender,279 token,280 <Balance<T>>::get((self.id, token, &sender)),281 ),282 <CommonWeights<T>>::burn_recursively_self_raw(),283 )284 }285286 fn transfer(287 &self,288 from: T::CrossAccountId,289 to: T::CrossAccountId,290 token: TokenId,291 amount: u128,292 nesting_budget: &dyn Budget,293 ) -> DispatchResultWithPostInfo {294 with_weight(295 <Pallet<T>>::transfer(self, &from, &to, token, amount, nesting_budget),296 <CommonWeights<T>>::transfer(),297 )298 }299300 fn approve(301 &self,302 sender: T::CrossAccountId,303 spender: T::CrossAccountId,304 token: TokenId,305 amount: u128,306 ) -> DispatchResultWithPostInfo {307 with_weight(308 <Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),309 <CommonWeights<T>>::approve(),310 )311 }312313 fn approve_from(314 &self,315 sender: T::CrossAccountId,316 from: T::CrossAccountId,317 to: T::CrossAccountId,318 token_id: TokenId,319 amount: u128,320 ) -> DispatchResultWithPostInfo {321 with_weight(322 <Pallet<T>>::set_allowance_from(self, &sender, &from, &to, token_id, amount),323 <CommonWeights<T>>::approve_from(),324 )325 }326327 fn transfer_from(328 &self,329 sender: T::CrossAccountId,330 from: T::CrossAccountId,331 to: T::CrossAccountId,332 token: TokenId,333 amount: u128,334 nesting_budget: &dyn Budget,335 ) -> DispatchResultWithPostInfo {336 with_weight(337 <Pallet<T>>::transfer_from(self, &sender, &from, &to, token, amount, nesting_budget),338 <CommonWeights<T>>::transfer_from(),339 )340 }341342 fn burn_from(343 &self,344 sender: T::CrossAccountId,345 from: T::CrossAccountId,346 token: TokenId,347 amount: u128,348 nesting_budget: &dyn Budget,349 ) -> DispatchResultWithPostInfo {350 with_weight(351 <Pallet<T>>::burn_from(self, &sender, &from, token, amount, nesting_budget),352 <CommonWeights<T>>::burn_from(),353 )354 }355356 fn set_collection_properties(357 &self,358 sender: T::CrossAccountId,359 properties: Vec<Property>,360 ) -> DispatchResultWithPostInfo {361 let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);362363 with_weight(364 <Pallet<T>>::set_collection_properties(self, &sender, properties),365 weight,366 )367 }368369 fn delete_collection_properties(370 &self,371 sender: &T::CrossAccountId,372 property_keys: Vec<PropertyKey>,373 ) -> DispatchResultWithPostInfo {374 let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);375376 with_weight(377 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),378 weight,379 )380 }381382 fn set_token_properties(383 &self,384 sender: T::CrossAccountId,385 token_id: TokenId,386 properties: Vec<Property>,387 nesting_budget: &dyn Budget,388 ) -> DispatchResultWithPostInfo {389 let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);390391 with_weight(392 <Pallet<T>>::set_token_properties(393 self,394 &sender,395 token_id,396 properties.into_iter(),397 nesting_budget,398 ),399 weight,400 )401 }402403 fn set_token_property_permissions(404 &self,405 sender: &T::CrossAccountId,406 property_permissions: Vec<PropertyKeyPermission>,407 ) -> DispatchResultWithPostInfo {408 let weight =409 <CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);410411 with_weight(412 <Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),413 weight,414 )415 }416417 fn delete_token_properties(418 &self,419 sender: T::CrossAccountId,420 token_id: TokenId,421 property_keys: Vec<PropertyKey>,422 nesting_budget: &dyn Budget,423 ) -> DispatchResultWithPostInfo {424 let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);425426 with_weight(427 <Pallet<T>>::delete_token_properties(428 self,429 &sender,430 token_id,431 property_keys.into_iter(),432 nesting_budget,433 ),434 weight,435 )436 }437438 fn get_token_properties_raw(439 &self,440 token_id: TokenId,441 ) -> Option<up_data_structs::TokenProperties> {442 <TokenProperties<T>>::get((self.id, token_id))443 }444445 fn set_token_properties_raw(&self, token_id: TokenId, map: up_data_structs::TokenProperties) {446 <TokenProperties<T>>::insert((self.id, token_id), map)447 }448449 fn check_nesting(450 &self,451 _sender: <T>::CrossAccountId,452 _from: (CollectionId, TokenId),453 _under: TokenId,454 _nesting_budget: &dyn Budget,455 ) -> sp_runtime::DispatchResult {456 fail!(<Error<T>>::RefungibleDisallowsNesting)457 }458459 fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}460461 fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}462463 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {464 <Owned<T>>::iter_prefix((self.id, account))465 .map(|(id, _)| id)466 .collect()467 }468469 fn collection_tokens(&self) -> Vec<TokenId> {470 <TotalSupply<T>>::iter_prefix((self.id,))471 .map(|(id, _)| id)472 .collect()473 }474475 fn token_exists(&self, token: TokenId) -> bool {476 <Pallet<T>>::token_exists(self, token)477 }478479 fn last_token_id(&self) -> TokenId {480 TokenId(<TokensMinted<T>>::get(self.id))481 }482483 fn token_owner(&self, token: TokenId) -> Result<T::CrossAccountId, TokenOwnerError> {484 <Pallet<T>>::token_owner(self.id, token)485 }486487 fn check_token_indirect_owner(488 &self,489 token: TokenId,490 maybe_owner: &T::CrossAccountId,491 nesting_budget: &dyn Budget,492 ) -> Result<bool, DispatchError> {493 let balance = self.balance(maybe_owner.clone(), token);494 let total_pieces: u128 = <Pallet<T>>::total_pieces(self.id, token).unwrap_or(u128::MAX);495 if balance != total_pieces {496 return Ok(false);497 }498499 let is_bundle_owner = <PalletStructure<T>>::check_indirectly_owned(500 maybe_owner.clone(),501 self.id,502 token,503 None,504 nesting_budget,505 )?;506507 Ok(is_bundle_owner)508 }509510 /// Returns 10 token in no particular order.511 fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {512 <Pallet<T>>::token_owners(self.id, token).unwrap_or_default()513 }514515 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {516 <Pallet<T>>::token_properties((self.id, token_id))?517 .get(key)518 .cloned()519 }520521 fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {522 let Some(properties) = <Pallet<T>>::token_properties((self.id, token_id)) else {523 return vec![];524 };525526 keys.map(|keys| {527 keys.into_iter()528 .filter_map(|key| {529 properties.get(&key).map(|value| Property {530 key,531 value: value.clone(),532 })533 })534 .collect()535 })536 .unwrap_or_else(|| {537 properties538 .into_iter()539 .map(|(key, value)| Property { key, value })540 .collect()541 })542 }543544 fn total_supply(&self) -> u32 {545 <Pallet<T>>::total_supply(self)546 }547548 fn account_balance(&self, account: T::CrossAccountId) -> u32 {549 <AccountBalance<T>>::get((self.id, account))550 }551552 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {553 <Balance<T>>::get((self.id, token, account))554 }555556 fn allowance(557 &self,558 sender: T::CrossAccountId,559 spender: T::CrossAccountId,560 token: TokenId,561 ) -> u128 {562 <Allowance<T>>::get((self.id, token, sender, spender))563 }564565 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>> {566 Some(self)567 }568569 fn total_pieces(&self, token: TokenId) -> Option<u128> {570 <Pallet<T>>::total_pieces(self.id, token)571 }572573 fn set_allowance_for_all(574 &self,575 owner: T::CrossAccountId,576 operator: T::CrossAccountId,577 approve: bool,578 ) -> DispatchResultWithPostInfo {579 with_weight(580 <Pallet<T>>::set_allowance_for_all(self, &owner, &operator, approve),581 <CommonWeights<T>>::set_allowance_for_all(),582 )583 }584585 fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool {586 <Pallet<T>>::allowance_for_all(self, &owner, &operator)587 }588589 fn repair_item(&self, token: TokenId) -> DispatchResultWithPostInfo {590 with_weight(591 <Pallet<T>>::repair_item(self, token),592 <CommonWeights<T>>::force_repair_item(),593 )594 }595}596597impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {598 fn repartition(599 &self,600 owner: &T::CrossAccountId,601 token: TokenId,602 amount: u128,603 ) -> DispatchResultWithPostInfo {604 with_weight(605 <Pallet<T>>::repartition(self, owner, token, amount),606 <SelfWeightOf<T>>::repartition_item(),607 )608 }609}pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -283,7 +283,8 @@
.try_into()
.map_err(|_| "key too long")?;
- let props = <TokenProperties<T>>::get((self.id, token_id));
+ let props =
+ <TokenProperties<T>>::get((self.id, token_id)).ok_or("Token properties not found")?;
let prop = props.get(&key).ok_or("key not found")?;
Ok(prop.to_vec().into())
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -106,8 +106,8 @@
use up_data_structs::{
AccessMode, budget::Budget, CollectionId, CreateCollectionData, mapping::TokenAddressMapping,
MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyScope,
- PropertyValue, TokenId, TrySetProperty, PropertiesPermissionMap,
- CreateRefungibleExMultipleOwners, TokenOwnerError, TokenProperties as TokenPropertiesT,
+ PropertyValue, TokenId, PropertiesPermissionMap, CreateRefungibleExMultipleOwners,
+ TokenOwnerError, TokenProperties as TokenPropertiesT,
};
pub use pallet::*;
@@ -175,7 +175,7 @@
pub type TokenProperties<T: Config> = StorageNMap<
Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
Value = TokenPropertiesT,
- QueryKind = ValueQuery,
+ QueryKind = OptionQuery,
>;
/// Total amount of pieces for token
@@ -292,35 +292,7 @@
/// - `token`: Token ID.
pub fn token_exists(collection: &RefungibleHandle<T>, token: TokenId) -> bool {
<TotalSupply<T>>::contains_key((collection.id, token))
- }
-
- pub fn set_scoped_token_property(
- collection_id: CollectionId,
- token_id: TokenId,
- scope: PropertyScope,
- property: Property,
- ) -> DispatchResult {
- TokenProperties::<T>::try_mutate((collection_id, token_id), |properties| {
- properties.try_scoped_set(scope, property.key, property.value)
- })
- .map_err(<CommonError<T>>::from)?;
-
- Ok(())
}
-
- pub fn set_scoped_token_properties(
- collection_id: CollectionId,
- token_id: TokenId,
- scope: PropertyScope,
- properties: impl Iterator<Item = Property>,
- ) -> DispatchResult {
- TokenProperties::<T>::try_mutate((collection_id, token_id), |stored_properties| {
- stored_properties.try_scoped_set_from_iter(scope, properties)
- })
- .map_err(<CommonError<T>>::from)?;
-
- Ok(())
- }
}
// unchecked calls skips any permission checks
@@ -1426,7 +1398,9 @@
pub fn repair_item(collection: &RefungibleHandle<T>, token: TokenId) -> DispatchResult {
<TokenProperties<T>>::mutate((collection.id, token), |properties| {
- properties.recompute_consumed_space();
+ if let Some(properties) = properties {
+ properties.recompute_consumed_space();
+ }
});
Ok(())