difftreelog
Merge pull request #422 from UniqueNetwork/feature/CORE-410
in: master
Feature/core 410 Properties for RFT
21 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6320,7 +6320,7 @@
[[package]]
name = "pallet-refungible"
-version = "0.1.0"
+version = "0.1.1"
dependencies = [
"frame-benchmarking",
"frame-support",
@@ -12733,7 +12733,7 @@
[[package]]
name = "up-data-structs"
-version = "0.1.0"
+version = "0.1.1"
dependencies = [
"derivative",
"frame-support",
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -966,7 +966,7 @@
),
);
<T as Config>::Currency::settle(
- &owner.as_sub(),
+ owner.as_sub(),
imbalance,
WithdrawReasons::TRANSFER,
ExistenceRequirement::KeepAlive,
pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -183,7 +183,7 @@
value: property_value(),
}).collect::<Vec<_>>();
let item = create_max_item(&collection, &owner, owner.clone())?;
- }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props, false, &Unlimited)?}
+ }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?}
delete_token_properties {
let b in 0..MAX_PROPERTIES_PER_ITEM;
@@ -205,7 +205,7 @@
value: property_value(),
}).collect::<Vec<_>>();
let item = create_max_item(&collection, &owner, owner.clone())?;
- <Pallet<T>>::set_token_properties(&collection, &owner, item, props, false, &Unlimited)?;
+ <Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?;
let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();
- }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete, &Unlimited)?}
+ }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete.into_iter(), &Unlimited)?}
}
pallets/nonfungible/src/weights.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -3,7 +3,7 @@
//! Autogenerated weights for pallet_nonfungible
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-06-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
// Executed Command:
@@ -56,7 +56,7 @@
// Storage: Nonfungible TokenData (r:0 w:1)
// Storage: Nonfungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (24_135_000 as Weight)
+ (20_328_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -65,9 +65,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (21_952_000 as Weight)
- // Standard Error: 5_000
- .saturating_add((4_727_000 as Weight).saturating_mul(b as Weight))
+ (10_134_000 as Weight)
+ // Standard Error: 3_000
+ .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
.saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))
@@ -77,9 +77,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items_ex(b: u32, ) -> Weight {
- (10_432_000 as Weight)
- // Standard Error: 6_000
- .saturating_add((7_383_000 as Weight).saturating_mul(b as Weight))
+ (5_710_000 as Weight)
+ // Standard Error: 4_000
+ .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
@@ -93,7 +93,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_item() -> Weight {
- (29_798_000 as Weight)
+ (28_433_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -105,7 +105,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_recursively_self_raw() -> Weight {
- (37_955_000 as Weight)
+ (34_435_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -119,8 +119,8 @@
// Storage: Common CollectionById (r:1 w:0)
fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_349_000
- .saturating_add((275_145_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_539_000
+ .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
@@ -131,14 +131,14 @@
// Storage: Nonfungible Allowance (r:1 w:0)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer() -> Weight {
- (27_867_000 as Weight)
+ (24_376_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
// Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible Allowance (r:1 w:1)
fn approve() -> Weight {
- (18_824_000 as Weight)
+ (15_890_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -147,7 +147,7 @@
// Storage: Nonfungible AccountBalance (r:2 w:2)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer_from() -> Weight {
- (32_879_000 as Weight)
+ (28_634_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
@@ -159,7 +159,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (37_061_000 as Weight)
+ (32_201_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
@@ -167,28 +167,26 @@
fn set_token_property_permissions(b: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 57_000
- .saturating_add((15_149_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:0)
- // Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn set_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 2_278_000
- .saturating_add((409_613_000 as Weight).saturating_mul(b as Weight))
- .saturating_add(T::DbWeight::get().reads(3 as Weight))
+ // Standard Error: 1_648_000
+ .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:0)
- // Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn delete_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 2_234_000
- .saturating_add((408_185_000 as Weight).saturating_mul(b as Weight))
- .saturating_add(T::DbWeight::get().reads(3 as Weight))
+ // Standard Error: 1_632_000
+ .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
}
@@ -200,7 +198,7 @@
// Storage: Nonfungible TokenData (r:0 w:1)
// Storage: Nonfungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (24_135_000 as Weight)
+ (20_328_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -209,9 +207,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (21_952_000 as Weight)
- // Standard Error: 5_000
- .saturating_add((4_727_000 as Weight).saturating_mul(b as Weight))
+ (10_134_000 as Weight)
+ // Standard Error: 3_000
+ .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
.saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))
@@ -221,9 +219,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items_ex(b: u32, ) -> Weight {
- (10_432_000 as Weight)
- // Standard Error: 6_000
- .saturating_add((7_383_000 as Weight).saturating_mul(b as Weight))
+ (5_710_000 as Weight)
+ // Standard Error: 4_000
+ .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
@@ -237,7 +235,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_item() -> Weight {
- (29_798_000 as Weight)
+ (28_433_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -249,7 +247,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_recursively_self_raw() -> Weight {
- (37_955_000 as Weight)
+ (34_435_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -263,8 +261,8 @@
// Storage: Common CollectionById (r:1 w:0)
fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_349_000
- .saturating_add((275_145_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_539_000
+ .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
@@ -275,14 +273,14 @@
// Storage: Nonfungible Allowance (r:1 w:0)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer() -> Weight {
- (27_867_000 as Weight)
+ (24_376_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
// Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible Allowance (r:1 w:1)
fn approve() -> Weight {
- (18_824_000 as Weight)
+ (15_890_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -291,7 +289,7 @@
// Storage: Nonfungible AccountBalance (r:2 w:2)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer_from() -> Weight {
- (32_879_000 as Weight)
+ (28_634_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
@@ -303,7 +301,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (37_061_000 as Weight)
+ (32_201_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
@@ -311,28 +309,26 @@
fn set_token_property_permissions(b: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 57_000
- .saturating_add((15_149_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:0)
- // Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn set_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 2_278_000
- .saturating_add((409_613_000 as Weight).saturating_mul(b as Weight))
- .saturating_add(RocksDbWeight::get().reads(3 as Weight))
+ // Standard Error: 1_648_000
+ .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:0)
- // Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn delete_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 2_234_000
- .saturating_add((408_185_000 as Weight).saturating_mul(b as Weight))
- .saturating_add(RocksDbWeight::get().reads(3 as Weight))
+ // Standard Error: 1_632_000
+ .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
}
pallets/refungible/Cargo.tomldiffbeforeafterboth--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "pallet-refungible"
-version = "0.1.0"
+version = "0.1.1"
license = "GPLv3"
edition = "2021"
pallets/refungible/Changelog.mddiffbeforeafterboth--- /dev/null
+++ b/pallets/refungible/Changelog.md
@@ -0,0 +1,3 @@
+### 0.1.1
+---
+* Added support for properties for RFT collections and tokens.
pallets/refungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -18,9 +18,12 @@
use crate::{Pallet, Config, RefungibleHandle};
use sp_std::prelude::*;
-use pallet_common::benchmarking::{create_collection_raw, create_data};
+use pallet_common::benchmarking::{create_collection_raw, property_key, property_value, create_data};
use frame_benchmarking::{benchmarks, account};
-use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT, budget::Unlimited};
+use up_data_structs::{
+ CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, CUSTOM_DATA_LIMIT,
+ budget::Unlimited,
+};
use pallet_common::bench_init;
use core::convert::TryInto;
use core::iter::IntoIterator;
@@ -38,6 +41,7 @@
.collect::<BTreeMap<_, _>>()
.try_into()
.unwrap(),
+ properties: Default::default(),
}
}
fn create_max_item<T: Config>(
@@ -204,6 +208,68 @@
<Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;
}: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}
+ set_token_property_permissions {
+ let b in 0..MAX_PROPERTIES_PER_ITEM;
+ bench_init!{
+ owner: sub; collection: collection(owner);
+ owner: cross_from_sub;
+ };
+ let perms = (0..b).map(|k| PropertyKeyPermission {
+ key: property_key(k as usize),
+ permission: PropertyPermission {
+ mutable: false,
+ collection_admin: false,
+ token_owner: false,
+ },
+ }).collect::<Vec<_>>();
+ }: {<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?}
+
+ set_token_properties {
+ let b in 0..MAX_PROPERTIES_PER_ITEM;
+ bench_init!{
+ owner: sub; collection: collection(owner);
+ owner: cross_from_sub;
+ };
+ let perms = (0..b).map(|k| PropertyKeyPermission {
+ key: property_key(k as usize),
+ permission: PropertyPermission {
+ mutable: false,
+ collection_admin: true,
+ token_owner: true,
+ },
+ }).collect::<Vec<_>>();
+ <Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
+ let props = (0..b).map(|k| Property {
+ key: property_key(k as usize),
+ value: property_value(),
+ }).collect::<Vec<_>>();
+ let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
+ }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?}
+
+ delete_token_properties {
+ let b in 0..MAX_PROPERTIES_PER_ITEM;
+ bench_init!{
+ owner: sub; collection: collection(owner);
+ owner: cross_from_sub;
+ };
+ let perms = (0..b).map(|k| PropertyKeyPermission {
+ key: property_key(k as usize),
+ permission: PropertyPermission {
+ mutable: true,
+ collection_admin: true,
+ token_owner: true,
+ },
+ }).collect::<Vec<_>>();
+ <Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;
+ let props = (0..b).map(|k| Property {
+ key: property_key(k as usize),
+ value: property_value(),
+ }).collect::<Vec<_>>();
+ let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;
+ <Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?;
+ let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();
+ }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete.into_iter(), &Unlimited)?}
+
repartition_item {
bench_init!{
owner: sub; collection: collection(owner);
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -20,9 +20,12 @@
use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};
use up_data_structs::{
CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,
- PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData,
+ PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData, CollectionPropertiesVec,
};
-use pallet_common::{CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight};
+use pallet_common::{
+ CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,
+ weights::WeightInfo as _,
+};
use pallet_structure::Error as StructureError;
use sp_runtime::{DispatchError};
use sp_std::{vec::Vec, vec};
@@ -41,6 +44,14 @@
};
}
+fn properties_weight<T: Config>(properties: &CollectionPropertiesVec) -> u64 {
+ if properties.len() > 0 {
+ <CommonWeights<T>>::set_token_properties(properties.len() as u32)
+ } else {
+ 0
+ }
+}
+
pub struct CommonWeights<T: Config>(PhantomData<T>);
impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {
fn create_item() -> Weight {
@@ -48,16 +59,31 @@
}
fn create_multiple_items(data: &[CreateItemData]) -> Weight {
- <SelfWeightOf<T>>::create_multiple_items(data.len() as u32)
+ <SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(
+ data.iter()
+ .map(|data| match data {
+ CreateItemData::ReFungible(rft_data) => {
+ properties_weight::<T>(&rft_data.properties)
+ }
+ _ => 0,
+ })
+ .fold(0, |a, b| a.saturating_add(b)),
+ )
}
fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {
match call {
CreateItemExData::RefungibleMultipleOwners(i) => {
<SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)
+ .saturating_add(properties_weight::<T>(&i.properties))
}
CreateItemExData::RefungibleMultipleItems(i) => {
<SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)
+ .saturating_add(
+ i.iter()
+ .map(|d| properties_weight::<T>(&d.properties))
+ .fold(0, |a, b| a.saturating_add(b)),
+ )
}
_ => 0,
}
@@ -67,29 +93,24 @@
max_weight_of!(burn_item_partial(), burn_item_fully())
}
- fn set_collection_properties(_amount: u32) -> Weight {
- // Error
- 0
+ fn set_collection_properties(amount: u32) -> Weight {
+ <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)
}
- fn delete_collection_properties(_amount: u32) -> Weight {
- // Error
- 0
+ fn delete_collection_properties(amount: u32) -> Weight {
+ <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)
}
- fn set_token_properties(_amount: u32) -> Weight {
- // Error
- 0
+ fn set_token_properties(amount: u32) -> Weight {
+ <SelfWeightOf<T>>::set_token_properties(amount)
}
- fn delete_token_properties(_amount: u32) -> Weight {
- // Error
- 0
+ fn delete_token_properties(amount: u32) -> Weight {
+ <SelfWeightOf<T>>::delete_token_properties(amount)
}
- fn set_token_property_permissions(_amount: u32) -> Weight {
- // Error
- 0
+ fn set_token_property_permissions(amount: u32) -> Weight {
+ <SelfWeightOf<T>>::set_token_property_permissions(amount)
}
fn transfer() -> Weight {
@@ -140,6 +161,7 @@
out.insert(to.clone(), data.pieces);
out.try_into().expect("limit > 0")
},
+ properties: data.properties,
}),
_ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),
}
@@ -297,46 +319,85 @@
fn set_collection_properties(
&self,
- _sender: T::CrossAccountId,
- _property: Vec<Property>,
+ sender: T::CrossAccountId,
+ properties: Vec<Property>,
) -> DispatchResultWithPostInfo {
- fail!(<Error<T>>::SettingPropertiesNotAllowed)
+ let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);
+
+ with_weight(
+ <Pallet<T>>::set_collection_properties(self, &sender, properties),
+ weight,
+ )
}
fn delete_collection_properties(
&self,
- _sender: &T::CrossAccountId,
- _property_keys: Vec<PropertyKey>,
+ sender: &T::CrossAccountId,
+ property_keys: Vec<PropertyKey>,
) -> DispatchResultWithPostInfo {
- fail!(<Error<T>>::SettingPropertiesNotAllowed)
+ let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);
+
+ with_weight(
+ <Pallet<T>>::delete_collection_properties(self, sender, property_keys),
+ weight,
+ )
}
fn set_token_properties(
&self,
- _sender: T::CrossAccountId,
- _token_id: TokenId,
- _property: Vec<Property>,
- _nesting_budget: &dyn Budget,
+ sender: T::CrossAccountId,
+ token_id: TokenId,
+ properties: Vec<Property>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
- fail!(<Error<T>>::SettingPropertiesNotAllowed)
+ let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);
+
+ with_weight(
+ <Pallet<T>>::set_token_properties(
+ self,
+ &sender,
+ token_id,
+ properties.into_iter(),
+ false,
+ nesting_budget,
+ ),
+ weight,
+ )
}
fn set_token_property_permissions(
&self,
- _sender: &T::CrossAccountId,
- _property_permissions: Vec<PropertyKeyPermission>,
+ sender: &T::CrossAccountId,
+ property_permissions: Vec<PropertyKeyPermission>,
) -> DispatchResultWithPostInfo {
- fail!(<Error<T>>::SettingPropertiesNotAllowed)
+ let weight =
+ <CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);
+
+ with_weight(
+ <Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),
+ weight,
+ )
}
fn delete_token_properties(
&self,
- _sender: T::CrossAccountId,
- _token_id: TokenId,
- _property_keys: Vec<PropertyKey>,
- _nesting_budget: &dyn Budget,
+ sender: T::CrossAccountId,
+ token_id: TokenId,
+ property_keys: Vec<PropertyKey>,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
- fail!(<Error<T>>::SettingPropertiesNotAllowed)
+ let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);
+
+ with_weight(
+ <Pallet<T>>::delete_token_properties(
+ self,
+ &sender,
+ token_id,
+ property_keys.into_iter(),
+ nesting_budget,
+ ),
+ weight,
+ )
}
fn check_nesting(
@@ -373,8 +434,8 @@
TokenId(<TokensMinted<T>>::get(self.id))
}
- fn token_owner(&self, _token: TokenId) -> Option<T::CrossAccountId> {
- None
+ fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {
+ <Pallet<T>>::token_owner(self.id, token)
}
fn token_property(&self, _token_id: TokenId, _key: &PropertyKey) -> Option<PropertyValue> {
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -87,15 +87,20 @@
#![cfg_attr(not(feature = "std"), no_std)]
-use frame_support::{ensure, BoundedVec};
+use frame_support::{ensure, fail, BoundedVec, transactional, storage::with_transaction};
use up_data_structs::{
AccessMode, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,
CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping, budget::Budget,
+ Property, PropertyScope, TrySetProperty, PropertyKey, PropertyValue, PropertyPermission,
+ PropertyKeyPermission,
};
use pallet_evm::account::CrossAccountId;
-use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon};
+use pallet_common::{
+ Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,
+ CommonCollectionOperations as _,
+};
use pallet_structure::Pallet as PalletStructure;
-use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
+use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
use core::ops::Deref;
use codec::{Encode, Decode, MaxEncodedLen};
@@ -175,6 +180,15 @@
QueryKind = ValueQuery,
>;
+ #[pallet::storage]
+ #[pallet::getter(fn token_properties)]
+ pub type TokenProperties<T: Config> = StorageNMap<
+ Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
+ Value = up_data_structs::Properties,
+ QueryKind = ValueQuery,
+ OnEmpty = up_data_structs::TokenProperties,
+ >;
+
/// Total amount of pieces for token
#[pallet::storage]
pub type TotalSupply<T: Config> = StorageNMap<
@@ -278,6 +292,34 @@
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
@@ -339,6 +381,7 @@
<TokensBurnt<T>>::insert(collection.id, burnt);
<TokenData<T>>::remove((collection.id, token_id));
+ <TokenProperties<T>>::remove((collection.id, token_id));
<TotalSupply<T>>::remove((collection.id, token_id));
<Balance<T>>::remove_prefix((collection.id, token_id), None);
<Allowance<T>>::remove_prefix((collection.id, token_id), None);
@@ -427,6 +470,170 @@
Ok(())
}
+ #[transactional]
+ fn modify_token_properties(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ token_id: TokenId,
+ properties: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,
+ is_token_create: bool,
+ nesting_budget: &dyn Budget,
+ ) -> DispatchResult {
+ let is_collection_admin = || collection.is_owner_or_admin(sender);
+ let is_token_owner = || -> Result<bool, DispatchError> {
+ let balance = collection.balance(sender.clone(), token_id);
+ let total_pieces: u128 =
+ Self::total_pieces(collection.id, token_id).unwrap_or(u128::MAX);
+ if balance != total_pieces {
+ return Ok(false);
+ }
+
+ let is_bundle_owner = <PalletStructure<T>>::check_indirectly_owned(
+ sender.clone(),
+ collection.id,
+ token_id,
+ None,
+ nesting_budget,
+ )?;
+
+ Ok(is_bundle_owner)
+ };
+
+ for (key, value) in properties {
+ let permission = <PalletCommon<T>>::property_permissions(collection.id)
+ .get(&key)
+ .cloned()
+ .unwrap_or_else(PropertyPermission::none);
+
+ let is_property_exists = TokenProperties::<T>::get((collection.id, token_id))
+ .get(&key)
+ .is_some();
+
+ match permission {
+ PropertyPermission { mutable: false, .. } if is_property_exists => {
+ return Err(<CommonError<T>>::NoPermission.into());
+ }
+
+ PropertyPermission {
+ collection_admin,
+ token_owner,
+ ..
+ } => {
+ //TODO: investigate threats during public minting.
+ let is_token_create =
+ is_token_create && (collection_admin || token_owner) && value.is_some();
+ if !(is_token_create
+ || (collection_admin && is_collection_admin())
+ || (token_owner && is_token_owner()?))
+ {
+ fail!(<CommonError<T>>::NoPermission);
+ }
+ }
+ }
+
+ match value {
+ Some(value) => {
+ <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {
+ properties.try_set(key.clone(), value)
+ })
+ .map_err(<CommonError<T>>::from)?;
+
+ <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(
+ collection.id,
+ token_id,
+ key,
+ ));
+ }
+ None => {
+ <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {
+ properties.remove(&key)
+ })
+ .map_err(<CommonError<T>>::from)?;
+
+ <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(
+ collection.id,
+ token_id,
+ key,
+ ));
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ pub fn set_token_properties(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ token_id: TokenId,
+ properties: impl Iterator<Item = Property>,
+ is_token_create: bool,
+ nesting_budget: &dyn Budget,
+ ) -> DispatchResult {
+ Self::modify_token_properties(
+ collection,
+ sender,
+ token_id,
+ properties.map(|p| (p.key, Some(p.value))),
+ is_token_create,
+ nesting_budget,
+ )
+ }
+
+ pub fn set_token_property(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ token_id: TokenId,
+ property: Property,
+ nesting_budget: &dyn Budget,
+ ) -> DispatchResult {
+ let is_token_create = false;
+
+ Self::set_token_properties(
+ collection,
+ sender,
+ token_id,
+ [property].into_iter(),
+ is_token_create,
+ nesting_budget,
+ )
+ }
+
+ pub fn delete_token_properties(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ token_id: TokenId,
+ property_keys: impl Iterator<Item = PropertyKey>,
+ nesting_budget: &dyn Budget,
+ ) -> DispatchResult {
+ let is_token_create = false;
+
+ Self::modify_token_properties(
+ collection,
+ sender,
+ token_id,
+ property_keys.into_iter().map(|key| (key, None)),
+ is_token_create,
+ nesting_budget,
+ )
+ }
+
+ pub fn delete_token_property(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ token_id: TokenId,
+ property_key: PropertyKey,
+ nesting_budget: &dyn Budget,
+ ) -> DispatchResult {
+ Self::delete_token_properties(
+ collection,
+ sender,
+ token_id,
+ [property_key].into_iter(),
+ nesting_budget,
+ )
+ }
+
/// Transfer RFT token pieces from one account to another.
///
/// If the sender is no longer owns any pieces after the `transfer` than she stops being an owner of the token.
@@ -629,32 +836,58 @@
// =========
+ with_transaction(|| {
+ for (i, data) in data.iter().enumerate() {
+ let token_id = first_token_id + i as u32 + 1;
+ <TotalSupply<T>>::insert((collection.id, token_id), totals[i]);
+
+ <TokenData<T>>::insert(
+ (collection.id, token_id),
+ ItemData {
+ const_data: data.const_data.clone(),
+ },
+ );
+
+ for (user, amount) in data.users.iter() {
+ if *amount == 0 {
+ continue;
+ }
+ <Balance<T>>::insert((collection.id, token_id, &user), amount);
+ <Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);
+ <PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+ user,
+ collection.id,
+ TokenId(token_id),
+ );
+ }
+
+ if let Err(e) = Self::set_token_properties(
+ collection,
+ sender,
+ TokenId(token_id),
+ data.properties.clone().into_iter(),
+ true,
+ nesting_budget,
+ ) {
+ return TransactionOutcome::Rollback(Err(e));
+ }
+ }
+ TransactionOutcome::Commit(Ok(()))
+ })?;
+
<TokensMinted<T>>::insert(collection.id, tokens_minted);
+
for (account, balance) in balances {
<AccountBalance<T>>::insert((collection.id, account), balance);
}
+
for (i, token) in data.into_iter().enumerate() {
let token_id = first_token_id + i as u32 + 1;
- <TotalSupply<T>>::insert((collection.id, token_id), totals[i]);
-
- <TokenData<T>>::insert(
- (collection.id, token_id),
- ItemData {
- const_data: token.const_data,
- },
- );
for (user, amount) in token.users.into_iter() {
if amount == 0 {
continue;
}
- <Balance<T>>::insert((collection.id, token_id, &user), amount);
- <Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);
- <PalletStructure<T>>::nest_if_sent_to_token_unchecked(
- &user,
- collection.id,
- TokenId(token_id),
- );
// TODO: ERC20 transfer event
<PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(
@@ -849,10 +1082,10 @@
);
ensure!(amount > 0, <CommonError<T>>::TokenValueTooLow);
// Ensure user owns all pieces
- let total_supply = <TotalSupply<T>>::get((collection.id, token));
+ let total_pieces = Self::total_pieces(collection.id, token).unwrap_or(u128::MAX);
let balance = <Balance<T>>::get((collection.id, token, owner));
ensure!(
- total_supply == balance,
+ total_pieces == balance,
<Error<T>>::RepartitionWhileNotOwningAllPieces
);
@@ -861,7 +1094,44 @@
Ok(())
}
+ fn token_owner(collection_id: CollectionId, token_id: TokenId) -> Option<T::CrossAccountId> {
+ let mut owner = None;
+ let mut count = 0;
+ for key in Balance::<T>::iter_key_prefix((collection_id, token_id)) {
+ count += 1;
+ if count > 1 {
+ return None;
+ }
+ owner = Some(key);
+ }
+ owner
+ }
+
fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128> {
<TotalSupply<T>>::try_get((collection_id, token_id)).ok()
}
+
+ pub fn set_collection_properties(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ properties: Vec<Property>,
+ ) -> DispatchResult {
+ <PalletCommon<T>>::set_collection_properties(collection, sender, properties)
+ }
+
+ pub fn delete_collection_properties(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ property_keys: Vec<PropertyKey>,
+ ) -> DispatchResult {
+ <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)
+ }
+
+ pub fn set_token_property_permissions(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ property_permissions: Vec<PropertyKeyPermission>,
+ ) -> DispatchResult {
+ <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)
+ }
}
pallets/refungible/src/weights.rsdiffbeforeafterboth--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -3,7 +3,7 @@
//! Autogenerated weights for pallet_refungible
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-06-27, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
// Executed Command:
@@ -49,6 +49,9 @@
fn transfer_from_removing() -> Weight;
fn transfer_from_creating_removing() -> Weight;
fn burn_from() -> Weight;
+ fn set_token_property_permissions(b: u32, ) -> Weight;
+ fn set_token_properties(b: u32, ) -> Weight;
+ fn delete_token_properties(b: u32, ) -> Weight;
fn repartition_item() -> Weight;
}
@@ -62,7 +65,7 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (17_553_000 as Weight)
+ (21_310_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
@@ -73,9 +76,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (10_654_000 as Weight)
- // Standard Error: 1_000
- .saturating_add((5_114_000 as Weight).saturating_mul(b as Weight))
+ (9_552_000 as Weight)
+ // Standard Error: 2_000
+ .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
.saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))
@@ -87,9 +90,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {
- (3_587_000 as Weight)
+ (4_857_000 as Weight)
// Standard Error: 2_000
- .saturating_add((7_931_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
@@ -102,9 +105,9 @@
// Storage: Refungible Balance (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {
- (1_980_000 as Weight)
+ (11_335_000 as Weight)
// Standard Error: 2_000
- .saturating_add((6_305_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
@@ -115,7 +118,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_partial() -> Weight {
- (21_010_000 as Weight)
+ (21_239_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -125,14 +128,15 @@
// Storage: Refungible TokensBurnt (r:1 w:1)
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
+ // Storage: Refungible TokenProperties (r:0 w:1)
fn burn_item_fully() -> Weight {
- (28_413_000 as Weight)
+ (29_426_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
- .saturating_add(T::DbWeight::get().writes(6 as Weight))
+ .saturating_add(T::DbWeight::get().writes(7 as Weight))
}
// Storage: Refungible Balance (r:2 w:2)
fn transfer_normal() -> Weight {
- (17_513_000 as Weight)
+ (17_743_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -140,7 +144,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_creating() -> Weight {
- (20_469_000 as Weight)
+ (20_699_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -148,7 +152,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_removing() -> Weight {
- (22_472_000 as Weight)
+ (22_833_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -156,21 +160,21 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_creating_removing() -> Weight {
- (24_866_000 as Weight)
+ (24_936_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:1 w:0)
// Storage: Refungible Allowance (r:0 w:1)
fn approve() -> Weight {
- (13_475_000 as Weight)
+ (13_446_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Refungible Allowance (r:1 w:1)
// Storage: Refungible Balance (r:2 w:2)
fn transfer_from_normal() -> Weight {
- (24_707_000 as Weight)
+ (24_777_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
@@ -179,7 +183,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_creating() -> Weight {
- (27_812_000 as Weight)
+ (28_483_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -188,7 +192,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_removing() -> Weight {
- (29_966_000 as Weight)
+ (29_896_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -197,7 +201,7 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_from_creating_removing() -> Weight {
- (31_660_000 as Weight)
+ (32_070_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(7 as Weight))
}
@@ -208,15 +212,42 @@
// Storage: Refungible TokensBurnt (r:1 w:1)
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
+ // Storage: Refungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (36_248_000 as Weight)
+ (36_789_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
- .saturating_add(T::DbWeight::get().writes(7 as Weight))
+ .saturating_add(T::DbWeight::get().writes(8 as Weight))
+ }
+ // Storage: Common CollectionPropertyPermissions (r:1 w:1)
+ fn set_token_property_permissions(b: u32, ) -> Weight {
+ (0 as Weight)
+ // Standard Error: 62_000
+ .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(T::DbWeight::get().reads(1 as Weight))
+ .saturating_add(T::DbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Common CollectionPropertyPermissions (r:1 w:0)
+ // Storage: Refungible TokenProperties (r:1 w:1)
+ fn set_token_properties(b: u32, ) -> Weight {
+ (0 as Weight)
+ // Standard Error: 1_668_000
+ .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
+ .saturating_add(T::DbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Common CollectionPropertyPermissions (r:1 w:0)
+ // Storage: Refungible TokenProperties (r:1 w:1)
+ fn delete_token_properties(b: u32, ) -> Weight {
+ (0 as Weight)
+ // Standard Error: 1_619_000
+ .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
+ .saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Refungible TotalSupply (r:1 w:1)
// Storage: Refungible Balance (r:1 w:1)
fn repartition_item() -> Weight {
- (8_226_000 as Weight)
+ (8_325_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -231,7 +262,7 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (17_553_000 as Weight)
+ (21_310_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
@@ -242,9 +273,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (10_654_000 as Weight)
- // Standard Error: 1_000
- .saturating_add((5_114_000 as Weight).saturating_mul(b as Weight))
+ (9_552_000 as Weight)
+ // Standard Error: 2_000
+ .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
.saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))
@@ -256,9 +287,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {
- (3_587_000 as Weight)
+ (4_857_000 as Weight)
// Standard Error: 2_000
- .saturating_add((7_931_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
@@ -271,9 +302,9 @@
// Storage: Refungible Balance (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {
- (1_980_000 as Weight)
+ (11_335_000 as Weight)
// Standard Error: 2_000
- .saturating_add((6_305_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
@@ -284,7 +315,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_partial() -> Weight {
- (21_010_000 as Weight)
+ (21_239_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -294,14 +325,15 @@
// Storage: Refungible TokensBurnt (r:1 w:1)
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
+ // Storage: Refungible TokenProperties (r:0 w:1)
fn burn_item_fully() -> Weight {
- (28_413_000 as Weight)
+ (29_426_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
- .saturating_add(RocksDbWeight::get().writes(6 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(7 as Weight))
}
// Storage: Refungible Balance (r:2 w:2)
fn transfer_normal() -> Weight {
- (17_513_000 as Weight)
+ (17_743_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
@@ -309,7 +341,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_creating() -> Weight {
- (20_469_000 as Weight)
+ (20_699_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -317,7 +349,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_removing() -> Weight {
- (22_472_000 as Weight)
+ (22_833_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -325,21 +357,21 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_creating_removing() -> Weight {
- (24_866_000 as Weight)
+ (24_936_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:1 w:0)
// Storage: Refungible Allowance (r:0 w:1)
fn approve() -> Weight {
- (13_475_000 as Weight)
+ (13_446_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Refungible Allowance (r:1 w:1)
// Storage: Refungible Balance (r:2 w:2)
fn transfer_from_normal() -> Weight {
- (24_707_000 as Weight)
+ (24_777_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
@@ -348,7 +380,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_creating() -> Weight {
- (27_812_000 as Weight)
+ (28_483_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -357,7 +389,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_removing() -> Weight {
- (29_966_000 as Weight)
+ (29_896_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -366,7 +398,7 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_from_creating_removing() -> Weight {
- (31_660_000 as Weight)
+ (32_070_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(7 as Weight))
}
@@ -377,15 +409,42 @@
// Storage: Refungible TokensBurnt (r:1 w:1)
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
+ // Storage: Refungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (36_248_000 as Weight)
+ (36_789_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
- .saturating_add(RocksDbWeight::get().writes(7 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(8 as Weight))
+ }
+ // Storage: Common CollectionPropertyPermissions (r:1 w:1)
+ fn set_token_property_permissions(b: u32, ) -> Weight {
+ (0 as Weight)
+ // Standard Error: 62_000
+ .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(RocksDbWeight::get().reads(1 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Common CollectionPropertyPermissions (r:1 w:0)
+ // Storage: Refungible TokenProperties (r:1 w:1)
+ fn set_token_properties(b: u32, ) -> Weight {
+ (0 as Weight)
+ // Standard Error: 1_668_000
+ .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
+ // Storage: Common CollectionPropertyPermissions (r:1 w:0)
+ // Storage: Refungible TokenProperties (r:1 w:1)
+ fn delete_token_properties(b: u32, ) -> Weight {
+ (0 as Weight)
+ // Standard Error: 1_619_000
+ .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(1 as Weight))
+ }
// Storage: Refungible TotalSupply (r:1 w:1)
// Storage: Refungible Balance (r:1 w:1)
fn repartition_item() -> Weight {
- (8_226_000 as Weight)
+ (8_325_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
primitives/data-structs/Cargo.tomldiffbeforeafterboth--- a/primitives/data-structs/Cargo.toml
+++ b/primitives/data-structs/Cargo.toml
@@ -6,7 +6,7 @@
license = 'GPLv3'
homepage = "https://unique.network"
repository = 'https://github.com/UniqueNetwork/unique-chain'
-version = '0.1.0'
+version = '0.1.1'
[dependencies]
scale-info = { version = "2.0.1", default-features = false, features = [
primitives/data-structs/Changelog.mddiffbeforeafterboth--- /dev/null
+++ b/primitives/data-structs/Changelog.md
@@ -0,0 +1,3 @@
+### 0.1.1
+---
+* Added fields with properties to `CreateReFungibleData` and `CreateRefungibleExData`.
\ No newline at end of file
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -534,7 +534,12 @@
#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
#[derivative(Debug(format_with = "bounded::vec_debug"))]
pub const_data: BoundedVec<u8, CustomDataLimit>,
+
pub pieces: u128,
+
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
+ pub properties: CollectionPropertiesVec,
}
#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]
@@ -568,6 +573,8 @@
pub const_data: BoundedVec<u8, CustomDataLimit>,
#[derivative(Debug(format_with = "bounded::map_debug"))]
pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
+ pub properties: CollectionPropertiesVec,
}
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
tests/src/createMultipleItems.test.tsdiffbeforeafterboth--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -376,14 +376,26 @@
// ReFungible
const collectionIdReFungible =
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const argsReFungible = [
- {ReFungible: ['1'.repeat(2049), 10]},
- {ReFungible: ['2'.repeat(2049), 10]},
- {ReFungible: ['3'.repeat(2049), 10]},
- ];
- const createMultipleItemsTxFungible = api.tx.unique
- .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);
- await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;
+ {
+ const argsReFungible = [
+ {ReFungible: ['1'.repeat(2049), 10, []]},
+ {ReFungible: ['2'.repeat(2049), 10, []]},
+ {ReFungible: ['3'.repeat(2049), 10, []]},
+ ];
+ const createMultipleItemsTxFungible = api.tx.unique
+ .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);
+ await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;
+ }
+ {
+ const argsReFungible = [
+ {ReFungible: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},
+ {ReFungible: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},
+ {ReFungible: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},
+ ];
+ const createMultipleItemsTxFungible = api.tx.unique
+ .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);
+ await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;
+ }
});
});
tests/src/interfaces/augment-api-query.tsdiffbeforeafterboth1// Auto-generated via `yarn polkadot-types-from-chain`, do not edit2/* eslint-disable */34import type { ApiTypes } from '@polkadot/api-base/types';5import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types-codec';6import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';7import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';8import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsTokenChild } from '@polkadot/types/lookup';9import type { Observable } from '@polkadot/types/types';1011declare module '@polkadot/api-base/types/storage' {12 export interface AugmentedQueries<ApiType extends ApiTypes> {13 balances: {14 /**15 * The Balances pallet example of storing the balance of an account.16 * 17 * # Example18 * 19 * ```nocompile20 * impl pallet_balances::Config for Runtime {21 * type AccountStore = StorageMapShim<Self::Account<Runtime>, frame_system::Provider<Runtime>, AccountId, Self::AccountData<Balance>>22 * }23 * ```24 * 25 * You can also store the balance of an account in the `System` pallet.26 * 27 * # Example28 * 29 * ```nocompile30 * impl pallet_balances::Config for Runtime {31 * type AccountStore = System32 * }33 * ```34 * 35 * But this comes with tradeoffs, storing account balances in the system pallet stores36 * `frame_system` data alongside the account data contrary to storing account balances in the37 * `Balances` pallet, which uses a `StorageMap` to store balances data only.38 * NOTE: This is only used in the case that this pallet is used to store balances.39 **/40 account: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<PalletBalancesAccountData>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;41 /**42 * Any liquidity locks on some account balances.43 * NOTE: Should only be accessed when setting, changing and freeing a lock.44 **/45 locks: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Vec<PalletBalancesBalanceLock>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;46 /**47 * Named reserves on some account balances.48 **/49 reserves: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Vec<PalletBalancesReserveData>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;50 /**51 * Storage version of the pallet.52 * 53 * This is set to v2.0.0 for new networks.54 **/55 storageVersion: AugmentedQuery<ApiType, () => Observable<PalletBalancesReleases>, []> & QueryableStorageEntry<ApiType, []>;56 /**57 * The total units issued in the system.58 **/59 totalIssuance: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;60 /**61 * Generic query62 **/63 [key: string]: QueryableStorageEntry<ApiType>;64 };65 charging: {66 /**67 * Generic query68 **/69 [key: string]: QueryableStorageEntry<ApiType>;70 };71 common: {72 adminAmount: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;73 /**74 * Allowlisted collection users75 **/76 allowlist: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;77 /**78 * Collection info79 **/80 collectionById: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<UpDataStructsCollection>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;81 /**82 * Collection properties83 **/84 collectionProperties: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;85 collectionPropertyPermissions: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<BTreeMap<Bytes, UpDataStructsPropertyPermission>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;86 createdCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;87 destroyedCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;88 /**89 * Not used by code, exists only to provide some types to metadata90 **/91 dummyStorageValue: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[UpDataStructsCollectionStats, u32, u32, UpDataStructsTokenChild, PhantomTypeUpDataStructs]>>>, []> & QueryableStorageEntry<ApiType, []>;92 /**93 * List of collection admins94 **/95 isAdmin: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;96 /**97 * Generic query98 **/99 [key: string]: QueryableStorageEntry<ApiType>;100 };101 dmpQueue: {102 /**103 * The configuration.104 **/105 configuration: AugmentedQuery<ApiType, () => Observable<CumulusPalletDmpQueueConfigData>, []> & QueryableStorageEntry<ApiType, []>;106 /**107 * The overweight messages.108 **/109 overweight: AugmentedQuery<ApiType, (arg: u64 | AnyNumber | Uint8Array) => Observable<Option<ITuple<[u32, Bytes]>>>, [u64]> & QueryableStorageEntry<ApiType, [u64]>;110 /**111 * The page index.112 **/113 pageIndex: AugmentedQuery<ApiType, () => Observable<CumulusPalletDmpQueuePageIndexData>, []> & QueryableStorageEntry<ApiType, []>;114 /**115 * The queue pages.116 **/117 pages: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<ITuple<[u32, Bytes]>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;118 /**119 * Generic query120 **/121 [key: string]: QueryableStorageEntry<ApiType>;122 };123 ethereum: {124 blockHash: AugmentedQuery<ApiType, (arg: U256 | AnyNumber | Uint8Array) => Observable<H256>, [U256]> & QueryableStorageEntry<ApiType, [U256]>;125 /**126 * The current Ethereum block.127 **/128 currentBlock: AugmentedQuery<ApiType, () => Observable<Option<EthereumBlock>>, []> & QueryableStorageEntry<ApiType, []>;129 /**130 * The current Ethereum receipts.131 **/132 currentReceipts: AugmentedQuery<ApiType, () => Observable<Option<Vec<EthereumReceiptReceiptV3>>>, []> & QueryableStorageEntry<ApiType, []>;133 /**134 * The current transaction statuses.135 **/136 currentTransactionStatuses: AugmentedQuery<ApiType, () => Observable<Option<Vec<FpRpcTransactionStatus>>>, []> & QueryableStorageEntry<ApiType, []>;137 /**138 * Injected transactions should have unique nonce, here we store current139 **/140 injectedNonce: AugmentedQuery<ApiType, () => Observable<U256>, []> & QueryableStorageEntry<ApiType, []>;141 /**142 * Current building block's transactions and receipts.143 **/144 pending: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[EthereumTransactionTransactionV2, FpRpcTransactionStatus, EthereumReceiptReceiptV3]>>>, []> & QueryableStorageEntry<ApiType, []>;145 /**146 * Generic query147 **/148 [key: string]: QueryableStorageEntry<ApiType>;149 };150 evm: {151 accountCodes: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<Bytes>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;152 accountStorages: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H256 | string | Uint8Array) => Observable<H256>, [H160, H256]> & QueryableStorageEntry<ApiType, [H160, H256]>;153 /**154 * Written on log, reset after transaction155 * Should be empty between transactions156 **/157 currentLogs: AugmentedQuery<ApiType, () => Observable<Vec<EthereumLog>>, []> & QueryableStorageEntry<ApiType, []>;158 /**159 * Generic query160 **/161 [key: string]: QueryableStorageEntry<ApiType>;162 };163 evmCoderSubstrate: {164 /**165 * Generic query166 **/167 [key: string]: QueryableStorageEntry<ApiType>;168 };169 evmContractHelpers: {170 allowlist: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H160 | string | Uint8Array) => Observable<bool>, [H160, H160]> & QueryableStorageEntry<ApiType, [H160, H160]>;171 allowlistEnabled: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;172 owner: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<H160>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;173 selfSponsoring: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;174 sponsorBasket: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H160 | string | Uint8Array) => Observable<Option<u32>>, [H160, H160]> & QueryableStorageEntry<ApiType, [H160, H160]>;175 sponsoringMode: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<Option<PalletEvmContractHelpersSponsoringModeT>>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;176 sponsoringRateLimit: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<u32>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;177 /**178 * Generic query179 **/180 [key: string]: QueryableStorageEntry<ApiType>;181 };182 evmMigration: {183 migrationPending: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;184 /**185 * Generic query186 **/187 [key: string]: QueryableStorageEntry<ApiType>;188 };189 fungible: {190 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;191 balance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;192 totalSupply: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u128>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;193 /**194 * Generic query195 **/196 [key: string]: QueryableStorageEntry<ApiType>;197 };198 inflation: {199 /**200 * Current inflation for `InflationBlockInterval` number of blocks201 **/202 blockInflation: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;203 /**204 * Next target (relay) block when inflation will be applied205 **/206 nextInflationBlock: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;207 /**208 * Next target (relay) block when inflation is recalculated209 **/210 nextRecalculationBlock: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;211 /**212 * Relay block when inflation has started213 **/214 startBlock: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;215 /**216 * starting year total issuance217 **/218 startingYearTotalIssuance: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;219 /**220 * Generic query221 **/222 [key: string]: QueryableStorageEntry<ApiType>;223 };224 nonfungible: {225 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;226 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletEvmAccountBasicCrossAccountIdRepr>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;227 /**228 * Used to enumerate tokens owned by account229 **/230 owned: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]>;231 tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;232 /**233 * Used to enumerate token's children234 **/235 tokenChildren: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array]) => Observable<bool>, [u32, u32, ITuple<[u32, u32]>]> & QueryableStorageEntry<ApiType, [u32, u32, ITuple<[u32, u32]>]>;236 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletNonfungibleItemData>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;237 tokenProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;238 tokensBurnt: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;239 tokensMinted: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;240 /**241 * Generic query242 **/243 [key: string]: QueryableStorageEntry<ApiType>;244 };245 parachainInfo: {246 parachainId: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;247 /**248 * Generic query249 **/250 [key: string]: QueryableStorageEntry<ApiType>;251 };252 parachainSystem: {253 /**254 * The number of HRMP messages we observed in `on_initialize` and thus used that number for255 * announcing the weight of `on_initialize` and `on_finalize`.256 **/257 announcedHrmpMessagesPerCandidate: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;258 /**259 * The next authorized upgrade, if there is one.260 **/261 authorizedUpgrade: AugmentedQuery<ApiType, () => Observable<Option<H256>>, []> & QueryableStorageEntry<ApiType, []>;262 /**263 * A custom head data that should be returned as result of `validate_block`.264 * 265 * See [`Pallet::set_custom_validation_head_data`] for more information.266 **/267 customValidationHeadData: AugmentedQuery<ApiType, () => Observable<Option<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;268 /**269 * Were the validation data set to notify the relay chain?270 **/271 didSetValidationCode: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;272 /**273 * The parachain host configuration that was obtained from the relay parent.274 * 275 * This field is meant to be updated each block with the validation data inherent. Therefore,276 * before processing of the inherent, e.g. in `on_initialize` this data may be stale.277 * 278 * This data is also absent from the genesis.279 **/280 hostConfiguration: AugmentedQuery<ApiType, () => Observable<Option<PolkadotPrimitivesV2AbridgedHostConfiguration>>, []> & QueryableStorageEntry<ApiType, []>;281 /**282 * HRMP messages that were sent in a block.283 * 284 * This will be cleared in `on_initialize` of each new block.285 **/286 hrmpOutboundMessages: AugmentedQuery<ApiType, () => Observable<Vec<PolkadotCorePrimitivesOutboundHrmpMessage>>, []> & QueryableStorageEntry<ApiType, []>;287 /**288 * HRMP watermark that was set in a block.289 * 290 * This will be cleared in `on_initialize` of each new block.291 **/292 hrmpWatermark: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;293 /**294 * The last downward message queue chain head we have observed.295 * 296 * This value is loaded before and saved after processing inbound downward messages carried297 * by the system inherent.298 **/299 lastDmqMqcHead: AugmentedQuery<ApiType, () => Observable<H256>, []> & QueryableStorageEntry<ApiType, []>;300 /**301 * The message queue chain heads we have observed per each channel incoming channel.302 * 303 * This value is loaded before and saved after processing inbound downward messages carried304 * by the system inherent.305 **/306 lastHrmpMqcHeads: AugmentedQuery<ApiType, () => Observable<BTreeMap<u32, H256>>, []> & QueryableStorageEntry<ApiType, []>;307 /**308 * Validation code that is set by the parachain and is to be communicated to collator and309 * consequently the relay-chain.310 * 311 * This will be cleared in `on_initialize` of each new block if no other pallet already set312 * the value.313 **/314 newValidationCode: AugmentedQuery<ApiType, () => Observable<Option<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;315 /**316 * Upward messages that are still pending and not yet send to the relay chain.317 **/318 pendingUpwardMessages: AugmentedQuery<ApiType, () => Observable<Vec<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;319 /**320 * In case of a scheduled upgrade, this storage field contains the validation code to be applied.321 * 322 * As soon as the relay chain gives us the go-ahead signal, we will overwrite the [`:code`][well_known_keys::CODE]323 * which will result the next block process with the new validation code. This concludes the upgrade process.324 * 325 * [well_known_keys::CODE]: sp_core::storage::well_known_keys::CODE326 **/327 pendingValidationCode: AugmentedQuery<ApiType, () => Observable<Bytes>, []> & QueryableStorageEntry<ApiType, []>;328 /**329 * Number of downward messages processed in a block.330 * 331 * This will be cleared in `on_initialize` of each new block.332 **/333 processedDownwardMessages: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;334 /**335 * The state proof for the last relay parent block.336 * 337 * This field is meant to be updated each block with the validation data inherent. Therefore,338 * before processing of the inherent, e.g. in `on_initialize` this data may be stale.339 * 340 * This data is also absent from the genesis.341 **/342 relayStateProof: AugmentedQuery<ApiType, () => Observable<Option<SpTrieStorageProof>>, []> & QueryableStorageEntry<ApiType, []>;343 /**344 * The snapshot of some state related to messaging relevant to the current parachain as per345 * the relay parent.346 * 347 * This field is meant to be updated each block with the validation data inherent. Therefore,348 * before processing of the inherent, e.g. in `on_initialize` this data may be stale.349 * 350 * This data is also absent from the genesis.351 **/352 relevantMessagingState: AugmentedQuery<ApiType, () => Observable<Option<CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot>>, []> & QueryableStorageEntry<ApiType, []>;353 /**354 * The weight we reserve at the beginning of the block for processing DMP messages. This355 * overrides the amount set in the Config trait.356 **/357 reservedDmpWeightOverride: AugmentedQuery<ApiType, () => Observable<Option<u64>>, []> & QueryableStorageEntry<ApiType, []>;358 /**359 * The weight we reserve at the beginning of the block for processing XCMP messages. This360 * overrides the amount set in the Config trait.361 **/362 reservedXcmpWeightOverride: AugmentedQuery<ApiType, () => Observable<Option<u64>>, []> & QueryableStorageEntry<ApiType, []>;363 /**364 * An option which indicates if the relay-chain restricts signalling a validation code upgrade.365 * In other words, if this is `Some` and [`NewValidationCode`] is `Some` then the produced366 * candidate will be invalid.367 * 368 * This storage item is a mirror of the corresponding value for the current parachain from the369 * relay-chain. This value is ephemeral which means it doesn't hit the storage. This value is370 * set after the inherent.371 **/372 upgradeRestrictionSignal: AugmentedQuery<ApiType, () => Observable<Option<PolkadotPrimitivesV2UpgradeRestriction>>, []> & QueryableStorageEntry<ApiType, []>;373 /**374 * Upward messages that were sent in a block.375 * 376 * This will be cleared in `on_initialize` of each new block.377 **/378 upwardMessages: AugmentedQuery<ApiType, () => Observable<Vec<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;379 /**380 * The [`PersistedValidationData`] set for this block.381 * This value is expected to be set only once per block and it's never stored382 * in the trie.383 **/384 validationData: AugmentedQuery<ApiType, () => Observable<Option<PolkadotPrimitivesV2PersistedValidationData>>, []> & QueryableStorageEntry<ApiType, []>;385 /**386 * Generic query387 **/388 [key: string]: QueryableStorageEntry<ApiType>;389 };390 randomnessCollectiveFlip: {391 /**392 * Series of block headers from the last 81 blocks that acts as random seed material. This393 * is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of394 * the oldest hash.395 **/396 randomMaterial: AugmentedQuery<ApiType, () => Observable<Vec<H256>>, []> & QueryableStorageEntry<ApiType, []>;397 /**398 * Generic query399 **/400 [key: string]: QueryableStorageEntry<ApiType>;401 };402 refungible: {403 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;404 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg4: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;405 balance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]>;406 /**407 * Used to enumerate tokens owned by account408 **/409 owned: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]>;410 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<PalletRefungibleItemData>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;411 tokensBurnt: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;412 tokensMinted: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;413 totalSupply: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u128>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;414 /**415 * Generic query416 **/417 [key: string]: QueryableStorageEntry<ApiType>;418 };419 rmrkCore: {420 collectionIndex: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;421 uniqueCollectionId: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;422 /**423 * Generic query424 **/425 [key: string]: QueryableStorageEntry<ApiType>;426 };427 rmrkEquip: {428 baseHasDefaultTheme: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;429 inernalPartId: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;430 /**431 * Generic query432 **/433 [key: string]: QueryableStorageEntry<ApiType>;434 };435 scheduler: {436 /**437 * Items to be executed, indexed by the block number that they should be executed on.438 **/439 agenda: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<Option<PalletUniqueSchedulerScheduledV3>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;440 /**441 * Lookup from identity to the block number and index of the task.442 **/443 lookup: AugmentedQuery<ApiType, (arg: U8aFixed | string | Uint8Array) => Observable<Option<ITuple<[u32, u32]>>>, [U8aFixed]> & QueryableStorageEntry<ApiType, [U8aFixed]>;444 /**445 * Generic query446 **/447 [key: string]: QueryableStorageEntry<ApiType>;448 };449 structure: {450 /**451 * Generic query452 **/453 [key: string]: QueryableStorageEntry<ApiType>;454 };455 sudo: {456 /**457 * The `AccountId` of the sudo key.458 **/459 key: AugmentedQuery<ApiType, () => Observable<Option<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;460 /**461 * Generic query462 **/463 [key: string]: QueryableStorageEntry<ApiType>;464 };465 system: {466 /**467 * The full account information for a particular account ID.468 **/469 account: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<FrameSystemAccountInfo>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;470 /**471 * Total length (in bytes) for all extrinsics put together, for the current block.472 **/473 allExtrinsicsLen: AugmentedQuery<ApiType, () => Observable<Option<u32>>, []> & QueryableStorageEntry<ApiType, []>;474 /**475 * Map of block numbers to block hashes.476 **/477 blockHash: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<H256>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;478 /**479 * The current weight for the block.480 **/481 blockWeight: AugmentedQuery<ApiType, () => Observable<FrameSupportWeightsPerDispatchClassU64>, []> & QueryableStorageEntry<ApiType, []>;482 /**483 * Digest of the current block, also part of the block header.484 **/485 digest: AugmentedQuery<ApiType, () => Observable<SpRuntimeDigest>, []> & QueryableStorageEntry<ApiType, []>;486 /**487 * The number of events in the `Events<T>` list.488 **/489 eventCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;490 /**491 * Events deposited for the current block.492 * 493 * NOTE: The item is unbound and should therefore never be read on chain.494 * It could otherwise inflate the PoV size of a block.495 * 496 * Events have a large in-memory size. Box the events to not go out-of-memory497 * just in case someone still reads them from within the runtime.498 **/499 events: AugmentedQuery<ApiType, () => Observable<Vec<FrameSystemEventRecord>>, []> & QueryableStorageEntry<ApiType, []>;500 /**501 * Mapping between a topic (represented by T::Hash) and a vector of indexes502 * of events in the `<Events<T>>` list.503 * 504 * All topic vectors have deterministic storage locations depending on the topic. This505 * allows light-clients to leverage the changes trie storage tracking mechanism and506 * in case of changes fetch the list of events of interest.507 * 508 * The value has the type `(T::BlockNumber, EventIndex)` because if we used only just509 * the `EventIndex` then in case if the topic has the same contents on the next block510 * no notification will be triggered thus the event might be lost.511 **/512 eventTopics: AugmentedQuery<ApiType, (arg: H256 | string | Uint8Array) => Observable<Vec<ITuple<[u32, u32]>>>, [H256]> & QueryableStorageEntry<ApiType, [H256]>;513 /**514 * The execution phase of the block.515 **/516 executionPhase: AugmentedQuery<ApiType, () => Observable<Option<FrameSystemPhase>>, []> & QueryableStorageEntry<ApiType, []>;517 /**518 * Total extrinsics count for the current block.519 **/520 extrinsicCount: AugmentedQuery<ApiType, () => Observable<Option<u32>>, []> & QueryableStorageEntry<ApiType, []>;521 /**522 * Extrinsics data for the current block (maps an extrinsic's index to its data).523 **/524 extrinsicData: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;525 /**526 * Stores the `spec_version` and `spec_name` of when the last runtime upgrade happened.527 **/528 lastRuntimeUpgrade: AugmentedQuery<ApiType, () => Observable<Option<FrameSystemLastRuntimeUpgradeInfo>>, []> & QueryableStorageEntry<ApiType, []>;529 /**530 * The current block number being processed. Set by `execute_block`.531 **/532 number: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;533 /**534 * Hash of the previous block.535 **/536 parentHash: AugmentedQuery<ApiType, () => Observable<H256>, []> & QueryableStorageEntry<ApiType, []>;537 /**538 * True if we have upgraded so that AccountInfo contains three types of `RefCount`. False539 * (default) if not.540 **/541 upgradedToTripleRefCount: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;542 /**543 * True if we have upgraded so that `type RefCount` is `u32`. False (default) if not.544 **/545 upgradedToU32RefCount: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;546 /**547 * Generic query548 **/549 [key: string]: QueryableStorageEntry<ApiType>;550 };551 timestamp: {552 /**553 * Did the timestamp get updated in this block?554 **/555 didUpdate: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;556 /**557 * Current time for the current block.558 **/559 now: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;560 /**561 * Generic query562 **/563 [key: string]: QueryableStorageEntry<ApiType>;564 };565 transactionPayment: {566 nextFeeMultiplier: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;567 storageVersion: AugmentedQuery<ApiType, () => Observable<PalletTransactionPaymentReleases>, []> & QueryableStorageEntry<ApiType, []>;568 /**569 * Generic query570 **/571 [key: string]: QueryableStorageEntry<ApiType>;572 };573 treasury: {574 /**575 * Proposal indices that have been approved but not yet awarded.576 **/577 approvals: AugmentedQuery<ApiType, () => Observable<Vec<u32>>, []> & QueryableStorageEntry<ApiType, []>;578 /**579 * Number of proposals that have been made.580 **/581 proposalCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;582 /**583 * Proposals that have been made.584 **/585 proposals: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletTreasuryProposal>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;586 /**587 * Generic query588 **/589 [key: string]: QueryableStorageEntry<ApiType>;590 };591 unique: {592 /**593 * Used for migrations594 **/595 chainVersion: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;596 /**597 * (Collection id (controlled?2), who created (real))598 * TODO: Off chain worker should remove from this map when collection gets removed599 **/600 createItemBasket: AugmentedQuery<ApiType, (arg: ITuple<[u32, AccountId32]> | [u32 | AnyNumber | Uint8Array, AccountId32 | string | Uint8Array]) => Observable<Option<u32>>, [ITuple<[u32, AccountId32]>]> & QueryableStorageEntry<ApiType, [ITuple<[u32, AccountId32]>]>;601 fungibleApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, AccountId32]>;602 /**603 * Collection id (controlled?2), owning user (real)604 **/605 fungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, AccountId32]>;606 /**607 * Approval sponsoring608 **/609 nftApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;610 /**611 * Collection id (controlled?2), token id (controlled?2)612 **/613 nftTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;614 refungibleApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, u32, AccountId32]>;615 /**616 * Collection id (controlled?2), token id (controlled?2)617 **/618 reFungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, u32, AccountId32]>;619 tokenPropertyBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;620 /**621 * Variable metadata sponsoring622 * Collection id (controlled?2), token id (controlled?2)623 **/624 variableMetaDataBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;625 /**626 * Generic query627 **/628 [key: string]: QueryableStorageEntry<ApiType>;629 };630 vesting: {631 /**632 * Vesting schedules of an account.633 * 634 * VestingSchedules: map AccountId => Vec<VestingSchedule>635 **/636 vestingSchedules: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Vec<OrmlVestingVestingSchedule>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;637 /**638 * Generic query639 **/640 [key: string]: QueryableStorageEntry<ApiType>;641 };642 xcmpQueue: {643 /**644 * Inbound aggregate XCMP messages. It can only be one per ParaId/block.645 **/646 inboundXcmpMessages: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;647 /**648 * Status of the inbound XCMP channels.649 **/650 inboundXcmpStatus: AugmentedQuery<ApiType, () => Observable<Vec<CumulusPalletXcmpQueueInboundChannelDetails>>, []> & QueryableStorageEntry<ApiType, []>;651 /**652 * The messages outbound in a given XCMP channel.653 **/654 outboundXcmpMessages: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u16 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32, u16]> & QueryableStorageEntry<ApiType, [u32, u16]>;655 /**656 * The non-empty XCMP channels in order of becoming non-empty, and the index of the first657 * and last outbound message. If the two indices are equal, then it indicates an empty658 * queue and there must be a non-`Ok` `OutboundStatus`. We assume queues grow no greater659 * than 65535 items. Queue indices for normal messages begin at one; zero is reserved in660 * case of the need to send a high-priority signal message this block.661 * The bool is true if there is a signal message waiting to be sent.662 **/663 outboundXcmpStatus: AugmentedQuery<ApiType, () => Observable<Vec<CumulusPalletXcmpQueueOutboundChannelDetails>>, []> & QueryableStorageEntry<ApiType, []>;664 /**665 * The messages that exceeded max individual message weight budget.666 * 667 * These message stay in this storage map until they are manually dispatched via668 * `service_overweight`.669 **/670 overweight: AugmentedQuery<ApiType, (arg: u64 | AnyNumber | Uint8Array) => Observable<Option<ITuple<[u32, u32, Bytes]>>>, [u64]> & QueryableStorageEntry<ApiType, [u64]>;671 /**672 * The number of overweight messages ever recorded in `Overweight`. Also doubles as the next673 * available free overweight index.674 **/675 overweightCount: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;676 /**677 * The configuration which controls the dynamics of the outbound queue.678 **/679 queueConfig: AugmentedQuery<ApiType, () => Observable<CumulusPalletXcmpQueueQueueConfigData>, []> & QueryableStorageEntry<ApiType, []>;680 /**681 * Whether or not the XCMP queue is suspended from executing incoming XCMs or not.682 **/683 queueSuspended: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;684 /**685 * Any signal messages waiting to be sent.686 **/687 signalMessages: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;688 /**689 * Generic query690 **/691 [key: string]: QueryableStorageEntry<ApiType>;692 };693 } // AugmentedQueries694} // declare module1// Auto-generated via `yarn polkadot-types-from-chain`, do not edit2/* eslint-disable */34import type { ApiTypes } from '@polkadot/api-base/types';5import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types-codec';6import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';7import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';8import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsTokenChild } from '@polkadot/types/lookup';9import type { Observable } from '@polkadot/types/types';1011declare module '@polkadot/api-base/types/storage' {12 export interface AugmentedQueries<ApiType extends ApiTypes> {13 balances: {14 /**15 * The Balances pallet example of storing the balance of an account.16 * 17 * # Example18 * 19 * ```nocompile20 * impl pallet_balances::Config for Runtime {21 * type AccountStore = StorageMapShim<Self::Account<Runtime>, frame_system::Provider<Runtime>, AccountId, Self::AccountData<Balance>>22 * }23 * ```24 * 25 * You can also store the balance of an account in the `System` pallet.26 * 27 * # Example28 * 29 * ```nocompile30 * impl pallet_balances::Config for Runtime {31 * type AccountStore = System32 * }33 * ```34 * 35 * But this comes with tradeoffs, storing account balances in the system pallet stores36 * `frame_system` data alongside the account data contrary to storing account balances in the37 * `Balances` pallet, which uses a `StorageMap` to store balances data only.38 * NOTE: This is only used in the case that this pallet is used to store balances.39 **/40 account: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<PalletBalancesAccountData>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;41 /**42 * Any liquidity locks on some account balances.43 * NOTE: Should only be accessed when setting, changing and freeing a lock.44 **/45 locks: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Vec<PalletBalancesBalanceLock>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;46 /**47 * Named reserves on some account balances.48 **/49 reserves: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Vec<PalletBalancesReserveData>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;50 /**51 * Storage version of the pallet.52 * 53 * This is set to v2.0.0 for new networks.54 **/55 storageVersion: AugmentedQuery<ApiType, () => Observable<PalletBalancesReleases>, []> & QueryableStorageEntry<ApiType, []>;56 /**57 * The total units issued in the system.58 **/59 totalIssuance: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;60 /**61 * Generic query62 **/63 [key: string]: QueryableStorageEntry<ApiType>;64 };65 charging: {66 /**67 * Generic query68 **/69 [key: string]: QueryableStorageEntry<ApiType>;70 };71 common: {72 adminAmount: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;73 /**74 * Allowlisted collection users75 **/76 allowlist: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;77 /**78 * Collection info79 **/80 collectionById: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<UpDataStructsCollection>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;81 /**82 * Collection properties83 **/84 collectionProperties: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;85 collectionPropertyPermissions: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<BTreeMap<Bytes, UpDataStructsPropertyPermission>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;86 createdCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;87 destroyedCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;88 /**89 * Not used by code, exists only to provide some types to metadata90 **/91 dummyStorageValue: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[UpDataStructsCollectionStats, u32, u32, UpDataStructsTokenChild, PhantomTypeUpDataStructs]>>>, []> & QueryableStorageEntry<ApiType, []>;92 /**93 * List of collection admins94 **/95 isAdmin: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;96 /**97 * Generic query98 **/99 [key: string]: QueryableStorageEntry<ApiType>;100 };101 dmpQueue: {102 /**103 * The configuration.104 **/105 configuration: AugmentedQuery<ApiType, () => Observable<CumulusPalletDmpQueueConfigData>, []> & QueryableStorageEntry<ApiType, []>;106 /**107 * The overweight messages.108 **/109 overweight: AugmentedQuery<ApiType, (arg: u64 | AnyNumber | Uint8Array) => Observable<Option<ITuple<[u32, Bytes]>>>, [u64]> & QueryableStorageEntry<ApiType, [u64]>;110 /**111 * The page index.112 **/113 pageIndex: AugmentedQuery<ApiType, () => Observable<CumulusPalletDmpQueuePageIndexData>, []> & QueryableStorageEntry<ApiType, []>;114 /**115 * The queue pages.116 **/117 pages: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<ITuple<[u32, Bytes]>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;118 /**119 * Generic query120 **/121 [key: string]: QueryableStorageEntry<ApiType>;122 };123 ethereum: {124 blockHash: AugmentedQuery<ApiType, (arg: U256 | AnyNumber | Uint8Array) => Observable<H256>, [U256]> & QueryableStorageEntry<ApiType, [U256]>;125 /**126 * The current Ethereum block.127 **/128 currentBlock: AugmentedQuery<ApiType, () => Observable<Option<EthereumBlock>>, []> & QueryableStorageEntry<ApiType, []>;129 /**130 * The current Ethereum receipts.131 **/132 currentReceipts: AugmentedQuery<ApiType, () => Observable<Option<Vec<EthereumReceiptReceiptV3>>>, []> & QueryableStorageEntry<ApiType, []>;133 /**134 * The current transaction statuses.135 **/136 currentTransactionStatuses: AugmentedQuery<ApiType, () => Observable<Option<Vec<FpRpcTransactionStatus>>>, []> & QueryableStorageEntry<ApiType, []>;137 /**138 * Injected transactions should have unique nonce, here we store current139 **/140 injectedNonce: AugmentedQuery<ApiType, () => Observable<U256>, []> & QueryableStorageEntry<ApiType, []>;141 /**142 * Current building block's transactions and receipts.143 **/144 pending: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[EthereumTransactionTransactionV2, FpRpcTransactionStatus, EthereumReceiptReceiptV3]>>>, []> & QueryableStorageEntry<ApiType, []>;145 /**146 * Generic query147 **/148 [key: string]: QueryableStorageEntry<ApiType>;149 };150 evm: {151 accountCodes: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<Bytes>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;152 accountStorages: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H256 | string | Uint8Array) => Observable<H256>, [H160, H256]> & QueryableStorageEntry<ApiType, [H160, H256]>;153 /**154 * Written on log, reset after transaction155 * Should be empty between transactions156 **/157 currentLogs: AugmentedQuery<ApiType, () => Observable<Vec<EthereumLog>>, []> & QueryableStorageEntry<ApiType, []>;158 /**159 * Generic query160 **/161 [key: string]: QueryableStorageEntry<ApiType>;162 };163 evmCoderSubstrate: {164 /**165 * Generic query166 **/167 [key: string]: QueryableStorageEntry<ApiType>;168 };169 evmContractHelpers: {170 allowlist: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H160 | string | Uint8Array) => Observable<bool>, [H160, H160]> & QueryableStorageEntry<ApiType, [H160, H160]>;171 allowlistEnabled: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;172 owner: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<H160>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;173 selfSponsoring: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;174 sponsorBasket: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H160 | string | Uint8Array) => Observable<Option<u32>>, [H160, H160]> & QueryableStorageEntry<ApiType, [H160, H160]>;175 sponsoringMode: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<Option<PalletEvmContractHelpersSponsoringModeT>>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;176 sponsoringRateLimit: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<u32>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;177 /**178 * Generic query179 **/180 [key: string]: QueryableStorageEntry<ApiType>;181 };182 evmMigration: {183 migrationPending: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;184 /**185 * Generic query186 **/187 [key: string]: QueryableStorageEntry<ApiType>;188 };189 fungible: {190 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;191 balance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;192 totalSupply: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u128>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;193 /**194 * Generic query195 **/196 [key: string]: QueryableStorageEntry<ApiType>;197 };198 inflation: {199 /**200 * Current inflation for `InflationBlockInterval` number of blocks201 **/202 blockInflation: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;203 /**204 * Next target (relay) block when inflation will be applied205 **/206 nextInflationBlock: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;207 /**208 * Next target (relay) block when inflation is recalculated209 **/210 nextRecalculationBlock: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;211 /**212 * Relay block when inflation has started213 **/214 startBlock: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;215 /**216 * starting year total issuance217 **/218 startingYearTotalIssuance: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;219 /**220 * Generic query221 **/222 [key: string]: QueryableStorageEntry<ApiType>;223 };224 nonfungible: {225 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;226 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletEvmAccountBasicCrossAccountIdRepr>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;227 /**228 * Used to enumerate tokens owned by account229 **/230 owned: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]>;231 tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;232 /**233 * Used to enumerate token's children234 **/235 tokenChildren: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: ITuple<[u32, u32]> | [u32 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array]) => Observable<bool>, [u32, u32, ITuple<[u32, u32]>]> & QueryableStorageEntry<ApiType, [u32, u32, ITuple<[u32, u32]>]>;236 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletNonfungibleItemData>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;237 tokenProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;238 tokensBurnt: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;239 tokensMinted: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;240 /**241 * Generic query242 **/243 [key: string]: QueryableStorageEntry<ApiType>;244 };245 parachainInfo: {246 parachainId: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;247 /**248 * Generic query249 **/250 [key: string]: QueryableStorageEntry<ApiType>;251 };252 parachainSystem: {253 /**254 * The number of HRMP messages we observed in `on_initialize` and thus used that number for255 * announcing the weight of `on_initialize` and `on_finalize`.256 **/257 announcedHrmpMessagesPerCandidate: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;258 /**259 * The next authorized upgrade, if there is one.260 **/261 authorizedUpgrade: AugmentedQuery<ApiType, () => Observable<Option<H256>>, []> & QueryableStorageEntry<ApiType, []>;262 /**263 * A custom head data that should be returned as result of `validate_block`.264 * 265 * See [`Pallet::set_custom_validation_head_data`] for more information.266 **/267 customValidationHeadData: AugmentedQuery<ApiType, () => Observable<Option<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;268 /**269 * Were the validation data set to notify the relay chain?270 **/271 didSetValidationCode: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;272 /**273 * The parachain host configuration that was obtained from the relay parent.274 * 275 * This field is meant to be updated each block with the validation data inherent. Therefore,276 * before processing of the inherent, e.g. in `on_initialize` this data may be stale.277 * 278 * This data is also absent from the genesis.279 **/280 hostConfiguration: AugmentedQuery<ApiType, () => Observable<Option<PolkadotPrimitivesV2AbridgedHostConfiguration>>, []> & QueryableStorageEntry<ApiType, []>;281 /**282 * HRMP messages that were sent in a block.283 * 284 * This will be cleared in `on_initialize` of each new block.285 **/286 hrmpOutboundMessages: AugmentedQuery<ApiType, () => Observable<Vec<PolkadotCorePrimitivesOutboundHrmpMessage>>, []> & QueryableStorageEntry<ApiType, []>;287 /**288 * HRMP watermark that was set in a block.289 * 290 * This will be cleared in `on_initialize` of each new block.291 **/292 hrmpWatermark: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;293 /**294 * The last downward message queue chain head we have observed.295 * 296 * This value is loaded before and saved after processing inbound downward messages carried297 * by the system inherent.298 **/299 lastDmqMqcHead: AugmentedQuery<ApiType, () => Observable<H256>, []> & QueryableStorageEntry<ApiType, []>;300 /**301 * The message queue chain heads we have observed per each channel incoming channel.302 * 303 * This value is loaded before and saved after processing inbound downward messages carried304 * by the system inherent.305 **/306 lastHrmpMqcHeads: AugmentedQuery<ApiType, () => Observable<BTreeMap<u32, H256>>, []> & QueryableStorageEntry<ApiType, []>;307 /**308 * Validation code that is set by the parachain and is to be communicated to collator and309 * consequently the relay-chain.310 * 311 * This will be cleared in `on_initialize` of each new block if no other pallet already set312 * the value.313 **/314 newValidationCode: AugmentedQuery<ApiType, () => Observable<Option<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;315 /**316 * Upward messages that are still pending and not yet send to the relay chain.317 **/318 pendingUpwardMessages: AugmentedQuery<ApiType, () => Observable<Vec<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;319 /**320 * In case of a scheduled upgrade, this storage field contains the validation code to be applied.321 * 322 * As soon as the relay chain gives us the go-ahead signal, we will overwrite the [`:code`][well_known_keys::CODE]323 * which will result the next block process with the new validation code. This concludes the upgrade process.324 * 325 * [well_known_keys::CODE]: sp_core::storage::well_known_keys::CODE326 **/327 pendingValidationCode: AugmentedQuery<ApiType, () => Observable<Bytes>, []> & QueryableStorageEntry<ApiType, []>;328 /**329 * Number of downward messages processed in a block.330 * 331 * This will be cleared in `on_initialize` of each new block.332 **/333 processedDownwardMessages: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;334 /**335 * The state proof for the last relay parent block.336 * 337 * This field is meant to be updated each block with the validation data inherent. Therefore,338 * before processing of the inherent, e.g. in `on_initialize` this data may be stale.339 * 340 * This data is also absent from the genesis.341 **/342 relayStateProof: AugmentedQuery<ApiType, () => Observable<Option<SpTrieStorageProof>>, []> & QueryableStorageEntry<ApiType, []>;343 /**344 * The snapshot of some state related to messaging relevant to the current parachain as per345 * the relay parent.346 * 347 * This field is meant to be updated each block with the validation data inherent. Therefore,348 * before processing of the inherent, e.g. in `on_initialize` this data may be stale.349 * 350 * This data is also absent from the genesis.351 **/352 relevantMessagingState: AugmentedQuery<ApiType, () => Observable<Option<CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot>>, []> & QueryableStorageEntry<ApiType, []>;353 /**354 * The weight we reserve at the beginning of the block for processing DMP messages. This355 * overrides the amount set in the Config trait.356 **/357 reservedDmpWeightOverride: AugmentedQuery<ApiType, () => Observable<Option<u64>>, []> & QueryableStorageEntry<ApiType, []>;358 /**359 * The weight we reserve at the beginning of the block for processing XCMP messages. This360 * overrides the amount set in the Config trait.361 **/362 reservedXcmpWeightOverride: AugmentedQuery<ApiType, () => Observable<Option<u64>>, []> & QueryableStorageEntry<ApiType, []>;363 /**364 * An option which indicates if the relay-chain restricts signalling a validation code upgrade.365 * In other words, if this is `Some` and [`NewValidationCode`] is `Some` then the produced366 * candidate will be invalid.367 * 368 * This storage item is a mirror of the corresponding value for the current parachain from the369 * relay-chain. This value is ephemeral which means it doesn't hit the storage. This value is370 * set after the inherent.371 **/372 upgradeRestrictionSignal: AugmentedQuery<ApiType, () => Observable<Option<PolkadotPrimitivesV2UpgradeRestriction>>, []> & QueryableStorageEntry<ApiType, []>;373 /**374 * Upward messages that were sent in a block.375 * 376 * This will be cleared in `on_initialize` of each new block.377 **/378 upwardMessages: AugmentedQuery<ApiType, () => Observable<Vec<Bytes>>, []> & QueryableStorageEntry<ApiType, []>;379 /**380 * The [`PersistedValidationData`] set for this block.381 * This value is expected to be set only once per block and it's never stored382 * in the trie.383 **/384 validationData: AugmentedQuery<ApiType, () => Observable<Option<PolkadotPrimitivesV2PersistedValidationData>>, []> & QueryableStorageEntry<ApiType, []>;385 /**386 * Generic query387 **/388 [key: string]: QueryableStorageEntry<ApiType>;389 };390 randomnessCollectiveFlip: {391 /**392 * Series of block headers from the last 81 blocks that acts as random seed material. This393 * is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of394 * the oldest hash.395 **/396 randomMaterial: AugmentedQuery<ApiType, () => Observable<Vec<H256>>, []> & QueryableStorageEntry<ApiType, []>;397 /**398 * Generic query399 **/400 [key: string]: QueryableStorageEntry<ApiType>;401 };402 refungible: {403 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;404 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg4: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;405 balance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]>;406 /**407 * Used to enumerate tokens owned by account408 **/409 owned: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]>;410 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<PalletRefungibleItemData>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;411 tokenProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;412 tokensBurnt: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;413 tokensMinted: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;414 totalSupply: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u128>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;415 /**416 * Generic query417 **/418 [key: string]: QueryableStorageEntry<ApiType>;419 };420 rmrkCore: {421 collectionIndex: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;422 uniqueCollectionId: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;423 /**424 * Generic query425 **/426 [key: string]: QueryableStorageEntry<ApiType>;427 };428 rmrkEquip: {429 baseHasDefaultTheme: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;430 inernalPartId: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;431 /**432 * Generic query433 **/434 [key: string]: QueryableStorageEntry<ApiType>;435 };436 scheduler: {437 /**438 * Items to be executed, indexed by the block number that they should be executed on.439 **/440 agenda: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<Option<PalletUniqueSchedulerScheduledV3>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;441 /**442 * Lookup from identity to the block number and index of the task.443 **/444 lookup: AugmentedQuery<ApiType, (arg: U8aFixed | string | Uint8Array) => Observable<Option<ITuple<[u32, u32]>>>, [U8aFixed]> & QueryableStorageEntry<ApiType, [U8aFixed]>;445 /**446 * Generic query447 **/448 [key: string]: QueryableStorageEntry<ApiType>;449 };450 structure: {451 /**452 * Generic query453 **/454 [key: string]: QueryableStorageEntry<ApiType>;455 };456 sudo: {457 /**458 * The `AccountId` of the sudo key.459 **/460 key: AugmentedQuery<ApiType, () => Observable<Option<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;461 /**462 * Generic query463 **/464 [key: string]: QueryableStorageEntry<ApiType>;465 };466 system: {467 /**468 * The full account information for a particular account ID.469 **/470 account: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<FrameSystemAccountInfo>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;471 /**472 * Total length (in bytes) for all extrinsics put together, for the current block.473 **/474 allExtrinsicsLen: AugmentedQuery<ApiType, () => Observable<Option<u32>>, []> & QueryableStorageEntry<ApiType, []>;475 /**476 * Map of block numbers to block hashes.477 **/478 blockHash: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<H256>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;479 /**480 * The current weight for the block.481 **/482 blockWeight: AugmentedQuery<ApiType, () => Observable<FrameSupportWeightsPerDispatchClassU64>, []> & QueryableStorageEntry<ApiType, []>;483 /**484 * Digest of the current block, also part of the block header.485 **/486 digest: AugmentedQuery<ApiType, () => Observable<SpRuntimeDigest>, []> & QueryableStorageEntry<ApiType, []>;487 /**488 * The number of events in the `Events<T>` list.489 **/490 eventCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;491 /**492 * Events deposited for the current block.493 * 494 * NOTE: The item is unbound and should therefore never be read on chain.495 * It could otherwise inflate the PoV size of a block.496 * 497 * Events have a large in-memory size. Box the events to not go out-of-memory498 * just in case someone still reads them from within the runtime.499 **/500 events: AugmentedQuery<ApiType, () => Observable<Vec<FrameSystemEventRecord>>, []> & QueryableStorageEntry<ApiType, []>;501 /**502 * Mapping between a topic (represented by T::Hash) and a vector of indexes503 * of events in the `<Events<T>>` list.504 * 505 * All topic vectors have deterministic storage locations depending on the topic. This506 * allows light-clients to leverage the changes trie storage tracking mechanism and507 * in case of changes fetch the list of events of interest.508 * 509 * The value has the type `(T::BlockNumber, EventIndex)` because if we used only just510 * the `EventIndex` then in case if the topic has the same contents on the next block511 * no notification will be triggered thus the event might be lost.512 **/513 eventTopics: AugmentedQuery<ApiType, (arg: H256 | string | Uint8Array) => Observable<Vec<ITuple<[u32, u32]>>>, [H256]> & QueryableStorageEntry<ApiType, [H256]>;514 /**515 * The execution phase of the block.516 **/517 executionPhase: AugmentedQuery<ApiType, () => Observable<Option<FrameSystemPhase>>, []> & QueryableStorageEntry<ApiType, []>;518 /**519 * Total extrinsics count for the current block.520 **/521 extrinsicCount: AugmentedQuery<ApiType, () => Observable<Option<u32>>, []> & QueryableStorageEntry<ApiType, []>;522 /**523 * Extrinsics data for the current block (maps an extrinsic's index to its data).524 **/525 extrinsicData: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;526 /**527 * Stores the `spec_version` and `spec_name` of when the last runtime upgrade happened.528 **/529 lastRuntimeUpgrade: AugmentedQuery<ApiType, () => Observable<Option<FrameSystemLastRuntimeUpgradeInfo>>, []> & QueryableStorageEntry<ApiType, []>;530 /**531 * The current block number being processed. Set by `execute_block`.532 **/533 number: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;534 /**535 * Hash of the previous block.536 **/537 parentHash: AugmentedQuery<ApiType, () => Observable<H256>, []> & QueryableStorageEntry<ApiType, []>;538 /**539 * True if we have upgraded so that AccountInfo contains three types of `RefCount`. False540 * (default) if not.541 **/542 upgradedToTripleRefCount: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;543 /**544 * True if we have upgraded so that `type RefCount` is `u32`. False (default) if not.545 **/546 upgradedToU32RefCount: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;547 /**548 * Generic query549 **/550 [key: string]: QueryableStorageEntry<ApiType>;551 };552 timestamp: {553 /**554 * Did the timestamp get updated in this block?555 **/556 didUpdate: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;557 /**558 * Current time for the current block.559 **/560 now: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;561 /**562 * Generic query563 **/564 [key: string]: QueryableStorageEntry<ApiType>;565 };566 transactionPayment: {567 nextFeeMultiplier: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;568 storageVersion: AugmentedQuery<ApiType, () => Observable<PalletTransactionPaymentReleases>, []> & QueryableStorageEntry<ApiType, []>;569 /**570 * Generic query571 **/572 [key: string]: QueryableStorageEntry<ApiType>;573 };574 treasury: {575 /**576 * Proposal indices that have been approved but not yet awarded.577 **/578 approvals: AugmentedQuery<ApiType, () => Observable<Vec<u32>>, []> & QueryableStorageEntry<ApiType, []>;579 /**580 * Number of proposals that have been made.581 **/582 proposalCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;583 /**584 * Proposals that have been made.585 **/586 proposals: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletTreasuryProposal>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;587 /**588 * Generic query589 **/590 [key: string]: QueryableStorageEntry<ApiType>;591 };592 unique: {593 /**594 * Used for migrations595 **/596 chainVersion: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;597 /**598 * (Collection id (controlled?2), who created (real))599 * TODO: Off chain worker should remove from this map when collection gets removed600 **/601 createItemBasket: AugmentedQuery<ApiType, (arg: ITuple<[u32, AccountId32]> | [u32 | AnyNumber | Uint8Array, AccountId32 | string | Uint8Array]) => Observable<Option<u32>>, [ITuple<[u32, AccountId32]>]> & QueryableStorageEntry<ApiType, [ITuple<[u32, AccountId32]>]>;602 fungibleApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, AccountId32]>;603 /**604 * Collection id (controlled?2), owning user (real)605 **/606 fungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, AccountId32]>;607 /**608 * Approval sponsoring609 **/610 nftApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;611 /**612 * Collection id (controlled?2), token id (controlled?2)613 **/614 nftTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;615 refungibleApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, u32, AccountId32]>;616 /**617 * Collection id (controlled?2), token id (controlled?2)618 **/619 reFungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, u32, AccountId32]>;620 tokenPropertyBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;621 /**622 * Variable metadata sponsoring623 * Collection id (controlled?2), token id (controlled?2)624 **/625 variableMetaDataBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;626 /**627 * Generic query628 **/629 [key: string]: QueryableStorageEntry<ApiType>;630 };631 vesting: {632 /**633 * Vesting schedules of an account.634 * 635 * VestingSchedules: map AccountId => Vec<VestingSchedule>636 **/637 vestingSchedules: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Vec<OrmlVestingVestingSchedule>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;638 /**639 * Generic query640 **/641 [key: string]: QueryableStorageEntry<ApiType>;642 };643 xcmpQueue: {644 /**645 * Inbound aggregate XCMP messages. It can only be one per ParaId/block.646 **/647 inboundXcmpMessages: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;648 /**649 * Status of the inbound XCMP channels.650 **/651 inboundXcmpStatus: AugmentedQuery<ApiType, () => Observable<Vec<CumulusPalletXcmpQueueInboundChannelDetails>>, []> & QueryableStorageEntry<ApiType, []>;652 /**653 * The messages outbound in a given XCMP channel.654 **/655 outboundXcmpMessages: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u16 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32, u16]> & QueryableStorageEntry<ApiType, [u32, u16]>;656 /**657 * The non-empty XCMP channels in order of becoming non-empty, and the index of the first658 * and last outbound message. If the two indices are equal, then it indicates an empty659 * queue and there must be a non-`Ok` `OutboundStatus`. We assume queues grow no greater660 * than 65535 items. Queue indices for normal messages begin at one; zero is reserved in661 * case of the need to send a high-priority signal message this block.662 * The bool is true if there is a signal message waiting to be sent.663 **/664 outboundXcmpStatus: AugmentedQuery<ApiType, () => Observable<Vec<CumulusPalletXcmpQueueOutboundChannelDetails>>, []> & QueryableStorageEntry<ApiType, []>;665 /**666 * The messages that exceeded max individual message weight budget.667 * 668 * These message stay in this storage map until they are manually dispatched via669 * `service_overweight`.670 **/671 overweight: AugmentedQuery<ApiType, (arg: u64 | AnyNumber | Uint8Array) => Observable<Option<ITuple<[u32, u32, Bytes]>>>, [u64]> & QueryableStorageEntry<ApiType, [u64]>;672 /**673 * The number of overweight messages ever recorded in `Overweight`. Also doubles as the next674 * available free overweight index.675 **/676 overweightCount: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;677 /**678 * The configuration which controls the dynamics of the outbound queue.679 **/680 queueConfig: AugmentedQuery<ApiType, () => Observable<CumulusPalletXcmpQueueQueueConfigData>, []> & QueryableStorageEntry<ApiType, []>;681 /**682 * Whether or not the XCMP queue is suspended from executing incoming XCMs or not.683 **/684 queueSuspended: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;685 /**686 * Any signal messages waiting to be sent.687 **/688 signalMessages: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Bytes>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;689 /**690 * Generic query691 **/692 [key: string]: QueryableStorageEntry<ApiType>;693 };694 } // AugmentedQueries695} // declare moduletests/src/interfaces/default/types.tsdiffbeforeafterboth--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -2461,12 +2461,14 @@
export interface UpDataStructsCreateReFungibleData extends Struct {
readonly constData: Bytes;
readonly pieces: u128;
+ readonly properties: Vec<UpDataStructsProperty>;
}
/** @name UpDataStructsCreateRefungibleExData */
export interface UpDataStructsCreateRefungibleExData extends Struct {
readonly constData: Bytes;
readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
+ readonly properties: Vec<UpDataStructsProperty>;
}
/** @name UpDataStructsNestingPermissions */
tests/src/interfaces/lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -1502,7 +1502,8 @@
**/
UpDataStructsCreateReFungibleData: {
constData: 'Bytes',
- pieces: 'u128'
+ pieces: 'u128',
+ properties: 'Vec<UpDataStructsProperty>'
},
/**
* Lookup193: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
@@ -1527,7 +1528,8 @@
**/
UpDataStructsCreateRefungibleExData: {
constData: 'Bytes',
- users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>'
+ users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',
+ properties: 'Vec<UpDataStructsProperty>'
},
/**
* Lookup204: pallet_unique_scheduler::pallet::Call<T>
tests/src/interfaces/types-lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1629,6 +1629,7 @@
export interface UpDataStructsCreateReFungibleData extends Struct {
readonly constData: Bytes;
readonly pieces: u128;
+ readonly properties: Vec<UpDataStructsProperty>;
}
/** @name UpDataStructsCreateItemExData (193) */
@@ -1654,6 +1655,7 @@
export interface UpDataStructsCreateRefungibleExData extends Struct {
readonly constData: Bytes;
readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
+ readonly properties: Vec<UpDataStructsProperty>;
}
/** @name PalletUniqueSchedulerCall (204) */
tests/src/nesting/properties.test.tsdiffbeforeafterboth--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -2,6 +2,7 @@
import usingApi, {executeTransaction} from '../substrate/substrate-api';
import {
addCollectionAdminExpectSuccess,
+ CollectionMode,
createCollectionExpectSuccess,
setCollectionPermissionsExpectSuccess,
createItemExpectSuccess,
@@ -23,9 +24,9 @@
});
});
- it('Makes sure collectionById supplies required fields', async () => {
+ async function testMakeSureSuppliesRequired(mode: CollectionMode) {
await usingApi(async api => {
- const collectionId = await createCollectionExpectSuccess();
+ const collectionId = await createCollectionExpectSuccess({mode: mode});
const collectionOption = await api.rpc.unique.collectionById(collectionId);
expect(collectionOption.isSome).to.be.true;
@@ -57,7 +58,15 @@
expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);
expect(collection.properties.toHuman()).to.be.deep.equal(collectionProperties);
});
+ }
+
+ it('Makes sure collectionById supplies required fields for NFT', async () => {
+ await testMakeSureSuppliesRequired({type: 'NFT'});
});
+
+ it('Makes sure collectionById supplies required fields for ReFungible', async () => {
+ await testMakeSureSuppliesRequired({type: 'ReFungible'});
+ });
});
// ---------- COLLECTION PROPERTIES
@@ -79,9 +88,10 @@
});
});
- it('Sets properties for a collection', async () => {
+
+ async function testSetsPropertiesForCollection(mode: string) {
await usingApi(async api => {
- const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: 'NFT'}));
+ const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: mode}));
const {collectionId} = getCreateCollectionResult(events);
// As owner
@@ -106,48 +116,54 @@
{key: 'black_hole', value: ''},
]);
});
+ }
+ it('Sets properties for a NFT collection', async () => {
+ await testSetsPropertiesForCollection('NFT');
});
+ it('Sets properties for a ReFungible collection', async () => {
+ await testSetsPropertiesForCollection('ReFungible');
+ });
- it('Check valid names for collection properties keys', async () => {
+ async function testCheckValidNames(mode: string) {
await usingApi(async api => {
- const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: 'NFT'}));
+ const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: mode}));
const {collectionId} = getCreateCollectionResult(events);
-
+
// alpha symbols
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'alpha'}]),
)).to.not.be.rejected;
-
+
// numeric symbols
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: '123'}]),
)).to.not.be.rejected;
-
+
// underscore symbol
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'black_hole'}]),
)).to.not.be.rejected;
-
+
// dash symbol
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'semi-automatic'}]),
)).to.not.be.rejected;
-
+
// underscore symbol
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'build.rs'}]),
)).to.not.be.rejected;
-
+
const propertyKeys = ['alpha', '123', 'black_hole', 'semi-automatic', 'build.rs'];
const properties = (await api.rpc.unique.collectionProperties(collectionId, propertyKeys)).toHuman();
expect(properties).to.be.deep.equal([
@@ -158,54 +174,72 @@
{key: 'build.rs', value: ''},
]);
});
+ }
+ it('Check valid names for NFT collection properties keys', async () => {
+ await testCheckValidNames('NFT');
+ });
+ it('Check valid names for ReFungible collection properties keys', async () => {
+ await testCheckValidNames('ReFungible');
});
- it('Changes properties of a collection', async () => {
+ async function testChangesProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole'}]),
)).to.not.be.rejected;
-
+
// Mutate the properties
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'bonded'}, {key: 'black_hole', value: 'LIGO'}]),
)).to.not.be.rejected;
-
+
const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();
expect(properties).to.be.deep.equal([
{key: 'electron', value: 'bonded'},
{key: 'black_hole', value: 'LIGO'},
]);
});
+ }
+ it('Changes properties of a NFT collection', async () => {
+ await testChangesProperties({type: 'NFT'});
+ });
+ it('Changes properties of a ReFungible collection', async () => {
+ await testChangesProperties({type: 'ReFungible'});
});
- it('Deletes properties of a collection', async () => {
+ async function testDeleteProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]),
)).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.deleteCollectionProperties(collection, ['electron']),
)).to.not.be.rejected;
-
+
const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();
expect(properties).to.be.deep.equal([
{key: 'black_hole', value: 'LIGO'},
]);
- });
+ });
+ }
+ it('Deletes properties of a NFT collection', async () => {
+ await testDeleteProperties({type: 'NFT'});
+ });
+ it('Deletes properties of a ReFungible collection', async () => {
+ await testDeleteProperties({type: 'ReFungible'});
});
});
@@ -217,10 +251,10 @@
});
});
- it('Fails to set properties in a collection if not its onwer/administrator', async () => {
+ async function testFailsSetPropertiesIfNotOwnerOrAdmin(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
bob,
@@ -230,14 +264,20 @@
const properties = (await api.query.common.collectionProperties(collection)).toJSON();
expect(properties.map).to.be.empty;
expect(properties.consumedSpace).to.equal(0);
- });
+ });
+ }
+ it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {
+ await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});
});
+ it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async () => {
+ await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});
+ });
- it('Fails to set properties that exceed the limits', async () => {
+ async function testFailsSetPropertiesThatExeedLimits(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
+ const collection = await createCollectionExpectSuccess({mode: mode});
const spaceLimit = (await api.query.common.collectionProperties(collection)).toJSON().spaceLimit as number;
-
+
// Mute the general tx parsing error, too many bytes to process
{
console.error = () => {};
@@ -247,10 +287,10 @@
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 9))}]),
)).to.be.rejected;
}
-
+
let properties = (await api.rpc.unique.collectionProperties(collection, ['electron'])).toJSON();
expect(properties).to.be.empty;
-
+
await expect(executeTransaction(
api,
alice,
@@ -259,16 +299,22 @@
{key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))},
]),
)).to.be.rejectedWith(/common\.NoSpaceForProperty/);
-
+
properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black hole'])).toJSON();
expect(properties).to.be.empty;
- });
+ });
+ }
+ it('Fails to set properties that exceed the limits (NFT)', async () => {
+ await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});
+ });
+ it('Fails to set properties that exceed the limits (ReFungible)', async () => {
+ await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});
});
- it('Fails to set more properties than it is allowed', async () => {
+ async function testFailsSetMorePropertiesThanAllowed(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const propertiesToBeSet = [];
for (let i = 0; i < 65; i++) {
propertiesToBeSet.push({
@@ -276,29 +322,35 @@
value: Math.random() > 0.5 ? 'high' : 'low',
});
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, propertiesToBeSet),
)).to.be.rejectedWith(/common\.PropertyLimitReached/);
-
+
const properties = (await api.query.common.collectionProperties(collection)).toJSON();
expect(properties.map).to.be.empty;
expect(properties.consumedSpace).to.equal(0);
- });
+ });
+ }
+ it('Fails to set more properties than it is allowed (NFT)', async () => {
+ await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});
});
-
- it('Fails to set properties with invalid names', async () => {
+ it('Fails to set more properties than it is allowed (ReFungible)', async () => {
+ await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});
+ });
+
+ async function testFailsSetPropertiesWithInvalidNames(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const invalidProperties = [
[{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],
[{key: 'Mr/Sandman', value: 'Bring me a gene'}],
[{key: 'déjà vu', value: 'hmm...'}],
];
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(executeTransaction(
api,
@@ -306,13 +358,13 @@
api.tx.unique.setCollectionProperties(collection, invalidProperties[i]),
), `on rejecting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: '', value: 'nothing must not exist'}]),
), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);
-
+
await expect(executeTransaction(
api,
alice,
@@ -320,14 +372,14 @@
{key: 'CRISPR-Cas9', value: 'rewriting nature!'},
]),
), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;
-
+
const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat('CRISPR-Cas9').concat('');
-
+
const properties = (await api.rpc.unique.collectionProperties(collection, keys)).toHuman();
expect(properties).to.be.deep.equal([
{key: 'CRISPR-Cas9', value: 'rewriting nature!'},
]);
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(executeTransaction(
api,
@@ -336,7 +388,13 @@
), `on trying to delete the non-existent badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
});
+ }
+ it('Fails to set properties with invalid names (NFT)', async () => {
+ await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});
});
+ it('Fails to set properties with invalid names (ReFungible)', async () => {
+ await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});
+ });
});
// ---------- ACCESS RIGHTS
@@ -357,54 +415,66 @@
});
});
- it('Sets access rights to properties of a collection', async () => {
+ async function testSetsAccessRightsToProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true}}]),
)).to.not.be.rejected;
-
+
await addCollectionAdminExpectSuccess(alice, collection, bob.address);
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'mindgame', permission: {collectionAdmin: true, tokenOwner: false}}]),
)).to.not.be.rejected;
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery', 'mindgame'])).toHuman();
expect(propertyRights).to.be.deep.equal([
{key: 'skullduggery', permission: {'mutable': true, 'collectionAdmin': false, 'tokenOwner': false}},
{key: 'mindgame', permission: {'mutable': false, 'collectionAdmin': true, 'tokenOwner': false}},
]);
- });
+ });
+ }
+ it('Sets access rights to properties of a collection (NFT)', async () => {
+ await testSetsAccessRightsToProperties({type: 'NFT'});
});
+ it('Sets access rights to properties of a collection (ReFungible)', async () => {
+ await testSetsAccessRightsToProperties({type: 'ReFungible'});
+ });
- it('Changes access rights to properties of a collection', async () => {
+ async function testChangesAccessRightsToProperty(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]),
)).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]),
)).to.not.be.rejected;
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();
expect(propertyRights).to.be.deep.equal([
{key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},
]);
});
+ }
+ it('Changes access rights to properties of a NFT collection', async () => {
+ await testChangesAccessRightsToProperty({type: 'NFT'});
});
+ it('Changes access rights to properties of a ReFungible collection', async () => {
+ await testChangesAccessRightsToProperty({type: 'ReFungible'});
+ });
});
describe('Negative Integration Test: Access Rights to Token Properties', () => {
@@ -415,25 +485,31 @@
});
});
- it('Prevents from setting access rights to properties of a collection if not an onwer/admin', async () => {
+ async function testPreventsFromSettingAccessRightsNotAdminOrOwner(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
bob,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]),
)).to.be.rejectedWith(/common\.NoPermission/);
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toJSON();
expect(propertyRights).to.be.empty;
});
+ }
+ it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {
+ await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});
});
+ it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async () => {
+ await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});
+ });
- it('Prevents from adding too many possible properties', async () => {
+ async function testPreventFromAddingTooManyPossibleProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const constitution = [];
for (let i = 0; i < 65; i++) {
constitution.push({
@@ -441,51 +517,63 @@
permission: Math.random() > 0.5 ? {mutable: true, collectionAdmin: true, tokenOwner: true} : {},
});
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, constitution),
)).to.be.rejectedWith(/common\.PropertyLimitReached/);
-
+
const propertyRights = (await api.query.common.collectionPropertyPermissions(collection)).toJSON();
expect(propertyRights).to.be.empty;
- });
+ });
+ }
+ it('Prevents from adding too many possible properties (NFT)', async () => {
+ await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});
});
+ it('Prevents from adding too many possible properties (ReFungible)', async () => {
+ await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});
+ });
- it('Prevents access rights to be modified if constant', async () => {
+ async function testPreventAccessRightsModifiedIfConstant(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]),
)).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {}}]),
)).to.be.rejectedWith(/common\.NoPermission/);
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();
expect(propertyRights).to.deep.equal([
{key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},
]);
- });
+ });
+ }
+ it('Prevents access rights to be modified if constant (NFT)', async () => {
+ await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});
+ });
+ it('Prevents access rights to be modified if constant (ReFungible)', async () => {
+ await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});
});
- it('Prevents adding properties with invalid names', async () => {
+ async function testPreventsAddingPropertiesWithInvalidNames(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const invalidProperties = [
[{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],
[{key: 'G#4', permission: {tokenOwner: true}}],
[{key: 'HÆMILTON', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}],
];
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(executeTransaction(
api,
@@ -493,13 +581,13 @@
api.tx.unique.setTokenPropertyPermissions(collection, invalidProperties[i]),
), `on setting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: '', permission: {}}]),
), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);
-
+
const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string
await expect(executeTransaction(
api,
@@ -508,30 +596,33 @@
{key: correctKey, permission: {collectionAdmin: true}},
]),
), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;
-
+
const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat(correctKey).concat('');
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, keys)).toHuman();
expect(propertyRights).to.be.deep.equal([
{key: correctKey, permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},
]);
});
+ }
+ it('Prevents adding properties with invalid names (NFT)', async () => {
+ await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});
+ });
+ it('Prevents adding properties with invalid names (ReFungible)', async () => {
+ await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});
});
});
// ---------- TOKEN PROPERTIES
describe('Integration Test: Token Properties', () => {
- let collection: number;
- let token: number;
- let nestedToken: number;
let permissions: {permission: any, signers: IKeyringPair[]}[];
before(async () => {
await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ alice = privateKeyWrapper('//Alice'); // collection owner
+ bob = privateKeyWrapper('//Bob'); // collection admin
+ charlie = privateKeyWrapper('//Charlie'); // token owner
permissions = [
{permission: {mutable: true, collectionAdmin: true}, signers: [alice, bob]},
@@ -543,36 +634,34 @@
];
});
});
-
- beforeEach(async () => {
- await usingApi(async () => {
- collection = await createCollectionExpectSuccess();
- await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
-
- token = await createItemExpectSuccess(alice, collection, 'NFT');
- nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});
-
- await addCollectionAdminExpectSuccess(alice, collection, bob.address);
- await transferExpectSuccess(collection, token, alice, charlie);
- });
- });
- it('Reads yet empty properties of a token', async () => {
+ async function testReadsYetEmptyProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
- const token = await createItemExpectSuccess(alice, collection, 'NFT');
+ const collection = await createCollectionExpectSuccess({mode: mode});
+ const token = await createItemExpectSuccess(alice, collection, mode.type);
const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();
expect(properties.map).to.be.empty;
expect(properties.consumedSpace).to.be.equal(0);
-
+
const tokenData = (await api.rpc.unique.tokenData(collection, token, ['anything'])).toJSON().properties;
expect(tokenData).to.be.empty;
});
+ }
+ it('Reads yet empty properties of a token (NFT)', async () => {
+ await testReadsYetEmptyProperties({type: 'NFT'});
});
+ it('Reads yet empty properties of a token (ReFungible)', async () => {
+ await testReadsYetEmptyProperties({type: 'ReFungible'});
+ });
- it('Assigns properties to a token according to permissions', async () => {
+ async function testAssignPropertiesAccordingToPermissions(mode: CollectionMode, pieces: number) {
await usingApi(async api => {
+ const collection = await createCollectionExpectSuccess({mode: mode});
+ const token = await createItemExpectSuccess(alice, collection, mode.type);
+ await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+ await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);
+
const propertyKeys: string[] = [];
let i = 0;
for (const permission of permissions) {
@@ -603,10 +692,21 @@
expect(tokensData[i].value).to.be.equal('Serotonin increase');
}
});
+ }
+ it('Assigns properties to a token according to permissions (NFT)', async () => {
+ await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);
+ });
+ it('Assigns properties to a token according to permissions (ReFungible)', async () => {
+ await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);
});
- it('Changes properties of a token according to permissions', async () => {
+ async function testChangesPropertiesAccordingPermission(mode: CollectionMode, pieces: number) {
await usingApi(async api => {
+ const collection = await createCollectionExpectSuccess({mode: mode});
+ const token = await createItemExpectSuccess(alice, collection, mode.type);
+ await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+ await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);
+
const propertyKeys: string[] = [];
let i = 0;
for (const permission of permissions) {
@@ -615,29 +715,29 @@
for (const signer of permission.signers) {
const key = i + '_' + signer.address;
propertyKeys.push(key);
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: key, permission: permission.permission}]),
), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
signer,
api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin increase'}]),
), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
signer,
api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin stable'}]),
), `on changing property ${i} by ${signer.address}`).to.not.be.rejected;
}
-
+
i++;
}
-
+
const properties = (await api.rpc.unique.tokenProperties(collection, token, propertyKeys)).toHuman() as any[];
const tokensData = (await api.rpc.unique.tokenData(collection, token, propertyKeys)).toHuman().properties as any[];
for (let i = 0; i < properties.length; i++) {
@@ -645,32 +745,43 @@
expect(tokensData[i].value).to.be.equal('Serotonin stable');
}
});
+ }
+ it('Changes properties of a token according to permissions (NFT)', async () => {
+ await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);
});
+ it('Changes properties of a token according to permissions (ReFungible)', async () => {
+ await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);
+ });
- it('Deletes properties of a token according to permissions', async () => {
+ async function testDeletePropertiesAccordingPermission(mode: CollectionMode, pieces: number) {
await usingApi(async api => {
+ const collection = await createCollectionExpectSuccess({mode: mode});
+ const token = await createItemExpectSuccess(alice, collection, mode.type);
+ await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+ await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);
+
const propertyKeys: string[] = [];
let i = 0;
-
+
for (const permission of permissions) {
if (!permission.permission.mutable) continue;
for (const signer of permission.signers) {
const key = i + '_' + signer.address;
propertyKeys.push(key);
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: key, permission: permission.permission}]),
), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
signer,
api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin increase'}]),
), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
signer,
@@ -680,17 +791,30 @@
i++;
}
-
+
const properties = (await api.rpc.unique.tokenProperties(collection, token, propertyKeys)).toJSON() as any[];
expect(properties).to.be.empty;
const tokensData = (await api.rpc.unique.tokenData(collection, token, propertyKeys)).toJSON().properties as any[];
expect(tokensData).to.be.empty;
expect((await api.query.nonfungible.tokenProperties(collection, token)).toJSON().consumedSpace).to.be.equal(0);
});
+ }
+ it('Deletes properties of a token according to permissions (NFT)', async () => {
+ await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);
});
+ it('Deletes properties of a token according to permissions (ReFungible)', async () => {
+ await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);
+ });
it('Assigns properties to a nested token according to permissions', async () => {
await usingApi(async api => {
+ const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+ await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
+ const token = await createItemExpectSuccess(alice, collection, 'NFT');
+ const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});
+ await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+ await transferExpectSuccess(collection, token, alice, charlie);
+
const propertyKeys: string[] = [];
let i = 0;
for (const permission of permissions) {
@@ -725,6 +849,13 @@
it('Changes properties of a nested token according to permissions', async () => {
await usingApi(async api => {
+ const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+ await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
+ const token = await createItemExpectSuccess(alice, collection, 'NFT');
+ const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});
+ await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+ await transferExpectSuccess(collection, token, alice, charlie);
+
const propertyKeys: string[] = [];
let i = 0;
for (const permission of permissions) {
@@ -767,6 +898,13 @@
it('Deletes properties of a nested token according to permissions', async () => {
await usingApi(async api => {
+ const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+ await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
+ const token = await createItemExpectSuccess(alice, collection, 'NFT');
+ const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});
+ await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+ await transferExpectSuccess(collection, token, alice, charlie);
+
const propertyKeys: string[] = [];
let i = 0;
@@ -832,11 +970,11 @@
});
});
- beforeEach(async () => {
- collection = await createCollectionExpectSuccess();
- token = await createItemExpectSuccess(alice, collection, 'NFT');
+ async function prepare(mode: CollectionMode, pieces: number) {
+ collection = await createCollectionExpectSuccess({mode: mode});
+ token = await createItemExpectSuccess(alice, collection, mode.type);
await addCollectionAdminExpectSuccess(alice, collection, bob.address);
- await transferExpectSuccess(collection, token, alice, charlie);
+ await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);
await usingApi(async api => {
let i = 0;
@@ -848,71 +986,89 @@
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: `${i}`, permission: passage.permission}]),
), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
signer,
api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin increase'}]),
), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;
-
+
i++;
}
-
+
originalSpace = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON().consumedSpace as number;
- });
- });
+ });
+ }
- it('Forbids changing/deleting properties of a token if the user is outside of permissions', async () => {
+ async function testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(mode: CollectionMode, pieces: number) {
+ await prepare(mode, pieces);
+
await usingApi(async api => {
let i = -1;
for (const forbiddance of constitution) {
i++;
if (!forbiddance.permission.mutable) continue;
-
+
await expect(executeTransaction(
api,
forbiddance.sinner,
api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin down'}]),
), `on failing to change property ${i} by ${forbiddance.sinner.address}`).to.be.rejectedWith(/common\.NoPermission/);
-
+
await expect(executeTransaction(
api,
forbiddance.sinner,
api.tx.unique.deleteTokenProperties(collection, token, [`${i}`]),
), `on failing to delete property ${i} by ${forbiddance.sinner.address}`).to.be.rejectedWith(/common\.NoPermission/);
}
-
+
const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();
expect(properties.consumedSpace).to.be.equal(originalSpace);
});
+ }
+ it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {
+ await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);
});
+ it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async () => {
+ await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);
+ });
- it('Forbids changing/deleting properties of a token if the property is permanent (immutable)', async () => {
+ async function testForbidsChangingDeletingPropertiesIfPropertyImmutable(mode: CollectionMode, pieces: number) {
+ await prepare(mode, pieces);
+
await usingApi(async api => {
let i = -1;
for (const permission of constitution) {
i++;
if (permission.permission.mutable) continue;
-
+
await expect(executeTransaction(
api,
permission.signers[0],
api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin down'}]),
), `on failing to change property ${i} by ${permission.signers[0].address}`).to.be.rejectedWith(/common\.NoPermission/);
-
+
await expect(executeTransaction(
api,
permission.signers[0],
api.tx.unique.deleteTokenProperties(collection, token, [i.toString()]),
), `on failing to delete property ${i} by ${permission.signers[0].address}`).to.be.rejectedWith(/common\.NoPermission/);
}
-
+
const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();
expect(properties.consumedSpace).to.be.equal(originalSpace);
- });
+ });
+ }
+ it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {
+ await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);
});
+ it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async () => {
+ await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);
+ });
+
+ async function testForbidsAddingPropertiesIfPropertyNotDeclared(mode: CollectionMode, pieces: number) {
+ await prepare(mode, pieces);
- it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission', async () => {
await usingApi(async api => {
await expect(executeTransaction(
api,
@@ -925,20 +1081,28 @@
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'now-existent', permission: {}}]),
), 'on setting a new non-permitted property').to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenProperties(collection, token, [{key: 'now-existent', value: 'I exist!'}]),
), 'on failing to add a property forbidden by the \'None\' permission').to.be.rejectedWith(/common\.NoPermission/);
-
+
expect((await api.rpc.unique.tokenProperties(collection, token, ['non-existent', 'now-existent'])).toJSON()).to.be.empty;
const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();
expect(properties.consumedSpace).to.be.equal(originalSpace);
});
+ }
+ it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async () => {
+ await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'NFT'}, 1);
+ });
+ it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async () => {
+ await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);
});
- it('Forbids adding too many properties to a token', async () => {
+ async function testForbidsAddingTooManyProperties(mode: CollectionMode, pieces: number) {
+ await prepare(mode, pieces);
+
await usingApi(async api => {
await expect(executeTransaction(
api,
@@ -948,7 +1112,7 @@
{key: 'young_years', permission: {collectionAdmin: true, tokenOwner: true}},
]),
), 'on setting a new non-permitted property').to.not.be.rejected;
-
+
// Mute the general tx parsing error
{
console.error = () => {};
@@ -958,7 +1122,7 @@
api.tx.unique.setCollectionProperties(collection, [{key: 'a_holy_book', value: 'word '.repeat(6554)}]),
)).to.be.rejected;
}
-
+
await expect(executeTransaction(
api,
alice,
@@ -967,10 +1131,107 @@
{key: 'young_years', value: 'neverending'.repeat(1490)},
]),
)).to.be.rejectedWith(/common\.NoSpaceForProperty/);
-
+
expect((await api.rpc.unique.tokenProperties(collection, token, ['a_holy_book', 'young_years'])).toJSON()).to.be.empty;
const propertiesMap = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();
expect(propertiesMap.consumedSpace).to.be.equal(originalSpace);
});
+ }
+ it('Forbids adding too many properties to a token (NFT)', async () => {
+ await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);
+ });
+ it('Forbids adding too many properties to a token (ReFungible)', async () => {
+ await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);
+ });
+});
+
+describe('ReFungible token properties permissions tests', () => {
+ let collection: number;
+ let token: number;
+
+ before(async () => {
+ await usingApi(async (api, privateKeyWrapper) => {
+ alice = privateKeyWrapper('//Alice');
+ bob = privateKeyWrapper('//Bob');
+ charlie = privateKeyWrapper('//Charlie');
+ });
+ });
+
+ beforeEach(async () => {
+ await usingApi(async api => {
+ collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+ token = await createItemExpectSuccess(alice, collection, 'ReFungible');
+ await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+
+ await expect(executeTransaction(
+ api,
+ alice,
+ api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'key', permission: {mutable:true, tokenOwner: true}}]),
+ )).to.not.be.rejected;
+ });
+ });
+
+ it('Forbids add token property with tokenOwher==true but signer have\'t all pieces', async () => {
+ await usingApi(async api => {
+ await transferExpectSuccess(collection, token, alice, charlie, 33, 'ReFungible');
+
+ await expect(executeTransaction(
+ api,
+ alice,
+ api.tx.unique.setTokenProperties(collection, token, [
+ {key: 'key', value: 'word'},
+ ]),
+ )).to.be.rejectedWith(/common\.NoPermission/);
+ });
+ });
+
+ it('Forbids mutate token property with tokenOwher==true but signer have\'t all pieces', async () => {
+ await usingApi(async api => {
+ await expect(executeTransaction(
+ api,
+ alice,
+ api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'key', permission: {mutable:true, tokenOwner: true}}]),
+ )).to.not.be.rejected;
+
+ await expect(executeTransaction(
+ api,
+ alice,
+ api.tx.unique.setTokenProperties(collection, token, [
+ {key: 'key', value: 'word'},
+ ]),
+ )).to.be.not.rejected;
+
+ await transferExpectSuccess(collection, token, alice, charlie, 33, 'ReFungible');
+
+ await expect(executeTransaction(
+ api,
+ alice,
+ api.tx.unique.setTokenProperties(collection, token, [
+ {key: 'key', value: 'bad word'},
+ ]),
+ )).to.be.rejectedWith(/common\.NoPermission/);
+ });
+ });
+
+ it('Forbids delete token property with tokenOwher==true but signer have\'t all pieces', async () => {
+ await usingApi(async api => {
+ await expect(executeTransaction(
+ api,
+ alice,
+ api.tx.unique.setTokenProperties(collection, token, [
+ {key: 'key', value: 'word'},
+ ]),
+ )).to.be.not.rejected;
+
+ await transferExpectSuccess(collection, token, alice, charlie, 33, 'ReFungible');
+
+ await expect(executeTransaction(
+ api,
+ alice,
+ api.tx.unique.deleteTokenProperties(collection, token, [
+ 'key',
+ ]),
+ )).to.be.rejectedWith(/common\.NoPermission/);
+ });
});
});
tests/src/refungible.test.tsdiffbeforeafterboth--- a/tests/src/refungible.test.ts
+++ b/tests/src/refungible.test.ts
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {default as usingApi} from './substrate/substrate-api';
+import {default as usingApi, executeTransaction} from './substrate/substrate-api';
import {IKeyringPair} from '@polkadot/types/types';
import {
createCollectionExpectSuccess,
@@ -30,6 +30,8 @@
transfer,
burnItem,
repartitionRFT,
+ createCollectionWithPropsExpectSuccess,
+ getDetailedCollectionInfo,
} from './util/helpers';
import chai from 'chai';
@@ -187,3 +189,26 @@
});
});
});
+
+describe('Test Refungible properties:', () => {
+ before(async () => {
+ await usingApi(async (api, privateKeyWrapper) => {
+ alice = privateKeyWrapper('//Alice');
+ bob = privateKeyWrapper('//Bob');
+ });
+ });
+
+ it('Сreate new collection with properties', async () => {
+ await usingApi(async api => {
+ const properties = [{key: 'key1', value: 'val1'}];
+ const propertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];
+ const collectionId = await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},
+ properties: properties,
+ propPerm: propertyPermissions,
+ });
+ const collection = (await getDetailedCollectionInfo(api, collectionId))!;
+ expect(collection.properties.toHuman()).to.be.deep.equal(properties);
+ expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);
+ });
+ });
+});
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -284,7 +284,7 @@
type: 'ReFungible';
}
-type CollectionMode = Nft | Fungible | ReFungible;
+export type CollectionMode = Nft | Fungible | ReFungible;
export type Property = {
key: any,
@@ -1414,7 +1414,7 @@
tx = api.tx.unique.createItem(collectionId, to, createData as any);
}
- const events = await submitTransactionAsync(sender, tx);
+ const events = await executeTransaction(api, sender, tx);
const result = getCreateItemResult(events);
const itemCountAfter = await getLastTokenId(api, collectionId);