git.delta.rocks / unique-network / refs/commits / 159d4fc7deeb

difftreelog

Merge pull request #893 from UniqueNetwork/feature/preimage

Yaroslav Bolyukin2023-02-22parents: #8c90034 #5894371.patch.diff
in: master

34 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5541,6 +5541,7 @@
  "pallet-inflation",
  "pallet-maintenance",
  "pallet-nonfungible",
+ "pallet-preimage",
  "pallet-randomness-collective-flip",
  "pallet-refungible",
  "pallet-session",
@@ -6480,6 +6481,7 @@
  "frame-system",
  "parity-scale-codec",
  "scale-info",
+ "sp-core",
  "sp-std",
 ]
 
@@ -8968,6 +8970,7 @@
  "pallet-inflation",
  "pallet-maintenance",
  "pallet-nonfungible",
+ "pallet-preimage",
  "pallet-randomness-collective-flip",
  "pallet-refungible",
  "pallet-session",
@@ -13198,6 +13201,7 @@
  "pallet-inflation",
  "pallet-maintenance",
  "pallet-nonfungible",
+ "pallet-preimage",
  "pallet-randomness-collective-flip",
  "pallet-refungible",
  "pallet-session",
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -98,6 +98,7 @@
 pallet-aura = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
 pallet-authorship = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
 pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
+pallet-preimage = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
 pallet-randomness-collective-flip = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
 pallet-session = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
 pallet-sudo = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
modifiedMakefilediffbeforeafterboth
--- a/Makefile
+++ b/Makefile
@@ -137,9 +137,13 @@
 bench-app-promotion:
 	make _bench PALLET=app-promotion PALLET_DIR=app-promotion
 
+.PHONY: bench-maintenance
+bench-maintenance:
+	make _bench PALLET=maintenance
+
 .PHONY: bench
 # Disabled: bench-scheduler, bench-collator-selection, bench-identity
-bench: bench-common bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-configuration bench-foreign-assets
+bench: bench-common bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-configuration bench-foreign-assets bench-maintenance
 
 .PHONY: check
 check:
modifiedpallets/maintenance/Cargo.tomldiffbeforeafterboth
--- a/pallets/maintenance/Cargo.toml
+++ b/pallets/maintenance/Cargo.toml
@@ -18,10 +18,11 @@
 frame-benchmarking = { workspace = true, optional = true }
 frame-support = { workspace = true }
 frame-system = { workspace = true }
+sp-core = { workspace = true }
 sp-std = { workspace = true }
 
 [features]
 default = ["std"]
 runtime-benchmarks = ["frame-benchmarking", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks"]
-std = ["codec/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", "scale-info/std", "sp-std/std"]
+std = ["codec/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", "scale-info/std", "sp-core/std", "sp-std/std"]
 try-runtime = ["frame-support/try-runtime"]
modifiedpallets/maintenance/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/maintenance/src/benchmarking.rs
+++ b/pallets/maintenance/src/benchmarking.rs
@@ -17,9 +17,10 @@
 use super::*;
 use crate::{Pallet as Maintenance, Config};
 
+use codec::Encode;
 use frame_benchmarking::benchmarks;
 use frame_system::RawOrigin;
-use frame_support::ensure;
+use frame_support::{ensure, pallet_prelude::Weight, traits::StorePreimage};
 
 benchmarks! {
 	enable {
@@ -34,4 +35,11 @@
 	verify {
 		ensure!(!<Enabled<T>>::get(), "didn't disable the MM");
 	}
+
+	execute_preimage {
+		let call = <T as Config>::RuntimeCall::from(frame_system::Call::<T>::remark { remark: 1u32.encode() });
+		let hash = T::Preimages::note(call.encode().into())?;
+	}: _(RawOrigin::Root, hash, Weight::from_parts(100000000000, 100000000000))
+	verify {
+	}
 }
modifiedpallets/maintenance/src/lib.rsdiffbeforeafterboth
--- a/pallets/maintenance/src/lib.rs
+++ b/pallets/maintenance/src/lib.rs
@@ -25,13 +25,36 @@
 
 #[frame_support::pallet]
 pub mod pallet {
-	use frame_support::pallet_prelude::*;
+	use frame_support::{dispatch::*, pallet_prelude::*};
+	use frame_support::{
+		traits::{QueryPreimage, StorePreimage},
+	};
 	use frame_system::pallet_prelude::*;
+	use sp_core::H256;
+
 	use crate::weights::WeightInfo;
 
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
+		/// The overarching event type.
 		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
+
+		/// The runtime origin type.
+		type RuntimeOrigin: From<RawOrigin<Self::AccountId>>
+			+ IsType<<Self as frame_system::Config>::RuntimeOrigin>;
+
+		/// The aggregated call type.
+		type RuntimeCall: Parameter
+			+ Dispatchable<
+				RuntimeOrigin = <Self as Config>::RuntimeOrigin,
+				PostInfo = PostDispatchInfo,
+			> + GetDispatchInfo
+			+ From<frame_system::Call<Self>>;
+
+		/// The preimage provider with which we look up call hashes to get the call.
+		type Preimages: QueryPreimage + StorePreimage;
+
+		/// Weight information for extrinsics in this pallet.
 		type WeightInfo: WeightInfo;
 	}
 
@@ -78,5 +101,49 @@
 
 			Ok(())
 		}
+
+		/// Execute a runtime call stored as a preimage.
+		///
+		/// `weight_bound` is the maximum weight that the caller is willing
+		/// to allow the extrinsic to be executed with.
+		#[pallet::call_index(2)]
+		#[pallet::weight(<T as Config>::WeightInfo::execute_preimage() + *weight_bound)]
+		pub fn execute_preimage(
+			origin: OriginFor<T>,
+			hash: H256,
+			weight_bound: Weight,
+		) -> DispatchResultWithPostInfo {
+			use codec::Decode;
+
+			ensure_root(origin)?;
+
+			let data = T::Preimages::fetch(&hash, None)?;
+			weight_bound.set_proof_size(
+				weight_bound
+					.proof_size()
+					.checked_sub(
+						data.len()
+							.try_into()
+							.map_err(|_| DispatchError::Corruption)?,
+					)
+					.ok_or(DispatchError::Exhausted)?,
+			);
+
+			let call = <T as Config>::RuntimeCall::decode(&mut &data[..])
+				.map_err(|_| DispatchError::Corruption)?;
+
+			ensure!(
+				call.get_dispatch_info().weight.all_lte(weight_bound),
+				DispatchError::Exhausted
+			);
+
+			match call.dispatch(frame_system::RawOrigin::Root.into()) {
+				Ok(_) => Ok(Pays::No.into()),
+				Err(error_and_info) => Err(DispatchErrorWithPostInfo {
+					post_info: Pays::No.into(),
+					error: error_and_info.error,
+				}),
+			}
+		}
 	}
 }
modifiedpallets/maintenance/src/weights.rsdiffbeforeafterboth
--- a/pallets/maintenance/src/weights.rs
+++ b/pallets/maintenance/src/weights.rs
@@ -3,7 +3,7 @@
 //! Autogenerated weights for pallet_maintenance
 //!
 //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-11-01, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2023-02-22, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
 
 // Executed Command:
@@ -26,6 +26,7 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 #![allow(unused_parens)]
 #![allow(unused_imports)]
+#![allow(missing_docs)]
 #![allow(clippy::unnecessary_cast)]
 
 use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
@@ -35,6 +36,7 @@
 pub trait WeightInfo {
 	fn enable() -> Weight;
 	fn disable() -> Weight;
+	fn execute_preimage() -> Weight;
 }
 
 /// Weights for pallet_maintenance using the Substrate node and recommended hardware.
@@ -42,13 +44,19 @@
 impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
 	// Storage: Maintenance Enabled (r:0 w:1)
 	fn enable() -> Weight {
-		Weight::from_ref_time(7_367_000)
-			.saturating_add(T::DbWeight::get().writes(1))
+		Weight::from_ref_time(10_860_000 as u64)
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
 	}
 	// Storage: Maintenance Enabled (r:0 w:1)
 	fn disable() -> Weight {
-		Weight::from_ref_time(7_273_000)
-			.saturating_add(T::DbWeight::get().writes(1))
+		Weight::from_ref_time(10_871_000 as u64)
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
+	// Storage: Preimage StatusFor (r:1 w:0)
+	// Storage: Preimage PreimageFor (r:1 w:0)
+	fn execute_preimage() -> Weight {
+		Weight::from_ref_time(10_068_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
 	}
 }
 
@@ -56,12 +64,18 @@
 impl WeightInfo for () {
 	// Storage: Maintenance Enabled (r:0 w:1)
 	fn enable() -> Weight {
-		Weight::from_ref_time(7_367_000)
-			.saturating_add(RocksDbWeight::get().writes(1))
+		Weight::from_ref_time(10_860_000 as u64)
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
 	}
 	// Storage: Maintenance Enabled (r:0 w:1)
 	fn disable() -> Weight {
-		Weight::from_ref_time(7_273_000)
-			.saturating_add(RocksDbWeight::get().writes(1))
+		Weight::from_ref_time(10_871_000 as u64)
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
+	// Storage: Preimage StatusFor (r:1 w:0)
+	// Storage: Preimage PreimageFor (r:1 w:0)
+	fn execute_preimage() -> Weight {
+		Weight::from_ref_time(10_068_000 as u64)
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
 	}
 }
modifiedpallets/scheduler-v2/Cargo.tomldiffbeforeafterboth
--- a/pallets/scheduler-v2/Cargo.toml
+++ b/pallets/scheduler-v2/Cargo.toml
@@ -24,7 +24,7 @@
 sp-std = { workspace = true }
 
 [dev-dependencies]
-pallet-preimage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
+pallet-preimage = { workspace = true }
 substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" }
 
 [features]
modifiedruntime/common/config/pallets/mod.rsdiffbeforeafterboth
--- a/runtime/common/config/pallets/mod.rs
+++ b/runtime/common/config/pallets/mod.rs
@@ -23,7 +23,7 @@
 		weights::CommonWeights,
 		RelayChainBlockNumberProvider,
 	},
-	Runtime, RuntimeEvent, RuntimeCall, Balances,
+	Runtime, RuntimeEvent, RuntimeCall, RuntimeOrigin, Balances,
 };
 use frame_support::traits::{ConstU32, ConstU64};
 use up_common::{
@@ -47,6 +47,9 @@
 #[cfg(feature = "collator-selection")]
 pub mod collator_selection;
 
+#[cfg(feature = "preimage")]
+pub mod preimage;
+
 parameter_types! {
 	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
 	pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
@@ -123,5 +126,11 @@
 
 impl pallet_maintenance::Config for Runtime {
 	type RuntimeEvent = RuntimeEvent;
+	type RuntimeOrigin = RuntimeOrigin;
+	type RuntimeCall = RuntimeCall;
+	#[cfg(feature = "preimage")]
+	type Preimages = crate::Preimage;
+	#[cfg(not(feature = "preimage"))]
+	type Preimages = ();
 	type WeightInfo = pallet_maintenance::weights::SubstrateWeight<Self>;
 }
addedruntime/common/config/pallets/preimage.rsdiffbeforeafterboth
--- /dev/null
+++ b/runtime/common/config/pallets/preimage.rs
@@ -0,0 +1,33 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+use frame_support::parameter_types;
+use frame_system::EnsureRoot;
+use crate::{AccountId, Balance, Balances, Runtime, RuntimeEvent};
+use up_common::constants::*;
+
+parameter_types! {
+	pub PreimageBaseDeposit: Balance = 1000 * UNIQUE;
+}
+
+impl pallet_preimage::Config for Runtime {
+	type WeightInfo = pallet_preimage::weights::SubstrateWeight<Runtime>;
+	type RuntimeEvent = RuntimeEvent;
+	type Currency = Balances;
+	type ManagerOrigin = EnsureRoot<AccountId>;
+	type BaseDeposit = PreimageBaseDeposit;
+	type ByteDeposit = TransactionByteFee;
+}
modifiedruntime/common/construct_runtime.rsdiffbeforeafterboth
--- a/runtime/common/construct_runtime.rs
+++ b/runtime/common/construct_runtime.rs
@@ -56,6 +56,9 @@
                 #[cfg(feature = "collator-selection")]
                 Identity: pallet_identity::{Pallet, Call, Storage, Event<T>} = 40,
 
+                #[cfg(feature = "preimage")]
+                Preimage: pallet_preimage::{Pallet, Call, Storage, Event<T>} = 41,
+
                 // XCM helpers.
                 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
                 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
modifiedruntime/common/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -568,6 +568,7 @@
                     #[cfg(feature = "foreign-assets")]
                     list_benchmark!(list, extra, pallet_foreign_assets, ForeignAssets);
 
+                    list_benchmark!(list, extra, pallet_maintenance, Maintenance);
 
                     // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);
 
@@ -632,6 +633,8 @@
                     #[cfg(feature = "foreign-assets")]
                     add_benchmark!(params, batches, pallet_foreign_assets, ForeignAssets);
 
+                    add_benchmark!(params, batches, pallet_maintenance, Maintenance);
+
                     // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);
 
                     if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -18,7 +18,7 @@
 [features]
 default = ['opal-runtime', 'std']
 limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
-opal-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'pallet-test-utils', 'refungible']
+opal-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'preimage', 'pallet-test-utils', 'refungible']
 pov-estimate = []
 runtime-benchmarks = [
 	'cumulus-pallet-parachain-system/runtime-benchmarks',
@@ -41,6 +41,7 @@
 	'pallet-inflation/runtime-benchmarks',
 	'pallet-maintenance/runtime-benchmarks',
 	'pallet-nonfungible/runtime-benchmarks',
+	"pallet-preimage/runtime-benchmarks",
 	'pallet-refungible/runtime-benchmarks',
 	'pallet-structure/runtime-benchmarks',
 	'pallet-timestamp/runtime-benchmarks',
@@ -69,6 +70,7 @@
 	# 'pallet-contracts-primitives/std',
 	# 'pallet-contracts-rpc-runtime-api/std',
 	# 'pallet-contract-helpers/std',
+	"pallet-preimage/std",
 	"pallet-authorship/std",
 	"pallet-session/std",
 	"sp-consensus-aura/std",
@@ -139,6 +141,7 @@
 	"pallet-collator-selection/try-runtime",
 	"pallet-identity/try-runtime",
 	"pallet-session/try-runtime",
+	"pallet-preimage/try-runtime",
 	'cumulus-pallet-aura-ext/try-runtime',
 	'cumulus-pallet-dmp-queue/try-runtime',
 	'cumulus-pallet-parachain-system/try-runtime',
@@ -188,6 +191,7 @@
 app-promotion = []
 collator-selection = []
 foreign-assets = []
+preimage = []
 pallet-test-utils = []
 refungible = []
 scheduler = []
@@ -218,6 +222,7 @@
 pallet-aura = { workspace = true }
 pallet-authorship = { workspace = true }
 pallet-balances = { workspace = true }
+pallet-preimage = { workspace = true }
 pallet-randomness-collective-flip = { workspace = true }
 pallet-session = { workspace = true }
 pallet-sudo = { workspace = true }
modifiedruntime/quartz/Cargo.tomldiffbeforeafterboth
--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -20,7 +20,7 @@
 default = ['quartz-runtime', 'std']
 limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
 pov-estimate = []
-quartz-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'refungible']
+quartz-runtime = ['app-promotion', 'collator-selection', 'foreign-assets', 'preimage', 'refungible']
 runtime-benchmarks = [
 	'cumulus-pallet-parachain-system/runtime-benchmarks',
 	'frame-benchmarking',
@@ -42,6 +42,7 @@
 	'pallet-inflation/runtime-benchmarks',
 	'pallet-maintenance/runtime-benchmarks',
 	'pallet-nonfungible/runtime-benchmarks',
+	"pallet-preimage/runtime-benchmarks",
 	'pallet-refungible/runtime-benchmarks',
 	'pallet-structure/runtime-benchmarks',
 	'pallet-timestamp/runtime-benchmarks',
@@ -69,6 +70,7 @@
 	# 'pallet-contracts-primitives/std',
 	# 'pallet-contracts-rpc-runtime-api/std',
 	# 'pallet-contract-helpers/std',
+	"pallet-preimage/std",
 	"pallet-authorship/std",
 	"pallet-identity/std",
 	"pallet-session/std",
@@ -136,6 +138,7 @@
 	"pallet-collator-selection/try-runtime",
 	"pallet-identity/try-runtime",
 	"pallet-session/try-runtime",
+	"pallet-preimage/try-runtime",
 	'cumulus-pallet-aura-ext/try-runtime',
 	'cumulus-pallet-dmp-queue/try-runtime',
 	'cumulus-pallet-parachain-system/try-runtime',
@@ -181,6 +184,7 @@
 app-promotion = []
 collator-selection = []
 foreign-assets = []
+preimage = []
 refungible = []
 scheduler = []
 
@@ -210,6 +214,7 @@
 pallet-aura = { workspace = true }
 pallet-authorship = { workspace = true }
 pallet-balances = { workspace = true }
+pallet-preimage = { workspace = true }
 pallet-randomness-collective-flip = { workspace = true }
 pallet-session = { workspace = true }
 pallet-sudo = { workspace = true }
modifiedruntime/unique/Cargo.tomldiffbeforeafterboth
--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -39,6 +39,7 @@
 	'pallet-inflation/runtime-benchmarks',
 	'pallet-maintenance/runtime-benchmarks',
 	'pallet-nonfungible/runtime-benchmarks',
+	"pallet-preimage/runtime-benchmarks",
 	'pallet-refungible/runtime-benchmarks',
 	'pallet-structure/runtime-benchmarks',
 	'pallet-timestamp/runtime-benchmarks',
@@ -67,6 +68,7 @@
 	# 'pallet-contracts-primitives/std',
 	# 'pallet-contracts-rpc-runtime-api/std',
 	# 'pallet-contract-helpers/std',
+	"pallet-preimage/std",
 	"pallet-authorship/std",
 	"pallet-identity/std",
 	"pallet-session/std",
@@ -134,6 +136,7 @@
 	"pallet-collator-selection/try-runtime",
 	"pallet-identity/try-runtime",
 	"pallet-session/try-runtime",
+	"pallet-preimage/try-runtime",
 	'cumulus-pallet-aura-ext/try-runtime',
 	'cumulus-pallet-dmp-queue/try-runtime',
 	'cumulus-pallet-parachain-system/try-runtime',
@@ -180,6 +183,7 @@
 app-promotion = []
 collator-selection = []
 foreign-assets = []
+preimage = []
 refungible = []
 scheduler = []
 
@@ -209,6 +213,7 @@
 pallet-aura = { workspace = true }
 pallet-authorship = { workspace = true }
 pallet-balances = { workspace = true }
+pallet-preimage = { workspace = true }
 pallet-randomness-collective-flip = { workspace = true }
 pallet-session = { workspace = true }
 pallet-sudo = { workspace = true }
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -82,7 +82,7 @@
     "testSetOffchainSchema": "mocha --timeout 9999999 -r ts-node/register ./**/setOffchainSchema.test.ts",
     "testNextSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/nextSponsoring.test.ts",
     "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",
-    "testMaintenance": "mocha --timeout 9999999 -r ts-node/register ./**/maintenanceMode.seqtest.ts",
+    "testMaintenance": "mocha --timeout 9999999 -r ts-node/register ./**/maintenance.seqtest.ts",
     "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.seqtest.ts",
     "testScheduler": "mocha --timeout 9999999 -r ts-node/register ./**/scheduler.seqtest.ts",
     "testSchedulingEVM": "mocha --timeout 9999999 -r ts-node/register ./**/eth/scheduling.test.ts",
modifiedtests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-consts.ts
+++ b/tests/src/interfaces/augment-api-consts.ts
@@ -41,6 +41,18 @@
        **/
       [key: string]: Codec;
     };
+    authorship: {
+      /**
+       * The number of blocks back we should accept uncles.
+       * This means that we will deal with uncle-parents that are
+       * `UncleGenerations + 1` before `now`.
+       **/
+      uncleGenerations: u32 & AugmentedConst<ApiType>;
+      /**
+       * Generic const
+       **/
+      [key: string]: Codec;
+    };
     balances: {
       /**
        * The minimum amount required to keep an account open.
@@ -102,6 +114,40 @@
        **/
       [key: string]: Codec;
     };
+    identity: {
+      /**
+       * The amount held on deposit for a registered identity
+       **/
+      basicDeposit: u128 & AugmentedConst<ApiType>;
+      /**
+       * The amount held on deposit per additional field for a registered identity.
+       **/
+      fieldDeposit: u128 & AugmentedConst<ApiType>;
+      /**
+       * Maximum number of additional fields that may be stored in an ID. Needed to bound the I/O
+       * required to access an identity, but can be pretty high.
+       **/
+      maxAdditionalFields: u32 & AugmentedConst<ApiType>;
+      /**
+       * Maxmimum number of registrars allowed in the system. Needed to bound the complexity
+       * of, e.g., updating judgements.
+       **/
+      maxRegistrars: u32 & AugmentedConst<ApiType>;
+      /**
+       * The maximum number of sub-accounts allowed per identified account.
+       **/
+      maxSubAccounts: u32 & AugmentedConst<ApiType>;
+      /**
+       * The amount held on deposit for a registered subaccount. This should account for the fact
+       * that one storage item's value will increase by the size of an account ID, and there will
+       * be another trie item whose value is the size of an account ID plus 32 bytes.
+       **/
+      subAccountDeposit: u128 & AugmentedConst<ApiType>;
+      /**
+       * Generic const
+       **/
+      [key: string]: Codec;
+    };
     inflation: {
       /**
        * Number of blocks that pass between treasury balance updates due to inflation
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -21,6 +21,10 @@
        **/
       IncorrectLockedBalanceOperation: AugmentedError<ApiType>;
       /**
+       * Errors caused by insufficient staked balance.
+       **/
+      InsufficientStakedBalance: AugmentedError<ApiType>;
+      /**
        * No permission to perform an action.
        **/
       NoPermission: AugmentedError<ApiType>;
@@ -41,6 +45,40 @@
        **/
       [key: string]: AugmentedError<ApiType>;
     };
+    authorship: {
+      /**
+       * The uncle is genesis.
+       **/
+      GenesisUncle: AugmentedError<ApiType>;
+      /**
+       * The uncle parent not in the chain.
+       **/
+      InvalidUncleParent: AugmentedError<ApiType>;
+      /**
+       * The uncle isn't recent enough to be included.
+       **/
+      OldUncle: AugmentedError<ApiType>;
+      /**
+       * The uncle is too high in chain.
+       **/
+      TooHighUncle: AugmentedError<ApiType>;
+      /**
+       * Too many uncles.
+       **/
+      TooManyUncles: AugmentedError<ApiType>;
+      /**
+       * The uncle is already included.
+       **/
+      UncleAlreadyIncluded: AugmentedError<ApiType>;
+      /**
+       * Uncles already set in the block.
+       **/
+      UnclesAlreadySet: AugmentedError<ApiType>;
+      /**
+       * Generic error
+       **/
+      [key: string]: AugmentedError<ApiType>;
+    };
     balances: {
       /**
        * Beneficiary account must pre-exist
@@ -79,6 +117,64 @@
        **/
       [key: string]: AugmentedError<ApiType>;
     };
+    collatorSelection: {
+      /**
+       * User is already a candidate
+       **/
+      AlreadyCandidate: AugmentedError<ApiType>;
+      /**
+       * User already holds license to collate
+       **/
+      AlreadyHoldingLicense: AugmentedError<ApiType>;
+      /**
+       * User is already an Invulnerable
+       **/
+      AlreadyInvulnerable: AugmentedError<ApiType>;
+      /**
+       * Account has no associated validator ID
+       **/
+      NoAssociatedValidatorId: AugmentedError<ApiType>;
+      /**
+       * User does not hold a license to collate
+       **/
+      NoLicense: AugmentedError<ApiType>;
+      /**
+       * User is not a candidate
+       **/
+      NotCandidate: AugmentedError<ApiType>;
+      /**
+       * User is not an Invulnerable
+       **/
+      NotInvulnerable: AugmentedError<ApiType>;
+      /**
+       * Permission issue
+       **/
+      Permission: AugmentedError<ApiType>;
+      /**
+       * Too few invulnerables
+       **/
+      TooFewInvulnerables: AugmentedError<ApiType>;
+      /**
+       * Too many candidates
+       **/
+      TooManyCandidates: AugmentedError<ApiType>;
+      /**
+       * Too many invulnerables
+       **/
+      TooManyInvulnerables: AugmentedError<ApiType>;
+      /**
+       * Unknown error
+       **/
+      Unknown: AugmentedError<ApiType>;
+      /**
+       * Validator ID is not yet registered
+       **/
+      ValidatorNotRegistered: AugmentedError<ApiType>;
+      /**
+       * Generic error
+       **/
+      [key: string]: AugmentedError<ApiType>;
+    };
     common: {
       /**
        * Account token limit exceeded per collection
@@ -425,6 +521,84 @@
        **/
       [key: string]: AugmentedError<ApiType>;
     };
+    identity: {
+      /**
+       * Account ID is already named.
+       **/
+      AlreadyClaimed: AugmentedError<ApiType>;
+      /**
+       * Empty index.
+       **/
+      EmptyIndex: AugmentedError<ApiType>;
+      /**
+       * Fee is changed.
+       **/
+      FeeChanged: AugmentedError<ApiType>;
+      /**
+       * The index is invalid.
+       **/
+      InvalidIndex: AugmentedError<ApiType>;
+      /**
+       * Invalid judgement.
+       **/
+      InvalidJudgement: AugmentedError<ApiType>;
+      /**
+       * The target is invalid.
+       **/
+      InvalidTarget: AugmentedError<ApiType>;
+      /**
+       * The provided judgement was for a different identity.
+       **/
+      JudgementForDifferentIdentity: AugmentedError<ApiType>;
+      /**
+       * Judgement given.
+       **/
+      JudgementGiven: AugmentedError<ApiType>;
+      /**
+       * Error that occurs when there is an issue paying for judgement.
+       **/
+      JudgementPaymentFailed: AugmentedError<ApiType>;
+      /**
+       * No identity found.
+       **/
+      NoIdentity: AugmentedError<ApiType>;
+      /**
+       * Account isn't found.
+       **/
+      NotFound: AugmentedError<ApiType>;
+      /**
+       * Account isn't named.
+       **/
+      NotNamed: AugmentedError<ApiType>;
+      /**
+       * Sub-account isn't owned by sender.
+       **/
+      NotOwned: AugmentedError<ApiType>;
+      /**
+       * Sender is not a sub-account.
+       **/
+      NotSub: AugmentedError<ApiType>;
+      /**
+       * Sticky judgement.
+       **/
+      StickyJudgement: AugmentedError<ApiType>;
+      /**
+       * Too many additional fields.
+       **/
+      TooManyFields: AugmentedError<ApiType>;
+      /**
+       * Maximum amount of registrars reached. Cannot add any more.
+       **/
+      TooManyRegistrars: AugmentedError<ApiType>;
+      /**
+       * Too many subs-accounts.
+       **/
+      TooManySubAccounts: AugmentedError<ApiType>;
+      /**
+       * Generic error
+       **/
+      [key: string]: AugmentedError<ApiType>;
+    };
     maintenance: {
       /**
        * Generic error
@@ -549,145 +723,83 @@
        **/
       [key: string]: AugmentedError<ApiType>;
     };
-    refungible: {
+    preimage: {
       /**
-       * Not Refungible item data used to mint in Refungible collection.
+       * Preimage has already been noted on-chain.
        **/
-      NotRefungibleDataUsedToMintFungibleCollectionToken: AugmentedError<ApiType>;
+      AlreadyNoted: AugmentedError<ApiType>;
       /**
-       * Refungible token can't nest other tokens.
+       * The user is not authorized to perform this action.
        **/
-      RefungibleDisallowsNesting: AugmentedError<ApiType>;
+      NotAuthorized: AugmentedError<ApiType>;
       /**
-       * Refungible token can't be repartitioned by user who isn't owns all pieces.
+       * The preimage cannot be removed since it has not yet been noted.
        **/
-      RepartitionWhileNotOwningAllPieces: AugmentedError<ApiType>;
+      NotNoted: AugmentedError<ApiType>;
       /**
-       * Setting item properties is not allowed.
+       * The preimage request cannot be removed since no outstanding requests exist.
        **/
-      SettingPropertiesNotAllowed: AugmentedError<ApiType>;
+      NotRequested: AugmentedError<ApiType>;
       /**
-       * Maximum refungibility exceeded.
+       * A preimage may not be removed when there are outstanding requests.
        **/
-      WrongRefungiblePieces: AugmentedError<ApiType>;
+      Requested: AugmentedError<ApiType>;
       /**
+       * Preimage is too large to store on-chain.
+       **/
+      TooBig: AugmentedError<ApiType>;
+      /**
        * Generic error
        **/
       [key: string]: AugmentedError<ApiType>;
     };
-    rmrkCore: {
-      /**
-       * Not the target owner of the sent NFT.
-       **/
-      CannotAcceptNonOwnedNft: AugmentedError<ApiType>;
-      /**
-       * Not the target owner of the sent NFT.
-       **/
-      CannotRejectNonOwnedNft: AugmentedError<ApiType>;
-      /**
-       * NFT was not sent and is not pending.
-       **/
-      CannotRejectNonPendingNft: AugmentedError<ApiType>;
-      /**
-       * If an NFT is sent to a descendant, that would form a nesting loop, an ouroboros.
-       * Sending to self is redundant.
-       **/
-      CannotSendToDescendentOrSelf: AugmentedError<ApiType>;
-      /**
-       * Too many tokens created in the collection, no new ones are allowed.
-       **/
-      CollectionFullOrLocked: AugmentedError<ApiType>;
-      /**
-       * Only destroying collections without tokens is allowed.
-       **/
-      CollectionNotEmpty: AugmentedError<ApiType>;
-      /**
-       * Collection does not exist, has a wrong type, or does not map to a Unique ID.
-       **/
-      CollectionUnknown: AugmentedError<ApiType>;
-      /**
-       * Property of the type of RMRK collection could not be read successfully.
-       **/
-      CorruptedCollectionType: AugmentedError<ApiType>;
-      /**
-       * Could not find an ID for a collection. It is likely there were too many collections created on the chain, causing an overflow.
-       **/
-      NoAvailableCollectionId: AugmentedError<ApiType>;
-      /**
-       * Token does not exist, or there is no suitable ID for it, likely too many tokens were created in a collection, causing an overflow.
-       **/
-      NoAvailableNftId: AugmentedError<ApiType>;
-      /**
-       * Could not find an ID for the resource. It is likely there were too many resources created on an NFT, causing an overflow.
-       **/
-      NoAvailableResourceId: AugmentedError<ApiType>;
-      /**
-       * Token is marked as non-transferable, and thus cannot be transferred.
-       **/
-      NonTransferable: AugmentedError<ApiType>;
+    refungible: {
       /**
-       * No permission to perform action.
-       **/
-      NoPermission: AugmentedError<ApiType>;
-      /**
-       * No such resource found.
+       * Not Refungible item data used to mint in Refungible collection.
        **/
-      ResourceDoesntExist: AugmentedError<ApiType>;
+      NotRefungibleDataUsedToMintFungibleCollectionToken: AugmentedError<ApiType>;
       /**
-       * Resource is not pending for the operation.
+       * Refungible token can't nest other tokens.
        **/
-      ResourceNotPending: AugmentedError<ApiType>;
+      RefungibleDisallowsNesting: AugmentedError<ApiType>;
       /**
-       * Could not find a property by the supplied key.
+       * Refungible token can't be repartitioned by user who isn't owns all pieces.
        **/
-      RmrkPropertyIsNotFound: AugmentedError<ApiType>;
+      RepartitionWhileNotOwningAllPieces: AugmentedError<ApiType>;
       /**
-       * Too many symbols supplied as the property key. The maximum is [256](up_data_structs::MAX_PROPERTY_KEY_LENGTH).
+       * Setting item properties is not allowed.
        **/
-      RmrkPropertyKeyIsTooLong: AugmentedError<ApiType>;
+      SettingPropertiesNotAllowed: AugmentedError<ApiType>;
       /**
-       * Too many bytes supplied as the property value. The maximum is [32768](up_data_structs::MAX_PROPERTY_VALUE_LENGTH).
+       * Maximum refungibility exceeded.
        **/
-      RmrkPropertyValueIsTooLong: AugmentedError<ApiType>;
+      WrongRefungiblePieces: AugmentedError<ApiType>;
       /**
-       * Something went wrong when decoding encoded data from the storage.
-       * Perhaps, there was a wrong key supplied for the type, or the data was improperly stored.
-       **/
-      UnableToDecodeRmrkData: AugmentedError<ApiType>;
-      /**
        * Generic error
        **/
       [key: string]: AugmentedError<ApiType>;
     };
-    rmrkEquip: {
+    session: {
       /**
-       * Base collection linked to this ID does not exist.
+       * Registered duplicate key.
        **/
-      BaseDoesntExist: AugmentedError<ApiType>;
-      /**
-       * No Theme named "default" is associated with the Base.
-       **/
-      NeedsDefaultThemeFirst: AugmentedError<ApiType>;
+      DuplicatedKey: AugmentedError<ApiType>;
       /**
-       * Could not find an ID for a Base collection. It is likely there were too many collections created on the chain, causing an overflow.
-       **/
-      NoAvailableBaseId: AugmentedError<ApiType>;
-      /**
-       * Could not find a suitable ID for a Part, likely too many Part tokens were created in the Base, causing an overflow
+       * Invalid ownership proof.
        **/
-      NoAvailablePartId: AugmentedError<ApiType>;
+      InvalidProof: AugmentedError<ApiType>;
       /**
-       * Cannot assign equippables to a fixed Part.
+       * Key setting account is not live, so it's impossible to associate keys.
        **/
-      NoEquippableOnFixedPart: AugmentedError<ApiType>;
+      NoAccount: AugmentedError<ApiType>;
       /**
-       * Part linked to this ID does not exist.
+       * No associated validator ID for account.
        **/
-      PartDoesntExist: AugmentedError<ApiType>;
+      NoAssociatedValidatorId: AugmentedError<ApiType>;
       /**
-       * No permission to perform action.
+       * No keys are associated with this account.
        **/
-      PermissionError: AugmentedError<ApiType>;
+      NoKeys: AugmentedError<ApiType>;
       /**
        * Generic error
        **/
@@ -699,6 +811,10 @@
        **/
       BreadthLimit: AugmentedError<ApiType>;
       /**
+       * Tried to nest token under collection contract address, instead of token address
+       **/
+      CantNestTokenUnderCollection: AugmentedError<ApiType>;
+      /**
        * While nesting, reached the depth limit of nesting, exceeding the provided budget.
        **/
       DepthLimit: AugmentedError<ApiType>;
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -8,7 +8,7 @@
 import type { ApiTypes, AugmentedEvent } from '@polkadot/api-base/types';
 import type { Bytes, Null, Option, Result, U8aFixed, bool, u128, u32, u64, u8 } from '@polkadot/types-codec';
 import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';
-import type { EthereumLog, EvmCoreErrorExitReason, FrameSupportDispatchDispatchInfo, FrameSupportTokensMiscBalanceStatus, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, SpRuntimeDispatchError, SpWeightsWeightV2Weight, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetMultiAssets, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup';
+import type { EthereumLog, EvmCoreErrorExitReason, FrameSupportDispatchDispatchInfo, FrameSupportTokensMiscBalanceStatus, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, SpRuntimeDispatchError, SpWeightsWeightV2Weight, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetMultiAssets, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup';
 
 export type __AugmentedEvent<ApiType extends ApiTypes> = AugmentedEvent<ApiType>;
 
@@ -100,6 +100,18 @@
        **/
       [key: string]: AugmentedEvent<ApiType>;
     };
+    collatorSelection: {
+      CandidateAdded: AugmentedEvent<ApiType, [accountId: AccountId32], { accountId: AccountId32 }>;
+      CandidateRemoved: AugmentedEvent<ApiType, [accountId: AccountId32], { accountId: AccountId32 }>;
+      InvulnerableAdded: AugmentedEvent<ApiType, [invulnerable: AccountId32], { invulnerable: AccountId32 }>;
+      InvulnerableRemoved: AugmentedEvent<ApiType, [invulnerable: AccountId32], { invulnerable: AccountId32 }>;
+      LicenseObtained: AugmentedEvent<ApiType, [accountId: AccountId32, deposit: u128], { accountId: AccountId32, deposit: u128 }>;
+      LicenseReleased: AugmentedEvent<ApiType, [accountId: AccountId32, depositReturned: u128], { accountId: AccountId32, depositReturned: u128 }>;
+      /**
+       * Generic event
+       **/
+      [key: string]: AugmentedEvent<ApiType>;
+    };
     common: {
       /**
        * Address was added to the allow list.
@@ -340,6 +352,65 @@
        **/
       [key: string]: AugmentedEvent<ApiType>;
     };
+    identity: {
+      /**
+       * A number of identities and associated info were forcibly inserted.
+       **/
+      IdentitiesInserted: AugmentedEvent<ApiType, [amount: u32], { amount: u32 }>;
+      /**
+       * A number of identities and all associated info were forcibly removed.
+       **/
+      IdentitiesRemoved: AugmentedEvent<ApiType, [amount: u32], { amount: u32 }>;
+      /**
+       * A name was cleared, and the given balance returned.
+       **/
+      IdentityCleared: AugmentedEvent<ApiType, [who: AccountId32, deposit: u128], { who: AccountId32, deposit: u128 }>;
+      /**
+       * A name was removed and the given balance slashed.
+       **/
+      IdentityKilled: AugmentedEvent<ApiType, [who: AccountId32, deposit: u128], { who: AccountId32, deposit: u128 }>;
+      /**
+       * A name was set or reset (which will remove all judgements).
+       **/
+      IdentitySet: AugmentedEvent<ApiType, [who: AccountId32], { who: AccountId32 }>;
+      /**
+       * A judgement was given by a registrar.
+       **/
+      JudgementGiven: AugmentedEvent<ApiType, [target: AccountId32, registrarIndex: u32], { target: AccountId32, registrarIndex: u32 }>;
+      /**
+       * A judgement was asked from a registrar.
+       **/
+      JudgementRequested: AugmentedEvent<ApiType, [who: AccountId32, registrarIndex: u32], { who: AccountId32, registrarIndex: u32 }>;
+      /**
+       * A judgement request was retracted.
+       **/
+      JudgementUnrequested: AugmentedEvent<ApiType, [who: AccountId32, registrarIndex: u32], { who: AccountId32, registrarIndex: u32 }>;
+      /**
+       * A registrar was added.
+       **/
+      RegistrarAdded: AugmentedEvent<ApiType, [registrarIndex: u32], { registrarIndex: u32 }>;
+      /**
+       * A number of identities were forcibly updated with new sub-identities.
+       **/
+      SubIdentitiesInserted: AugmentedEvent<ApiType, [amount: u32], { amount: u32 }>;
+      /**
+       * A sub-identity was added to an identity and the deposit paid.
+       **/
+      SubIdentityAdded: AugmentedEvent<ApiType, [sub: AccountId32, main: AccountId32, deposit: u128], { sub: AccountId32, main: AccountId32, deposit: u128 }>;
+      /**
+       * A sub-identity was removed from an identity and the deposit freed.
+       **/
+      SubIdentityRemoved: AugmentedEvent<ApiType, [sub: AccountId32, main: AccountId32, deposit: u128], { sub: AccountId32, main: AccountId32, deposit: u128 }>;
+      /**
+       * A sub-identity was cleared, and the given deposit repatriated from the
+       * main identity account to the sub-identity account.
+       **/
+      SubIdentityRevoked: AugmentedEvent<ApiType, [sub: AccountId32, main: AccountId32, deposit: u128], { sub: AccountId32, main: AccountId32, deposit: u128 }>;
+      /**
+       * Generic event
+       **/
+      [key: string]: AugmentedEvent<ApiType>;
+    };
     maintenance: {
       MaintenanceDisabled: AugmentedEvent<ApiType, []>;
       MaintenanceEnabled: AugmentedEvent<ApiType, []>;
@@ -506,30 +577,30 @@
        **/
       [key: string]: AugmentedEvent<ApiType>;
     };
-    rmrkCore: {
-      CollectionCreated: AugmentedEvent<ApiType, [issuer: AccountId32, collectionId: u32], { issuer: AccountId32, collectionId: u32 }>;
-      CollectionDestroyed: AugmentedEvent<ApiType, [issuer: AccountId32, collectionId: u32], { issuer: AccountId32, collectionId: u32 }>;
-      CollectionLocked: AugmentedEvent<ApiType, [issuer: AccountId32, collectionId: u32], { issuer: AccountId32, collectionId: u32 }>;
-      IssuerChanged: AugmentedEvent<ApiType, [oldIssuer: AccountId32, newIssuer: AccountId32, collectionId: u32], { oldIssuer: AccountId32, newIssuer: AccountId32, collectionId: u32 }>;
-      NFTAccepted: AugmentedEvent<ApiType, [sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32], { sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32 }>;
-      NFTBurned: AugmentedEvent<ApiType, [owner: AccountId32, nftId: u32], { owner: AccountId32, nftId: u32 }>;
-      NftMinted: AugmentedEvent<ApiType, [owner: AccountId32, collectionId: u32, nftId: u32], { owner: AccountId32, collectionId: u32, nftId: u32 }>;
-      NFTRejected: AugmentedEvent<ApiType, [sender: AccountId32, collectionId: u32, nftId: u32], { sender: AccountId32, collectionId: u32, nftId: u32 }>;
-      NFTSent: AugmentedEvent<ApiType, [sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32, approvalRequired: bool], { sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32, approvalRequired: bool }>;
-      PrioritySet: AugmentedEvent<ApiType, [collectionId: u32, nftId: u32], { collectionId: u32, nftId: u32 }>;
-      PropertySet: AugmentedEvent<ApiType, [collectionId: u32, maybeNftId: Option<u32>, key: Bytes, value: Bytes], { collectionId: u32, maybeNftId: Option<u32>, key: Bytes, value: Bytes }>;
-      ResourceAccepted: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
-      ResourceAdded: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
-      ResourceRemoval: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
-      ResourceRemovalAccepted: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
+    preimage: {
+      /**
+       * A preimage has ben cleared.
+       **/
+      Cleared: AugmentedEvent<ApiType, [hash_: H256], { hash_: H256 }>;
+      /**
+       * A preimage has been noted.
+       **/
+      Noted: AugmentedEvent<ApiType, [hash_: H256], { hash_: H256 }>;
+      /**
+       * A preimage has been requested.
+       **/
+      Requested: AugmentedEvent<ApiType, [hash_: H256], { hash_: H256 }>;
       /**
        * Generic event
        **/
       [key: string]: AugmentedEvent<ApiType>;
     };
-    rmrkEquip: {
-      BaseCreated: AugmentedEvent<ApiType, [issuer: AccountId32, baseId: u32], { issuer: AccountId32, baseId: u32 }>;
-      EquippablesUpdated: AugmentedEvent<ApiType, [baseId: u32, slotId: u32], { baseId: u32, slotId: u32 }>;
+    session: {
+      /**
+       * New session has happened. Note that the argument is the session index, not the
+       * block number as the type might suggest.
+       **/
+      NewSession: AugmentedEvent<ApiType, [sessionIndex: u32], { sessionIndex: u32 }>;
       /**
        * Generic event
        **/
@@ -707,6 +778,10 @@
        **/
       Spending: AugmentedEvent<ApiType, [budgetRemaining: u128], { budgetRemaining: u128 }>;
       /**
+       * The inactive funds of the pallet have been updated.
+       **/
+      UpdatedInactive: AugmentedEvent<ApiType, [reactivated: u128, deactivated: u128], { reactivated: u128, deactivated: u128 }>;
+      /**
        * Generic event
        **/
       [key: string]: AugmentedEvent<ApiType>;
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -6,10 +6,11 @@
 import '@polkadot/api-base/types/storage';
 
 import type { ApiTypes, AugmentedQuery, QueryableStorageEntry } from '@polkadot/api-base/types';
+import type { Data } from '@polkadot/types';
 import type { BTreeMap, Bytes, Option, U256, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
 import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';
 import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';
-import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportDispatchPerDispatchClassWeight, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensReserveData, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReserveData, PalletConfigurationAppPromotionConfiguration, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletNonfungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, SpWeightsWeightV2Weight, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, XcmV1MultiLocation } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportDispatchPerDispatchClassWeight, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OpalRuntimeRuntimeCommonSessionKeys, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensReserveData, OrmlVestingVestingSchedule, PalletAuthorshipUncleEntryItem, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReserveData, PalletConfigurationAppPromotionConfiguration, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletIdentityRegistrarInfo, PalletIdentityRegistration, PalletNonfungibleItemData, PalletPreimageRequestStatus, PalletTransactionPaymentReleases, PalletTreasuryProposal, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpCoreCryptoKeyTypeId, SpRuntimeDigest, SpTrieStorageProof, SpWeightsWeightV2Weight, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, XcmV1MultiLocation } from '@polkadot/types/lookup';
 import type { Observable } from '@polkadot/types/types';
 
 export type __AugmentedQuery<ApiType extends ApiTypes> = AugmentedQuery<ApiType, () => unknown>;
@@ -23,7 +24,7 @@
        **/
       admin: AugmentedQuery<ApiType, () => Observable<Option<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
       /**
-       * Stores amount of stakes for an `Account`.
+       * Pending unstake records for an `Account`.
        * 
        * * **Key** - Staker account.
        * * **Value** - Amount of stakes.
@@ -44,7 +45,7 @@
        **/
       staked: AugmentedQuery<ApiType, (arg1: AccountId32 | string | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<ITuple<[u128, u32]>>, [AccountId32, u32]> & QueryableStorageEntry<ApiType, [AccountId32, u32]>;
       /**
-       * Stores amount of stakes for an `Account`.
+       * Stores number of stake records for an `Account`.
        * 
        * * **Key** - Staker account.
        * * **Value** - Amount of stakes.
@@ -54,11 +55,30 @@
        * Stores the total staked amount.
        **/
       totalStaked: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;
+      upgradedToReserves: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;
       /**
        * Generic query
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
+    authorship: {
+      /**
+       * Author of current block.
+       **/
+      author: AugmentedQuery<ApiType, () => Observable<Option<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * Whether uncles were already set in this block.
+       **/
+      didSetUncles: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * Uncles
+       **/
+      uncles: AugmentedQuery<ApiType, () => Observable<Vec<PalletAuthorshipUncleEntryItem>>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * Generic query
+       **/
+      [key: string]: QueryableStorageEntry<ApiType>;
+    };
     balances: {
       /**
        * The Balances pallet example of storing the balance of an account.
@@ -115,6 +135,28 @@
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
+    collatorSelection: {
+      /**
+       * The (community, limited) collation candidates.
+       **/
+      candidates: AugmentedQuery<ApiType, () => Observable<Vec<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * The invulnerable, fixed collators.
+       **/
+      invulnerables: AugmentedQuery<ApiType, () => Observable<Vec<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * Last block authored by collator.
+       **/
+      lastAuthoredBlock: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<u32>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      /**
+       * The (community) collation license holders.
+       **/
+      licenseDepositOf: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<u128>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      /**
+       * Generic query
+       **/
+      [key: string]: QueryableStorageEntry<ApiType>;
+    };
     common: {
       /**
        * Storage of the amount of collection admins.
@@ -267,6 +309,9 @@
        * * **Value** - owner for contract.
        **/
       owner: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<H160>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
+      /**
+       * Deprecated: this storage is deprecated
+       **/
       selfSponsoring: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
       sponsorBasket: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H160 | string | Uint8Array) => Observable<Option<u32>>, [H160, H160]> & QueryableStorageEntry<ApiType, [H160, H160]>;
       /**
@@ -366,6 +411,38 @@
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
+    identity: {
+      /**
+       * Information that is pertinent to identify the entity behind an account.
+       * 
+       * TWOX-NOTE: OK ― `AccountId` is a secure hash.
+       **/
+      identityOf: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Option<PalletIdentityRegistration>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      /**
+       * The set of registrars. Not expected to get very big as can only be added through a
+       * special origin (likely a council motion).
+       * 
+       * The index into this can be cast to `RegistrarIndex` to get a valid value.
+       **/
+      registrars: AugmentedQuery<ApiType, () => Observable<Vec<Option<PalletIdentityRegistrarInfo>>>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * Alternative "sub" identities of this account.
+       * 
+       * The first item is the deposit, the second is a vector of the accounts.
+       * 
+       * TWOX-NOTE: OK ― `AccountId` is a secure hash.
+       **/
+      subsOf: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<ITuple<[u128, Vec<AccountId32>]>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      /**
+       * The super-identity of an alternative "sub" identity together with its name, within that
+       * context. If the account is not some other account's sub-identity, then just `None`.
+       **/
+      superOf: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Option<ITuple<[AccountId32, Data]>>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      /**
+       * Generic query
+       **/
+      [key: string]: QueryableStorageEntry<ApiType>;
+    };
     inflation: {
       /**
        * Current inflation for `InflationBlockInterval` number of blocks
@@ -425,7 +502,7 @@
        * usual [`TokenProperties`] due to an unlimited number
        * and separately stored and written-to key-value pairs.
        * 
-       * Currently used to store RMRK data.
+       * Currently unused.
        **/
       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]>;
       /**
@@ -602,6 +679,17 @@
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
+    preimage: {
+      preimageFor: AugmentedQuery<ApiType, (arg: ITuple<[H256, u32]> | [H256 | string | Uint8Array, u32 | AnyNumber | Uint8Array]) => Observable<Option<Bytes>>, [ITuple<[H256, u32]>]> & QueryableStorageEntry<ApiType, [ITuple<[H256, u32]>]>;
+      /**
+       * The request status of a given hash.
+       **/
+      statusFor: AugmentedQuery<ApiType, (arg: H256 | string | Uint8Array) => Observable<Option<PalletPreimageRequestStatus>>, [H256]> & QueryableStorageEntry<ApiType, [H256]>;
+      /**
+       * Generic query
+       **/
+      [key: string]: QueryableStorageEntry<ApiType>;
+    };
     randomnessCollectiveFlip: {
       /**
        * Series of block headers from the last 81 blocks that acts as random seed material. This
@@ -628,7 +716,7 @@
        **/
       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]>;
       /**
-       * Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet.
+       * Spender set by a wallet owner that could perform certain transactions on all tokens in the wallet.
        **/
       collectionAllowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;
       /**
@@ -656,29 +744,41 @@
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
-    rmrkCore: {
+    session: {
       /**
-       * Latest yet-unused collection ID.
+       * Current index of the session.
        **/
-      collectionIndex: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
+      currentIndex: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
       /**
-       * Mapping from RMRK collection ID to Unique's.
+       * Indices of disabled validators.
+       * 
+       * The vec is always kept sorted so that we can find whether a given validator is
+       * disabled using binary search. It gets cleared when `on_session_ending` returns
+       * a new set of identities.
        **/
-      uniqueCollectionId: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
+      disabledValidators: AugmentedQuery<ApiType, () => Observable<Vec<u32>>, []> & QueryableStorageEntry<ApiType, []>;
       /**
-       * Generic query
+       * The owner of a key. The key is the `KeyTypeId` + the encoded key.
+       **/
+      keyOwner: AugmentedQuery<ApiType, (arg: ITuple<[SpCoreCryptoKeyTypeId, Bytes]> | [SpCoreCryptoKeyTypeId | string | Uint8Array, Bytes | string | Uint8Array]) => Observable<Option<AccountId32>>, [ITuple<[SpCoreCryptoKeyTypeId, Bytes]>]> & QueryableStorageEntry<ApiType, [ITuple<[SpCoreCryptoKeyTypeId, Bytes]>]>;
+      /**
+       * The next session keys for a validator.
+       **/
+      nextKeys: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Option<OpalRuntimeRuntimeCommonSessionKeys>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      /**
+       * True if the underlying economic identities or weighting behind the validators
+       * has changed in the queued validator set.
        **/
-      [key: string]: QueryableStorageEntry<ApiType>;
-    };
-    rmrkEquip: {
+      queuedChanged: AugmentedQuery<ApiType, () => Observable<bool>, []> & QueryableStorageEntry<ApiType, []>;
       /**
-       * Checkmark that a Base has a Theme NFT named "default".
+       * The queued keys for the next session. When the next session begins, these keys
+       * will be used to determine the validator's session keys.
        **/
-      baseHasDefaultTheme: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
+      queuedKeys: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[AccountId32, OpalRuntimeRuntimeCommonSessionKeys]>>>, []> & QueryableStorageEntry<ApiType, []>;
       /**
-       * Map of a Base ID and a Part ID to an NFT in the Base collection serving as the Part.
+       * The current set of validators.
        **/
-      inernalPartId: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
+      validators: AugmentedQuery<ApiType, () => Observable<Vec<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
       /**
        * Generic query
        **/
@@ -852,7 +952,7 @@
       /**
        * The amount which has been reported as inactive to Currency.
        **/
-      inactive: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;
+      deactivated: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;
       /**
        * Number of proposals that have been made.
        **/
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-rpc.ts
+++ b/tests/src/interfaces/augment-api-rpc.ts
@@ -5,7 +5,7 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/rpc-core/types/jsonrpc';
 
-import type { PalletEvmAccountBasicCrossAccountIdRepr, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsPartPartType, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsTheme, UpDataStructsCollectionLimits, UpDataStructsCollectionStats, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsRpcCollection, UpDataStructsTokenChild, UpDataStructsTokenData, UpPovEstimateRpcPovInfo } from './default';
+import type { PalletEvmAccountBasicCrossAccountIdRepr, UpDataStructsCollectionLimits, UpDataStructsCollectionStats, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsRpcCollection, UpDataStructsTokenChild, UpDataStructsTokenData, UpPovEstimateRpcPovInfo } from './default';
 import type { AugmentedRpc } from '@polkadot/rpc-core/types';
 import type { Metadata, StorageKey } from '@polkadot/types';
 import type { Bytes, HashMap, Json, Null, Option, Text, U256, U64, Vec, bool, f64, u128, u32, u64 } from '@polkadot/types-codec';
@@ -26,7 +26,7 @@
 import type { StorageKind } from '@polkadot/types/interfaces/offchain';
 import type { FeeDetails, RuntimeDispatchInfoV1 } from '@polkadot/types/interfaces/payment';
 import type { RpcMethods } from '@polkadot/types/interfaces/rpc';
-import type { AccountId, AccountId32, BlockNumber, H160, H256, H64, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime';
+import type { AccountId, BlockNumber, H160, H256, H64, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime';
 import type { MigrationStatusResult, ReadProof, RuntimeVersion, TraceBlockResponse } from '@polkadot/types/interfaces/state';
 import type { ApplyExtrinsicResult, ChainProperties, ChainType, Health, NetworkState, NodeRole, PeerInfo, SyncState } from '@polkadot/types/interfaces/system';
 import type { IExtrinsic, Observable } from '@polkadot/types/types';
@@ -441,60 +441,6 @@
        * Estimate PoV size of encoded signed extrinsics
        **/
       estimateExtrinsicPoV: AugmentedRpc<(encodedXt: Vec<Bytes> | (Bytes | string | Uint8Array)[], at?: Hash | string | Uint8Array) => Observable<UpPovEstimateRpcPovInfo>>;
-    };
-    rmrk: {
-      /**
-       * Get tokens owned by an account in a collection
-       **/
-      accountTokens: AugmentedRpc<(accountId: AccountId32 | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<u32>>>;
-      /**
-       * Get base info
-       **/
-      base: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsBaseBaseInfo>>>;
-      /**
-       * Get all Base's parts
-       **/
-      baseParts: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsPartPartType>>>;
-      /**
-       * Get collection by id
-       **/
-      collectionById: AugmentedRpc<(id: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsCollectionCollectionInfo>>>;
-      /**
-       * Get collection properties
-       **/
-      collectionProperties: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, filterKeys?: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsPropertyPropertyInfo>>>;
-      /**
-       * Get the latest created collection id
-       **/
-      lastCollectionIdx: AugmentedRpc<(at?: Hash | string | Uint8Array) => Observable<u32>>;
-      /**
-       * Get NFT by collection id and NFT id
-       **/
-      nftById: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsNftNftInfo>>>;
-      /**
-       * Get NFT children
-       **/
-      nftChildren: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsNftNftChild>>>;
-      /**
-       * Get NFT properties
-       **/
-      nftProperties: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, filterKeys?: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsPropertyPropertyInfo>>>;
-      /**
-       * Get NFT resource priorities
-       **/
-      nftResourcePriority: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<u32>>>;
-      /**
-       * Get NFT resources
-       **/
-      nftResources: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsResourceResourceInfo>>>;
-      /**
-       * Get Base's theme names
-       **/
-      themeNames: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<Bytes>>>;
-      /**
-       * Get Theme's keys values
-       **/
-      themes: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, themeName: Text | string, keys: Option<Vec<Text>> | null | Uint8Array | Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsTheme>>>;
     };
     rpc: {
       /**
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -6,10 +6,11 @@
 import '@polkadot/api-base/types/submittable';
 
 import type { ApiTypes, AugmentedSubmittable, SubmittableExtrinsic, SubmittableExtrinsicFunction } from '@polkadot/api-base/types';
+import type { Data } from '@polkadot/types';
 import type { Bytes, Compact, Option, U256, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
 import type { AnyNumber, IMethod, ITuple } from '@polkadot/types-codec/types';
-import type { AccountId32, Call, H160, H256, MultiAddress, Permill } from '@polkadot/types/interfaces/runtime';
-import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumLog, EthereumTransactionTransactionV2, OrmlVestingVestingSchedule, PalletConfigurationAppPromotionConfiguration, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsPartEquippableList, RmrkTraitsPartPartType, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, SpWeightsWeightV2Weight, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { AccountId32, Call, H160, H256, MultiAddress } from '@polkadot/types/interfaces/runtime';
+import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumLog, EthereumTransactionTransactionV2, OpalRuntimeRuntimeCommonSessionKeys, OrmlVestingVestingSchedule, PalletConfigurationAppPromotionConfiguration, PalletEvmAccountBasicCrossAccountIdRepr, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletIdentityBitFlags, PalletIdentityIdentityInfo, PalletIdentityJudgement, PalletIdentityRegistration, SpRuntimeHeader, SpWeightsWeightV2Weight, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 
 export type __AugmentedSubmittable = AugmentedSubmittable<() => unknown>;
 export type __SubmittableExtrinsic<ApiType extends ApiTypes> = SubmittableExtrinsic<ApiType>;
@@ -109,11 +110,31 @@
       stopSponsoringContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160]>;
       /**
        * Unstakes all stakes.
-       * Moves the sum of all stakes to the `reserved` state.
        * After the end of `PendingInterval` this sum becomes completely
        * free for further use.
        **/
-      unstake: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      unstakeAll: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Unstakes the amount of balance for the staker.
+       * After the end of `PendingInterval` this sum becomes completely
+       * free for further use.
+       * 
+       * # Arguments
+       * 
+       * * `staker`: staker account.
+       * * `amount`: amount of unstaked funds.
+       **/
+      unstakePartial: AugmentedSubmittable<(amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u128]>;
+      /**
+       * Generic tx
+       **/
+      [key: string]: SubmittableExtrinsicFunction<ApiType>;
+    };
+    authorship: {
+      /**
+       * Provide a set of uncles.
+       **/
+      setUncles: AugmentedSubmittable<(newUncles: Vec<SpRuntimeHeader> | (SpRuntimeHeader | { parentHash?: any; number?: any; stateRoot?: any; extrinsicsRoot?: any; digest?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Vec<SpRuntimeHeader>]>;
       /**
        * Generic tx
        **/
@@ -214,6 +235,54 @@
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
+    collatorSelection: {
+      /**
+       * Add a collator to the list of invulnerable (fixed) collators.
+       **/
+      addInvulnerable: AugmentedSubmittable<(updated: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [AccountId32]>;
+      /**
+       * Force deregister `origin` as a collator candidate as a governing authority, and revoke its license.
+       * Note that the collator can only leave on session change.
+       * The `LicenseBond` will be unreserved and returned immediately.
+       * 
+       * This call is, of course, not applicable to `Invulnerable` collators.
+       **/
+      forceReleaseLicense: AugmentedSubmittable<(who: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [AccountId32]>;
+      /**
+       * Purchase a license on block collation for this account.
+       * It does not make it a collator candidate, use `onboard` afterward. The account must
+       * (a) already have registered session keys and (b) be able to reserve the `LicenseBond`.
+       * 
+       * This call is not available to `Invulnerable` collators.
+       **/
+      getLicense: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Deregister `origin` as a collator candidate. Note that the collator can only leave on
+       * session change. The license to `onboard` later at any other time will remain.
+       **/
+      offboard: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Register this account as a candidate for collators for next sessions.
+       * The account must already hold a license, and cannot offboard immediately during a session.
+       * 
+       * This call is not available to `Invulnerable` collators.
+       **/
+      onboard: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Forfeit `origin`'s own license. The `LicenseBond` will be unreserved immediately.
+       * 
+       * This call is not available to `Invulnerable` collators.
+       **/
+      releaseLicense: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Remove a collator from the list of invulnerable (fixed) collators.
+       **/
+      removeInvulnerable: AugmentedSubmittable<(who: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [AccountId32]>;
+      /**
+       * Generic tx
+       **/
+      [key: string]: SubmittableExtrinsicFunction<ApiType>;
+    };
     configuration: {
       setAppPromotionConfigurationOverride: AugmentedSubmittable<(configuration: PalletConfigurationAppPromotionConfiguration | { recalculationInterval?: any; pendingInterval?: any; intervalIncome?: any; maxStakersPerCalculation?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletConfigurationAppPromotionConfiguration]>;
       setCollatorSelectionDesiredCollators: AugmentedSubmittable<(max: Option<u32> | null | Uint8Array | u32 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u32>]>;
@@ -308,6 +377,10 @@
        **/
       insertEvents: AugmentedSubmittable<(events: Vec<Bytes> | (Bytes | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Vec<Bytes>]>;
       /**
+       * Remove remark compatibility data leftovers
+       **/
+      removeRmrkData: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
        * Insert items into contract storage, this method can be called
        * multiple times
        **/
@@ -325,6 +398,298 @@
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
+    identity: {
+      /**
+       * Add a registrar to the system.
+       * 
+       * The dispatch origin for this call must be `T::RegistrarOrigin`.
+       * 
+       * - `account`: the account of the registrar.
+       * 
+       * Emits `RegistrarAdded` if successful.
+       * 
+       * # <weight>
+       * - `O(R)` where `R` registrar-count (governance-bounded and code-bounded).
+       * - One storage mutation (codec `O(R)`).
+       * - One event.
+       * # </weight>
+       **/
+      addRegistrar: AugmentedSubmittable<(account: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress]>;
+      /**
+       * Add the given account to the sender's subs.
+       * 
+       * Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
+       * to the sender.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a registered
+       * sub identity of `sub`.
+       **/
+      addSub: AugmentedSubmittable<(sub: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, data: Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress, Data]>;
+      /**
+       * Cancel a previous request.
+       * 
+       * Payment: A previously reserved deposit is returned on success.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a
+       * registered identity.
+       * 
+       * - `reg_index`: The index of the registrar whose judgement is no longer requested.
+       * 
+       * Emits `JudgementUnrequested` if successful.
+       * 
+       * # <weight>
+       * - `O(R + X)`.
+       * - One balance-reserve operation.
+       * - One storage mutation `O(R + X)`.
+       * - One event
+       * # </weight>
+       **/
+      cancelRequest: AugmentedSubmittable<(regIndex: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      /**
+       * Clear an account's identity info and all sub-accounts and return all deposits.
+       * 
+       * Payment: All reserved balances on the account are returned.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a registered
+       * identity.
+       * 
+       * Emits `IdentityCleared` if successful.
+       * 
+       * # <weight>
+       * - `O(R + S + X)`
+       * - where `R` registrar-count (governance-bounded).
+       * - where `S` subs-count (hard- and deposit-bounded).
+       * - where `X` additional-field-count (deposit-bounded and code-bounded).
+       * - One balance-unreserve operation.
+       * - `2` storage reads and `S + 2` storage deletions.
+       * - One event.
+       * # </weight>
+       **/
+      clearIdentity: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Set identities to be associated with the provided accounts as force origin.
+       * 
+       * This is not meant to operate in tandem with the identity pallet as is,
+       * and be instead used to keep identities made and verified externally,
+       * forbidden from interacting with an ordinary user, since it ignores any safety mechanism.
+       **/
+      forceInsertIdentities: AugmentedSubmittable<(identities: Vec<ITuple<[AccountId32, PalletIdentityRegistration]>> | ([AccountId32 | string | Uint8Array, PalletIdentityRegistration | { judgements?: any; deposit?: any; info?: any } | string | Uint8Array])[]) => SubmittableExtrinsic<ApiType>, [Vec<ITuple<[AccountId32, PalletIdentityRegistration]>>]>;
+      /**
+       * Remove identities associated with the provided accounts as force origin.
+       * 
+       * This is not meant to operate in tandem with the identity pallet as is,
+       * and be instead used to keep identities made and verified externally,
+       * forbidden from interacting with an ordinary user, since it ignores any safety mechanism.
+       **/
+      forceRemoveIdentities: AugmentedSubmittable<(identities: Vec<AccountId32> | (AccountId32 | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Vec<AccountId32>]>;
+      /**
+       * Set sub-identities to be associated with the provided accounts as force origin.
+       * 
+       * This is not meant to operate in tandem with the identity pallet as is,
+       * and be instead used to keep identities made and verified externally,
+       * forbidden from interacting with an ordinary user, since it ignores any safety mechanism.
+       **/
+      forceSetSubs: AugmentedSubmittable<(subs: Vec<ITuple<[AccountId32, ITuple<[u128, Vec<ITuple<[AccountId32, Data]>>]>]>> | ([AccountId32 | string | Uint8Array, ITuple<[u128, Vec<ITuple<[AccountId32, Data]>>]> | [u128 | AnyNumber | Uint8Array, Vec<ITuple<[AccountId32, Data]>> | ([AccountId32 | string | Uint8Array, Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array])[]]])[]) => SubmittableExtrinsic<ApiType>, [Vec<ITuple<[AccountId32, ITuple<[u128, Vec<ITuple<[AccountId32, Data]>>]>]>>]>;
+      /**
+       * Remove an account's identity and sub-account information and slash the deposits.
+       * 
+       * Payment: Reserved balances from `set_subs` and `set_identity` are slashed and handled by
+       * `Slash`. Verification request deposits are not returned; they should be cancelled
+       * manually using `cancel_request`.
+       * 
+       * The dispatch origin for this call must match `T::ForceOrigin`.
+       * 
+       * - `target`: the account whose identity the judgement is upon. This must be an account
+       * with a registered identity.
+       * 
+       * Emits `IdentityKilled` if successful.
+       * 
+       * # <weight>
+       * - `O(R + S + X)`.
+       * - One balance-reserve operation.
+       * - `S + 2` storage mutations.
+       * - One event.
+       * # </weight>
+       **/
+      killIdentity: AugmentedSubmittable<(target: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress]>;
+      /**
+       * Provide a judgement for an account's identity.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must be the account
+       * of the registrar whose index is `reg_index`.
+       * 
+       * - `reg_index`: the index of the registrar whose judgement is being made.
+       * - `target`: the account whose identity the judgement is upon. This must be an account
+       * with a registered identity.
+       * - `judgement`: the judgement of the registrar of index `reg_index` about `target`.
+       * - `identity`: The hash of the [`IdentityInfo`] for that the judgement is provided.
+       * 
+       * Emits `JudgementGiven` if successful.
+       * 
+       * # <weight>
+       * - `O(R + X)`.
+       * - One balance-transfer operation.
+       * - Up to one account-lookup operation.
+       * - Storage: 1 read `O(R)`, 1 mutate `O(R + X)`.
+       * - One event.
+       * # </weight>
+       **/
+      provideJudgement: AugmentedSubmittable<(regIndex: Compact<u32> | AnyNumber | Uint8Array, target: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, judgement: PalletIdentityJudgement | { Unknown: any } | { FeePaid: any } | { Reasonable: any } | { KnownGood: any } | { OutOfDate: any } | { LowQuality: any } | { Erroneous: any } | string | Uint8Array, identity: H256 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, MultiAddress, PalletIdentityJudgement, H256]>;
+      /**
+       * Remove the sender as a sub-account.
+       * 
+       * Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
+       * to the sender (*not* the original depositor).
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a registered
+       * super-identity.
+       * 
+       * NOTE: This should not normally be used, but is provided in the case that the non-
+       * controller of an account is maliciously registered as a sub-account.
+       **/
+      quitSub: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Remove the given account from the sender's subs.
+       * 
+       * Payment: Balance reserved by a previous `set_subs` call for one sub will be repatriated
+       * to the sender.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a registered
+       * sub identity of `sub`.
+       **/
+      removeSub: AugmentedSubmittable<(sub: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress]>;
+      /**
+       * Alter the associated name of the given sub-account.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a registered
+       * sub identity of `sub`.
+       **/
+      renameSub: AugmentedSubmittable<(sub: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, data: Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress, Data]>;
+      /**
+       * Request a judgement from a registrar.
+       * 
+       * Payment: At most `max_fee` will be reserved for payment to the registrar if judgement
+       * given.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a
+       * registered identity.
+       * 
+       * - `reg_index`: The index of the registrar whose judgement is requested.
+       * - `max_fee`: The maximum fee that may be paid. This should just be auto-populated as:
+       * 
+       * ```nocompile
+       * Self::registrars().get(reg_index).unwrap().fee
+       * ```
+       * 
+       * Emits `JudgementRequested` if successful.
+       * 
+       * # <weight>
+       * - `O(R + X)`.
+       * - One balance-reserve operation.
+       * - Storage: 1 read `O(R)`, 1 mutate `O(X + R)`.
+       * - One event.
+       * # </weight>
+       **/
+      requestJudgement: AugmentedSubmittable<(regIndex: Compact<u32> | AnyNumber | Uint8Array, maxFee: Compact<u128> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, Compact<u128>]>;
+      /**
+       * Change the account associated with a registrar.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must be the account
+       * of the registrar whose index is `index`.
+       * 
+       * - `index`: the index of the registrar whose fee is to be set.
+       * - `new`: the new account ID.
+       * 
+       * # <weight>
+       * - `O(R)`.
+       * - One storage mutation `O(R)`.
+       * - Benchmark: 8.823 + R * 0.32 µs (min squares analysis)
+       * # </weight>
+       **/
+      setAccountId: AugmentedSubmittable<(index: Compact<u32> | AnyNumber | Uint8Array, updated: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, MultiAddress]>;
+      /**
+       * Set the fee required for a judgement to be requested from a registrar.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must be the account
+       * of the registrar whose index is `index`.
+       * 
+       * - `index`: the index of the registrar whose fee is to be set.
+       * - `fee`: the new fee.
+       * 
+       * # <weight>
+       * - `O(R)`.
+       * - One storage mutation `O(R)`.
+       * - Benchmark: 7.315 + R * 0.329 µs (min squares analysis)
+       * # </weight>
+       **/
+      setFee: AugmentedSubmittable<(index: Compact<u32> | AnyNumber | Uint8Array, fee: Compact<u128> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, Compact<u128>]>;
+      /**
+       * Set the field information for a registrar.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must be the account
+       * of the registrar whose index is `index`.
+       * 
+       * - `index`: the index of the registrar whose fee is to be set.
+       * - `fields`: the fields that the registrar concerns themselves with.
+       * 
+       * # <weight>
+       * - `O(R)`.
+       * - One storage mutation `O(R)`.
+       * - Benchmark: 7.464 + R * 0.325 µs (min squares analysis)
+       * # </weight>
+       **/
+      setFields: AugmentedSubmittable<(index: Compact<u32> | AnyNumber | Uint8Array, fields: PalletIdentityBitFlags) => SubmittableExtrinsic<ApiType>, [Compact<u32>, PalletIdentityBitFlags]>;
+      /**
+       * Set an account's identity information and reserve the appropriate deposit.
+       * 
+       * If the account already has identity information, the deposit is taken as part payment
+       * for the new deposit.
+       * 
+       * The dispatch origin for this call must be _Signed_.
+       * 
+       * - `info`: The identity information.
+       * 
+       * Emits `IdentitySet` if successful.
+       * 
+       * # <weight>
+       * - `O(X + X' + R)`
+       * - where `X` additional-field-count (deposit-bounded and code-bounded)
+       * - where `R` judgements-count (registrar-count-bounded)
+       * - One balance reserve operation.
+       * - One storage mutation (codec-read `O(X' + R)`, codec-write `O(X + R)`).
+       * - One event.
+       * # </weight>
+       **/
+      setIdentity: AugmentedSubmittable<(info: PalletIdentityIdentityInfo | { additional?: any; display?: any; legal?: any; web?: any; riot?: any; email?: any; pgpFingerprint?: any; image?: any; twitter?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletIdentityIdentityInfo]>;
+      /**
+       * Set the sub-accounts of the sender.
+       * 
+       * Payment: Any aggregate balance reserved by previous `set_subs` calls will be returned
+       * and an amount `SubAccountDeposit` will be reserved for each item in `subs`.
+       * 
+       * The dispatch origin for this call must be _Signed_ and the sender must have a registered
+       * identity.
+       * 
+       * - `subs`: The identity's (new) sub-accounts.
+       * 
+       * # <weight>
+       * - `O(P + S)`
+       * - where `P` old-subs-count (hard- and deposit-bounded).
+       * - where `S` subs-count (hard- and deposit-bounded).
+       * - At most one balance operations.
+       * - DB:
+       * - `P + S` storage mutations (codec complexity `O(1)`)
+       * - One storage read (codec complexity `O(P)`).
+       * - One storage write (codec complexity `O(S)`).
+       * - One storage-exists (`IdentityOf::contains_key`).
+       * # </weight>
+       **/
+      setSubs: AugmentedSubmittable<(subs: Vec<ITuple<[AccountId32, Data]>> | ([AccountId32 | string | Uint8Array, Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array])[]) => SubmittableExtrinsic<ApiType>, [Vec<ITuple<[AccountId32, Data]>>]>;
+      /**
+       * Generic tx
+       **/
+      [key: string]: SubmittableExtrinsicFunction<ApiType>;
+    };
     inflation: {
       /**
        * This method sets the inflation start date. Can be only called once.
@@ -349,6 +714,13 @@
       disable: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
       enable: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
       /**
+       * Execute a runtime call stored as a preimage.
+       * 
+       * `weight_bound` is the maximum weight that the caller is willing
+       * to allow the extrinsic to be executed with.
+       **/
+      executePreimage: AugmentedSubmittable<(hash: H256 | string | Uint8Array, weightBound: SpWeightsWeightV2Weight | { refTime?: any; proofSize?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H256, SpWeightsWeightV2Weight]>;
+      /**
        * Generic tx
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
@@ -506,337 +878,78 @@
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
-    rmrkCore: {
-      /**
-       * Accept an NFT sent from another account to self or an owned NFT.
-       * 
-       * The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.
-       * 
-       * # Permissions:
-       * - Token-owner-to-be
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID of the NFT to be accepted.
-       * - `rmrk_nft_id`: ID of the NFT to be accepted.
-       * - `new_owner`: Either the sender's account ID or a sender-owned NFT,
-       * whichever the accepted NFT was sent to.
-       **/
-      acceptNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;
-      /**
-       * Accept the addition of a newly created pending resource to an existing NFT.
-       * 
-       * This transaction is needed when a resource is created and assigned to an NFT
-       * by a non-owner, i.e. the collection issuer, with one of the
-       * [`add_...` transactions](Pallet::add_basic_resource).
-       * 
-       * # Permissions:
-       * - Token owner
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID of the NFT.
-       * - `rmrk_nft_id`: ID of the NFT with a pending resource to be accepted.
-       * - `resource_id`: ID of the newly created pending resource.
-       * accept the addition of a new resource to an existing NFT
-       **/
-      acceptResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
-      /**
-       * Accept the removal of a removal-pending resource from an NFT.
-       * 
-       * This transaction is needed when a non-owner, i.e. the collection issuer,
-       * requests a [removal](`Pallet::remove_resource`) of a resource from an NFT.
-       * 
-       * # Permissions:
-       * - Token owner
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID of the NFT.
-       * - `rmrk_nft_id`: ID of the NFT with a resource to be removed.
-       * - `resource_id`: ID of the removal-pending resource.
-       **/
-      acceptResourceRemoval: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
-      /**
-       * Create and set/propose a basic resource for an NFT.
-       * 
-       * A basic resource is the simplest, lacking a Base and anything that comes with it.
-       * See RMRK docs for more information and examples.
-       * 
-       * # Permissions:
-       * - Collection issuer - if not the token owner, adding the resource will warrant
-       * the owner's [acceptance](Pallet::accept_resource).
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID of the NFT.
-       * - `nft_id`: ID of the NFT to assign a resource to.
-       * - `resource`: Data of the resource to be created.
-       **/
-      addBasicResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceBasicResource | { src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceBasicResource]>;
-      /**
-       * Create and set/propose a composable resource for an NFT.
-       * 
-       * A composable resource links to a Base and has a subset of its Parts it is composed of.
-       * See RMRK docs for more information and examples.
-       * 
-       * # Permissions:
-       * - Collection issuer - if not the token owner, adding the resource will warrant
-       * the owner's [acceptance](Pallet::accept_resource).
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID of the NFT.
-       * - `nft_id`: ID of the NFT to assign a resource to.
-       * - `resource`: Data of the resource to be created.
-       **/
-      addComposableResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceComposableResource | { parts?: any; base?: any; src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceComposableResource]>;
+    preimage: {
       /**
-       * Create and set/propose a slot resource for an NFT.
-       * 
-       * A slot resource links to a Base and a slot ID in it which it can fit into.
-       * See RMRK docs for more information and examples.
-       * 
-       * # Permissions:
-       * - Collection issuer - if not the token owner, adding the resource will warrant
-       * the owner's [acceptance](Pallet::accept_resource).
+       * Register a preimage on-chain.
        * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID of the NFT.
-       * - `nft_id`: ID of the NFT to assign a resource to.
-       * - `resource`: Data of the resource to be created.
+       * If the preimage was previously requested, no fees or deposits are taken for providing
+       * the preimage. Otherwise, a deposit is taken proportional to the size of the preimage.
        **/
-      addSlotResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceSlotResource | { base?: any; src?: any; metadata?: any; slot?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceSlotResource]>;
-      /**
-       * Burn an NFT, destroying it and its nested tokens up to the specified limit.
-       * If the burning budget is exceeded, the transaction is reverted.
-       * 
-       * This is the way to burn a nested token as well.
-       * 
-       * For more information, see [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively).
-       * 
-       * # Permissions:
-       * * Token owner
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `collection_id`: RMRK ID of the collection in which the NFT to burn belongs to.
-       * - `nft_id`: ID of the NFT to be destroyed.
-       * - `max_burns`: Maximum number of tokens to burn, assuming nesting. The transaction
-       * is reverted if there are more tokens to burn in the nesting tree than this number.
-       * This is primarily a mechanism of transaction weight control.
-       **/
-      burnNft: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, maxBurns: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
+      notePreimage: AugmentedSubmittable<(bytes: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Bytes]>;
       /**
-       * Change the issuer of a collection. Analogous to Unique's collection's [`owner`](up_data_structs::Collection).
+       * Request a preimage be uploaded to the chain without paying any fees or deposits.
        * 
-       * # Permissions:
-       * * Collection issuer
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `collection_id`: RMRK collection ID to change the issuer of.
-       * - `new_issuer`: Collection's new issuer.
+       * If the preimage requests has already been provided on-chain, we unreserve any deposit
+       * a user may have paid, and take the control of the preimage out of their hands.
        **/
-      changeCollectionIssuer: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newIssuer: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, MultiAddress]>;
+      requestPreimage: AugmentedSubmittable<(hash: H256 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H256]>;
       /**
-       * Create a new collection of NFTs.
+       * Clear an unrequested preimage from the runtime storage.
        * 
-       * # Permissions:
-       * * Anyone - will be assigned as the issuer of the collection.
+       * If `len` is provided, then it will be a much cheaper operation.
        * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `metadata`: Metadata describing the collection, e.g. IPFS hash. Cannot be changed.
-       * - `max`: Optional maximum number of tokens.
-       * - `symbol`: UTF-8 string with token prefix, by which to represent the token in wallets and UIs.
-       * Analogous to Unique's [`token_prefix`](up_data_structs::Collection). Cannot be changed.
+       * - `hash`: The hash of the preimage to be removed from the store.
+       * - `len`: The length of the preimage of `hash`.
        **/
-      createCollection: AugmentedSubmittable<(metadata: Bytes | string | Uint8Array, max: Option<u32> | null | Uint8Array | u32 | AnyNumber, symbol: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Bytes, Option<u32>, Bytes]>;
+      unnotePreimage: AugmentedSubmittable<(hash: H256 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H256]>;
       /**
-       * Destroy a collection.
-       * 
-       * Only empty collections can be destroyed. If it has any tokens, they must be burned first.
+       * Clear a previously made request for a preimage.
        * 
-       * # Permissions:
-       * * Collection issuer
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `collection_id`: RMRK ID of the collection to destroy.
+       * NOTE: THIS MUST NOT BE CALLED ON `hash` MORE TIMES THAN `request_preimage`.
        **/
-      destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
-      /**
-       * "Lock" the collection and prevent new token creation. Cannot be undone.
-       * 
-       * # Permissions:
-       * * Collection issuer
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `collection_id`: RMRK ID of the collection to lock.
-       **/
-      lockCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
-      /**
-       * Mint an NFT in a specified collection.
-       * 
-       * # Permissions:
-       * * Collection issuer
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `owner`: Owner account of the NFT. If set to None, defaults to the sender (collection issuer).
-       * - `collection_id`: RMRK collection ID for the NFT to be minted within. Cannot be changed.
-       * - `recipient`: Receiver account of the royalty. Has no effect if the `royalty_amount` is not set. Cannot be changed.
-       * - `royalty_amount`: Optional permillage reward from each trade for the `recipient`. Cannot be changed.
-       * - `metadata`: Arbitrary data about an NFT, e.g. IPFS hash. Cannot be changed.
-       * - `transferable`: Can this NFT be transferred? Cannot be changed.
-       * - `resources`: Resource data to be added to the NFT immediately after minting.
-       **/
-      mintNft: AugmentedSubmittable<(owner: Option<AccountId32> | null | Uint8Array | AccountId32 | string, collectionId: u32 | AnyNumber | Uint8Array, recipient: Option<AccountId32> | null | Uint8Array | AccountId32 | string, royaltyAmount: Option<Permill> | null | Uint8Array | Permill | AnyNumber, metadata: Bytes | string | Uint8Array, transferable: bool | boolean | Uint8Array, resources: Option<Vec<RmrkTraitsResourceResourceTypes>> | null | Uint8Array | Vec<RmrkTraitsResourceResourceTypes> | (RmrkTraitsResourceResourceTypes | { Basic: any } | { Composable: any } | { Slot: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Option<AccountId32>, u32, Option<AccountId32>, Option<Permill>, Bytes, bool, Option<Vec<RmrkTraitsResourceResourceTypes>>]>;
-      /**
-       * Reject an NFT sent from another account to self or owned NFT.
-       * The NFT in question will not be sent back and burnt instead.
-       * 
-       * The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.
-       * 
-       * # Permissions:
-       * - Token-owner-to-be-not
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK ID of the NFT to be rejected.
-       * - `rmrk_nft_id`: ID of the NFT to be rejected.
-       **/
-      rejectNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
-      /**
-       * Remove and erase a resource from an NFT.
-       * 
-       * If the sender does not own the NFT, then it will be pending confirmation,
-       * and will have to be [accepted](Pallet::accept_resource_removal) by the token owner.
-       * 
-       * # Permissions
-       * - Collection issuer
-       * 
-       * # Arguments
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK ID of a collection to which the NFT making use of the resource belongs to.
-       * - `nft_id`: ID of the NFT with a resource to be removed.
-       * - `resource_id`: ID of the resource to be removed.
-       **/
-      removeResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
-      /**
-       * Transfer an NFT from an account/NFT A to another account/NFT B.
-       * The token must be transferable. Nesting cannot occur deeper than the [`NESTING_BUDGET`].
-       * 
-       * If the target owner is an NFT owned by another account, then the NFT will enter
-       * the pending state and will have to be accepted by the other account.
-       * 
-       * # Permissions:
-       * - Token owner
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK ID of the collection of the NFT to be transferred.
-       * - `rmrk_nft_id`: ID of the NFT to be transferred.
-       * - `new_owner`: New owner of the nft which can be either an account or a NFT.
-       **/
-      send: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;
+      unrequestPreimage: AugmentedSubmittable<(hash: H256 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H256]>;
       /**
-       * Set a different order of resource priorities for an NFT. Priorities can be used,
-       * for example, for order of rendering.
-       * 
-       * Note that the priorities are not updated automatically, and are an empty vector
-       * by default. There is no pre-set definition for the order to be particular,
-       * it can be interpreted arbitrarily use-case by use-case.
-       * 
-       * # Permissions:
-       * - Token owner
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID of the NFT.
-       * - `rmrk_nft_id`: ID of the NFT to rearrange resource priorities for.
-       * - `priorities`: Ordered vector of resource IDs.
-       **/
-      setPriority: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, priorities: Vec<u32> | (u32 | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<u32>]>;
-      /**
-       * Add or edit a custom user property, a key-value pair, describing the metadata
-       * of a token or a collection, on either one of these.
-       * 
-       * Note that in this proxy implementation many details regarding RMRK are stored
-       * as scoped properties prefixed with "rmrk:", normally inaccessible
-       * to external transactions and RPCs.
-       * 
-       * # Permissions:
-       * - Collection issuer - in case of collection property
-       * - Token owner - in case of NFT property
-       * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `rmrk_collection_id`: RMRK collection ID.
-       * - `maybe_nft_id`: Optional ID of the NFT. If left empty, then the property is set for the collection.
-       * - `key`: Key of the custom property to be referenced by.
-       * - `value`: Value of the custom property to be stored.
-       **/
-      setProperty: AugmentedSubmittable<(rmrkCollectionId: Compact<u32> | AnyNumber | Uint8Array, maybeNftId: Option<u32> | null | Uint8Array | u32 | AnyNumber, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, Option<u32>, Bytes, Bytes]>;
-      /**
        * Generic tx
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
-    rmrkEquip: {
+    session: {
       /**
-       * Create a new Base.
+       * Removes any session key(s) of the function caller.
        * 
-       * Modeled after the [Base interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/base.md)
+       * This doesn't take effect until the next session.
        * 
-       * # Permissions
-       * - Anyone - will be assigned as the issuer of the Base.
-       * 
-       * # Arguments:
-       * - `origin`: Caller, will be assigned as the issuer of the Base
-       * - `base_type`: Arbitrary media type, e.g. "svg".
-       * - `symbol`: Arbitrary client-chosen symbol.
-       * - `parts`: Array of Fixed and Slot Parts composing the Base,
-       * confined in length by [`RmrkPartsLimit`](up_data_structs::RmrkPartsLimit).
-       **/
-      createBase: AugmentedSubmittable<(baseType: Bytes | string | Uint8Array, symbol: Bytes | string | Uint8Array, parts: Vec<RmrkTraitsPartPartType> | (RmrkTraitsPartPartType | { FixedPart: any } | { SlotPart: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Bytes, Bytes, Vec<RmrkTraitsPartPartType>]>;
-      /**
-       * Update the array of Collections allowed to be equipped to a Base's specified Slot Part.
-       * 
-       * Modeled after [equippable interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/equippable.md).
-       * 
-       * # Permissions:
-       * - Base issuer
+       * The dispatch origin of this function must be Signed and the account must be either be
+       * convertible to a validator ID using the chain's typical addressing system (this usually
+       * means being a controller account) or directly convertible into a validator ID (which
+       * usually means being a stash account).
        * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `base_id`: Base containing the Slot Part to be updated.
-       * - `slot_id`: Slot Part whose Equippable List is being updated .
-       * - `equippables`: List of equippables that will override the current Equippables list.
+       * # <weight>
+       * - Complexity: `O(1)` in number of key types. Actual cost depends on the number of length
+       * of `T::Keys::key_ids()` which is fixed.
+       * - DbReads: `T::ValidatorIdOf`, `NextKeys`, `origin account`
+       * - DbWrites: `NextKeys`, `origin account`
+       * - DbWrites per key id: `KeyOwner`
+       * # </weight>
        **/
-      equippable: AugmentedSubmittable<(baseId: u32 | AnyNumber | Uint8Array, slotId: u32 | AnyNumber | Uint8Array, equippables: RmrkTraitsPartEquippableList | { All: any } | { Empty: any } | { Custom: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsPartEquippableList]>;
+      purgeKeys: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
       /**
-       * Add a Theme to a Base.
-       * A Theme named "default" is required prior to adding other Themes.
-       * 
-       * Modeled after [Themeadd interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/themeadd.md).
+       * Sets the session key(s) of the function caller to `keys`.
+       * Allows an account to set its session key prior to becoming a validator.
+       * This doesn't take effect until the next session.
        * 
-       * # Permissions:
-       * - Base issuer
+       * The dispatch origin of this function must be signed.
        * 
-       * # Arguments:
-       * - `origin`: sender of the transaction
-       * - `base_id`: Base ID containing the Theme to be updated.
-       * - `theme`: Theme to add to the Base.  A Theme has a name and properties, which are an
-       * array of [key, value, inherit].
-       * - `key`: Arbitrary BoundedString, defined by client.
-       * - `value`: Arbitrary BoundedString, defined by client.
-       * - `inherit`: Optional bool.
+       * # <weight>
+       * - Complexity: `O(1)`. Actual cost depends on the number of length of
+       * `T::Keys::key_ids()` which is fixed.
+       * - DbReads: `origin account`, `T::ValidatorIdOf`, `NextKeys`
+       * - DbWrites: `origin account`, `NextKeys`
+       * - DbReads per key id: `KeyOwner`
+       * - DbWrites per key id: `KeyOwner`
+       * # </weight>
        **/
-      themeAdd: AugmentedSubmittable<(baseId: u32 | AnyNumber | Uint8Array, theme: RmrkTraitsTheme | { name?: any; properties?: any; inherit?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, RmrkTraitsTheme]>;
+      setKeys: AugmentedSubmittable<(keys: OpalRuntimeRuntimeCommonSessionKeys | { aura?: any } | string | Uint8Array, proof: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [OpalRuntimeRuntimeCommonSessionKeys, Bytes]>;
       /**
        * Generic tx
        **/
@@ -1328,6 +1441,10 @@
        * * `token_prefix`: Byte string containing the token prefix to mark a collection
        * to which a token belongs (limit [`MAX_TOKEN_PREFIX_LENGTH`]).
        * * `mode`: Type of items stored in the collection and type dependent data.
+       * 
+       * returns collection ID
+       * 
+       * Deprecated: `create_collection_ex` is more up-to-date and advanced, prefer it instead.
        **/
       createCollection: AugmentedSubmittable<(collectionName: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], collectionDescription: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], tokenPrefix: Bytes | string | Uint8Array, mode: UpDataStructsCollectionMode | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Vec<u16>, Vec<u16>, Bytes, UpDataStructsCollectionMode]>;
       /**
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -5,7 +5,7 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/types/types/registry';
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationAppPromotionConfiguration, PalletConfigurationCall, PalletConfigurationError, PalletConfigurationEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionValidityInvalidTransaction, SpRuntimeTransactionValidityTransactionValidityError, SpRuntimeTransactionValidityUnknownTransaction, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, UpPovEstimateRpcPovInfo, UpPovEstimateRpcTrieKeyValue, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OpalRuntimeRuntimeCommonSessionKeys, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletAuthorshipCall, PalletAuthorshipError, PalletAuthorshipUncleEntryItem, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReserveData, PalletCollatorSelectionCall, PalletCollatorSelectionError, PalletCollatorSelectionEvent, PalletCommonError, PalletCommonEvent, PalletConfigurationAppPromotionConfiguration, PalletConfigurationCall, PalletConfigurationError, PalletConfigurationEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletIdentityBitFlags, PalletIdentityCall, PalletIdentityError, PalletIdentityEvent, PalletIdentityIdentityField, PalletIdentityIdentityInfo, PalletIdentityJudgement, PalletIdentityRegistrarInfo, PalletIdentityRegistration, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletPreimageCall, PalletPreimageError, PalletPreimageEvent, PalletPreimageRequestStatus, PalletRefungibleError, PalletSessionCall, PalletSessionError, PalletSessionEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpArithmeticArithmeticError, SpConsensusAuraSr25519AppSr25519Public, SpCoreCryptoKeyTypeId, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Public, SpCoreSr25519Signature, SpRuntimeBlakeTwo256, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeHeader, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionValidityInvalidTransaction, SpRuntimeTransactionValidityTransactionValidityError, SpRuntimeTransactionValidityUnknownTransaction, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, UpPovEstimateRpcPovInfo, UpPovEstimateRpcTrieKeyValue, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
 import type { Data, StorageKey } from '@polkadot/types';
 import type { BitVec, Bool, Bytes, F32, F64, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, f32, f64, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
 import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
@@ -774,6 +774,7 @@
     OpalRuntimeRuntime: OpalRuntimeRuntime;
     OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls: OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls;
     OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance: OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance;
+    OpalRuntimeRuntimeCommonSessionKeys: OpalRuntimeRuntimeCommonSessionKeys;
     OpaqueCall: OpaqueCall;
     OpaqueKeyOwnershipProof: OpaqueKeyOwnershipProof;
     OpaqueMetadata: OpaqueMetadata;
@@ -818,6 +819,9 @@
     PalletAppPromotionCall: PalletAppPromotionCall;
     PalletAppPromotionError: PalletAppPromotionError;
     PalletAppPromotionEvent: PalletAppPromotionEvent;
+    PalletAuthorshipCall: PalletAuthorshipCall;
+    PalletAuthorshipError: PalletAuthorshipError;
+    PalletAuthorshipUncleEntryItem: PalletAuthorshipUncleEntryItem;
     PalletBalancesAccountData: PalletBalancesAccountData;
     PalletBalancesBalanceLock: PalletBalancesBalanceLock;
     PalletBalancesCall: PalletBalancesCall;
@@ -827,6 +831,9 @@
     PalletBalancesReserveData: PalletBalancesReserveData;
     PalletCallMetadataLatest: PalletCallMetadataLatest;
     PalletCallMetadataV14: PalletCallMetadataV14;
+    PalletCollatorSelectionCall: PalletCollatorSelectionCall;
+    PalletCollatorSelectionError: PalletCollatorSelectionError;
+    PalletCollatorSelectionEvent: PalletCollatorSelectionEvent;
     PalletCommonError: PalletCommonError;
     PalletCommonEvent: PalletCommonEvent;
     PalletConfigurationAppPromotionConfiguration: PalletConfigurationAppPromotionConfiguration;
@@ -862,6 +869,15 @@
     PalletForeignAssetsNativeCurrency: PalletForeignAssetsNativeCurrency;
     PalletFungibleError: PalletFungibleError;
     PalletId: PalletId;
+    PalletIdentityBitFlags: PalletIdentityBitFlags;
+    PalletIdentityCall: PalletIdentityCall;
+    PalletIdentityError: PalletIdentityError;
+    PalletIdentityEvent: PalletIdentityEvent;
+    PalletIdentityIdentityField: PalletIdentityIdentityField;
+    PalletIdentityIdentityInfo: PalletIdentityIdentityInfo;
+    PalletIdentityJudgement: PalletIdentityJudgement;
+    PalletIdentityRegistrarInfo: PalletIdentityRegistrarInfo;
+    PalletIdentityRegistration: PalletIdentityRegistration;
     PalletInflationCall: PalletInflationCall;
     PalletMaintenanceCall: PalletMaintenanceCall;
     PalletMaintenanceError: PalletMaintenanceError;
@@ -870,13 +886,14 @@
     PalletMetadataV14: PalletMetadataV14;
     PalletNonfungibleError: PalletNonfungibleError;
     PalletNonfungibleItemData: PalletNonfungibleItemData;
+    PalletPreimageCall: PalletPreimageCall;
+    PalletPreimageError: PalletPreimageError;
+    PalletPreimageEvent: PalletPreimageEvent;
+    PalletPreimageRequestStatus: PalletPreimageRequestStatus;
     PalletRefungibleError: PalletRefungibleError;
-    PalletRmrkCoreCall: PalletRmrkCoreCall;
-    PalletRmrkCoreError: PalletRmrkCoreError;
-    PalletRmrkCoreEvent: PalletRmrkCoreEvent;
-    PalletRmrkEquipCall: PalletRmrkEquipCall;
-    PalletRmrkEquipError: PalletRmrkEquipError;
-    PalletRmrkEquipEvent: PalletRmrkEquipEvent;
+    PalletSessionCall: PalletSessionCall;
+    PalletSessionError: PalletSessionError;
+    PalletSessionEvent: PalletSessionEvent;
     PalletsOrigin: PalletsOrigin;
     PalletStorageMetadataLatest: PalletStorageMetadataLatest;
     PalletStorageMetadataV14: PalletStorageMetadataV14;
@@ -1036,24 +1053,6 @@
     Retriable: Retriable;
     RewardDestination: RewardDestination;
     RewardPoint: RewardPoint;
-    RmrkTraitsBaseBaseInfo: RmrkTraitsBaseBaseInfo;
-    RmrkTraitsCollectionCollectionInfo: RmrkTraitsCollectionCollectionInfo;
-    RmrkTraitsNftAccountIdOrCollectionNftTuple: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-    RmrkTraitsNftNftChild: RmrkTraitsNftNftChild;
-    RmrkTraitsNftNftInfo: RmrkTraitsNftNftInfo;
-    RmrkTraitsNftRoyaltyInfo: RmrkTraitsNftRoyaltyInfo;
-    RmrkTraitsPartEquippableList: RmrkTraitsPartEquippableList;
-    RmrkTraitsPartFixedPart: RmrkTraitsPartFixedPart;
-    RmrkTraitsPartPartType: RmrkTraitsPartPartType;
-    RmrkTraitsPartSlotPart: RmrkTraitsPartSlotPart;
-    RmrkTraitsPropertyPropertyInfo: RmrkTraitsPropertyPropertyInfo;
-    RmrkTraitsResourceBasicResource: RmrkTraitsResourceBasicResource;
-    RmrkTraitsResourceComposableResource: RmrkTraitsResourceComposableResource;
-    RmrkTraitsResourceResourceInfo: RmrkTraitsResourceResourceInfo;
-    RmrkTraitsResourceResourceTypes: RmrkTraitsResourceResourceTypes;
-    RmrkTraitsResourceSlotResource: RmrkTraitsResourceSlotResource;
-    RmrkTraitsTheme: RmrkTraitsTheme;
-    RmrkTraitsThemeThemeProperty: RmrkTraitsThemeThemeProperty;
     RoundSnapshot: RoundSnapshot;
     RoundState: RoundState;
     RpcMethods: RpcMethods;
@@ -1176,14 +1175,19 @@
     SolutionSupports: SolutionSupports;
     SpanIndex: SpanIndex;
     SpanRecord: SpanRecord;
+    SpArithmeticArithmeticError: SpArithmeticArithmeticError;
+    SpConsensusAuraSr25519AppSr25519Public: SpConsensusAuraSr25519AppSr25519Public;
+    SpCoreCryptoKeyTypeId: SpCoreCryptoKeyTypeId;
     SpCoreEcdsaSignature: SpCoreEcdsaSignature;
     SpCoreEd25519Signature: SpCoreEd25519Signature;
+    SpCoreSr25519Public: SpCoreSr25519Public;
     SpCoreSr25519Signature: SpCoreSr25519Signature;
     SpecVersion: SpecVersion;
-    SpRuntimeArithmeticError: SpRuntimeArithmeticError;
+    SpRuntimeBlakeTwo256: SpRuntimeBlakeTwo256;
     SpRuntimeDigest: SpRuntimeDigest;
     SpRuntimeDigestDigestItem: SpRuntimeDigestDigestItem;
     SpRuntimeDispatchError: SpRuntimeDispatchError;
+    SpRuntimeHeader: SpRuntimeHeader;
     SpRuntimeModuleError: SpRuntimeModuleError;
     SpRuntimeMultiSignature: SpRuntimeMultiSignature;
     SpRuntimeTokenError: SpRuntimeTokenError;
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -1,9 +1,10 @@
 // Auto-generated via `yarn polkadot-types-from-defs`, do not edit
 /* eslint-disable */
 
+import type { Data } from '@polkadot/types';
 import type { BTreeMap, BTreeSet, Bytes, Compact, Enum, Null, Option, Result, Struct, Text, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
 import type { ITuple } from '@polkadot/types-codec/types';
-import type { AccountId32, Call, H160, H256, MultiAddress, Perbill, Permill } from '@polkadot/types/interfaces/runtime';
+import type { AccountId32, Call, H160, H256, MultiAddress, Perbill } from '@polkadot/types/interfaces/runtime';
 import type { Event } from '@polkadot/types/interfaces/system';
 
 /** @name CumulusPalletDmpQueueCall */
@@ -441,6 +442,7 @@
   readonly isOther: boolean;
   readonly asOther: Text;
   readonly isInvalidCode: boolean;
+  readonly asInvalidCode: u8;
   readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
 }
 
@@ -698,6 +700,11 @@
 /** @name OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance */
 export interface OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance extends Null {}
 
+/** @name OpalRuntimeRuntimeCommonSessionKeys */
+export interface OpalRuntimeRuntimeCommonSessionKeys extends Struct {
+  readonly aura: SpConsensusAuraSr25519AppSr25519Public;
+}
+
 /** @name OrmlTokensAccountData */
 export interface OrmlTokensAccountData extends Struct {
   readonly free: u128;
@@ -1007,7 +1014,7 @@
   readonly asStake: {
     readonly amount: u128;
   } & Struct;
-  readonly isUnstake: boolean;
+  readonly isUnstakeAll: boolean;
   readonly isSponsorCollection: boolean;
   readonly asSponsorCollection: {
     readonly collectionId: u32;
@@ -1028,7 +1035,11 @@
   readonly asPayoutStakers: {
     readonly stakersNumber: Option<u8>;
   } & Struct;
-  readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers';
+  readonly isUnstakePartial: boolean;
+  readonly asUnstakePartial: {
+    readonly amount: u128;
+  } & Struct;
+  readonly type: 'SetAdminAddress' | 'Stake' | 'UnstakeAll' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers' | 'UnstakePartial';
 }
 
 /** @name PalletAppPromotionError */
@@ -1039,7 +1050,8 @@
   readonly isPendingForBlockOverflow: boolean;
   readonly isSponsorNotSet: boolean;
   readonly isIncorrectLockedBalanceOperation: boolean;
-  readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation';
+  readonly isInsufficientStakedBalance: boolean;
+  readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation' | 'InsufficientStakedBalance';
 }
 
 /** @name PalletAppPromotionEvent */
@@ -1055,6 +1067,36 @@
   readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin';
 }
 
+/** @name PalletAuthorshipCall */
+export interface PalletAuthorshipCall extends Enum {
+  readonly isSetUncles: boolean;
+  readonly asSetUncles: {
+    readonly newUncles: Vec<SpRuntimeHeader>;
+  } & Struct;
+  readonly type: 'SetUncles';
+}
+
+/** @name PalletAuthorshipError */
+export interface PalletAuthorshipError extends Enum {
+  readonly isInvalidUncleParent: boolean;
+  readonly isUnclesAlreadySet: boolean;
+  readonly isTooManyUncles: boolean;
+  readonly isGenesisUncle: boolean;
+  readonly isTooHighUncle: boolean;
+  readonly isUncleAlreadyIncluded: boolean;
+  readonly isOldUncle: boolean;
+  readonly type: 'InvalidUncleParent' | 'UnclesAlreadySet' | 'TooManyUncles' | 'GenesisUncle' | 'TooHighUncle' | 'UncleAlreadyIncluded' | 'OldUncle';
+}
+
+/** @name PalletAuthorshipUncleEntryItem */
+export interface PalletAuthorshipUncleEntryItem extends Enum {
+  readonly isInclusionHeight: boolean;
+  readonly asInclusionHeight: u32;
+  readonly isUncle: boolean;
+  readonly asUncle: ITuple<[H256, Option<AccountId32>]>;
+  readonly type: 'InclusionHeight' | 'Uncle';
+}
+
 /** @name PalletBalancesAccountData */
 export interface PalletBalancesAccountData extends Struct {
   readonly free: u128;
@@ -1193,6 +1235,76 @@
   readonly amount: u128;
 }
 
+/** @name PalletCollatorSelectionCall */
+export interface PalletCollatorSelectionCall extends Enum {
+  readonly isAddInvulnerable: boolean;
+  readonly asAddInvulnerable: {
+    readonly new_: AccountId32;
+  } & Struct;
+  readonly isRemoveInvulnerable: boolean;
+  readonly asRemoveInvulnerable: {
+    readonly who: AccountId32;
+  } & Struct;
+  readonly isGetLicense: boolean;
+  readonly isOnboard: boolean;
+  readonly isOffboard: boolean;
+  readonly isReleaseLicense: boolean;
+  readonly isForceReleaseLicense: boolean;
+  readonly asForceReleaseLicense: {
+    readonly who: AccountId32;
+  } & Struct;
+  readonly type: 'AddInvulnerable' | 'RemoveInvulnerable' | 'GetLicense' | 'Onboard' | 'Offboard' | 'ReleaseLicense' | 'ForceReleaseLicense';
+}
+
+/** @name PalletCollatorSelectionError */
+export interface PalletCollatorSelectionError extends Enum {
+  readonly isTooManyCandidates: boolean;
+  readonly isUnknown: boolean;
+  readonly isPermission: boolean;
+  readonly isAlreadyHoldingLicense: boolean;
+  readonly isNoLicense: boolean;
+  readonly isAlreadyCandidate: boolean;
+  readonly isNotCandidate: boolean;
+  readonly isTooManyInvulnerables: boolean;
+  readonly isTooFewInvulnerables: boolean;
+  readonly isAlreadyInvulnerable: boolean;
+  readonly isNotInvulnerable: boolean;
+  readonly isNoAssociatedValidatorId: boolean;
+  readonly isValidatorNotRegistered: boolean;
+  readonly type: 'TooManyCandidates' | 'Unknown' | 'Permission' | 'AlreadyHoldingLicense' | 'NoLicense' | 'AlreadyCandidate' | 'NotCandidate' | 'TooManyInvulnerables' | 'TooFewInvulnerables' | 'AlreadyInvulnerable' | 'NotInvulnerable' | 'NoAssociatedValidatorId' | 'ValidatorNotRegistered';
+}
+
+/** @name PalletCollatorSelectionEvent */
+export interface PalletCollatorSelectionEvent extends Enum {
+  readonly isInvulnerableAdded: boolean;
+  readonly asInvulnerableAdded: {
+    readonly invulnerable: AccountId32;
+  } & Struct;
+  readonly isInvulnerableRemoved: boolean;
+  readonly asInvulnerableRemoved: {
+    readonly invulnerable: AccountId32;
+  } & Struct;
+  readonly isLicenseObtained: boolean;
+  readonly asLicenseObtained: {
+    readonly accountId: AccountId32;
+    readonly deposit: u128;
+  } & Struct;
+  readonly isLicenseReleased: boolean;
+  readonly asLicenseReleased: {
+    readonly accountId: AccountId32;
+    readonly depositReturned: u128;
+  } & Struct;
+  readonly isCandidateAdded: boolean;
+  readonly asCandidateAdded: {
+    readonly accountId: AccountId32;
+  } & Struct;
+  readonly isCandidateRemoved: boolean;
+  readonly asCandidateRemoved: {
+    readonly accountId: AccountId32;
+  } & Struct;
+  readonly type: 'InvulnerableAdded' | 'InvulnerableRemoved' | 'LicenseObtained' | 'LicenseReleased' | 'CandidateAdded' | 'CandidateRemoved';
+}
+
 /** @name PalletCommonError */
 export interface PalletCommonError extends Enum {
   readonly isCollectionNotFound: boolean;
@@ -1532,7 +1644,8 @@
   readonly asInsertEvents: {
     readonly events: Vec<Bytes>;
   } & Struct;
-  readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents';
+  readonly isRemoveRmrkData: boolean;
+  readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents' | 'RemoveRmrkData';
 }
 
 /** @name PalletEvmMigrationError */
@@ -1638,6 +1751,243 @@
   readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed' | 'SettingAllowanceForAllNotAllowed' | 'FungibleTokensAreAlwaysValid';
 }
 
+/** @name PalletIdentityBitFlags */
+export interface PalletIdentityBitFlags extends Struct {
+  readonly _bitLength: 64;
+  readonly Display: 1;
+  readonly Legal: 2;
+  readonly Web: 4;
+  readonly Riot: 8;
+  readonly Email: 16;
+  readonly PgpFingerprint: 32;
+  readonly Image: 64;
+  readonly Twitter: 128;
+}
+
+/** @name PalletIdentityCall */
+export interface PalletIdentityCall extends Enum {
+  readonly isAddRegistrar: boolean;
+  readonly asAddRegistrar: {
+    readonly account: MultiAddress;
+  } & Struct;
+  readonly isSetIdentity: boolean;
+  readonly asSetIdentity: {
+    readonly info: PalletIdentityIdentityInfo;
+  } & Struct;
+  readonly isSetSubs: boolean;
+  readonly asSetSubs: {
+    readonly subs: Vec<ITuple<[AccountId32, Data]>>;
+  } & Struct;
+  readonly isClearIdentity: boolean;
+  readonly isRequestJudgement: boolean;
+  readonly asRequestJudgement: {
+    readonly regIndex: Compact<u32>;
+    readonly maxFee: Compact<u128>;
+  } & Struct;
+  readonly isCancelRequest: boolean;
+  readonly asCancelRequest: {
+    readonly regIndex: u32;
+  } & Struct;
+  readonly isSetFee: boolean;
+  readonly asSetFee: {
+    readonly index: Compact<u32>;
+    readonly fee: Compact<u128>;
+  } & Struct;
+  readonly isSetAccountId: boolean;
+  readonly asSetAccountId: {
+    readonly index: Compact<u32>;
+    readonly new_: MultiAddress;
+  } & Struct;
+  readonly isSetFields: boolean;
+  readonly asSetFields: {
+    readonly index: Compact<u32>;
+    readonly fields: PalletIdentityBitFlags;
+  } & Struct;
+  readonly isProvideJudgement: boolean;
+  readonly asProvideJudgement: {
+    readonly regIndex: Compact<u32>;
+    readonly target: MultiAddress;
+    readonly judgement: PalletIdentityJudgement;
+    readonly identity: H256;
+  } & Struct;
+  readonly isKillIdentity: boolean;
+  readonly asKillIdentity: {
+    readonly target: MultiAddress;
+  } & Struct;
+  readonly isAddSub: boolean;
+  readonly asAddSub: {
+    readonly sub: MultiAddress;
+    readonly data: Data;
+  } & Struct;
+  readonly isRenameSub: boolean;
+  readonly asRenameSub: {
+    readonly sub: MultiAddress;
+    readonly data: Data;
+  } & Struct;
+  readonly isRemoveSub: boolean;
+  readonly asRemoveSub: {
+    readonly sub: MultiAddress;
+  } & Struct;
+  readonly isQuitSub: boolean;
+  readonly isForceInsertIdentities: boolean;
+  readonly asForceInsertIdentities: {
+    readonly identities: Vec<ITuple<[AccountId32, PalletIdentityRegistration]>>;
+  } & Struct;
+  readonly isForceRemoveIdentities: boolean;
+  readonly asForceRemoveIdentities: {
+    readonly identities: Vec<AccountId32>;
+  } & Struct;
+  readonly isForceSetSubs: boolean;
+  readonly asForceSetSubs: {
+    readonly subs: Vec<ITuple<[AccountId32, ITuple<[u128, Vec<ITuple<[AccountId32, Data]>>]>]>>;
+  } & Struct;
+  readonly type: 'AddRegistrar' | 'SetIdentity' | 'SetSubs' | 'ClearIdentity' | 'RequestJudgement' | 'CancelRequest' | 'SetFee' | 'SetAccountId' | 'SetFields' | 'ProvideJudgement' | 'KillIdentity' | 'AddSub' | 'RenameSub' | 'RemoveSub' | 'QuitSub' | 'ForceInsertIdentities' | 'ForceRemoveIdentities' | 'ForceSetSubs';
+}
+
+/** @name PalletIdentityError */
+export interface PalletIdentityError extends Enum {
+  readonly isTooManySubAccounts: boolean;
+  readonly isNotFound: boolean;
+  readonly isNotNamed: boolean;
+  readonly isEmptyIndex: boolean;
+  readonly isFeeChanged: boolean;
+  readonly isNoIdentity: boolean;
+  readonly isStickyJudgement: boolean;
+  readonly isJudgementGiven: boolean;
+  readonly isInvalidJudgement: boolean;
+  readonly isInvalidIndex: boolean;
+  readonly isInvalidTarget: boolean;
+  readonly isTooManyFields: boolean;
+  readonly isTooManyRegistrars: boolean;
+  readonly isAlreadyClaimed: boolean;
+  readonly isNotSub: boolean;
+  readonly isNotOwned: boolean;
+  readonly isJudgementForDifferentIdentity: boolean;
+  readonly isJudgementPaymentFailed: boolean;
+  readonly type: 'TooManySubAccounts' | 'NotFound' | 'NotNamed' | 'EmptyIndex' | 'FeeChanged' | 'NoIdentity' | 'StickyJudgement' | 'JudgementGiven' | 'InvalidJudgement' | 'InvalidIndex' | 'InvalidTarget' | 'TooManyFields' | 'TooManyRegistrars' | 'AlreadyClaimed' | 'NotSub' | 'NotOwned' | 'JudgementForDifferentIdentity' | 'JudgementPaymentFailed';
+}
+
+/** @name PalletIdentityEvent */
+export interface PalletIdentityEvent extends Enum {
+  readonly isIdentitySet: boolean;
+  readonly asIdentitySet: {
+    readonly who: AccountId32;
+  } & Struct;
+  readonly isIdentityCleared: boolean;
+  readonly asIdentityCleared: {
+    readonly who: AccountId32;
+    readonly deposit: u128;
+  } & Struct;
+  readonly isIdentityKilled: boolean;
+  readonly asIdentityKilled: {
+    readonly who: AccountId32;
+    readonly deposit: u128;
+  } & Struct;
+  readonly isIdentitiesInserted: boolean;
+  readonly asIdentitiesInserted: {
+    readonly amount: u32;
+  } & Struct;
+  readonly isIdentitiesRemoved: boolean;
+  readonly asIdentitiesRemoved: {
+    readonly amount: u32;
+  } & Struct;
+  readonly isJudgementRequested: boolean;
+  readonly asJudgementRequested: {
+    readonly who: AccountId32;
+    readonly registrarIndex: u32;
+  } & Struct;
+  readonly isJudgementUnrequested: boolean;
+  readonly asJudgementUnrequested: {
+    readonly who: AccountId32;
+    readonly registrarIndex: u32;
+  } & Struct;
+  readonly isJudgementGiven: boolean;
+  readonly asJudgementGiven: {
+    readonly target: AccountId32;
+    readonly registrarIndex: u32;
+  } & Struct;
+  readonly isRegistrarAdded: boolean;
+  readonly asRegistrarAdded: {
+    readonly registrarIndex: u32;
+  } & Struct;
+  readonly isSubIdentityAdded: boolean;
+  readonly asSubIdentityAdded: {
+    readonly sub: AccountId32;
+    readonly main: AccountId32;
+    readonly deposit: u128;
+  } & Struct;
+  readonly isSubIdentityRemoved: boolean;
+  readonly asSubIdentityRemoved: {
+    readonly sub: AccountId32;
+    readonly main: AccountId32;
+    readonly deposit: u128;
+  } & Struct;
+  readonly isSubIdentityRevoked: boolean;
+  readonly asSubIdentityRevoked: {
+    readonly sub: AccountId32;
+    readonly main: AccountId32;
+    readonly deposit: u128;
+  } & Struct;
+  readonly isSubIdentitiesInserted: boolean;
+  readonly asSubIdentitiesInserted: {
+    readonly amount: u32;
+  } & Struct;
+  readonly type: 'IdentitySet' | 'IdentityCleared' | 'IdentityKilled' | 'IdentitiesInserted' | 'IdentitiesRemoved' | 'JudgementRequested' | 'JudgementUnrequested' | 'JudgementGiven' | 'RegistrarAdded' | 'SubIdentityAdded' | 'SubIdentityRemoved' | 'SubIdentityRevoked' | 'SubIdentitiesInserted';
+}
+
+/** @name PalletIdentityIdentityField */
+export interface PalletIdentityIdentityField extends Enum {
+  readonly isDisplay: boolean;
+  readonly isLegal: boolean;
+  readonly isWeb: boolean;
+  readonly isRiot: boolean;
+  readonly isEmail: boolean;
+  readonly isPgpFingerprint: boolean;
+  readonly isImage: boolean;
+  readonly isTwitter: boolean;
+  readonly type: 'Display' | 'Legal' | 'Web' | 'Riot' | 'Email' | 'PgpFingerprint' | 'Image' | 'Twitter';
+}
+
+/** @name PalletIdentityIdentityInfo */
+export interface PalletIdentityIdentityInfo extends Struct {
+  readonly additional: Vec<ITuple<[Data, Data]>>;
+  readonly display: Data;
+  readonly legal: Data;
+  readonly web: Data;
+  readonly riot: Data;
+  readonly email: Data;
+  readonly pgpFingerprint: Option<U8aFixed>;
+  readonly image: Data;
+  readonly twitter: Data;
+}
+
+/** @name PalletIdentityJudgement */
+export interface PalletIdentityJudgement extends Enum {
+  readonly isUnknown: boolean;
+  readonly isFeePaid: boolean;
+  readonly asFeePaid: u128;
+  readonly isReasonable: boolean;
+  readonly isKnownGood: boolean;
+  readonly isOutOfDate: boolean;
+  readonly isLowQuality: boolean;
+  readonly isErroneous: boolean;
+  readonly type: 'Unknown' | 'FeePaid' | 'Reasonable' | 'KnownGood' | 'OutOfDate' | 'LowQuality' | 'Erroneous';
+}
+
+/** @name PalletIdentityRegistrarInfo */
+export interface PalletIdentityRegistrarInfo extends Struct {
+  readonly account: AccountId32;
+  readonly fee: u128;
+  readonly fields: PalletIdentityBitFlags;
+}
+
+/** @name PalletIdentityRegistration */
+export interface PalletIdentityRegistration extends Struct {
+  readonly judgements: Vec<ITuple<[u32, PalletIdentityJudgement]>>;
+  readonly deposit: u128;
+  readonly info: PalletIdentityIdentityInfo;
+}
+
 /** @name PalletInflationCall */
 export interface PalletInflationCall extends Enum {
   readonly isStartInflation: boolean;
@@ -1651,7 +2001,12 @@
 export interface PalletMaintenanceCall extends Enum {
   readonly isEnable: boolean;
   readonly isDisable: boolean;
-  readonly type: 'Enable' | 'Disable';
+  readonly isExecutePreimage: boolean;
+  readonly asExecutePreimage: {
+    readonly hash_: H256;
+    readonly weightBound: SpWeightsWeightV2Weight;
+  } & Struct;
+  readonly type: 'Enable' | 'Disable' | 'ExecutePreimage';
 }
 
 /** @name PalletMaintenanceError */
@@ -1677,283 +2032,109 @@
   readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
 }
 
-/** @name PalletRefungibleError */
-export interface PalletRefungibleError extends Enum {
-  readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
-  readonly isWrongRefungiblePieces: boolean;
-  readonly isRepartitionWhileNotOwningAllPieces: boolean;
-  readonly isRefungibleDisallowsNesting: boolean;
-  readonly isSettingPropertiesNotAllowed: boolean;
-  readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
-}
-
-/** @name PalletRmrkCoreCall */
-export interface PalletRmrkCoreCall extends Enum {
-  readonly isCreateCollection: boolean;
-  readonly asCreateCollection: {
-    readonly metadata: Bytes;
-    readonly max: Option<u32>;
-    readonly symbol: Bytes;
+/** @name PalletPreimageCall */
+export interface PalletPreimageCall extends Enum {
+  readonly isNotePreimage: boolean;
+  readonly asNotePreimage: {
+    readonly bytes: Bytes;
   } & Struct;
-  readonly isDestroyCollection: boolean;
-  readonly asDestroyCollection: {
-    readonly collectionId: u32;
+  readonly isUnnotePreimage: boolean;
+  readonly asUnnotePreimage: {
+    readonly hash_: H256;
   } & Struct;
-  readonly isChangeCollectionIssuer: boolean;
-  readonly asChangeCollectionIssuer: {
-    readonly collectionId: u32;
-    readonly newIssuer: MultiAddress;
+  readonly isRequestPreimage: boolean;
+  readonly asRequestPreimage: {
+    readonly hash_: H256;
   } & Struct;
-  readonly isLockCollection: boolean;
-  readonly asLockCollection: {
-    readonly collectionId: u32;
+  readonly isUnrequestPreimage: boolean;
+  readonly asUnrequestPreimage: {
+    readonly hash_: H256;
   } & Struct;
-  readonly isMintNft: boolean;
-  readonly asMintNft: {
-    readonly owner: Option<AccountId32>;
-    readonly collectionId: u32;
-    readonly recipient: Option<AccountId32>;
-    readonly royaltyAmount: Option<Permill>;
-    readonly metadata: Bytes;
-    readonly transferable: bool;
-    readonly resources: Option<Vec<RmrkTraitsResourceResourceTypes>>;
-  } & Struct;
-  readonly isBurnNft: boolean;
-  readonly asBurnNft: {
-    readonly collectionId: u32;
-    readonly nftId: u32;
-    readonly maxBurns: u32;
-  } & Struct;
-  readonly isSend: boolean;
-  readonly asSend: {
-    readonly rmrkCollectionId: u32;
-    readonly rmrkNftId: u32;
-    readonly newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-  } & Struct;
-  readonly isAcceptNft: boolean;
-  readonly asAcceptNft: {
-    readonly rmrkCollectionId: u32;
-    readonly rmrkNftId: u32;
-    readonly newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-  } & Struct;
-  readonly isRejectNft: boolean;
-  readonly asRejectNft: {
-    readonly rmrkCollectionId: u32;
-    readonly rmrkNftId: u32;
-  } & Struct;
-  readonly isAcceptResource: boolean;
-  readonly asAcceptResource: {
-    readonly rmrkCollectionId: u32;
-    readonly rmrkNftId: u32;
-    readonly resourceId: u32;
-  } & Struct;
-  readonly isAcceptResourceRemoval: boolean;
-  readonly asAcceptResourceRemoval: {
-    readonly rmrkCollectionId: u32;
-    readonly rmrkNftId: u32;
-    readonly resourceId: u32;
-  } & Struct;
-  readonly isSetProperty: boolean;
-  readonly asSetProperty: {
-    readonly rmrkCollectionId: Compact<u32>;
-    readonly maybeNftId: Option<u32>;
-    readonly key: Bytes;
-    readonly value: Bytes;
-  } & Struct;
-  readonly isSetPriority: boolean;
-  readonly asSetPriority: {
-    readonly rmrkCollectionId: u32;
-    readonly rmrkNftId: u32;
-    readonly priorities: Vec<u32>;
-  } & Struct;
-  readonly isAddBasicResource: boolean;
-  readonly asAddBasicResource: {
-    readonly rmrkCollectionId: u32;
-    readonly nftId: u32;
-    readonly resource: RmrkTraitsResourceBasicResource;
-  } & Struct;
-  readonly isAddComposableResource: boolean;
-  readonly asAddComposableResource: {
-    readonly rmrkCollectionId: u32;
-    readonly nftId: u32;
-    readonly resource: RmrkTraitsResourceComposableResource;
-  } & Struct;
-  readonly isAddSlotResource: boolean;
-  readonly asAddSlotResource: {
-    readonly rmrkCollectionId: u32;
-    readonly nftId: u32;
-    readonly resource: RmrkTraitsResourceSlotResource;
-  } & Struct;
-  readonly isRemoveResource: boolean;
-  readonly asRemoveResource: {
-    readonly rmrkCollectionId: u32;
-    readonly nftId: u32;
-    readonly resourceId: u32;
-  } & Struct;
-  readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource';
+  readonly type: 'NotePreimage' | 'UnnotePreimage' | 'RequestPreimage' | 'UnrequestPreimage';
 }
 
-/** @name PalletRmrkCoreError */
-export interface PalletRmrkCoreError extends Enum {
-  readonly isCorruptedCollectionType: boolean;
-  readonly isRmrkPropertyKeyIsTooLong: boolean;
-  readonly isRmrkPropertyValueIsTooLong: boolean;
-  readonly isRmrkPropertyIsNotFound: boolean;
-  readonly isUnableToDecodeRmrkData: boolean;
-  readonly isCollectionNotEmpty: boolean;
-  readonly isNoAvailableCollectionId: boolean;
-  readonly isNoAvailableNftId: boolean;
-  readonly isCollectionUnknown: boolean;
-  readonly isNoPermission: boolean;
-  readonly isNonTransferable: boolean;
-  readonly isCollectionFullOrLocked: boolean;
-  readonly isResourceDoesntExist: boolean;
-  readonly isCannotSendToDescendentOrSelf: boolean;
-  readonly isCannotAcceptNonOwnedNft: boolean;
-  readonly isCannotRejectNonOwnedNft: boolean;
-  readonly isCannotRejectNonPendingNft: boolean;
-  readonly isResourceNotPending: boolean;
-  readonly isNoAvailableResourceId: boolean;
-  readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
+/** @name PalletPreimageError */
+export interface PalletPreimageError extends Enum {
+  readonly isTooBig: boolean;
+  readonly isAlreadyNoted: boolean;
+  readonly isNotAuthorized: boolean;
+  readonly isNotNoted: boolean;
+  readonly isRequested: boolean;
+  readonly isNotRequested: boolean;
+  readonly type: 'TooBig' | 'AlreadyNoted' | 'NotAuthorized' | 'NotNoted' | 'Requested' | 'NotRequested';
 }
 
-/** @name PalletRmrkCoreEvent */
-export interface PalletRmrkCoreEvent extends Enum {
-  readonly isCollectionCreated: boolean;
-  readonly asCollectionCreated: {
-    readonly issuer: AccountId32;
-    readonly collectionId: u32;
+/** @name PalletPreimageEvent */
+export interface PalletPreimageEvent extends Enum {
+  readonly isNoted: boolean;
+  readonly asNoted: {
+    readonly hash_: H256;
   } & Struct;
-  readonly isCollectionDestroyed: boolean;
-  readonly asCollectionDestroyed: {
-    readonly issuer: AccountId32;
-    readonly collectionId: u32;
+  readonly isRequested: boolean;
+  readonly asRequested: {
+    readonly hash_: H256;
   } & Struct;
-  readonly isIssuerChanged: boolean;
-  readonly asIssuerChanged: {
-    readonly oldIssuer: AccountId32;
-    readonly newIssuer: AccountId32;
-    readonly collectionId: u32;
+  readonly isCleared: boolean;
+  readonly asCleared: {
+    readonly hash_: H256;
   } & Struct;
-  readonly isCollectionLocked: boolean;
-  readonly asCollectionLocked: {
-    readonly issuer: AccountId32;
-    readonly collectionId: u32;
+  readonly type: 'Noted' | 'Requested' | 'Cleared';
+}
+
+/** @name PalletPreimageRequestStatus */
+export interface PalletPreimageRequestStatus extends Enum {
+  readonly isUnrequested: boolean;
+  readonly asUnrequested: {
+    readonly deposit: ITuple<[AccountId32, u128]>;
+    readonly len: u32;
   } & Struct;
-  readonly isNftMinted: boolean;
-  readonly asNftMinted: {
-    readonly owner: AccountId32;
-    readonly collectionId: u32;
-    readonly nftId: u32;
+  readonly isRequested: boolean;
+  readonly asRequested: {
+    readonly deposit: Option<ITuple<[AccountId32, u128]>>;
+    readonly count: u32;
+    readonly len: Option<u32>;
   } & Struct;
-  readonly isNftBurned: boolean;
-  readonly asNftBurned: {
-    readonly owner: AccountId32;
-    readonly nftId: u32;
-  } & Struct;
-  readonly isNftSent: boolean;
-  readonly asNftSent: {
-    readonly sender: AccountId32;
-    readonly recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-    readonly collectionId: u32;
-    readonly nftId: u32;
-    readonly approvalRequired: bool;
-  } & Struct;
-  readonly isNftAccepted: boolean;
-  readonly asNftAccepted: {
-    readonly sender: AccountId32;
-    readonly recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-    readonly collectionId: u32;
-    readonly nftId: u32;
-  } & Struct;
-  readonly isNftRejected: boolean;
-  readonly asNftRejected: {
-    readonly sender: AccountId32;
-    readonly collectionId: u32;
-    readonly nftId: u32;
-  } & Struct;
-  readonly isPropertySet: boolean;
-  readonly asPropertySet: {
-    readonly collectionId: u32;
-    readonly maybeNftId: Option<u32>;
-    readonly key: Bytes;
-    readonly value: Bytes;
-  } & Struct;
-  readonly isResourceAdded: boolean;
-  readonly asResourceAdded: {
-    readonly nftId: u32;
-    readonly resourceId: u32;
-  } & Struct;
-  readonly isResourceRemoval: boolean;
-  readonly asResourceRemoval: {
-    readonly nftId: u32;
-    readonly resourceId: u32;
-  } & Struct;
-  readonly isResourceAccepted: boolean;
-  readonly asResourceAccepted: {
-    readonly nftId: u32;
-    readonly resourceId: u32;
-  } & Struct;
-  readonly isResourceRemovalAccepted: boolean;
-  readonly asResourceRemovalAccepted: {
-    readonly nftId: u32;
-    readonly resourceId: u32;
-  } & Struct;
-  readonly isPrioritySet: boolean;
-  readonly asPrioritySet: {
-    readonly collectionId: u32;
-    readonly nftId: u32;
-  } & Struct;
-  readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet';
+  readonly type: 'Unrequested' | 'Requested';
+}
+
+/** @name PalletRefungibleError */
+export interface PalletRefungibleError extends Enum {
+  readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
+  readonly isWrongRefungiblePieces: boolean;
+  readonly isRepartitionWhileNotOwningAllPieces: boolean;
+  readonly isRefungibleDisallowsNesting: boolean;
+  readonly isSettingPropertiesNotAllowed: boolean;
+  readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
 }
 
-/** @name PalletRmrkEquipCall */
-export interface PalletRmrkEquipCall extends Enum {
-  readonly isCreateBase: boolean;
-  readonly asCreateBase: {
-    readonly baseType: Bytes;
-    readonly symbol: Bytes;
-    readonly parts: Vec<RmrkTraitsPartPartType>;
+/** @name PalletSessionCall */
+export interface PalletSessionCall extends Enum {
+  readonly isSetKeys: boolean;
+  readonly asSetKeys: {
+    readonly keys_: OpalRuntimeRuntimeCommonSessionKeys;
+    readonly proof: Bytes;
   } & Struct;
-  readonly isThemeAdd: boolean;
-  readonly asThemeAdd: {
-    readonly baseId: u32;
-    readonly theme: RmrkTraitsTheme;
-  } & Struct;
-  readonly isEquippable: boolean;
-  readonly asEquippable: {
-    readonly baseId: u32;
-    readonly slotId: u32;
-    readonly equippables: RmrkTraitsPartEquippableList;
-  } & Struct;
-  readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable';
+  readonly isPurgeKeys: boolean;
+  readonly type: 'SetKeys' | 'PurgeKeys';
 }
 
-/** @name PalletRmrkEquipError */
-export interface PalletRmrkEquipError extends Enum {
-  readonly isPermissionError: boolean;
-  readonly isNoAvailableBaseId: boolean;
-  readonly isNoAvailablePartId: boolean;
-  readonly isBaseDoesntExist: boolean;
-  readonly isNeedsDefaultThemeFirst: boolean;
-  readonly isPartDoesntExist: boolean;
-  readonly isNoEquippableOnFixedPart: boolean;
-  readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart';
+/** @name PalletSessionError */
+export interface PalletSessionError extends Enum {
+  readonly isInvalidProof: boolean;
+  readonly isNoAssociatedValidatorId: boolean;
+  readonly isDuplicatedKey: boolean;
+  readonly isNoKeys: boolean;
+  readonly isNoAccount: boolean;
+  readonly type: 'InvalidProof' | 'NoAssociatedValidatorId' | 'DuplicatedKey' | 'NoKeys' | 'NoAccount';
 }
 
-/** @name PalletRmrkEquipEvent */
-export interface PalletRmrkEquipEvent extends Enum {
-  readonly isBaseCreated: boolean;
-  readonly asBaseCreated: {
-    readonly issuer: AccountId32;
-    readonly baseId: u32;
+/** @name PalletSessionEvent */
+export interface PalletSessionEvent extends Enum {
+  readonly isNewSession: boolean;
+  readonly asNewSession: {
+    readonly sessionIndex: u32;
   } & Struct;
-  readonly isEquippablesUpdated: boolean;
-  readonly asEquippablesUpdated: {
-    readonly baseId: u32;
-    readonly slotId: u32;
-  } & Struct;
-  readonly type: 'BaseCreated' | 'EquippablesUpdated';
+  readonly type: 'NewSession';
 }
 
 /** @name PalletStructureCall */
@@ -1965,7 +2146,8 @@
   readonly isDepthLimit: boolean;
   readonly isBreadthLimit: boolean;
   readonly isTokenNotFound: boolean;
-  readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
+  readonly isCantNestTokenUnderCollection: boolean;
+  readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound' | 'CantNestTokenUnderCollection';
 }
 
 /** @name PalletStructureEvent */
@@ -2165,7 +2347,12 @@
     readonly amount: u128;
     readonly beneficiary: AccountId32;
   } & Struct;
-  readonly type: 'Proposed' | 'Spending' | 'Awarded' | 'Rejected' | 'Burnt' | 'Rollover' | 'Deposit' | 'SpendApproved';
+  readonly isUpdatedInactive: boolean;
+  readonly asUpdatedInactive: {
+    readonly reactivated: u128;
+    readonly deactivated: u128;
+  } & Struct;
+  readonly type: 'Proposed' | 'Spending' | 'Awarded' | 'Rejected' | 'Burnt' | 'Rollover' | 'Deposit' | 'SpendApproved' | 'UpdatedInactive';
 }
 
 /** @name PalletTreasuryProposal */
@@ -2485,7 +2672,7 @@
 }
 
 /** @name PhantomTypeUpDataStructs */
-export interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsPropertyPropertyInfo, RmrkTraitsBaseBaseInfo, RmrkTraitsPartPartType, RmrkTraitsTheme, RmrkTraitsNftNftChild, UpPovEstimateRpcPovInfo]>> {}
+export interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, UpPovEstimateRpcPovInfo]>> {}
 
 /** @name PolkadotCorePrimitivesInboundDownwardMessage */
 export interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct {
@@ -2550,150 +2737,19 @@
   readonly type: 'Present';
 }
 
-/** @name RmrkTraitsBaseBaseInfo */
-export interface RmrkTraitsBaseBaseInfo extends Struct {
-  readonly issuer: AccountId32;
-  readonly baseType: Bytes;
-  readonly symbol: Bytes;
+/** @name SpArithmeticArithmeticError */
+export interface SpArithmeticArithmeticError extends Enum {
+  readonly isUnderflow: boolean;
+  readonly isOverflow: boolean;
+  readonly isDivisionByZero: boolean;
+  readonly type: 'Underflow' | 'Overflow' | 'DivisionByZero';
 }
 
-/** @name RmrkTraitsCollectionCollectionInfo */
-export interface RmrkTraitsCollectionCollectionInfo extends Struct {
-  readonly issuer: AccountId32;
-  readonly metadata: Bytes;
-  readonly max: Option<u32>;
-  readonly symbol: Bytes;
-  readonly nftsCount: u32;
-}
+/** @name SpConsensusAuraSr25519AppSr25519Public */
+export interface SpConsensusAuraSr25519AppSr25519Public extends SpCoreSr25519Public {}
 
-/** @name RmrkTraitsNftAccountIdOrCollectionNftTuple */
-export interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum {
-  readonly isAccountId: boolean;
-  readonly asAccountId: AccountId32;
-  readonly isCollectionAndNftTuple: boolean;
-  readonly asCollectionAndNftTuple: ITuple<[u32, u32]>;
-  readonly type: 'AccountId' | 'CollectionAndNftTuple';
-}
-
-/** @name RmrkTraitsNftNftChild */
-export interface RmrkTraitsNftNftChild extends Struct {
-  readonly collectionId: u32;
-  readonly nftId: u32;
-}
-
-/** @name RmrkTraitsNftNftInfo */
-export interface RmrkTraitsNftNftInfo extends Struct {
-  readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-  readonly royalty: Option<RmrkTraitsNftRoyaltyInfo>;
-  readonly metadata: Bytes;
-  readonly equipped: bool;
-  readonly pending: bool;
-}
-
-/** @name RmrkTraitsNftRoyaltyInfo */
-export interface RmrkTraitsNftRoyaltyInfo extends Struct {
-  readonly recipient: AccountId32;
-  readonly amount: Permill;
-}
-
-/** @name RmrkTraitsPartEquippableList */
-export interface RmrkTraitsPartEquippableList extends Enum {
-  readonly isAll: boolean;
-  readonly isEmpty: boolean;
-  readonly isCustom: boolean;
-  readonly asCustom: Vec<u32>;
-  readonly type: 'All' | 'Empty' | 'Custom';
-}
-
-/** @name RmrkTraitsPartFixedPart */
-export interface RmrkTraitsPartFixedPart extends Struct {
-  readonly id: u32;
-  readonly z: u32;
-  readonly src: Bytes;
-}
-
-/** @name RmrkTraitsPartPartType */
-export interface RmrkTraitsPartPartType extends Enum {
-  readonly isFixedPart: boolean;
-  readonly asFixedPart: RmrkTraitsPartFixedPart;
-  readonly isSlotPart: boolean;
-  readonly asSlotPart: RmrkTraitsPartSlotPart;
-  readonly type: 'FixedPart' | 'SlotPart';
-}
-
-/** @name RmrkTraitsPartSlotPart */
-export interface RmrkTraitsPartSlotPart extends Struct {
-  readonly id: u32;
-  readonly equippable: RmrkTraitsPartEquippableList;
-  readonly src: Bytes;
-  readonly z: u32;
-}
-
-/** @name RmrkTraitsPropertyPropertyInfo */
-export interface RmrkTraitsPropertyPropertyInfo extends Struct {
-  readonly key: Bytes;
-  readonly value: Bytes;
-}
-
-/** @name RmrkTraitsResourceBasicResource */
-export interface RmrkTraitsResourceBasicResource extends Struct {
-  readonly src: Option<Bytes>;
-  readonly metadata: Option<Bytes>;
-  readonly license: Option<Bytes>;
-  readonly thumb: Option<Bytes>;
-}
-
-/** @name RmrkTraitsResourceComposableResource */
-export interface RmrkTraitsResourceComposableResource extends Struct {
-  readonly parts: Vec<u32>;
-  readonly base: u32;
-  readonly src: Option<Bytes>;
-  readonly metadata: Option<Bytes>;
-  readonly license: Option<Bytes>;
-  readonly thumb: Option<Bytes>;
-}
-
-/** @name RmrkTraitsResourceResourceInfo */
-export interface RmrkTraitsResourceResourceInfo extends Struct {
-  readonly id: u32;
-  readonly resource: RmrkTraitsResourceResourceTypes;
-  readonly pending: bool;
-  readonly pendingRemoval: bool;
-}
-
-/** @name RmrkTraitsResourceResourceTypes */
-export interface RmrkTraitsResourceResourceTypes extends Enum {
-  readonly isBasic: boolean;
-  readonly asBasic: RmrkTraitsResourceBasicResource;
-  readonly isComposable: boolean;
-  readonly asComposable: RmrkTraitsResourceComposableResource;
-  readonly isSlot: boolean;
-  readonly asSlot: RmrkTraitsResourceSlotResource;
-  readonly type: 'Basic' | 'Composable' | 'Slot';
-}
-
-/** @name RmrkTraitsResourceSlotResource */
-export interface RmrkTraitsResourceSlotResource extends Struct {
-  readonly base: u32;
-  readonly src: Option<Bytes>;
-  readonly metadata: Option<Bytes>;
-  readonly slot: u32;
-  readonly license: Option<Bytes>;
-  readonly thumb: Option<Bytes>;
-}
-
-/** @name RmrkTraitsTheme */
-export interface RmrkTraitsTheme extends Struct {
-  readonly name: Bytes;
-  readonly properties: Vec<RmrkTraitsThemeThemeProperty>;
-  readonly inherit: bool;
-}
-
-/** @name RmrkTraitsThemeThemeProperty */
-export interface RmrkTraitsThemeThemeProperty extends Struct {
-  readonly key: Bytes;
-  readonly value: Bytes;
-}
+/** @name SpCoreCryptoKeyTypeId */
+export interface SpCoreCryptoKeyTypeId extends U8aFixed {}
 
 /** @name SpCoreEcdsaSignature */
 export interface SpCoreEcdsaSignature extends U8aFixed {}
@@ -2701,16 +2757,14 @@
 /** @name SpCoreEd25519Signature */
 export interface SpCoreEd25519Signature extends U8aFixed {}
 
+/** @name SpCoreSr25519Public */
+export interface SpCoreSr25519Public extends U8aFixed {}
+
 /** @name SpCoreSr25519Signature */
 export interface SpCoreSr25519Signature extends U8aFixed {}
 
-/** @name SpRuntimeArithmeticError */
-export interface SpRuntimeArithmeticError extends Enum {
-  readonly isUnderflow: boolean;
-  readonly isOverflow: boolean;
-  readonly isDivisionByZero: boolean;
-  readonly type: 'Underflow' | 'Overflow' | 'DivisionByZero';
-}
+/** @name SpRuntimeBlakeTwo256 */
+export interface SpRuntimeBlakeTwo256 extends Null {}
 
 /** @name SpRuntimeDigest */
 export interface SpRuntimeDigest extends Struct {
@@ -2744,7 +2798,7 @@
   readonly isToken: boolean;
   readonly asToken: SpRuntimeTokenError;
   readonly isArithmetic: boolean;
-  readonly asArithmetic: SpRuntimeArithmeticError;
+  readonly asArithmetic: SpArithmeticArithmeticError;
   readonly isTransactional: boolean;
   readonly asTransactional: SpRuntimeTransactionalError;
   readonly isExhausted: boolean;
@@ -2753,6 +2807,15 @@
   readonly type: 'Other' | 'CannotLookup' | 'BadOrigin' | 'Module' | 'ConsumerRemaining' | 'NoProviders' | 'TooManyConsumers' | 'Token' | 'Arithmetic' | 'Transactional' | 'Exhausted' | 'Corruption' | 'Unavailable';
 }
 
+/** @name SpRuntimeHeader */
+export interface SpRuntimeHeader extends Struct {
+  readonly parentHash: H256;
+  readonly number: Compact<u32>;
+  readonly stateRoot: H256;
+  readonly extrinsicsRoot: H256;
+  readonly digest: SpRuntimeDigest;
+}
+
 /** @name SpRuntimeModuleError */
 export interface SpRuntimeModuleError extends Struct {
   readonly index: u8;
@@ -3160,7 +3223,10 @@
   readonly isTechnical: boolean;
   readonly isLegislative: boolean;
   readonly isJudicial: boolean;
-  readonly type: 'Unit' | 'Named' | 'Index' | 'Executive' | 'Technical' | 'Legislative' | 'Judicial';
+  readonly isDefense: boolean;
+  readonly isAdministration: boolean;
+  readonly isTreasury: boolean;
+  readonly type: 'Unit' | 'Named' | 'Index' | 'Executive' | 'Technical' | 'Legislative' | 'Judicial' | 'Defense' | 'Administration' | 'Treasury';
 }
 
 /** @name XcmV0JunctionBodyPart */
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -129,7 +129,7 @@
       NoProviders: 'Null',
       TooManyConsumers: 'Null',
       Token: 'SpRuntimeTokenError',
-      Arithmetic: 'SpRuntimeArithmeticError',
+      Arithmetic: 'SpArithmeticArithmeticError',
       Transactional: 'SpRuntimeTransactionalError',
       Exhausted: 'Null',
       Corruption: 'Null',
@@ -150,9 +150,9 @@
     _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']
   },
   /**
-   * Lookup27: sp_runtime::ArithmeticError
+   * Lookup27: sp_arithmetic::ArithmeticError
    **/
-  SpRuntimeArithmeticError: {
+  SpArithmeticArithmeticError: {
     _enum: ['Underflow', 'Overflow', 'DivisionByZero']
   },
   /**
@@ -184,7 +184,44 @@
     }
   },
   /**
-   * Lookup30: pallet_balances::pallet::Event<T, I>
+   * Lookup30: pallet_collator_selection::pallet::Event<T>
+   **/
+  PalletCollatorSelectionEvent: {
+    _enum: {
+      InvulnerableAdded: {
+        invulnerable: 'AccountId32',
+      },
+      InvulnerableRemoved: {
+        invulnerable: 'AccountId32',
+      },
+      LicenseObtained: {
+        accountId: 'AccountId32',
+        deposit: 'u128',
+      },
+      LicenseReleased: {
+        accountId: 'AccountId32',
+        depositReturned: 'u128',
+      },
+      CandidateAdded: {
+        accountId: 'AccountId32',
+      },
+      CandidateRemoved: {
+        accountId: 'AccountId32'
+      }
+    }
+  },
+  /**
+   * Lookup31: pallet_session::pallet::Event
+   **/
+  PalletSessionEvent: {
+    _enum: {
+      NewSession: {
+        sessionIndex: 'u32'
+      }
+    }
+  },
+  /**
+   * Lookup32: pallet_balances::pallet::Event<T, I>
    **/
   PalletBalancesEvent: {
     _enum: {
@@ -235,13 +272,13 @@
     }
   },
   /**
-   * Lookup31: frame_support::traits::tokens::misc::BalanceStatus
+   * Lookup33: frame_support::traits::tokens::misc::BalanceStatus
    **/
   FrameSupportTokensMiscBalanceStatus: {
     _enum: ['Free', 'Reserved']
   },
   /**
-   * Lookup32: pallet_transaction_payment::pallet::Event<T>
+   * Lookup34: pallet_transaction_payment::pallet::Event<T>
    **/
   PalletTransactionPaymentEvent: {
     _enum: {
@@ -253,7 +290,7 @@
     }
   },
   /**
-   * Lookup33: pallet_treasury::pallet::Event<T, I>
+   * Lookup35: pallet_treasury::pallet::Event<T, I>
    **/
   PalletTreasuryEvent: {
     _enum: {
@@ -284,12 +321,16 @@
       SpendApproved: {
         proposalIndex: 'u32',
         amount: 'u128',
-        beneficiary: 'AccountId32'
+        beneficiary: 'AccountId32',
+      },
+      UpdatedInactive: {
+        reactivated: 'u128',
+        deactivated: 'u128'
       }
     }
   },
   /**
-   * Lookup34: pallet_sudo::pallet::Event<T>
+   * Lookup36: pallet_sudo::pallet::Event<T>
    **/
   PalletSudoEvent: {
     _enum: {
@@ -305,7 +346,7 @@
     }
   },
   /**
-   * Lookup38: orml_vesting::module::Event<T>
+   * Lookup40: orml_vesting::module::Event<T>
    **/
   OrmlVestingModuleEvent: {
     _enum: {
@@ -324,7 +365,7 @@
     }
   },
   /**
-   * Lookup39: orml_vesting::VestingSchedule<BlockNumber, Balance>
+   * Lookup41: orml_vesting::VestingSchedule<BlockNumber, Balance>
    **/
   OrmlVestingVestingSchedule: {
     start: 'u32',
@@ -333,7 +374,7 @@
     perPeriod: 'Compact<u128>'
   },
   /**
-   * Lookup41: orml_xtokens::module::Event<T>
+   * Lookup43: orml_xtokens::module::Event<T>
    **/
   OrmlXtokensModuleEvent: {
     _enum: {
@@ -346,18 +387,18 @@
     }
   },
   /**
-   * Lookup42: xcm::v1::multiasset::MultiAssets
+   * Lookup44: xcm::v1::multiasset::MultiAssets
    **/
   XcmV1MultiassetMultiAssets: 'Vec<XcmV1MultiAsset>',
   /**
-   * Lookup44: xcm::v1::multiasset::MultiAsset
+   * Lookup46: xcm::v1::multiasset::MultiAsset
    **/
   XcmV1MultiAsset: {
     id: 'XcmV1MultiassetAssetId',
     fun: 'XcmV1MultiassetFungibility'
   },
   /**
-   * Lookup45: xcm::v1::multiasset::AssetId
+   * Lookup47: xcm::v1::multiasset::AssetId
    **/
   XcmV1MultiassetAssetId: {
     _enum: {
@@ -366,14 +407,14 @@
     }
   },
   /**
-   * Lookup46: xcm::v1::multilocation::MultiLocation
+   * Lookup48: xcm::v1::multilocation::MultiLocation
    **/
   XcmV1MultiLocation: {
     parents: 'u8',
     interior: 'XcmV1MultilocationJunctions'
   },
   /**
-   * Lookup47: xcm::v1::multilocation::Junctions
+   * Lookup49: xcm::v1::multilocation::Junctions
    **/
   XcmV1MultilocationJunctions: {
     _enum: {
@@ -389,7 +430,7 @@
     }
   },
   /**
-   * Lookup48: xcm::v1::junction::Junction
+   * Lookup50: xcm::v1::junction::Junction
    **/
   XcmV1Junction: {
     _enum: {
@@ -417,7 +458,7 @@
     }
   },
   /**
-   * Lookup50: xcm::v0::junction::NetworkId
+   * Lookup52: xcm::v0::junction::NetworkId
    **/
   XcmV0JunctionNetworkId: {
     _enum: {
@@ -428,7 +469,7 @@
     }
   },
   /**
-   * Lookup53: xcm::v0::junction::BodyId
+   * Lookup55: xcm::v0::junction::BodyId
    **/
   XcmV0JunctionBodyId: {
     _enum: {
@@ -438,11 +479,14 @@
       Executive: 'Null',
       Technical: 'Null',
       Legislative: 'Null',
-      Judicial: 'Null'
+      Judicial: 'Null',
+      Defense: 'Null',
+      Administration: 'Null',
+      Treasury: 'Null'
     }
   },
   /**
-   * Lookup54: xcm::v0::junction::BodyPart
+   * Lookup56: xcm::v0::junction::BodyPart
    **/
   XcmV0JunctionBodyPart: {
     _enum: {
@@ -465,7 +509,7 @@
     }
   },
   /**
-   * Lookup55: xcm::v1::multiasset::Fungibility
+   * Lookup57: xcm::v1::multiasset::Fungibility
    **/
   XcmV1MultiassetFungibility: {
     _enum: {
@@ -474,7 +518,7 @@
     }
   },
   /**
-   * Lookup56: xcm::v1::multiasset::AssetInstance
+   * Lookup58: xcm::v1::multiasset::AssetInstance
    **/
   XcmV1MultiassetAssetInstance: {
     _enum: {
@@ -488,7 +532,7 @@
     }
   },
   /**
-   * Lookup59: orml_tokens::module::Event<T>
+   * Lookup61: orml_tokens::module::Event<T>
    **/
   OrmlTokensModuleEvent: {
     _enum: {
@@ -565,7 +609,7 @@
     }
   },
   /**
-   * Lookup60: pallet_foreign_assets::AssetIds
+   * Lookup62: pallet_foreign_assets::AssetIds
    **/
   PalletForeignAssetsAssetIds: {
     _enum: {
@@ -574,14 +618,96 @@
     }
   },
   /**
-   * Lookup61: pallet_foreign_assets::NativeCurrency
+   * Lookup63: pallet_foreign_assets::NativeCurrency
    **/
   PalletForeignAssetsNativeCurrency: {
     _enum: ['Here', 'Parent']
   },
   /**
-   * Lookup62: cumulus_pallet_xcmp_queue::pallet::Event<T>
+   * Lookup64: pallet_identity::pallet::Event<T>
    **/
+  PalletIdentityEvent: {
+    _enum: {
+      IdentitySet: {
+        who: 'AccountId32',
+      },
+      IdentityCleared: {
+        who: 'AccountId32',
+        deposit: 'u128',
+      },
+      IdentityKilled: {
+        who: 'AccountId32',
+        deposit: 'u128',
+      },
+      IdentitiesInserted: {
+        amount: 'u32',
+      },
+      IdentitiesRemoved: {
+        amount: 'u32',
+      },
+      JudgementRequested: {
+        who: 'AccountId32',
+        registrarIndex: 'u32',
+      },
+      JudgementUnrequested: {
+        who: 'AccountId32',
+        registrarIndex: 'u32',
+      },
+      JudgementGiven: {
+        target: 'AccountId32',
+        registrarIndex: 'u32',
+      },
+      RegistrarAdded: {
+        registrarIndex: 'u32',
+      },
+      SubIdentityAdded: {
+        sub: 'AccountId32',
+        main: 'AccountId32',
+        deposit: 'u128',
+      },
+      SubIdentityRemoved: {
+        sub: 'AccountId32',
+        main: 'AccountId32',
+        deposit: 'u128',
+      },
+      SubIdentityRevoked: {
+        sub: 'AccountId32',
+        main: 'AccountId32',
+        deposit: 'u128',
+      },
+      SubIdentitiesInserted: {
+        amount: 'u32'
+      }
+    }
+  },
+  /**
+   * Lookup65: pallet_preimage::pallet::Event<T>
+   **/
+  PalletPreimageEvent: {
+    _enum: {
+      Noted: {
+        _alias: {
+          hash_: 'hash',
+        },
+        hash_: 'H256',
+      },
+      Requested: {
+        _alias: {
+          hash_: 'hash',
+        },
+        hash_: 'H256',
+      },
+      Cleared: {
+        _alias: {
+          hash_: 'hash',
+        },
+        hash_: 'H256'
+      }
+    }
+  },
+  /**
+   * Lookup66: cumulus_pallet_xcmp_queue::pallet::Event<T>
+   **/
   CumulusPalletXcmpQueueEvent: {
     _enum: {
       Success: {
@@ -618,7 +744,7 @@
     }
   },
   /**
-   * Lookup64: xcm::v2::traits::Error
+   * Lookup68: xcm::v2::traits::Error
    **/
   XcmV2TraitsError: {
     _enum: {
@@ -651,7 +777,7 @@
     }
   },
   /**
-   * Lookup66: pallet_xcm::pallet::Event<T>
+   * Lookup70: pallet_xcm::pallet::Event<T>
    **/
   PalletXcmEvent: {
     _enum: {
@@ -675,7 +801,7 @@
     }
   },
   /**
-   * Lookup67: xcm::v2::traits::Outcome
+   * Lookup71: xcm::v2::traits::Outcome
    **/
   XcmV2TraitsOutcome: {
     _enum: {
@@ -685,11 +811,11 @@
     }
   },
   /**
-   * Lookup68: xcm::v2::Xcm<RuntimeCall>
+   * Lookup72: xcm::v2::Xcm<RuntimeCall>
    **/
   XcmV2Xcm: 'Vec<XcmV2Instruction>',
   /**
-   * Lookup70: xcm::v2::Instruction<RuntimeCall>
+   * Lookup74: xcm::v2::Instruction<RuntimeCall>
    **/
   XcmV2Instruction: {
     _enum: {
@@ -787,7 +913,7 @@
     }
   },
   /**
-   * Lookup71: xcm::v2::Response
+   * Lookup75: xcm::v2::Response
    **/
   XcmV2Response: {
     _enum: {
@@ -798,19 +924,19 @@
     }
   },
   /**
-   * Lookup74: xcm::v0::OriginKind
+   * Lookup78: xcm::v0::OriginKind
    **/
   XcmV0OriginKind: {
     _enum: ['Native', 'SovereignAccount', 'Superuser', 'Xcm']
   },
   /**
-   * Lookup75: xcm::double_encoded::DoubleEncoded<T>
+   * Lookup79: xcm::double_encoded::DoubleEncoded<T>
    **/
   XcmDoubleEncoded: {
     encoded: 'Bytes'
   },
   /**
-   * Lookup76: xcm::v1::multiasset::MultiAssetFilter
+   * Lookup80: xcm::v1::multiasset::MultiAssetFilter
    **/
   XcmV1MultiassetMultiAssetFilter: {
     _enum: {
@@ -819,7 +945,7 @@
     }
   },
   /**
-   * Lookup77: xcm::v1::multiasset::WildMultiAsset
+   * Lookup81: xcm::v1::multiasset::WildMultiAsset
    **/
   XcmV1MultiassetWildMultiAsset: {
     _enum: {
@@ -831,13 +957,13 @@
     }
   },
   /**
-   * Lookup78: xcm::v1::multiasset::WildFungibility
+   * Lookup82: xcm::v1::multiasset::WildFungibility
    **/
   XcmV1MultiassetWildFungibility: {
     _enum: ['Fungible', 'NonFungible']
   },
   /**
-   * Lookup79: xcm::v2::WeightLimit
+   * Lookup83: xcm::v2::WeightLimit
    **/
   XcmV2WeightLimit: {
     _enum: {
@@ -846,7 +972,7 @@
     }
   },
   /**
-   * Lookup81: xcm::VersionedMultiAssets
+   * Lookup85: xcm::VersionedMultiAssets
    **/
   XcmVersionedMultiAssets: {
     _enum: {
@@ -855,7 +981,7 @@
     }
   },
   /**
-   * Lookup83: xcm::v0::multi_asset::MultiAsset
+   * Lookup87: xcm::v0::multi_asset::MultiAsset
    **/
   XcmV0MultiAsset: {
     _enum: {
@@ -894,7 +1020,7 @@
     }
   },
   /**
-   * Lookup84: xcm::v0::multi_location::MultiLocation
+   * Lookup88: xcm::v0::multi_location::MultiLocation
    **/
   XcmV0MultiLocation: {
     _enum: {
@@ -910,7 +1036,7 @@
     }
   },
   /**
-   * Lookup85: xcm::v0::junction::Junction
+   * Lookup89: xcm::v0::junction::Junction
    **/
   XcmV0Junction: {
     _enum: {
@@ -939,7 +1065,7 @@
     }
   },
   /**
-   * Lookup86: xcm::VersionedMultiLocation
+   * Lookup90: xcm::VersionedMultiLocation
    **/
   XcmVersionedMultiLocation: {
     _enum: {
@@ -948,7 +1074,7 @@
     }
   },
   /**
-   * Lookup87: cumulus_pallet_xcm::pallet::Event<T>
+   * Lookup91: cumulus_pallet_xcm::pallet::Event<T>
    **/
   CumulusPalletXcmEvent: {
     _enum: {
@@ -958,7 +1084,7 @@
     }
   },
   /**
-   * Lookup88: cumulus_pallet_dmp_queue::pallet::Event<T>
+   * Lookup92: cumulus_pallet_dmp_queue::pallet::Event<T>
    **/
   CumulusPalletDmpQueueEvent: {
     _enum: {
@@ -989,7 +1115,7 @@
     }
   },
   /**
-   * Lookup89: pallet_configuration::pallet::Event<T>
+   * Lookup93: pallet_configuration::pallet::Event<T>
    **/
   PalletConfigurationEvent: {
     _enum: {
@@ -1005,7 +1131,7 @@
     }
   },
   /**
-   * Lookup92: pallet_common::pallet::Event<T>
+   * Lookup96: pallet_common::pallet::Event<T>
    **/
   PalletCommonEvent: {
     _enum: {
@@ -1034,7 +1160,7 @@
     }
   },
   /**
-   * Lookup95: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
+   * Lookup99: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
    **/
   PalletEvmAccountBasicCrossAccountIdRepr: {
     _enum: {
@@ -1043,116 +1169,15 @@
     }
   },
   /**
-   * Lookup99: pallet_structure::pallet::Event<T>
+   * Lookup103: pallet_structure::pallet::Event<T>
    **/
   PalletStructureEvent: {
     _enum: {
       Executed: 'Result<Null, SpRuntimeDispatchError>'
-    }
-  },
-  /**
-   * Lookup100: pallet_rmrk_core::pallet::Event<T>
-   **/
-  PalletRmrkCoreEvent: {
-    _enum: {
-      CollectionCreated: {
-        issuer: 'AccountId32',
-        collectionId: 'u32',
-      },
-      CollectionDestroyed: {
-        issuer: 'AccountId32',
-        collectionId: 'u32',
-      },
-      IssuerChanged: {
-        oldIssuer: 'AccountId32',
-        newIssuer: 'AccountId32',
-        collectionId: 'u32',
-      },
-      CollectionLocked: {
-        issuer: 'AccountId32',
-        collectionId: 'u32',
-      },
-      NftMinted: {
-        owner: 'AccountId32',
-        collectionId: 'u32',
-        nftId: 'u32',
-      },
-      NFTBurned: {
-        owner: 'AccountId32',
-        nftId: 'u32',
-      },
-      NFTSent: {
-        sender: 'AccountId32',
-        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
-        collectionId: 'u32',
-        nftId: 'u32',
-        approvalRequired: 'bool',
-      },
-      NFTAccepted: {
-        sender: 'AccountId32',
-        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
-        collectionId: 'u32',
-        nftId: 'u32',
-      },
-      NFTRejected: {
-        sender: 'AccountId32',
-        collectionId: 'u32',
-        nftId: 'u32',
-      },
-      PropertySet: {
-        collectionId: 'u32',
-        maybeNftId: 'Option<u32>',
-        key: 'Bytes',
-        value: 'Bytes',
-      },
-      ResourceAdded: {
-        nftId: 'u32',
-        resourceId: 'u32',
-      },
-      ResourceRemoval: {
-        nftId: 'u32',
-        resourceId: 'u32',
-      },
-      ResourceAccepted: {
-        nftId: 'u32',
-        resourceId: 'u32',
-      },
-      ResourceRemovalAccepted: {
-        nftId: 'u32',
-        resourceId: 'u32',
-      },
-      PrioritySet: {
-        collectionId: 'u32',
-        nftId: 'u32'
-      }
     }
   },
   /**
-   * Lookup101: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
-   **/
-  RmrkTraitsNftAccountIdOrCollectionNftTuple: {
-    _enum: {
-      AccountId: 'AccountId32',
-      CollectionAndNftTuple: '(u32,u32)'
-    }
-  },
-  /**
-   * Lookup104: pallet_rmrk_equip::pallet::Event<T>
-   **/
-  PalletRmrkEquipEvent: {
-    _enum: {
-      BaseCreated: {
-        issuer: 'AccountId32',
-        baseId: 'u32',
-      },
-      EquippablesUpdated: {
-        baseId: 'u32',
-        slotId: 'u32'
-      }
-    }
-  },
-  /**
-   * Lookup105: pallet_app_promotion::pallet::Event<T>
+   * Lookup104: pallet_app_promotion::pallet::Event<T>
    **/
   PalletAppPromotionEvent: {
     _enum: {
@@ -1163,7 +1188,7 @@
     }
   },
   /**
-   * Lookup106: pallet_foreign_assets::module::Event<T>
+   * Lookup105: pallet_foreign_assets::module::Event<T>
    **/
   PalletForeignAssetsModuleEvent: {
     _enum: {
@@ -1188,7 +1213,7 @@
     }
   },
   /**
-   * Lookup107: pallet_foreign_assets::module::AssetMetadata<Balance>
+   * Lookup106: pallet_foreign_assets::module::AssetMetadata<Balance>
    **/
   PalletForeignAssetsModuleAssetMetadata: {
     name: 'Bytes',
@@ -1197,7 +1222,7 @@
     minimalBalance: 'u128'
   },
   /**
-   * Lookup108: pallet_evm::pallet::Event<T>
+   * Lookup107: pallet_evm::pallet::Event<T>
    **/
   PalletEvmEvent: {
     _enum: {
@@ -1219,7 +1244,7 @@
     }
   },
   /**
-   * Lookup109: ethereum::log::Log
+   * Lookup108: ethereum::log::Log
    **/
   EthereumLog: {
     address: 'H160',
@@ -1227,7 +1252,7 @@
     data: 'Bytes'
   },
   /**
-   * Lookup111: pallet_ethereum::pallet::Event
+   * Lookup110: pallet_ethereum::pallet::Event
    **/
   PalletEthereumEvent: {
     _enum: {
@@ -1240,7 +1265,7 @@
     }
   },
   /**
-   * Lookup112: evm_core::error::ExitReason
+   * Lookup111: evm_core::error::ExitReason
    **/
   EvmCoreErrorExitReason: {
     _enum: {
@@ -1251,13 +1276,13 @@
     }
   },
   /**
-   * Lookup113: evm_core::error::ExitSucceed
+   * Lookup112: evm_core::error::ExitSucceed
    **/
   EvmCoreErrorExitSucceed: {
     _enum: ['Stopped', 'Returned', 'Suicided']
   },
   /**
-   * Lookup114: evm_core::error::ExitError
+   * Lookup113: evm_core::error::ExitError
    **/
   EvmCoreErrorExitError: {
     _enum: {
@@ -1275,7 +1300,8 @@
       PCUnderflow: 'Null',
       CreateEmpty: 'Null',
       Other: 'Text',
-      InvalidCode: 'Null'
+      __Unused14: 'Null',
+      InvalidCode: 'u8'
     }
   },
   /**
@@ -1551,28 +1577,135 @@
     _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']
   },
   /**
-   * Lookup172: pallet_balances::BalanceLock<Balance>
+   * Lookup172: pallet_authorship::UncleEntryItem<BlockNumber, primitive_types::H256, sp_core::crypto::AccountId32>
+   **/
+  PalletAuthorshipUncleEntryItem: {
+    _enum: {
+      InclusionHeight: 'u32',
+      Uncle: '(H256,Option<AccountId32>)'
+    }
+  },
+  /**
+   * Lookup174: pallet_authorship::pallet::Call<T>
+   **/
+  PalletAuthorshipCall: {
+    _enum: {
+      set_uncles: {
+        newUncles: 'Vec<SpRuntimeHeader>'
+      }
+    }
+  },
+  /**
+   * Lookup176: sp_runtime::generic::header::Header<Number, sp_runtime::traits::BlakeTwo256>
+   **/
+  SpRuntimeHeader: {
+    parentHash: 'H256',
+    number: 'Compact<u32>',
+    stateRoot: 'H256',
+    extrinsicsRoot: 'H256',
+    digest: 'SpRuntimeDigest'
+  },
+  /**
+   * Lookup177: sp_runtime::traits::BlakeTwo256
+   **/
+  SpRuntimeBlakeTwo256: 'Null',
+  /**
+   * Lookup178: pallet_authorship::pallet::Error<T>
+   **/
+  PalletAuthorshipError: {
+    _enum: ['InvalidUncleParent', 'UnclesAlreadySet', 'TooManyUncles', 'GenesisUncle', 'TooHighUncle', 'UncleAlreadyIncluded', 'OldUncle']
+  },
+  /**
+   * Lookup181: pallet_collator_selection::pallet::Call<T>
    **/
+  PalletCollatorSelectionCall: {
+    _enum: {
+      add_invulnerable: {
+        _alias: {
+          new_: 'new',
+        },
+        new_: 'AccountId32',
+      },
+      remove_invulnerable: {
+        who: 'AccountId32',
+      },
+      get_license: 'Null',
+      onboard: 'Null',
+      offboard: 'Null',
+      release_license: 'Null',
+      force_release_license: {
+        who: 'AccountId32'
+      }
+    }
+  },
+  /**
+   * Lookup182: pallet_collator_selection::pallet::Error<T>
+   **/
+  PalletCollatorSelectionError: {
+    _enum: ['TooManyCandidates', 'Unknown', 'Permission', 'AlreadyHoldingLicense', 'NoLicense', 'AlreadyCandidate', 'NotCandidate', 'TooManyInvulnerables', 'TooFewInvulnerables', 'AlreadyInvulnerable', 'NotInvulnerable', 'NoAssociatedValidatorId', 'ValidatorNotRegistered']
+  },
+  /**
+   * Lookup185: opal_runtime::runtime_common::SessionKeys
+   **/
+  OpalRuntimeRuntimeCommonSessionKeys: {
+    aura: 'SpConsensusAuraSr25519AppSr25519Public'
+  },
+  /**
+   * Lookup186: sp_consensus_aura::sr25519::app_sr25519::Public
+   **/
+  SpConsensusAuraSr25519AppSr25519Public: 'SpCoreSr25519Public',
+  /**
+   * Lookup187: sp_core::sr25519::Public
+   **/
+  SpCoreSr25519Public: '[u8;32]',
+  /**
+   * Lookup190: sp_core::crypto::KeyTypeId
+   **/
+  SpCoreCryptoKeyTypeId: '[u8;4]',
+  /**
+   * Lookup191: pallet_session::pallet::Call<T>
+   **/
+  PalletSessionCall: {
+    _enum: {
+      set_keys: {
+        _alias: {
+          keys_: 'keys',
+        },
+        keys_: 'OpalRuntimeRuntimeCommonSessionKeys',
+        proof: 'Bytes',
+      },
+      purge_keys: 'Null'
+    }
+  },
+  /**
+   * Lookup192: pallet_session::pallet::Error<T>
+   **/
+  PalletSessionError: {
+    _enum: ['InvalidProof', 'NoAssociatedValidatorId', 'DuplicatedKey', 'NoKeys', 'NoAccount']
+  },
+  /**
+   * Lookup194: pallet_balances::BalanceLock<Balance>
+   **/
   PalletBalancesBalanceLock: {
     id: '[u8;8]',
     amount: 'u128',
     reasons: 'PalletBalancesReasons'
   },
   /**
-   * Lookup173: pallet_balances::Reasons
+   * Lookup195: pallet_balances::Reasons
    **/
   PalletBalancesReasons: {
     _enum: ['Fee', 'Misc', 'All']
   },
   /**
-   * Lookup176: pallet_balances::ReserveData<ReserveIdentifier, Balance>
+   * Lookup198: pallet_balances::ReserveData<ReserveIdentifier, Balance>
    **/
   PalletBalancesReserveData: {
     id: '[u8;16]',
     amount: 'u128'
   },
   /**
-   * Lookup178: pallet_balances::pallet::Call<T, I>
+   * Lookup200: pallet_balances::pallet::Call<T, I>
    **/
   PalletBalancesCall: {
     _enum: {
@@ -1605,13 +1738,13 @@
     }
   },
   /**
-   * Lookup181: pallet_balances::pallet::Error<T, I>
+   * Lookup203: pallet_balances::pallet::Error<T, I>
    **/
   PalletBalancesError: {
     _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']
   },
   /**
-   * Lookup183: pallet_timestamp::pallet::Call<T>
+   * Lookup205: pallet_timestamp::pallet::Call<T>
    **/
   PalletTimestampCall: {
     _enum: {
@@ -1621,13 +1754,13 @@
     }
   },
   /**
-   * Lookup185: pallet_transaction_payment::Releases
+   * Lookup207: pallet_transaction_payment::Releases
    **/
   PalletTransactionPaymentReleases: {
     _enum: ['V1Ancient', 'V2']
   },
   /**
-   * Lookup186: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>
+   * Lookup208: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>
    **/
   PalletTreasuryProposal: {
     proposer: 'AccountId32',
@@ -1636,7 +1769,7 @@
     bond: 'u128'
   },
   /**
-   * Lookup189: pallet_treasury::pallet::Call<T, I>
+   * Lookup210: pallet_treasury::pallet::Call<T, I>
    **/
   PalletTreasuryCall: {
     _enum: {
@@ -1660,17 +1793,17 @@
     }
   },
   /**
-   * Lookup191: frame_support::PalletId
+   * Lookup212: frame_support::PalletId
    **/
   FrameSupportPalletId: '[u8;8]',
   /**
-   * Lookup192: pallet_treasury::pallet::Error<T, I>
+   * Lookup213: pallet_treasury::pallet::Error<T, I>
    **/
   PalletTreasuryError: {
     _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved']
   },
   /**
-   * Lookup193: pallet_sudo::pallet::Call<T>
+   * Lookup214: pallet_sudo::pallet::Call<T>
    **/
   PalletSudoCall: {
     _enum: {
@@ -1694,7 +1827,7 @@
     }
   },
   /**
-   * Lookup195: orml_vesting::module::Call<T>
+   * Lookup216: orml_vesting::module::Call<T>
    **/
   OrmlVestingModuleCall: {
     _enum: {
@@ -1713,7 +1846,7 @@
     }
   },
   /**
-   * Lookup197: orml_xtokens::module::Call<T>
+   * Lookup218: orml_xtokens::module::Call<T>
    **/
   OrmlXtokensModuleCall: {
     _enum: {
@@ -1756,7 +1889,7 @@
     }
   },
   /**
-   * Lookup198: xcm::VersionedMultiAsset
+   * Lookup219: xcm::VersionedMultiAsset
    **/
   XcmVersionedMultiAsset: {
     _enum: {
@@ -1765,7 +1898,7 @@
     }
   },
   /**
-   * Lookup201: orml_tokens::module::Call<T>
+   * Lookup222: orml_tokens::module::Call<T>
    **/
   OrmlTokensModuleCall: {
     _enum: {
@@ -1799,7 +1932,160 @@
     }
   },
   /**
-   * Lookup202: cumulus_pallet_xcmp_queue::pallet::Call<T>
+   * Lookup223: pallet_identity::pallet::Call<T>
+   **/
+  PalletIdentityCall: {
+    _enum: {
+      add_registrar: {
+        account: 'MultiAddress',
+      },
+      set_identity: {
+        info: 'PalletIdentityIdentityInfo',
+      },
+      set_subs: {
+        subs: 'Vec<(AccountId32,Data)>',
+      },
+      clear_identity: 'Null',
+      request_judgement: {
+        regIndex: 'Compact<u32>',
+        maxFee: 'Compact<u128>',
+      },
+      cancel_request: {
+        regIndex: 'u32',
+      },
+      set_fee: {
+        index: 'Compact<u32>',
+        fee: 'Compact<u128>',
+      },
+      set_account_id: {
+        _alias: {
+          new_: 'new',
+        },
+        index: 'Compact<u32>',
+        new_: 'MultiAddress',
+      },
+      set_fields: {
+        index: 'Compact<u32>',
+        fields: 'PalletIdentityBitFlags',
+      },
+      provide_judgement: {
+        regIndex: 'Compact<u32>',
+        target: 'MultiAddress',
+        judgement: 'PalletIdentityJudgement',
+        identity: 'H256',
+      },
+      kill_identity: {
+        target: 'MultiAddress',
+      },
+      add_sub: {
+        sub: 'MultiAddress',
+        data: 'Data',
+      },
+      rename_sub: {
+        sub: 'MultiAddress',
+        data: 'Data',
+      },
+      remove_sub: {
+        sub: 'MultiAddress',
+      },
+      quit_sub: 'Null',
+      force_insert_identities: {
+        identities: 'Vec<(AccountId32,PalletIdentityRegistration)>',
+      },
+      force_remove_identities: {
+        identities: 'Vec<AccountId32>',
+      },
+      force_set_subs: {
+        subs: 'Vec<(AccountId32,(u128,Vec<(AccountId32,Data)>))>'
+      }
+    }
+  },
+  /**
+   * Lookup224: pallet_identity::types::IdentityInfo<FieldLimit>
+   **/
+  PalletIdentityIdentityInfo: {
+    additional: 'Vec<(Data,Data)>',
+    display: 'Data',
+    legal: 'Data',
+    web: 'Data',
+    riot: 'Data',
+    email: 'Data',
+    pgpFingerprint: 'Option<[u8;20]>',
+    image: 'Data',
+    twitter: 'Data'
+  },
+  /**
+   * Lookup260: pallet_identity::types::BitFlags<pallet_identity::types::IdentityField>
+   **/
+  PalletIdentityBitFlags: {
+    _bitLength: 64,
+    Display: 1,
+    Legal: 2,
+    Web: 4,
+    Riot: 8,
+    Email: 16,
+    PgpFingerprint: 32,
+    Image: 64,
+    Twitter: 128
+  },
+  /**
+   * Lookup261: pallet_identity::types::IdentityField
+   **/
+  PalletIdentityIdentityField: {
+    _enum: ['__Unused0', 'Display', 'Legal', '__Unused3', 'Web', '__Unused5', '__Unused6', '__Unused7', 'Riot', '__Unused9', '__Unused10', '__Unused11', '__Unused12', '__Unused13', '__Unused14', '__Unused15', 'Email', '__Unused17', '__Unused18', '__Unused19', '__Unused20', '__Unused21', '__Unused22', '__Unused23', '__Unused24', '__Unused25', '__Unused26', '__Unused27', '__Unused28', '__Unused29', '__Unused30', '__Unused31', 'PgpFingerprint', '__Unused33', '__Unused34', '__Unused35', '__Unused36', '__Unused37', '__Unused38', '__Unused39', '__Unused40', '__Unused41', '__Unused42', '__Unused43', '__Unused44', '__Unused45', '__Unused46', '__Unused47', '__Unused48', '__Unused49', '__Unused50', '__Unused51', '__Unused52', '__Unused53', '__Unused54', '__Unused55', '__Unused56', '__Unused57', '__Unused58', '__Unused59', '__Unused60', '__Unused61', '__Unused62', '__Unused63', 'Image', '__Unused65', '__Unused66', '__Unused67', '__Unused68', '__Unused69', '__Unused70', '__Unused71', '__Unused72', '__Unused73', '__Unused74', '__Unused75', '__Unused76', '__Unused77', '__Unused78', '__Unused79', '__Unused80', '__Unused81', '__Unused82', '__Unused83', '__Unused84', '__Unused85', '__Unused86', '__Unused87', '__Unused88', '__Unused89', '__Unused90', '__Unused91', '__Unused92', '__Unused93', '__Unused94', '__Unused95', '__Unused96', '__Unused97', '__Unused98', '__Unused99', '__Unused100', '__Unused101', '__Unused102', '__Unused103', '__Unused104', '__Unused105', '__Unused106', '__Unused107', '__Unused108', '__Unused109', '__Unused110', '__Unused111', '__Unused112', '__Unused113', '__Unused114', '__Unused115', '__Unused116', '__Unused117', '__Unused118', '__Unused119', '__Unused120', '__Unused121', '__Unused122', '__Unused123', '__Unused124', '__Unused125', '__Unused126', '__Unused127', 'Twitter']
+  },
+  /**
+   * Lookup262: pallet_identity::types::Judgement<Balance>
+   **/
+  PalletIdentityJudgement: {
+    _enum: {
+      Unknown: 'Null',
+      FeePaid: 'u128',
+      Reasonable: 'Null',
+      KnownGood: 'Null',
+      OutOfDate: 'Null',
+      LowQuality: 'Null',
+      Erroneous: 'Null'
+    }
+  },
+  /**
+   * Lookup265: pallet_identity::types::Registration<Balance, MaxJudgements, MaxAdditionalFields>
+   **/
+  PalletIdentityRegistration: {
+    judgements: 'Vec<(u32,PalletIdentityJudgement)>',
+    deposit: 'u128',
+    info: 'PalletIdentityIdentityInfo'
+  },
+  /**
+   * Lookup273: pallet_preimage::pallet::Call<T>
+   **/
+  PalletPreimageCall: {
+    _enum: {
+      note_preimage: {
+        bytes: 'Bytes',
+      },
+      unnote_preimage: {
+        _alias: {
+          hash_: 'hash',
+        },
+        hash_: 'H256',
+      },
+      request_preimage: {
+        _alias: {
+          hash_: 'hash',
+        },
+        hash_: 'H256',
+      },
+      unrequest_preimage: {
+        _alias: {
+          hash_: 'hash',
+        },
+        hash_: 'H256'
+      }
+    }
+  },
+  /**
+   * Lookup274: cumulus_pallet_xcmp_queue::pallet::Call<T>
    **/
   CumulusPalletXcmpQueueCall: {
     _enum: {
@@ -1848,7 +2134,7 @@
     }
   },
   /**
-   * Lookup203: pallet_xcm::pallet::Call<T>
+   * Lookup275: pallet_xcm::pallet::Call<T>
    **/
   PalletXcmCall: {
     _enum: {
@@ -1902,7 +2188,7 @@
     }
   },
   /**
-   * Lookup204: xcm::VersionedXcm<RuntimeCall>
+   * Lookup276: xcm::VersionedXcm<RuntimeCall>
    **/
   XcmVersionedXcm: {
     _enum: {
@@ -1912,7 +2198,7 @@
     }
   },
   /**
-   * Lookup205: xcm::v0::Xcm<RuntimeCall>
+   * Lookup277: xcm::v0::Xcm<RuntimeCall>
    **/
   XcmV0Xcm: {
     _enum: {
@@ -1966,7 +2252,7 @@
     }
   },
   /**
-   * Lookup207: xcm::v0::order::Order<RuntimeCall>
+   * Lookup279: xcm::v0::order::Order<RuntimeCall>
    **/
   XcmV0Order: {
     _enum: {
@@ -2009,7 +2295,7 @@
     }
   },
   /**
-   * Lookup209: xcm::v0::Response
+   * Lookup281: xcm::v0::Response
    **/
   XcmV0Response: {
     _enum: {
@@ -2017,7 +2303,7 @@
     }
   },
   /**
-   * Lookup210: xcm::v1::Xcm<RuntimeCall>
+   * Lookup282: xcm::v1::Xcm<RuntimeCall>
    **/
   XcmV1Xcm: {
     _enum: {
@@ -2076,7 +2362,7 @@
     }
   },
   /**
-   * Lookup212: xcm::v1::order::Order<RuntimeCall>
+   * Lookup284: xcm::v1::order::Order<RuntimeCall>
    **/
   XcmV1Order: {
     _enum: {
@@ -2121,7 +2407,7 @@
     }
   },
   /**
-   * Lookup214: xcm::v1::Response
+   * Lookup286: xcm::v1::Response
    **/
   XcmV1Response: {
     _enum: {
@@ -2130,11 +2416,11 @@
     }
   },
   /**
-   * Lookup228: cumulus_pallet_xcm::pallet::Call<T>
+   * Lookup300: cumulus_pallet_xcm::pallet::Call<T>
    **/
   CumulusPalletXcmCall: 'Null',
   /**
-   * Lookup229: cumulus_pallet_dmp_queue::pallet::Call<T>
+   * Lookup301: cumulus_pallet_dmp_queue::pallet::Call<T>
    **/
   CumulusPalletDmpQueueCall: {
     _enum: {
@@ -2145,7 +2431,7 @@
     }
   },
   /**
-   * Lookup230: pallet_inflation::pallet::Call<T>
+   * Lookup302: pallet_inflation::pallet::Call<T>
    **/
   PalletInflationCall: {
     _enum: {
@@ -2155,7 +2441,7 @@
     }
   },
   /**
-   * Lookup231: pallet_unique::Call<T>
+   * Lookup303: pallet_unique::Call<T>
    **/
   PalletUniqueCall: {
     _enum: {
@@ -2306,7 +2592,7 @@
     }
   },
   /**
-   * Lookup236: up_data_structs::CollectionMode
+   * Lookup308: up_data_structs::CollectionMode
    **/
   UpDataStructsCollectionMode: {
     _enum: {
@@ -2316,7 +2602,7 @@
     }
   },
   /**
-   * Lookup237: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>
+   * Lookup309: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>
    **/
   UpDataStructsCreateCollectionData: {
     mode: 'UpDataStructsCollectionMode',
@@ -2331,13 +2617,13 @@
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup239: up_data_structs::AccessMode
+   * Lookup311: up_data_structs::AccessMode
    **/
   UpDataStructsAccessMode: {
     _enum: ['Normal', 'AllowList']
   },
   /**
-   * Lookup241: up_data_structs::CollectionLimits
+   * Lookup313: up_data_structs::CollectionLimits
    **/
   UpDataStructsCollectionLimits: {
     accountTokenOwnershipLimit: 'Option<u32>',
@@ -2351,7 +2637,7 @@
     transfersEnabled: 'Option<bool>'
   },
   /**
-   * Lookup243: up_data_structs::SponsoringRateLimit
+   * Lookup315: up_data_structs::SponsoringRateLimit
    **/
   UpDataStructsSponsoringRateLimit: {
     _enum: {
@@ -2360,7 +2646,7 @@
     }
   },
   /**
-   * Lookup246: up_data_structs::CollectionPermissions
+   * Lookup318: up_data_structs::CollectionPermissions
    **/
   UpDataStructsCollectionPermissions: {
     access: 'Option<UpDataStructsAccessMode>',
@@ -2368,7 +2654,7 @@
     nesting: 'Option<UpDataStructsNestingPermissions>'
   },
   /**
-   * Lookup248: up_data_structs::NestingPermissions
+   * Lookup320: up_data_structs::NestingPermissions
    **/
   UpDataStructsNestingPermissions: {
     tokenOwner: 'bool',
@@ -2376,18 +2662,18 @@
     restricted: 'Option<UpDataStructsOwnerRestrictedSet>'
   },
   /**
-   * Lookup250: up_data_structs::OwnerRestrictedSet
+   * Lookup322: up_data_structs::OwnerRestrictedSet
    **/
   UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',
   /**
-   * Lookup255: up_data_structs::PropertyKeyPermission
+   * Lookup327: up_data_structs::PropertyKeyPermission
    **/
   UpDataStructsPropertyKeyPermission: {
     key: 'Bytes',
     permission: 'UpDataStructsPropertyPermission'
   },
   /**
-   * Lookup256: up_data_structs::PropertyPermission
+   * Lookup328: up_data_structs::PropertyPermission
    **/
   UpDataStructsPropertyPermission: {
     mutable: 'bool',
@@ -2395,14 +2681,14 @@
     tokenOwner: 'bool'
   },
   /**
-   * Lookup259: up_data_structs::Property
+   * Lookup331: up_data_structs::Property
    **/
   UpDataStructsProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup262: up_data_structs::CreateItemData
+   * Lookup334: up_data_structs::CreateItemData
    **/
   UpDataStructsCreateItemData: {
     _enum: {
@@ -2412,26 +2698,26 @@
     }
   },
   /**
-   * Lookup263: up_data_structs::CreateNftData
+   * Lookup335: up_data_structs::CreateNftData
    **/
   UpDataStructsCreateNftData: {
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup264: up_data_structs::CreateFungibleData
+   * Lookup336: up_data_structs::CreateFungibleData
    **/
   UpDataStructsCreateFungibleData: {
     value: 'u128'
   },
   /**
-   * Lookup265: up_data_structs::CreateReFungibleData
+   * Lookup337: up_data_structs::CreateReFungibleData
    **/
   UpDataStructsCreateReFungibleData: {
     pieces: 'u128',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup268: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup340: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateItemExData: {
     _enum: {
@@ -2442,14 +2728,14 @@
     }
   },
   /**
-   * Lookup270: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup342: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateNftExData: {
     properties: 'Vec<UpDataStructsProperty>',
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup277: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup349: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExSingleOwner: {
     user: 'PalletEvmAccountBasicCrossAccountIdRepr',
@@ -2457,14 +2743,14 @@
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup279: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup351: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExMultipleOwners: {
     users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup280: pallet_configuration::pallet::Call<T>
+   * Lookup352: pallet_configuration::pallet::Call<T>
    **/
   PalletConfigurationCall: {
     _enum: {
@@ -2492,7 +2778,7 @@
     }
   },
   /**
-   * Lookup285: pallet_configuration::AppPromotionConfiguration<BlockNumber>
+   * Lookup357: pallet_configuration::AppPromotionConfiguration<BlockNumber>
    **/
   PalletConfigurationAppPromotionConfiguration: {
     recalculationInterval: 'Option<u32>',
@@ -2501,220 +2787,16 @@
     maxStakersPerCalculation: 'Option<u8>'
   },
   /**
-   * Lookup289: pallet_template_transaction_payment::Call<T>
+   * Lookup361: pallet_template_transaction_payment::Call<T>
    **/
   PalletTemplateTransactionPaymentCall: 'Null',
   /**
-   * Lookup290: pallet_structure::pallet::Call<T>
+   * Lookup362: pallet_structure::pallet::Call<T>
    **/
   PalletStructureCall: 'Null',
   /**
-   * Lookup291: pallet_rmrk_core::pallet::Call<T>
-   **/
-  PalletRmrkCoreCall: {
-    _enum: {
-      create_collection: {
-        metadata: 'Bytes',
-        max: 'Option<u32>',
-        symbol: 'Bytes',
-      },
-      destroy_collection: {
-        collectionId: 'u32',
-      },
-      change_collection_issuer: {
-        collectionId: 'u32',
-        newIssuer: 'MultiAddress',
-      },
-      lock_collection: {
-        collectionId: 'u32',
-      },
-      mint_nft: {
-        owner: 'Option<AccountId32>',
-        collectionId: 'u32',
-        recipient: 'Option<AccountId32>',
-        royaltyAmount: 'Option<Permill>',
-        metadata: 'Bytes',
-        transferable: 'bool',
-        resources: 'Option<Vec<RmrkTraitsResourceResourceTypes>>',
-      },
-      burn_nft: {
-        collectionId: 'u32',
-        nftId: 'u32',
-        maxBurns: 'u32',
-      },
-      send: {
-        rmrkCollectionId: 'u32',
-        rmrkNftId: 'u32',
-        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
-      },
-      accept_nft: {
-        rmrkCollectionId: 'u32',
-        rmrkNftId: 'u32',
-        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
-      },
-      reject_nft: {
-        rmrkCollectionId: 'u32',
-        rmrkNftId: 'u32',
-      },
-      accept_resource: {
-        rmrkCollectionId: 'u32',
-        rmrkNftId: 'u32',
-        resourceId: 'u32',
-      },
-      accept_resource_removal: {
-        rmrkCollectionId: 'u32',
-        rmrkNftId: 'u32',
-        resourceId: 'u32',
-      },
-      set_property: {
-        rmrkCollectionId: 'Compact<u32>',
-        maybeNftId: 'Option<u32>',
-        key: 'Bytes',
-        value: 'Bytes',
-      },
-      set_priority: {
-        rmrkCollectionId: 'u32',
-        rmrkNftId: 'u32',
-        priorities: 'Vec<u32>',
-      },
-      add_basic_resource: {
-        rmrkCollectionId: 'u32',
-        nftId: 'u32',
-        resource: 'RmrkTraitsResourceBasicResource',
-      },
-      add_composable_resource: {
-        rmrkCollectionId: 'u32',
-        nftId: 'u32',
-        resource: 'RmrkTraitsResourceComposableResource',
-      },
-      add_slot_resource: {
-        rmrkCollectionId: 'u32',
-        nftId: 'u32',
-        resource: 'RmrkTraitsResourceSlotResource',
-      },
-      remove_resource: {
-        rmrkCollectionId: 'u32',
-        nftId: 'u32',
-        resourceId: 'u32'
-      }
-    }
-  },
-  /**
-   * Lookup297: rmrk_traits::resource::ResourceTypes<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsResourceResourceTypes: {
-    _enum: {
-      Basic: 'RmrkTraitsResourceBasicResource',
-      Composable: 'RmrkTraitsResourceComposableResource',
-      Slot: 'RmrkTraitsResourceSlotResource'
-    }
-  },
-  /**
-   * Lookup299: rmrk_traits::resource::BasicResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsResourceBasicResource: {
-    src: 'Option<Bytes>',
-    metadata: 'Option<Bytes>',
-    license: 'Option<Bytes>',
-    thumb: 'Option<Bytes>'
-  },
-  /**
-   * Lookup301: rmrk_traits::resource::ComposableResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsResourceComposableResource: {
-    parts: 'Vec<u32>',
-    base: 'u32',
-    src: 'Option<Bytes>',
-    metadata: 'Option<Bytes>',
-    license: 'Option<Bytes>',
-    thumb: 'Option<Bytes>'
-  },
-  /**
-   * Lookup302: rmrk_traits::resource::SlotResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsResourceSlotResource: {
-    base: 'u32',
-    src: 'Option<Bytes>',
-    metadata: 'Option<Bytes>',
-    slot: 'u32',
-    license: 'Option<Bytes>',
-    thumb: 'Option<Bytes>'
-  },
-  /**
-   * Lookup305: pallet_rmrk_equip::pallet::Call<T>
-   **/
-  PalletRmrkEquipCall: {
-    _enum: {
-      create_base: {
-        baseType: 'Bytes',
-        symbol: 'Bytes',
-        parts: 'Vec<RmrkTraitsPartPartType>',
-      },
-      theme_add: {
-        baseId: 'u32',
-        theme: 'RmrkTraitsTheme',
-      },
-      equippable: {
-        baseId: 'u32',
-        slotId: 'u32',
-        equippables: 'RmrkTraitsPartEquippableList'
-      }
-    }
-  },
-  /**
-   * Lookup308: rmrk_traits::part::PartType<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup363: pallet_app_promotion::pallet::Call<T>
    **/
-  RmrkTraitsPartPartType: {
-    _enum: {
-      FixedPart: 'RmrkTraitsPartFixedPart',
-      SlotPart: 'RmrkTraitsPartSlotPart'
-    }
-  },
-  /**
-   * Lookup310: rmrk_traits::part::FixedPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsPartFixedPart: {
-    id: 'u32',
-    z: 'u32',
-    src: 'Bytes'
-  },
-  /**
-   * Lookup311: rmrk_traits::part::SlotPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsPartSlotPart: {
-    id: 'u32',
-    equippable: 'RmrkTraitsPartEquippableList',
-    src: 'Bytes',
-    z: 'u32'
-  },
-  /**
-   * Lookup312: rmrk_traits::part::EquippableList<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsPartEquippableList: {
-    _enum: {
-      All: 'Null',
-      Empty: 'Null',
-      Custom: 'Vec<u32>'
-    }
-  },
-  /**
-   * Lookup314: rmrk_traits::theme::Theme<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>, S>>
-   **/
-  RmrkTraitsTheme: {
-    name: 'Bytes',
-    properties: 'Vec<RmrkTraitsThemeThemeProperty>',
-    inherit: 'bool'
-  },
-  /**
-   * Lookup316: rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsThemeThemeProperty: {
-    key: 'Bytes',
-    value: 'Bytes'
-  },
-  /**
-   * Lookup318: pallet_app_promotion::pallet::Call<T>
-   **/
   PalletAppPromotionCall: {
     _enum: {
       set_admin_address: {
@@ -2723,7 +2805,7 @@
       stake: {
         amount: 'u128',
       },
-      unstake: 'Null',
+      unstake_all: 'Null',
       sponsor_collection: {
         collectionId: 'u32',
       },
@@ -2737,12 +2819,15 @@
         contractId: 'H160',
       },
       payout_stakers: {
-        stakersNumber: 'Option<u8>'
+        stakersNumber: 'Option<u8>',
+      },
+      unstake_partial: {
+        amount: 'u128'
       }
     }
   },
   /**
-   * Lookup319: pallet_foreign_assets::module::Call<T>
+   * Lookup364: pallet_foreign_assets::module::Call<T>
    **/
   PalletForeignAssetsModuleCall: {
     _enum: {
@@ -2759,7 +2844,7 @@
     }
   },
   /**
-   * Lookup320: pallet_evm::pallet::Call<T>
+   * Lookup365: pallet_evm::pallet::Call<T>
    **/
   PalletEvmCall: {
     _enum: {
@@ -2802,7 +2887,7 @@
     }
   },
   /**
-   * Lookup326: pallet_ethereum::pallet::Call<T>
+   * Lookup371: pallet_ethereum::pallet::Call<T>
    **/
   PalletEthereumCall: {
     _enum: {
@@ -2812,7 +2897,7 @@
     }
   },
   /**
-   * Lookup327: ethereum::transaction::TransactionV2
+   * Lookup372: ethereum::transaction::TransactionV2
    **/
   EthereumTransactionTransactionV2: {
     _enum: {
@@ -2822,7 +2907,7 @@
     }
   },
   /**
-   * Lookup328: ethereum::transaction::LegacyTransaction
+   * Lookup373: ethereum::transaction::LegacyTransaction
    **/
   EthereumTransactionLegacyTransaction: {
     nonce: 'U256',
@@ -2834,7 +2919,7 @@
     signature: 'EthereumTransactionTransactionSignature'
   },
   /**
-   * Lookup329: ethereum::transaction::TransactionAction
+   * Lookup374: ethereum::transaction::TransactionAction
    **/
   EthereumTransactionTransactionAction: {
     _enum: {
@@ -2843,7 +2928,7 @@
     }
   },
   /**
-   * Lookup330: ethereum::transaction::TransactionSignature
+   * Lookup375: ethereum::transaction::TransactionSignature
    **/
   EthereumTransactionTransactionSignature: {
     v: 'u64',
@@ -2851,7 +2936,7 @@
     s: 'H256'
   },
   /**
-   * Lookup332: ethereum::transaction::EIP2930Transaction
+   * Lookup377: ethereum::transaction::EIP2930Transaction
    **/
   EthereumTransactionEip2930Transaction: {
     chainId: 'u64',
@@ -2867,14 +2952,14 @@
     s: 'H256'
   },
   /**
-   * Lookup334: ethereum::transaction::AccessListItem
+   * Lookup379: ethereum::transaction::AccessListItem
    **/
   EthereumTransactionAccessListItem: {
     address: 'H160',
     storageKeys: 'Vec<H256>'
   },
   /**
-   * Lookup335: ethereum::transaction::EIP1559Transaction
+   * Lookup380: ethereum::transaction::EIP1559Transaction
    **/
   EthereumTransactionEip1559Transaction: {
     chainId: 'u64',
@@ -2891,7 +2976,7 @@
     s: 'H256'
   },
   /**
-   * Lookup336: pallet_evm_migration::pallet::Call<T>
+   * Lookup381: pallet_evm_migration::pallet::Call<T>
    **/
   PalletEvmMigrationCall: {
     _enum: {
@@ -2910,18 +2995,29 @@
         logs: 'Vec<EthereumLog>',
       },
       insert_events: {
-        events: 'Vec<Bytes>'
-      }
+        events: 'Vec<Bytes>',
+      },
+      remove_rmrk_data: 'Null'
     }
   },
   /**
-   * Lookup340: pallet_maintenance::pallet::Call<T>
+   * Lookup385: pallet_maintenance::pallet::Call<T>
    **/
   PalletMaintenanceCall: {
-    _enum: ['enable', 'disable']
+    _enum: {
+      enable: 'Null',
+      disable: 'Null',
+      execute_preimage: {
+        _alias: {
+          hash_: 'hash',
+        },
+        hash_: 'H256',
+        weightBound: 'SpWeightsWeightV2Weight'
+      }
+    }
   },
   /**
-   * Lookup341: pallet_test_utils::pallet::Call<T>
+   * Lookup386: pallet_test_utils::pallet::Call<T>
    **/
   PalletTestUtilsCall: {
     _enum: {
@@ -2940,32 +3036,32 @@
     }
   },
   /**
-   * Lookup343: pallet_sudo::pallet::Error<T>
+   * Lookup388: pallet_sudo::pallet::Error<T>
    **/
   PalletSudoError: {
     _enum: ['RequireSudo']
   },
   /**
-   * Lookup345: orml_vesting::module::Error<T>
+   * Lookup390: orml_vesting::module::Error<T>
    **/
   OrmlVestingModuleError: {
     _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']
   },
   /**
-   * Lookup346: orml_xtokens::module::Error<T>
+   * Lookup391: orml_xtokens::module::Error<T>
    **/
   OrmlXtokensModuleError: {
     _enum: ['AssetHasNoReserve', 'NotCrossChainTransfer', 'InvalidDest', 'NotCrossChainTransferableCurrency', 'UnweighableMessage', 'XcmExecutionFailed', 'CannotReanchor', 'InvalidAncestry', 'InvalidAsset', 'DestinationNotInvertible', 'BadVersion', 'DistinctReserveForAssetAndFee', 'ZeroFee', 'ZeroAmount', 'TooManyAssetsBeingSent', 'AssetIndexNonExistent', 'FeeNotEnough', 'NotSupportedMultiLocation', 'MinXcmFeeNotDefined']
   },
   /**
-   * Lookup349: orml_tokens::BalanceLock<Balance>
+   * Lookup394: orml_tokens::BalanceLock<Balance>
    **/
   OrmlTokensBalanceLock: {
     id: '[u8;8]',
     amount: 'u128'
   },
   /**
-   * Lookup351: orml_tokens::AccountData<Balance>
+   * Lookup396: orml_tokens::AccountData<Balance>
    **/
   OrmlTokensAccountData: {
     free: 'u128',
@@ -2973,20 +3069,56 @@
     frozen: 'u128'
   },
   /**
-   * Lookup353: orml_tokens::ReserveData<ReserveIdentifier, Balance>
+   * Lookup398: orml_tokens::ReserveData<ReserveIdentifier, Balance>
    **/
   OrmlTokensReserveData: {
     id: 'Null',
     amount: 'u128'
   },
   /**
-   * Lookup355: orml_tokens::module::Error<T>
+   * Lookup400: orml_tokens::module::Error<T>
    **/
   OrmlTokensModuleError: {
     _enum: ['BalanceTooLow', 'AmountIntoBalanceFailed', 'LiquidityRestrictions', 'MaxLocksExceeded', 'KeepAlive', 'ExistentialDeposit', 'DeadAccount', 'TooManyReserves']
   },
   /**
-   * Lookup357: cumulus_pallet_xcmp_queue::InboundChannelDetails
+   * Lookup405: pallet_identity::types::RegistrarInfo<Balance, sp_core::crypto::AccountId32>
+   **/
+  PalletIdentityRegistrarInfo: {
+    account: 'AccountId32',
+    fee: 'u128',
+    fields: 'PalletIdentityBitFlags'
+  },
+  /**
+   * Lookup407: pallet_identity::pallet::Error<T>
+   **/
+  PalletIdentityError: {
+    _enum: ['TooManySubAccounts', 'NotFound', 'NotNamed', 'EmptyIndex', 'FeeChanged', 'NoIdentity', 'StickyJudgement', 'JudgementGiven', 'InvalidJudgement', 'InvalidIndex', 'InvalidTarget', 'TooManyFields', 'TooManyRegistrars', 'AlreadyClaimed', 'NotSub', 'NotOwned', 'JudgementForDifferentIdentity', 'JudgementPaymentFailed']
+  },
+  /**
+   * Lookup408: pallet_preimage::RequestStatus<sp_core::crypto::AccountId32, Balance>
+   **/
+  PalletPreimageRequestStatus: {
+    _enum: {
+      Unrequested: {
+        deposit: '(AccountId32,u128)',
+        len: 'u32',
+      },
+      Requested: {
+        deposit: 'Option<(AccountId32,u128)>',
+        count: 'u32',
+        len: 'Option<u32>'
+      }
+    }
+  },
+  /**
+   * Lookup413: pallet_preimage::pallet::Error<T>
+   **/
+  PalletPreimageError: {
+    _enum: ['TooBig', 'AlreadyNoted', 'NotAuthorized', 'NotNoted', 'Requested', 'NotRequested']
+  },
+  /**
+   * Lookup415: cumulus_pallet_xcmp_queue::InboundChannelDetails
    **/
   CumulusPalletXcmpQueueInboundChannelDetails: {
     sender: 'u32',
@@ -2994,19 +3126,19 @@
     messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'
   },
   /**
-   * Lookup358: cumulus_pallet_xcmp_queue::InboundState
+   * Lookup416: cumulus_pallet_xcmp_queue::InboundState
    **/
   CumulusPalletXcmpQueueInboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup361: polkadot_parachain::primitives::XcmpMessageFormat
+   * Lookup419: polkadot_parachain::primitives::XcmpMessageFormat
    **/
   PolkadotParachainPrimitivesXcmpMessageFormat: {
     _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']
   },
   /**
-   * Lookup364: cumulus_pallet_xcmp_queue::OutboundChannelDetails
+   * Lookup422: cumulus_pallet_xcmp_queue::OutboundChannelDetails
    **/
   CumulusPalletXcmpQueueOutboundChannelDetails: {
     recipient: 'u32',
@@ -3016,13 +3148,13 @@
     lastIndex: 'u16'
   },
   /**
-   * Lookup365: cumulus_pallet_xcmp_queue::OutboundState
+   * Lookup423: cumulus_pallet_xcmp_queue::OutboundState
    **/
   CumulusPalletXcmpQueueOutboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup367: cumulus_pallet_xcmp_queue::QueueConfigData
+   * Lookup425: cumulus_pallet_xcmp_queue::QueueConfigData
    **/
   CumulusPalletXcmpQueueQueueConfigData: {
     suspendThreshold: 'u32',
@@ -3033,29 +3165,29 @@
     xcmpMaxIndividualWeight: 'SpWeightsWeightV2Weight'
   },
   /**
-   * Lookup369: cumulus_pallet_xcmp_queue::pallet::Error<T>
+   * Lookup427: cumulus_pallet_xcmp_queue::pallet::Error<T>
    **/
   CumulusPalletXcmpQueueError: {
     _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']
   },
   /**
-   * Lookup370: pallet_xcm::pallet::Error<T>
+   * Lookup428: pallet_xcm::pallet::Error<T>
    **/
   PalletXcmError: {
     _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']
   },
   /**
-   * Lookup371: cumulus_pallet_xcm::pallet::Error<T>
+   * Lookup429: cumulus_pallet_xcm::pallet::Error<T>
    **/
   CumulusPalletXcmError: 'Null',
   /**
-   * Lookup372: cumulus_pallet_dmp_queue::ConfigData
+   * Lookup430: cumulus_pallet_dmp_queue::ConfigData
    **/
   CumulusPalletDmpQueueConfigData: {
     maxIndividual: 'SpWeightsWeightV2Weight'
   },
   /**
-   * Lookup373: cumulus_pallet_dmp_queue::PageIndexData
+   * Lookup431: cumulus_pallet_dmp_queue::PageIndexData
    **/
   CumulusPalletDmpQueuePageIndexData: {
     beginUsed: 'u32',
@@ -3063,25 +3195,25 @@
     overweightCount: 'u64'
   },
   /**
-   * Lookup376: cumulus_pallet_dmp_queue::pallet::Error<T>
+   * Lookup434: cumulus_pallet_dmp_queue::pallet::Error<T>
    **/
   CumulusPalletDmpQueueError: {
     _enum: ['Unknown', 'OverLimit']
   },
   /**
-   * Lookup380: pallet_unique::Error<T>
+   * Lookup438: pallet_unique::Error<T>
    **/
   PalletUniqueError: {
     _enum: ['CollectionDecimalPointLimitExceeded', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']
   },
   /**
-   * Lookup381: pallet_configuration::pallet::Error<T>
+   * Lookup439: pallet_configuration::pallet::Error<T>
    **/
   PalletConfigurationError: {
     _enum: ['InconsistentConfiguration']
   },
   /**
-   * Lookup382: up_data_structs::Collection<sp_core::crypto::AccountId32>
+   * Lookup440: up_data_structs::Collection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsCollection: {
     owner: 'AccountId32',
@@ -3095,7 +3227,7 @@
     flags: '[u8;1]'
   },
   /**
-   * Lookup383: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
+   * Lookup441: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
    **/
   UpDataStructsSponsorshipStateAccountId32: {
     _enum: {
@@ -3105,7 +3237,7 @@
     }
   },
   /**
-   * Lookup385: up_data_structs::Properties
+   * Lookup442: up_data_structs::Properties
    **/
   UpDataStructsProperties: {
     map: 'UpDataStructsPropertiesMapBoundedVec',
@@ -3113,15 +3245,15 @@
     spaceLimit: 'u32'
   },
   /**
-   * Lookup386: up_data_structs::PropertiesMap<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup443: up_data_structs::PropertiesMap<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',
   /**
-   * Lookup391: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
+   * Lookup448: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
    **/
   UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',
   /**
-   * Lookup398: up_data_structs::CollectionStats
+   * Lookup455: up_data_structs::CollectionStats
    **/
   UpDataStructsCollectionStats: {
     created: 'u32',
@@ -3129,18 +3261,18 @@
     alive: 'u32'
   },
   /**
-   * Lookup399: up_data_structs::TokenChild
+   * Lookup456: up_data_structs::TokenChild
    **/
   UpDataStructsTokenChild: {
     token: 'u32',
     collection: 'u32'
   },
   /**
-   * Lookup400: PhantomType::up_data_structs<T>
+   * Lookup457: PhantomType::up_data_structs<T>
    **/
-  PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild,UpPovEstimateRpcPovInfo);0]',
+  PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,UpPovEstimateRpcPovInfo);0]',
   /**
-   * Lookup402: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup459: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsTokenData: {
     properties: 'Vec<UpDataStructsProperty>',
@@ -3148,7 +3280,7 @@
     pieces: 'u128'
   },
   /**
-   * Lookup404: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
+   * Lookup461: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsRpcCollection: {
     owner: 'AccountId32',
@@ -3165,73 +3297,15 @@
     flags: 'UpDataStructsRpcCollectionFlags'
   },
   /**
-   * Lookup405: up_data_structs::RpcCollectionFlags
+   * Lookup462: up_data_structs::RpcCollectionFlags
    **/
   UpDataStructsRpcCollectionFlags: {
     foreign: 'bool',
     erc721metadata: 'bool'
   },
   /**
-   * Lookup406: rmrk_traits::collection::CollectionInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
-   **/
-  RmrkTraitsCollectionCollectionInfo: {
-    issuer: 'AccountId32',
-    metadata: 'Bytes',
-    max: 'Option<u32>',
-    symbol: 'Bytes',
-    nftsCount: 'u32'
-  },
-  /**
-   * Lookup407: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsNftNftInfo: {
-    owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
-    royalty: 'Option<RmrkTraitsNftRoyaltyInfo>',
-    metadata: 'Bytes',
-    equipped: 'bool',
-    pending: 'bool'
-  },
-  /**
-   * Lookup409: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
+   * Lookup463: up_pov_estimate_rpc::PovInfo
    **/
-  RmrkTraitsNftRoyaltyInfo: {
-    recipient: 'AccountId32',
-    amount: 'Permill'
-  },
-  /**
-   * Lookup410: rmrk_traits::resource::ResourceInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsResourceResourceInfo: {
-    id: 'u32',
-    resource: 'RmrkTraitsResourceResourceTypes',
-    pending: 'bool',
-    pendingRemoval: 'bool'
-  },
-  /**
-   * Lookup411: rmrk_traits::property::PropertyInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsPropertyPropertyInfo: {
-    key: 'Bytes',
-    value: 'Bytes'
-  },
-  /**
-   * Lookup412: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
-   **/
-  RmrkTraitsBaseBaseInfo: {
-    issuer: 'AccountId32',
-    baseType: 'Bytes',
-    symbol: 'Bytes'
-  },
-  /**
-   * Lookup413: rmrk_traits::nft::NftChild
-   **/
-  RmrkTraitsNftNftChild: {
-    collectionId: 'u32',
-    nftId: 'u32'
-  },
-  /**
-   * Lookup414: up_pov_estimate_rpc::PovInfo
-   **/
   UpPovEstimateRpcPovInfo: {
     proofSize: 'u64',
     compactProofSize: 'u64',
@@ -3240,7 +3314,7 @@
     keyValues: 'Vec<UpPovEstimateRpcTrieKeyValue>'
   },
   /**
-   * Lookup417: sp_runtime::transaction_validity::TransactionValidityError
+   * Lookup466: sp_runtime::transaction_validity::TransactionValidityError
    **/
   SpRuntimeTransactionValidityTransactionValidityError: {
     _enum: {
@@ -3249,7 +3323,7 @@
     }
   },
   /**
-   * Lookup418: sp_runtime::transaction_validity::InvalidTransaction
+   * Lookup467: sp_runtime::transaction_validity::InvalidTransaction
    **/
   SpRuntimeTransactionValidityInvalidTransaction: {
     _enum: {
@@ -3267,7 +3341,7 @@
     }
   },
   /**
-   * Lookup419: sp_runtime::transaction_validity::UnknownTransaction
+   * Lookup468: sp_runtime::transaction_validity::UnknownTransaction
    **/
   SpRuntimeTransactionValidityUnknownTransaction: {
     _enum: {
@@ -3277,86 +3351,74 @@
     }
   },
   /**
-   * Lookup421: up_pov_estimate_rpc::TrieKeyValue
+   * Lookup470: up_pov_estimate_rpc::TrieKeyValue
    **/
   UpPovEstimateRpcTrieKeyValue: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup423: pallet_common::pallet::Error<T>
+   * Lookup472: pallet_common::pallet::Error<T>
    **/
   PalletCommonError: {
     _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsNotEthMirror', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal', 'ConfirmSponsorshipFail', 'UserIsNotCollectionAdmin']
   },
   /**
-   * Lookup425: pallet_fungible::pallet::Error<T>
+   * Lookup474: pallet_fungible::pallet::Error<T>
    **/
   PalletFungibleError: {
     _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed', 'SettingAllowanceForAllNotAllowed', 'FungibleTokensAreAlwaysValid']
   },
   /**
-   * Lookup429: pallet_refungible::pallet::Error<T>
+   * Lookup478: pallet_refungible::pallet::Error<T>
    **/
   PalletRefungibleError: {
     _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
   },
   /**
-   * Lookup430: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup479: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   PalletNonfungibleItemData: {
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup432: up_data_structs::PropertyScope
+   * Lookup481: up_data_structs::PropertyScope
    **/
   UpDataStructsPropertyScope: {
     _enum: ['None', 'Rmrk']
   },
   /**
-   * Lookup435: pallet_nonfungible::pallet::Error<T>
+   * Lookup484: pallet_nonfungible::pallet::Error<T>
    **/
   PalletNonfungibleError: {
     _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']
   },
   /**
-   * Lookup436: pallet_structure::pallet::Error<T>
+   * Lookup485: pallet_structure::pallet::Error<T>
    **/
   PalletStructureError: {
-    _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']
+    _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound', 'CantNestTokenUnderCollection']
   },
   /**
-   * Lookup437: pallet_rmrk_core::pallet::Error<T>
-   **/
-  PalletRmrkCoreError: {
-    _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']
-  },
-  /**
-   * Lookup439: pallet_rmrk_equip::pallet::Error<T>
-   **/
-  PalletRmrkEquipError: {
-    _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']
-  },
-  /**
-   * Lookup445: pallet_app_promotion::pallet::Error<T>
+   * Lookup490: pallet_app_promotion::pallet::Error<T>
    **/
   PalletAppPromotionError: {
-    _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation']
+    _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation', 'InsufficientStakedBalance']
   },
   /**
-   * Lookup446: pallet_foreign_assets::module::Error<T>
+   * Lookup491: pallet_foreign_assets::module::Error<T>
    **/
   PalletForeignAssetsModuleError: {
     _enum: ['BadLocation', 'MultiLocationExisted', 'AssetIdNotExists', 'AssetIdExisted']
   },
   /**
-   * Lookup448: pallet_evm::pallet::Error<T>
+   * Lookup493: pallet_evm::pallet::Error<T>
    **/
   PalletEvmError: {
     _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce', 'GasLimitTooLow', 'GasLimitTooHigh', 'Undefined', 'Reentrancy', 'TransactionMustComeFromEOA']
   },
   /**
-   * Lookup451: fp_rpc::TransactionStatus
+   * Lookup496: fp_rpc::TransactionStatus
    **/
   FpRpcTransactionStatus: {
     transactionHash: 'H256',
@@ -3368,11 +3430,11 @@
     logsBloom: 'EthbloomBloom'
   },
   /**
-   * Lookup453: ethbloom::Bloom
+   * Lookup498: ethbloom::Bloom
    **/
   EthbloomBloom: '[u8;256]',
   /**
-   * Lookup455: ethereum::receipt::ReceiptV3
+   * Lookup500: ethereum::receipt::ReceiptV3
    **/
   EthereumReceiptReceiptV3: {
     _enum: {
@@ -3382,7 +3444,7 @@
     }
   },
   /**
-   * Lookup456: ethereum::receipt::EIP658ReceiptData
+   * Lookup501: ethereum::receipt::EIP658ReceiptData
    **/
   EthereumReceiptEip658ReceiptData: {
     statusCode: 'u8',
@@ -3391,7 +3453,7 @@
     logs: 'Vec<EthereumLog>'
   },
   /**
-   * Lookup457: ethereum::block::Block<ethereum::transaction::TransactionV2>
+   * Lookup502: ethereum::block::Block<ethereum::transaction::TransactionV2>
    **/
   EthereumBlock: {
     header: 'EthereumHeader',
@@ -3399,7 +3461,7 @@
     ommers: 'Vec<EthereumHeader>'
   },
   /**
-   * Lookup458: ethereum::header::Header
+   * Lookup503: ethereum::header::Header
    **/
   EthereumHeader: {
     parentHash: 'H256',
@@ -3419,23 +3481,23 @@
     nonce: 'EthereumTypesHashH64'
   },
   /**
-   * Lookup459: ethereum_types::hash::H64
+   * Lookup504: ethereum_types::hash::H64
    **/
   EthereumTypesHashH64: '[u8;8]',
   /**
-   * Lookup464: pallet_ethereum::pallet::Error<T>
+   * Lookup509: pallet_ethereum::pallet::Error<T>
    **/
   PalletEthereumError: {
     _enum: ['InvalidSignature', 'PreLogExists']
   },
   /**
-   * Lookup465: pallet_evm_coder_substrate::pallet::Error<T>
+   * Lookup510: pallet_evm_coder_substrate::pallet::Error<T>
    **/
   PalletEvmCoderSubstrateError: {
     _enum: ['OutOfGas', 'OutOfFund']
   },
   /**
-   * Lookup466: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup511: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: {
     _enum: {
@@ -3445,35 +3507,35 @@
     }
   },
   /**
-   * Lookup467: pallet_evm_contract_helpers::SponsoringModeT
+   * Lookup512: pallet_evm_contract_helpers::SponsoringModeT
    **/
   PalletEvmContractHelpersSponsoringModeT: {
     _enum: ['Disabled', 'Allowlisted', 'Generous']
   },
   /**
-   * Lookup473: pallet_evm_contract_helpers::pallet::Error<T>
+   * Lookup518: pallet_evm_contract_helpers::pallet::Error<T>
    **/
   PalletEvmContractHelpersError: {
     _enum: ['NoPermission', 'NoPendingSponsor', 'TooManyMethodsHaveSponsoredLimit']
   },
   /**
-   * Lookup474: pallet_evm_migration::pallet::Error<T>
+   * Lookup519: pallet_evm_migration::pallet::Error<T>
    **/
   PalletEvmMigrationError: {
     _enum: ['AccountNotEmpty', 'AccountIsNotMigrating', 'BadEvent']
   },
   /**
-   * Lookup475: pallet_maintenance::pallet::Error<T>
+   * Lookup520: pallet_maintenance::pallet::Error<T>
    **/
   PalletMaintenanceError: 'Null',
   /**
-   * Lookup476: pallet_test_utils::pallet::Error<T>
+   * Lookup521: pallet_test_utils::pallet::Error<T>
    **/
   PalletTestUtilsError: {
     _enum: ['TestPalletDisabled', 'TriggerRollback']
   },
   /**
-   * Lookup478: sp_runtime::MultiSignature
+   * Lookup523: sp_runtime::MultiSignature
    **/
   SpRuntimeMultiSignature: {
     _enum: {
@@ -3483,55 +3545,55 @@
     }
   },
   /**
-   * Lookup479: sp_core::ed25519::Signature
+   * Lookup524: sp_core::ed25519::Signature
    **/
   SpCoreEd25519Signature: '[u8;64]',
   /**
-   * Lookup481: sp_core::sr25519::Signature
+   * Lookup526: sp_core::sr25519::Signature
    **/
   SpCoreSr25519Signature: '[u8;64]',
   /**
-   * Lookup482: sp_core::ecdsa::Signature
+   * Lookup527: sp_core::ecdsa::Signature
    **/
   SpCoreEcdsaSignature: '[u8;65]',
   /**
-   * Lookup485: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
+   * Lookup530: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
    **/
   FrameSystemExtensionsCheckSpecVersion: 'Null',
   /**
-   * Lookup486: frame_system::extensions::check_tx_version::CheckTxVersion<T>
+   * Lookup531: frame_system::extensions::check_tx_version::CheckTxVersion<T>
    **/
   FrameSystemExtensionsCheckTxVersion: 'Null',
   /**
-   * Lookup487: frame_system::extensions::check_genesis::CheckGenesis<T>
+   * Lookup532: frame_system::extensions::check_genesis::CheckGenesis<T>
    **/
   FrameSystemExtensionsCheckGenesis: 'Null',
   /**
-   * Lookup490: frame_system::extensions::check_nonce::CheckNonce<T>
+   * Lookup535: frame_system::extensions::check_nonce::CheckNonce<T>
    **/
   FrameSystemExtensionsCheckNonce: 'Compact<u32>',
   /**
-   * Lookup491: frame_system::extensions::check_weight::CheckWeight<T>
+   * Lookup536: frame_system::extensions::check_weight::CheckWeight<T>
    **/
   FrameSystemExtensionsCheckWeight: 'Null',
   /**
-   * Lookup492: opal_runtime::runtime_common::maintenance::CheckMaintenance
+   * Lookup537: opal_runtime::runtime_common::maintenance::CheckMaintenance
    **/
   OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance: 'Null',
   /**
-   * Lookup493: opal_runtime::runtime_common::identity::DisableIdentityCalls
+   * Lookup538: opal_runtime::runtime_common::identity::DisableIdentityCalls
    **/
   OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls: 'Null',
   /**
-   * Lookup494: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
+   * Lookup539: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
    **/
   PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',
   /**
-   * Lookup495: opal_runtime::Runtime
+   * Lookup540: opal_runtime::Runtime
    **/
   OpalRuntimeRuntime: 'Null',
   /**
-   * Lookup496: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
+   * Lookup541: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
    **/
   PalletEthereumFakeTransactionFinalizer: 'Null'
 };
modifiedtests/src/interfaces/registry.tsdiffbeforeafterboth
--- a/tests/src/interfaces/registry.ts
+++ b/tests/src/interfaces/registry.ts
@@ -5,7 +5,7 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/types/types/registry';
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationAppPromotionConfiguration, PalletConfigurationCall, PalletConfigurationError, PalletConfigurationEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionValidityInvalidTransaction, SpRuntimeTransactionValidityTransactionValidityError, SpRuntimeTransactionValidityUnknownTransaction, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, UpPovEstimateRpcPovInfo, UpPovEstimateRpcTrieKeyValue, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OpalRuntimeRuntimeCommonSessionKeys, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletAuthorshipCall, PalletAuthorshipError, PalletAuthorshipUncleEntryItem, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReserveData, PalletCollatorSelectionCall, PalletCollatorSelectionError, PalletCollatorSelectionEvent, PalletCommonError, PalletCommonEvent, PalletConfigurationAppPromotionConfiguration, PalletConfigurationCall, PalletConfigurationError, PalletConfigurationEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletIdentityBitFlags, PalletIdentityCall, PalletIdentityError, PalletIdentityEvent, PalletIdentityIdentityField, PalletIdentityIdentityInfo, PalletIdentityJudgement, PalletIdentityRegistrarInfo, PalletIdentityRegistration, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletPreimageCall, PalletPreimageError, PalletPreimageEvent, PalletPreimageRequestStatus, PalletRefungibleError, PalletSessionCall, PalletSessionError, PalletSessionEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpArithmeticArithmeticError, SpConsensusAuraSr25519AppSr25519Public, SpCoreCryptoKeyTypeId, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Public, SpCoreSr25519Signature, SpRuntimeBlakeTwo256, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeHeader, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionValidityInvalidTransaction, SpRuntimeTransactionValidityTransactionValidityError, SpRuntimeTransactionValidityUnknownTransaction, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, UpPovEstimateRpcPovInfo, UpPovEstimateRpcTrieKeyValue, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 
 declare module '@polkadot/types/types/registry' {
   interface InterfaceTypes {
@@ -76,6 +76,7 @@
     OpalRuntimeRuntime: OpalRuntimeRuntime;
     OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls: OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls;
     OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance: OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance;
+    OpalRuntimeRuntimeCommonSessionKeys: OpalRuntimeRuntimeCommonSessionKeys;
     OrmlTokensAccountData: OrmlTokensAccountData;
     OrmlTokensBalanceLock: OrmlTokensBalanceLock;
     OrmlTokensModuleCall: OrmlTokensModuleCall;
@@ -92,6 +93,9 @@
     PalletAppPromotionCall: PalletAppPromotionCall;
     PalletAppPromotionError: PalletAppPromotionError;
     PalletAppPromotionEvent: PalletAppPromotionEvent;
+    PalletAuthorshipCall: PalletAuthorshipCall;
+    PalletAuthorshipError: PalletAuthorshipError;
+    PalletAuthorshipUncleEntryItem: PalletAuthorshipUncleEntryItem;
     PalletBalancesAccountData: PalletBalancesAccountData;
     PalletBalancesBalanceLock: PalletBalancesBalanceLock;
     PalletBalancesCall: PalletBalancesCall;
@@ -99,6 +103,9 @@
     PalletBalancesEvent: PalletBalancesEvent;
     PalletBalancesReasons: PalletBalancesReasons;
     PalletBalancesReserveData: PalletBalancesReserveData;
+    PalletCollatorSelectionCall: PalletCollatorSelectionCall;
+    PalletCollatorSelectionError: PalletCollatorSelectionError;
+    PalletCollatorSelectionEvent: PalletCollatorSelectionEvent;
     PalletCommonError: PalletCommonError;
     PalletCommonEvent: PalletCommonEvent;
     PalletConfigurationAppPromotionConfiguration: PalletConfigurationAppPromotionConfiguration;
@@ -127,19 +134,29 @@
     PalletForeignAssetsModuleEvent: PalletForeignAssetsModuleEvent;
     PalletForeignAssetsNativeCurrency: PalletForeignAssetsNativeCurrency;
     PalletFungibleError: PalletFungibleError;
+    PalletIdentityBitFlags: PalletIdentityBitFlags;
+    PalletIdentityCall: PalletIdentityCall;
+    PalletIdentityError: PalletIdentityError;
+    PalletIdentityEvent: PalletIdentityEvent;
+    PalletIdentityIdentityField: PalletIdentityIdentityField;
+    PalletIdentityIdentityInfo: PalletIdentityIdentityInfo;
+    PalletIdentityJudgement: PalletIdentityJudgement;
+    PalletIdentityRegistrarInfo: PalletIdentityRegistrarInfo;
+    PalletIdentityRegistration: PalletIdentityRegistration;
     PalletInflationCall: PalletInflationCall;
     PalletMaintenanceCall: PalletMaintenanceCall;
     PalletMaintenanceError: PalletMaintenanceError;
     PalletMaintenanceEvent: PalletMaintenanceEvent;
     PalletNonfungibleError: PalletNonfungibleError;
     PalletNonfungibleItemData: PalletNonfungibleItemData;
+    PalletPreimageCall: PalletPreimageCall;
+    PalletPreimageError: PalletPreimageError;
+    PalletPreimageEvent: PalletPreimageEvent;
+    PalletPreimageRequestStatus: PalletPreimageRequestStatus;
     PalletRefungibleError: PalletRefungibleError;
-    PalletRmrkCoreCall: PalletRmrkCoreCall;
-    PalletRmrkCoreError: PalletRmrkCoreError;
-    PalletRmrkCoreEvent: PalletRmrkCoreEvent;
-    PalletRmrkEquipCall: PalletRmrkEquipCall;
-    PalletRmrkEquipError: PalletRmrkEquipError;
-    PalletRmrkEquipEvent: PalletRmrkEquipEvent;
+    PalletSessionCall: PalletSessionCall;
+    PalletSessionError: PalletSessionError;
+    PalletSessionEvent: PalletSessionEvent;
     PalletStructureCall: PalletStructureCall;
     PalletStructureError: PalletStructureError;
     PalletStructureEvent: PalletStructureEvent;
@@ -172,31 +189,18 @@
     PolkadotPrimitivesV2AbridgedHrmpChannel: PolkadotPrimitivesV2AbridgedHrmpChannel;
     PolkadotPrimitivesV2PersistedValidationData: PolkadotPrimitivesV2PersistedValidationData;
     PolkadotPrimitivesV2UpgradeRestriction: PolkadotPrimitivesV2UpgradeRestriction;
-    RmrkTraitsBaseBaseInfo: RmrkTraitsBaseBaseInfo;
-    RmrkTraitsCollectionCollectionInfo: RmrkTraitsCollectionCollectionInfo;
-    RmrkTraitsNftAccountIdOrCollectionNftTuple: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-    RmrkTraitsNftNftChild: RmrkTraitsNftNftChild;
-    RmrkTraitsNftNftInfo: RmrkTraitsNftNftInfo;
-    RmrkTraitsNftRoyaltyInfo: RmrkTraitsNftRoyaltyInfo;
-    RmrkTraitsPartEquippableList: RmrkTraitsPartEquippableList;
-    RmrkTraitsPartFixedPart: RmrkTraitsPartFixedPart;
-    RmrkTraitsPartPartType: RmrkTraitsPartPartType;
-    RmrkTraitsPartSlotPart: RmrkTraitsPartSlotPart;
-    RmrkTraitsPropertyPropertyInfo: RmrkTraitsPropertyPropertyInfo;
-    RmrkTraitsResourceBasicResource: RmrkTraitsResourceBasicResource;
-    RmrkTraitsResourceComposableResource: RmrkTraitsResourceComposableResource;
-    RmrkTraitsResourceResourceInfo: RmrkTraitsResourceResourceInfo;
-    RmrkTraitsResourceResourceTypes: RmrkTraitsResourceResourceTypes;
-    RmrkTraitsResourceSlotResource: RmrkTraitsResourceSlotResource;
-    RmrkTraitsTheme: RmrkTraitsTheme;
-    RmrkTraitsThemeThemeProperty: RmrkTraitsThemeThemeProperty;
+    SpArithmeticArithmeticError: SpArithmeticArithmeticError;
+    SpConsensusAuraSr25519AppSr25519Public: SpConsensusAuraSr25519AppSr25519Public;
+    SpCoreCryptoKeyTypeId: SpCoreCryptoKeyTypeId;
     SpCoreEcdsaSignature: SpCoreEcdsaSignature;
     SpCoreEd25519Signature: SpCoreEd25519Signature;
+    SpCoreSr25519Public: SpCoreSr25519Public;
     SpCoreSr25519Signature: SpCoreSr25519Signature;
-    SpRuntimeArithmeticError: SpRuntimeArithmeticError;
+    SpRuntimeBlakeTwo256: SpRuntimeBlakeTwo256;
     SpRuntimeDigest: SpRuntimeDigest;
     SpRuntimeDigestDigestItem: SpRuntimeDigestDigestItem;
     SpRuntimeDispatchError: SpRuntimeDispatchError;
+    SpRuntimeHeader: SpRuntimeHeader;
     SpRuntimeModuleError: SpRuntimeModuleError;
     SpRuntimeMultiSignature: SpRuntimeMultiSignature;
     SpRuntimeTokenError: SpRuntimeTokenError;
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -5,9 +5,10 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/types/lookup';
 
-import type { BTreeMap, BTreeSet, Bytes, Compact, Enum, Null, Option, Result, Struct, Text, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
+import type { Data } from '@polkadot/types';
+import type { BTreeMap, BTreeSet, Bytes, Compact, Enum, Null, Option, Result, Set, Struct, Text, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
 import type { ITuple } from '@polkadot/types-codec/types';
-import type { AccountId32, Call, H160, H256, MultiAddress, Perbill, Permill } from '@polkadot/types/interfaces/runtime';
+import type { AccountId32, Call, H160, H256, MultiAddress, Perbill } from '@polkadot/types/interfaces/runtime';
 import type { Event } from '@polkadot/types/interfaces/system';
 
 declare module '@polkadot/types/lookup' {
@@ -130,7 +131,7 @@
     readonly isToken: boolean;
     readonly asToken: SpRuntimeTokenError;
     readonly isArithmetic: boolean;
-    readonly asArithmetic: SpRuntimeArithmeticError;
+    readonly asArithmetic: SpArithmeticArithmeticError;
     readonly isTransactional: boolean;
     readonly asTransactional: SpRuntimeTransactionalError;
     readonly isExhausted: boolean;
@@ -157,8 +158,8 @@
     readonly type: 'NoFunds' | 'WouldDie' | 'BelowMinimum' | 'CannotCreate' | 'UnknownAsset' | 'Frozen' | 'Unsupported';
   }
 
-  /** @name SpRuntimeArithmeticError (27) */
-  interface SpRuntimeArithmeticError extends Enum {
+  /** @name SpArithmeticArithmeticError (27) */
+  interface SpArithmeticArithmeticError extends Enum {
     readonly isUnderflow: boolean;
     readonly isOverflow: boolean;
     readonly isDivisionByZero: boolean;
@@ -196,7 +197,47 @@
     readonly type: 'ValidationFunctionStored' | 'ValidationFunctionApplied' | 'ValidationFunctionDiscarded' | 'UpgradeAuthorized' | 'DownwardMessagesReceived' | 'DownwardMessagesProcessed';
   }
 
-  /** @name PalletBalancesEvent (30) */
+  /** @name PalletCollatorSelectionEvent (30) */
+  interface PalletCollatorSelectionEvent extends Enum {
+    readonly isInvulnerableAdded: boolean;
+    readonly asInvulnerableAdded: {
+      readonly invulnerable: AccountId32;
+    } & Struct;
+    readonly isInvulnerableRemoved: boolean;
+    readonly asInvulnerableRemoved: {
+      readonly invulnerable: AccountId32;
+    } & Struct;
+    readonly isLicenseObtained: boolean;
+    readonly asLicenseObtained: {
+      readonly accountId: AccountId32;
+      readonly deposit: u128;
+    } & Struct;
+    readonly isLicenseReleased: boolean;
+    readonly asLicenseReleased: {
+      readonly accountId: AccountId32;
+      readonly depositReturned: u128;
+    } & Struct;
+    readonly isCandidateAdded: boolean;
+    readonly asCandidateAdded: {
+      readonly accountId: AccountId32;
+    } & Struct;
+    readonly isCandidateRemoved: boolean;
+    readonly asCandidateRemoved: {
+      readonly accountId: AccountId32;
+    } & Struct;
+    readonly type: 'InvulnerableAdded' | 'InvulnerableRemoved' | 'LicenseObtained' | 'LicenseReleased' | 'CandidateAdded' | 'CandidateRemoved';
+  }
+
+  /** @name PalletSessionEvent (31) */
+  interface PalletSessionEvent extends Enum {
+    readonly isNewSession: boolean;
+    readonly asNewSession: {
+      readonly sessionIndex: u32;
+    } & Struct;
+    readonly type: 'NewSession';
+  }
+
+  /** @name PalletBalancesEvent (32) */
   interface PalletBalancesEvent extends Enum {
     readonly isEndowed: boolean;
     readonly asEndowed: {
@@ -255,14 +296,14 @@
     readonly type: 'Endowed' | 'DustLost' | 'Transfer' | 'BalanceSet' | 'Reserved' | 'Unreserved' | 'ReserveRepatriated' | 'Deposit' | 'Withdraw' | 'Slashed';
   }
 
-  /** @name FrameSupportTokensMiscBalanceStatus (31) */
+  /** @name FrameSupportTokensMiscBalanceStatus (33) */
   interface FrameSupportTokensMiscBalanceStatus extends Enum {
     readonly isFree: boolean;
     readonly isReserved: boolean;
     readonly type: 'Free' | 'Reserved';
   }
 
-  /** @name PalletTransactionPaymentEvent (32) */
+  /** @name PalletTransactionPaymentEvent (34) */
   interface PalletTransactionPaymentEvent extends Enum {
     readonly isTransactionFeePaid: boolean;
     readonly asTransactionFeePaid: {
@@ -273,7 +314,7 @@
     readonly type: 'TransactionFeePaid';
   }
 
-  /** @name PalletTreasuryEvent (33) */
+  /** @name PalletTreasuryEvent (35) */
   interface PalletTreasuryEvent extends Enum {
     readonly isProposed: boolean;
     readonly asProposed: {
@@ -312,10 +353,15 @@
       readonly amount: u128;
       readonly beneficiary: AccountId32;
     } & Struct;
-    readonly type: 'Proposed' | 'Spending' | 'Awarded' | 'Rejected' | 'Burnt' | 'Rollover' | 'Deposit' | 'SpendApproved';
+    readonly isUpdatedInactive: boolean;
+    readonly asUpdatedInactive: {
+      readonly reactivated: u128;
+      readonly deactivated: u128;
+    } & Struct;
+    readonly type: 'Proposed' | 'Spending' | 'Awarded' | 'Rejected' | 'Burnt' | 'Rollover' | 'Deposit' | 'SpendApproved' | 'UpdatedInactive';
   }
 
-  /** @name PalletSudoEvent (34) */
+  /** @name PalletSudoEvent (36) */
   interface PalletSudoEvent extends Enum {
     readonly isSudid: boolean;
     readonly asSudid: {
@@ -332,7 +378,7 @@
     readonly type: 'Sudid' | 'KeyChanged' | 'SudoAsDone';
   }
 
-  /** @name OrmlVestingModuleEvent (38) */
+  /** @name OrmlVestingModuleEvent (40) */
   interface OrmlVestingModuleEvent extends Enum {
     readonly isVestingScheduleAdded: boolean;
     readonly asVestingScheduleAdded: {
@@ -352,7 +398,7 @@
     readonly type: 'VestingScheduleAdded' | 'Claimed' | 'VestingSchedulesUpdated';
   }
 
-  /** @name OrmlVestingVestingSchedule (39) */
+  /** @name OrmlVestingVestingSchedule (41) */
   interface OrmlVestingVestingSchedule extends Struct {
     readonly start: u32;
     readonly period: u32;
@@ -360,7 +406,7 @@
     readonly perPeriod: Compact<u128>;
   }
 
-  /** @name OrmlXtokensModuleEvent (41) */
+  /** @name OrmlXtokensModuleEvent (43) */
   interface OrmlXtokensModuleEvent extends Enum {
     readonly isTransferredMultiAssets: boolean;
     readonly asTransferredMultiAssets: {
@@ -372,16 +418,16 @@
     readonly type: 'TransferredMultiAssets';
   }
 
-  /** @name XcmV1MultiassetMultiAssets (42) */
+  /** @name XcmV1MultiassetMultiAssets (44) */
   interface XcmV1MultiassetMultiAssets extends Vec<XcmV1MultiAsset> {}
 
-  /** @name XcmV1MultiAsset (44) */
+  /** @name XcmV1MultiAsset (46) */
   interface XcmV1MultiAsset extends Struct {
     readonly id: XcmV1MultiassetAssetId;
     readonly fun: XcmV1MultiassetFungibility;
   }
 
-  /** @name XcmV1MultiassetAssetId (45) */
+  /** @name XcmV1MultiassetAssetId (47) */
   interface XcmV1MultiassetAssetId extends Enum {
     readonly isConcrete: boolean;
     readonly asConcrete: XcmV1MultiLocation;
@@ -390,13 +436,13 @@
     readonly type: 'Concrete' | 'Abstract';
   }
 
-  /** @name XcmV1MultiLocation (46) */
+  /** @name XcmV1MultiLocation (48) */
   interface XcmV1MultiLocation extends Struct {
     readonly parents: u8;
     readonly interior: XcmV1MultilocationJunctions;
   }
 
-  /** @name XcmV1MultilocationJunctions (47) */
+  /** @name XcmV1MultilocationJunctions (49) */
   interface XcmV1MultilocationJunctions extends Enum {
     readonly isHere: boolean;
     readonly isX1: boolean;
@@ -418,7 +464,7 @@
     readonly type: 'Here' | 'X1' | 'X2' | 'X3' | 'X4' | 'X5' | 'X6' | 'X7' | 'X8';
   }
 
-  /** @name XcmV1Junction (48) */
+  /** @name XcmV1Junction (50) */
   interface XcmV1Junction extends Enum {
     readonly isParachain: boolean;
     readonly asParachain: Compact<u32>;
@@ -452,7 +498,7 @@
     readonly type: 'Parachain' | 'AccountId32' | 'AccountIndex64' | 'AccountKey20' | 'PalletInstance' | 'GeneralIndex' | 'GeneralKey' | 'OnlyChild' | 'Plurality';
   }
 
-  /** @name XcmV0JunctionNetworkId (50) */
+  /** @name XcmV0JunctionNetworkId (52) */
   interface XcmV0JunctionNetworkId extends Enum {
     readonly isAny: boolean;
     readonly isNamed: boolean;
@@ -462,7 +508,7 @@
     readonly type: 'Any' | 'Named' | 'Polkadot' | 'Kusama';
   }
 
-  /** @name XcmV0JunctionBodyId (53) */
+  /** @name XcmV0JunctionBodyId (55) */
   interface XcmV0JunctionBodyId extends Enum {
     readonly isUnit: boolean;
     readonly isNamed: boolean;
@@ -473,10 +519,13 @@
     readonly isTechnical: boolean;
     readonly isLegislative: boolean;
     readonly isJudicial: boolean;
-    readonly type: 'Unit' | 'Named' | 'Index' | 'Executive' | 'Technical' | 'Legislative' | 'Judicial';
+    readonly isDefense: boolean;
+    readonly isAdministration: boolean;
+    readonly isTreasury: boolean;
+    readonly type: 'Unit' | 'Named' | 'Index' | 'Executive' | 'Technical' | 'Legislative' | 'Judicial' | 'Defense' | 'Administration' | 'Treasury';
   }
 
-  /** @name XcmV0JunctionBodyPart (54) */
+  /** @name XcmV0JunctionBodyPart (56) */
   interface XcmV0JunctionBodyPart extends Enum {
     readonly isVoice: boolean;
     readonly isMembers: boolean;
@@ -501,7 +550,7 @@
     readonly type: 'Voice' | 'Members' | 'Fraction' | 'AtLeastProportion' | 'MoreThanProportion';
   }
 
-  /** @name XcmV1MultiassetFungibility (55) */
+  /** @name XcmV1MultiassetFungibility (57) */
   interface XcmV1MultiassetFungibility extends Enum {
     readonly isFungible: boolean;
     readonly asFungible: Compact<u128>;
@@ -510,7 +559,7 @@
     readonly type: 'Fungible' | 'NonFungible';
   }
 
-  /** @name XcmV1MultiassetAssetInstance (56) */
+  /** @name XcmV1MultiassetAssetInstance (58) */
   interface XcmV1MultiassetAssetInstance extends Enum {
     readonly isUndefined: boolean;
     readonly isIndex: boolean;
@@ -528,7 +577,7 @@
     readonly type: 'Undefined' | 'Index' | 'Array4' | 'Array8' | 'Array16' | 'Array32' | 'Blob';
   }
 
-  /** @name OrmlTokensModuleEvent (59) */
+  /** @name OrmlTokensModuleEvent (61) */
   interface OrmlTokensModuleEvent extends Enum {
     readonly isEndowed: boolean;
     readonly asEndowed: {
@@ -616,7 +665,7 @@
     readonly type: 'Endowed' | 'DustLost' | 'Transfer' | 'Reserved' | 'Unreserved' | 'ReserveRepatriated' | 'BalanceSet' | 'TotalIssuanceSet' | 'Withdrawn' | 'Slashed' | 'Deposited' | 'LockSet' | 'LockRemoved';
   }
 
-  /** @name PalletForeignAssetsAssetIds (60) */
+  /** @name PalletForeignAssetsAssetIds (62) */
   interface PalletForeignAssetsAssetIds extends Enum {
     readonly isForeignAssetId: boolean;
     readonly asForeignAssetId: u32;
@@ -625,14 +674,99 @@
     readonly type: 'ForeignAssetId' | 'NativeAssetId';
   }
 
-  /** @name PalletForeignAssetsNativeCurrency (61) */
+  /** @name PalletForeignAssetsNativeCurrency (63) */
   interface PalletForeignAssetsNativeCurrency extends Enum {
     readonly isHere: boolean;
     readonly isParent: boolean;
     readonly type: 'Here' | 'Parent';
   }
 
-  /** @name CumulusPalletXcmpQueueEvent (62) */
+  /** @name PalletIdentityEvent (64) */
+  interface PalletIdentityEvent extends Enum {
+    readonly isIdentitySet: boolean;
+    readonly asIdentitySet: {
+      readonly who: AccountId32;
+    } & Struct;
+    readonly isIdentityCleared: boolean;
+    readonly asIdentityCleared: {
+      readonly who: AccountId32;
+      readonly deposit: u128;
+    } & Struct;
+    readonly isIdentityKilled: boolean;
+    readonly asIdentityKilled: {
+      readonly who: AccountId32;
+      readonly deposit: u128;
+    } & Struct;
+    readonly isIdentitiesInserted: boolean;
+    readonly asIdentitiesInserted: {
+      readonly amount: u32;
+    } & Struct;
+    readonly isIdentitiesRemoved: boolean;
+    readonly asIdentitiesRemoved: {
+      readonly amount: u32;
+    } & Struct;
+    readonly isJudgementRequested: boolean;
+    readonly asJudgementRequested: {
+      readonly who: AccountId32;
+      readonly registrarIndex: u32;
+    } & Struct;
+    readonly isJudgementUnrequested: boolean;
+    readonly asJudgementUnrequested: {
+      readonly who: AccountId32;
+      readonly registrarIndex: u32;
+    } & Struct;
+    readonly isJudgementGiven: boolean;
+    readonly asJudgementGiven: {
+      readonly target: AccountId32;
+      readonly registrarIndex: u32;
+    } & Struct;
+    readonly isRegistrarAdded: boolean;
+    readonly asRegistrarAdded: {
+      readonly registrarIndex: u32;
+    } & Struct;
+    readonly isSubIdentityAdded: boolean;
+    readonly asSubIdentityAdded: {
+      readonly sub: AccountId32;
+      readonly main: AccountId32;
+      readonly deposit: u128;
+    } & Struct;
+    readonly isSubIdentityRemoved: boolean;
+    readonly asSubIdentityRemoved: {
+      readonly sub: AccountId32;
+      readonly main: AccountId32;
+      readonly deposit: u128;
+    } & Struct;
+    readonly isSubIdentityRevoked: boolean;
+    readonly asSubIdentityRevoked: {
+      readonly sub: AccountId32;
+      readonly main: AccountId32;
+      readonly deposit: u128;
+    } & Struct;
+    readonly isSubIdentitiesInserted: boolean;
+    readonly asSubIdentitiesInserted: {
+      readonly amount: u32;
+    } & Struct;
+    readonly type: 'IdentitySet' | 'IdentityCleared' | 'IdentityKilled' | 'IdentitiesInserted' | 'IdentitiesRemoved' | 'JudgementRequested' | 'JudgementUnrequested' | 'JudgementGiven' | 'RegistrarAdded' | 'SubIdentityAdded' | 'SubIdentityRemoved' | 'SubIdentityRevoked' | 'SubIdentitiesInserted';
+  }
+
+  /** @name PalletPreimageEvent (65) */
+  interface PalletPreimageEvent extends Enum {
+    readonly isNoted: boolean;
+    readonly asNoted: {
+      readonly hash_: H256;
+    } & Struct;
+    readonly isRequested: boolean;
+    readonly asRequested: {
+      readonly hash_: H256;
+    } & Struct;
+    readonly isCleared: boolean;
+    readonly asCleared: {
+      readonly hash_: H256;
+    } & Struct;
+    readonly type: 'Noted' | 'Requested' | 'Cleared';
+  }
+
+  /** @name CumulusPalletXcmpQueueEvent (66) */
   interface CumulusPalletXcmpQueueEvent extends Enum {
     readonly isSuccess: boolean;
     readonly asSuccess: {
@@ -676,7 +810,7 @@
     readonly type: 'Success' | 'Fail' | 'BadVersion' | 'BadFormat' | 'UpwardMessageSent' | 'XcmpMessageSent' | 'OverweightEnqueued' | 'OverweightServiced';
   }
 
-  /** @name XcmV2TraitsError (64) */
+  /** @name XcmV2TraitsError (68) */
   interface XcmV2TraitsError extends Enum {
     readonly isOverflow: boolean;
     readonly isUnimplemented: boolean;
@@ -709,7 +843,7 @@
     readonly type: 'Overflow' | 'Unimplemented' | 'UntrustedReserveLocation' | 'UntrustedTeleportLocation' | 'MultiLocationFull' | 'MultiLocationNotInvertible' | 'BadOrigin' | 'InvalidLocation' | 'AssetNotFound' | 'FailedToTransactAsset' | 'NotWithdrawable' | 'LocationCannotHold' | 'ExceedsMaxMessageSize' | 'DestinationUnsupported' | 'Transport' | 'Unroutable' | 'UnknownClaim' | 'FailedToDecode' | 'MaxWeightInvalid' | 'NotHoldingFees' | 'TooExpensive' | 'Trap' | 'UnhandledXcmVersion' | 'WeightLimitReached' | 'Barrier' | 'WeightNotComputable';
   }
 
-  /** @name PalletXcmEvent (66) */
+  /** @name PalletXcmEvent (70) */
   interface PalletXcmEvent extends Enum {
     readonly isAttempted: boolean;
     readonly asAttempted: XcmV2TraitsOutcome;
@@ -748,7 +882,7 @@
     readonly type: 'Attempted' | 'Sent' | 'UnexpectedResponse' | 'ResponseReady' | 'Notified' | 'NotifyOverweight' | 'NotifyDispatchError' | 'NotifyDecodeFailed' | 'InvalidResponder' | 'InvalidResponderVersion' | 'ResponseTaken' | 'AssetsTrapped' | 'VersionChangeNotified' | 'SupportedVersionChanged' | 'NotifyTargetSendFail' | 'NotifyTargetMigrationFail' | 'AssetsClaimed';
   }
 
-  /** @name XcmV2TraitsOutcome (67) */
+  /** @name XcmV2TraitsOutcome (71) */
   interface XcmV2TraitsOutcome extends Enum {
     readonly isComplete: boolean;
     readonly asComplete: u64;
@@ -759,10 +893,10 @@
     readonly type: 'Complete' | 'Incomplete' | 'Error';
   }
 
-  /** @name XcmV2Xcm (68) */
+  /** @name XcmV2Xcm (72) */
   interface XcmV2Xcm extends Vec<XcmV2Instruction> {}
 
-  /** @name XcmV2Instruction (70) */
+  /** @name XcmV2Instruction (74) */
   interface XcmV2Instruction extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: XcmV1MultiassetMultiAssets;
@@ -882,7 +1016,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'ClearOrigin' | 'DescendOrigin' | 'ReportError' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution' | 'RefundSurplus' | 'SetErrorHandler' | 'SetAppendix' | 'ClearError' | 'ClaimAsset' | 'Trap' | 'SubscribeVersion' | 'UnsubscribeVersion';
   }
 
-  /** @name XcmV2Response (71) */
+  /** @name XcmV2Response (75) */
   interface XcmV2Response extends Enum {
     readonly isNull: boolean;
     readonly isAssets: boolean;
@@ -894,7 +1028,7 @@
     readonly type: 'Null' | 'Assets' | 'ExecutionResult' | 'Version';
   }
 
-  /** @name XcmV0OriginKind (74) */
+  /** @name XcmV0OriginKind (78) */
   interface XcmV0OriginKind extends Enum {
     readonly isNative: boolean;
     readonly isSovereignAccount: boolean;
@@ -903,12 +1037,12 @@
     readonly type: 'Native' | 'SovereignAccount' | 'Superuser' | 'Xcm';
   }
 
-  /** @name XcmDoubleEncoded (75) */
+  /** @name XcmDoubleEncoded (79) */
   interface XcmDoubleEncoded extends Struct {
     readonly encoded: Bytes;
   }
 
-  /** @name XcmV1MultiassetMultiAssetFilter (76) */
+  /** @name XcmV1MultiassetMultiAssetFilter (80) */
   interface XcmV1MultiassetMultiAssetFilter extends Enum {
     readonly isDefinite: boolean;
     readonly asDefinite: XcmV1MultiassetMultiAssets;
@@ -917,7 +1051,7 @@
     readonly type: 'Definite' | 'Wild';
   }
 
-  /** @name XcmV1MultiassetWildMultiAsset (77) */
+  /** @name XcmV1MultiassetWildMultiAsset (81) */
   interface XcmV1MultiassetWildMultiAsset extends Enum {
     readonly isAll: boolean;
     readonly isAllOf: boolean;
@@ -928,14 +1062,14 @@
     readonly type: 'All' | 'AllOf';
   }
 
-  /** @name XcmV1MultiassetWildFungibility (78) */
+  /** @name XcmV1MultiassetWildFungibility (82) */
   interface XcmV1MultiassetWildFungibility extends Enum {
     readonly isFungible: boolean;
     readonly isNonFungible: boolean;
     readonly type: 'Fungible' | 'NonFungible';
   }
 
-  /** @name XcmV2WeightLimit (79) */
+  /** @name XcmV2WeightLimit (83) */
   interface XcmV2WeightLimit extends Enum {
     readonly isUnlimited: boolean;
     readonly isLimited: boolean;
@@ -943,7 +1077,7 @@
     readonly type: 'Unlimited' | 'Limited';
   }
 
-  /** @name XcmVersionedMultiAssets (81) */
+  /** @name XcmVersionedMultiAssets (85) */
   interface XcmVersionedMultiAssets extends Enum {
     readonly isV0: boolean;
     readonly asV0: Vec<XcmV0MultiAsset>;
@@ -952,7 +1086,7 @@
     readonly type: 'V0' | 'V1';
   }
 
-  /** @name XcmV0MultiAsset (83) */
+  /** @name XcmV0MultiAsset (87) */
   interface XcmV0MultiAsset extends Enum {
     readonly isNone: boolean;
     readonly isAll: boolean;
@@ -997,7 +1131,7 @@
     readonly type: 'None' | 'All' | 'AllFungible' | 'AllNonFungible' | 'AllAbstractFungible' | 'AllAbstractNonFungible' | 'AllConcreteFungible' | 'AllConcreteNonFungible' | 'AbstractFungible' | 'AbstractNonFungible' | 'ConcreteFungible' | 'ConcreteNonFungible';
   }
 
-  /** @name XcmV0MultiLocation (84) */
+  /** @name XcmV0MultiLocation (88) */
   interface XcmV0MultiLocation extends Enum {
     readonly isNull: boolean;
     readonly isX1: boolean;
@@ -1019,7 +1153,7 @@
     readonly type: 'Null' | 'X1' | 'X2' | 'X3' | 'X4' | 'X5' | 'X6' | 'X7' | 'X8';
   }
 
-  /** @name XcmV0Junction (85) */
+  /** @name XcmV0Junction (89) */
   interface XcmV0Junction extends Enum {
     readonly isParent: boolean;
     readonly isParachain: boolean;
@@ -1054,7 +1188,7 @@
     readonly type: 'Parent' | 'Parachain' | 'AccountId32' | 'AccountIndex64' | 'AccountKey20' | 'PalletInstance' | 'GeneralIndex' | 'GeneralKey' | 'OnlyChild' | 'Plurality';
   }
 
-  /** @name XcmVersionedMultiLocation (86) */
+  /** @name XcmVersionedMultiLocation (90) */
   interface XcmVersionedMultiLocation extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0MultiLocation;
@@ -1063,7 +1197,7 @@
     readonly type: 'V0' | 'V1';
   }
 
-  /** @name CumulusPalletXcmEvent (87) */
+  /** @name CumulusPalletXcmEvent (91) */
   interface CumulusPalletXcmEvent extends Enum {
     readonly isInvalidFormat: boolean;
     readonly asInvalidFormat: U8aFixed;
@@ -1074,7 +1208,7 @@
     readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward';
   }
 
-  /** @name CumulusPalletDmpQueueEvent (88) */
+  /** @name CumulusPalletDmpQueueEvent (92) */
   interface CumulusPalletDmpQueueEvent extends Enum {
     readonly isInvalidFormat: boolean;
     readonly asInvalidFormat: {
@@ -1109,7 +1243,7 @@
     readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward' | 'WeightExhausted' | 'OverweightEnqueued' | 'OverweightServiced';
   }
 
-  /** @name PalletConfigurationEvent (89) */
+  /** @name PalletConfigurationEvent (93) */
   interface PalletConfigurationEvent extends Enum {
     readonly isNewDesiredCollators: boolean;
     readonly asNewDesiredCollators: {
@@ -1126,7 +1260,7 @@
     readonly type: 'NewDesiredCollators' | 'NewCollatorLicenseBond' | 'NewCollatorKickThreshold';
   }
 
-  /** @name PalletCommonEvent (92) */
+  /** @name PalletCommonEvent (96) */
   interface PalletCommonEvent extends Enum {
     readonly isCollectionCreated: boolean;
     readonly asCollectionCreated: ITuple<[u32, u8, AccountId32]>;
@@ -1175,7 +1309,7 @@
     readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'ApprovedForAll' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet' | 'AllowListAddressAdded' | 'AllowListAddressRemoved' | 'CollectionAdminAdded' | 'CollectionAdminRemoved' | 'CollectionLimitSet' | 'CollectionOwnerChanged' | 'CollectionPermissionSet' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionSponsorRemoved';
   }
 
-  /** @name PalletEvmAccountBasicCrossAccountIdRepr (95) */
+  /** @name PalletEvmAccountBasicCrossAccountIdRepr (99) */
   interface PalletEvmAccountBasicCrossAccountIdRepr extends Enum {
     readonly isSubstrate: boolean;
     readonly asSubstrate: AccountId32;
@@ -1184,128 +1318,14 @@
     readonly type: 'Substrate' | 'Ethereum';
   }
 
-  /** @name PalletStructureEvent (99) */
+  /** @name PalletStructureEvent (103) */
   interface PalletStructureEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: Result<Null, SpRuntimeDispatchError>;
     readonly type: 'Executed';
   }
 
-  /** @name PalletRmrkCoreEvent (100) */
-  interface PalletRmrkCoreEvent extends Enum {
-    readonly isCollectionCreated: boolean;
-    readonly asCollectionCreated: {
-      readonly issuer: AccountId32;
-      readonly collectionId: u32;
-    } & Struct;
-    readonly isCollectionDestroyed: boolean;
-    readonly asCollectionDestroyed: {
-      readonly issuer: AccountId32;
-      readonly collectionId: u32;
-    } & Struct;
-    readonly isIssuerChanged: boolean;
-    readonly asIssuerChanged: {
-      readonly oldIssuer: AccountId32;
-      readonly newIssuer: AccountId32;
-      readonly collectionId: u32;
-    } & Struct;
-    readonly isCollectionLocked: boolean;
-    readonly asCollectionLocked: {
-      readonly issuer: AccountId32;
-      readonly collectionId: u32;
-    } & Struct;
-    readonly isNftMinted: boolean;
-    readonly asNftMinted: {
-      readonly owner: AccountId32;
-      readonly collectionId: u32;
-      readonly nftId: u32;
-    } & Struct;
-    readonly isNftBurned: boolean;
-    readonly asNftBurned: {
-      readonly owner: AccountId32;
-      readonly nftId: u32;
-    } & Struct;
-    readonly isNftSent: boolean;
-    readonly asNftSent: {
-      readonly sender: AccountId32;
-      readonly recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-      readonly collectionId: u32;
-      readonly nftId: u32;
-      readonly approvalRequired: bool;
-    } & Struct;
-    readonly isNftAccepted: boolean;
-    readonly asNftAccepted: {
-      readonly sender: AccountId32;
-      readonly recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-      readonly collectionId: u32;
-      readonly nftId: u32;
-    } & Struct;
-    readonly isNftRejected: boolean;
-    readonly asNftRejected: {
-      readonly sender: AccountId32;
-      readonly collectionId: u32;
-      readonly nftId: u32;
-    } & Struct;
-    readonly isPropertySet: boolean;
-    readonly asPropertySet: {
-      readonly collectionId: u32;
-      readonly maybeNftId: Option<u32>;
-      readonly key: Bytes;
-      readonly value: Bytes;
-    } & Struct;
-    readonly isResourceAdded: boolean;
-    readonly asResourceAdded: {
-      readonly nftId: u32;
-      readonly resourceId: u32;
-    } & Struct;
-    readonly isResourceRemoval: boolean;
-    readonly asResourceRemoval: {
-      readonly nftId: u32;
-      readonly resourceId: u32;
-    } & Struct;
-    readonly isResourceAccepted: boolean;
-    readonly asResourceAccepted: {
-      readonly nftId: u32;
-      readonly resourceId: u32;
-    } & Struct;
-    readonly isResourceRemovalAccepted: boolean;
-    readonly asResourceRemovalAccepted: {
-      readonly nftId: u32;
-      readonly resourceId: u32;
-    } & Struct;
-    readonly isPrioritySet: boolean;
-    readonly asPrioritySet: {
-      readonly collectionId: u32;
-      readonly nftId: u32;
-    } & Struct;
-    readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet';
-  }
-
-  /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (101) */
-  interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum {
-    readonly isAccountId: boolean;
-    readonly asAccountId: AccountId32;
-    readonly isCollectionAndNftTuple: boolean;
-    readonly asCollectionAndNftTuple: ITuple<[u32, u32]>;
-    readonly type: 'AccountId' | 'CollectionAndNftTuple';
-  }
-
-  /** @name PalletRmrkEquipEvent (104) */
-  interface PalletRmrkEquipEvent extends Enum {
-    readonly isBaseCreated: boolean;
-    readonly asBaseCreated: {
-      readonly issuer: AccountId32;
-      readonly baseId: u32;
-    } & Struct;
-    readonly isEquippablesUpdated: boolean;
-    readonly asEquippablesUpdated: {
-      readonly baseId: u32;
-      readonly slotId: u32;
-    } & Struct;
-    readonly type: 'BaseCreated' | 'EquippablesUpdated';
-  }
-
-  /** @name PalletAppPromotionEvent (105) */
+  /** @name PalletAppPromotionEvent (104) */
   interface PalletAppPromotionEvent extends Enum {
     readonly isStakingRecalculation: boolean;
     readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>;
@@ -1318,7 +1338,7 @@
     readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin';
   }
 
-  /** @name PalletForeignAssetsModuleEvent (106) */
+  /** @name PalletForeignAssetsModuleEvent (105) */
   interface PalletForeignAssetsModuleEvent extends Enum {
     readonly isForeignAssetRegistered: boolean;
     readonly asForeignAssetRegistered: {
@@ -1345,7 +1365,7 @@
     readonly type: 'ForeignAssetRegistered' | 'ForeignAssetUpdated' | 'AssetRegistered' | 'AssetUpdated';
   }
 
-  /** @name PalletForeignAssetsModuleAssetMetadata (107) */
+  /** @name PalletForeignAssetsModuleAssetMetadata (106) */
   interface PalletForeignAssetsModuleAssetMetadata extends Struct {
     readonly name: Bytes;
     readonly symbol: Bytes;
@@ -1353,7 +1373,7 @@
     readonly minimalBalance: u128;
   }
 
-  /** @name PalletEvmEvent (108) */
+  /** @name PalletEvmEvent (107) */
   interface PalletEvmEvent extends Enum {
     readonly isLog: boolean;
     readonly asLog: {
@@ -1378,14 +1398,14 @@
     readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed';
   }
 
-  /** @name EthereumLog (109) */
+  /** @name EthereumLog (108) */
   interface EthereumLog extends Struct {
     readonly address: H160;
     readonly topics: Vec<H256>;
     readonly data: Bytes;
   }
 
-  /** @name PalletEthereumEvent (111) */
+  /** @name PalletEthereumEvent (110) */
   interface PalletEthereumEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: {
@@ -1397,7 +1417,7 @@
     readonly type: 'Executed';
   }
 
-  /** @name EvmCoreErrorExitReason (112) */
+  /** @name EvmCoreErrorExitReason (111) */
   interface EvmCoreErrorExitReason extends Enum {
     readonly isSucceed: boolean;
     readonly asSucceed: EvmCoreErrorExitSucceed;
@@ -1410,7 +1430,7 @@
     readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal';
   }
 
-  /** @name EvmCoreErrorExitSucceed (113) */
+  /** @name EvmCoreErrorExitSucceed (112) */
   interface EvmCoreErrorExitSucceed extends Enum {
     readonly isStopped: boolean;
     readonly isReturned: boolean;
@@ -1418,7 +1438,7 @@
     readonly type: 'Stopped' | 'Returned' | 'Suicided';
   }
 
-  /** @name EvmCoreErrorExitError (114) */
+  /** @name EvmCoreErrorExitError (113) */
   interface EvmCoreErrorExitError extends Enum {
     readonly isStackUnderflow: boolean;
     readonly isStackOverflow: boolean;
@@ -1436,6 +1456,7 @@
     readonly isOther: boolean;
     readonly asOther: Text;
     readonly isInvalidCode: boolean;
+    readonly asInvalidCode: u8;
     readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
   }
 
@@ -1714,14 +1735,130 @@
     readonly type: 'OverlappingUpgrades' | 'ProhibitedByPolkadot' | 'TooBig' | 'ValidationDataNotAvailable' | 'HostConfigurationNotAvailable' | 'NotScheduled' | 'NothingAuthorized' | 'Unauthorized';
   }
 
-  /** @name PalletBalancesBalanceLock (172) */
+  /** @name PalletAuthorshipUncleEntryItem (172) */
+  interface PalletAuthorshipUncleEntryItem extends Enum {
+    readonly isInclusionHeight: boolean;
+    readonly asInclusionHeight: u32;
+    readonly isUncle: boolean;
+    readonly asUncle: ITuple<[H256, Option<AccountId32>]>;
+    readonly type: 'InclusionHeight' | 'Uncle';
+  }
+
+  /** @name PalletAuthorshipCall (174) */
+  interface PalletAuthorshipCall extends Enum {
+    readonly isSetUncles: boolean;
+    readonly asSetUncles: {
+      readonly newUncles: Vec<SpRuntimeHeader>;
+    } & Struct;
+    readonly type: 'SetUncles';
+  }
+
+  /** @name SpRuntimeHeader (176) */
+  interface SpRuntimeHeader extends Struct {
+    readonly parentHash: H256;
+    readonly number: Compact<u32>;
+    readonly stateRoot: H256;
+    readonly extrinsicsRoot: H256;
+    readonly digest: SpRuntimeDigest;
+  }
+
+  /** @name SpRuntimeBlakeTwo256 (177) */
+  type SpRuntimeBlakeTwo256 = Null;
+
+  /** @name PalletAuthorshipError (178) */
+  interface PalletAuthorshipError extends Enum {
+    readonly isInvalidUncleParent: boolean;
+    readonly isUnclesAlreadySet: boolean;
+    readonly isTooManyUncles: boolean;
+    readonly isGenesisUncle: boolean;
+    readonly isTooHighUncle: boolean;
+    readonly isUncleAlreadyIncluded: boolean;
+    readonly isOldUncle: boolean;
+    readonly type: 'InvalidUncleParent' | 'UnclesAlreadySet' | 'TooManyUncles' | 'GenesisUncle' | 'TooHighUncle' | 'UncleAlreadyIncluded' | 'OldUncle';
+  }
+
+  /** @name PalletCollatorSelectionCall (181) */
+  interface PalletCollatorSelectionCall extends Enum {
+    readonly isAddInvulnerable: boolean;
+    readonly asAddInvulnerable: {
+      readonly new_: AccountId32;
+    } & Struct;
+    readonly isRemoveInvulnerable: boolean;
+    readonly asRemoveInvulnerable: {
+      readonly who: AccountId32;
+    } & Struct;
+    readonly isGetLicense: boolean;
+    readonly isOnboard: boolean;
+    readonly isOffboard: boolean;
+    readonly isReleaseLicense: boolean;
+    readonly isForceReleaseLicense: boolean;
+    readonly asForceReleaseLicense: {
+      readonly who: AccountId32;
+    } & Struct;
+    readonly type: 'AddInvulnerable' | 'RemoveInvulnerable' | 'GetLicense' | 'Onboard' | 'Offboard' | 'ReleaseLicense' | 'ForceReleaseLicense';
+  }
+
+  /** @name PalletCollatorSelectionError (182) */
+  interface PalletCollatorSelectionError extends Enum {
+    readonly isTooManyCandidates: boolean;
+    readonly isUnknown: boolean;
+    readonly isPermission: boolean;
+    readonly isAlreadyHoldingLicense: boolean;
+    readonly isNoLicense: boolean;
+    readonly isAlreadyCandidate: boolean;
+    readonly isNotCandidate: boolean;
+    readonly isTooManyInvulnerables: boolean;
+    readonly isTooFewInvulnerables: boolean;
+    readonly isAlreadyInvulnerable: boolean;
+    readonly isNotInvulnerable: boolean;
+    readonly isNoAssociatedValidatorId: boolean;
+    readonly isValidatorNotRegistered: boolean;
+    readonly type: 'TooManyCandidates' | 'Unknown' | 'Permission' | 'AlreadyHoldingLicense' | 'NoLicense' | 'AlreadyCandidate' | 'NotCandidate' | 'TooManyInvulnerables' | 'TooFewInvulnerables' | 'AlreadyInvulnerable' | 'NotInvulnerable' | 'NoAssociatedValidatorId' | 'ValidatorNotRegistered';
+  }
+
+  /** @name OpalRuntimeRuntimeCommonSessionKeys (185) */
+  interface OpalRuntimeRuntimeCommonSessionKeys extends Struct {
+    readonly aura: SpConsensusAuraSr25519AppSr25519Public;
+  }
+
+  /** @name SpConsensusAuraSr25519AppSr25519Public (186) */
+  interface SpConsensusAuraSr25519AppSr25519Public extends SpCoreSr25519Public {}
+
+  /** @name SpCoreSr25519Public (187) */
+  interface SpCoreSr25519Public extends U8aFixed {}
+
+  /** @name SpCoreCryptoKeyTypeId (190) */
+  interface SpCoreCryptoKeyTypeId extends U8aFixed {}
+
+  /** @name PalletSessionCall (191) */
+  interface PalletSessionCall extends Enum {
+    readonly isSetKeys: boolean;
+    readonly asSetKeys: {
+      readonly keys_: OpalRuntimeRuntimeCommonSessionKeys;
+      readonly proof: Bytes;
+    } & Struct;
+    readonly isPurgeKeys: boolean;
+    readonly type: 'SetKeys' | 'PurgeKeys';
+  }
+
+  /** @name PalletSessionError (192) */
+  interface PalletSessionError extends Enum {
+    readonly isInvalidProof: boolean;
+    readonly isNoAssociatedValidatorId: boolean;
+    readonly isDuplicatedKey: boolean;
+    readonly isNoKeys: boolean;
+    readonly isNoAccount: boolean;
+    readonly type: 'InvalidProof' | 'NoAssociatedValidatorId' | 'DuplicatedKey' | 'NoKeys' | 'NoAccount';
+  }
+
+  /** @name PalletBalancesBalanceLock (194) */
   interface PalletBalancesBalanceLock extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
     readonly reasons: PalletBalancesReasons;
   }
 
-  /** @name PalletBalancesReasons (173) */
+  /** @name PalletBalancesReasons (195) */
   interface PalletBalancesReasons extends Enum {
     readonly isFee: boolean;
     readonly isMisc: boolean;
@@ -1729,13 +1866,13 @@
     readonly type: 'Fee' | 'Misc' | 'All';
   }
 
-  /** @name PalletBalancesReserveData (176) */
+  /** @name PalletBalancesReserveData (198) */
   interface PalletBalancesReserveData extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
   }
 
-  /** @name PalletBalancesCall (178) */
+  /** @name PalletBalancesCall (200) */
   interface PalletBalancesCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1772,7 +1909,7 @@
     readonly type: 'Transfer' | 'SetBalance' | 'ForceTransfer' | 'TransferKeepAlive' | 'TransferAll' | 'ForceUnreserve';
   }
 
-  /** @name PalletBalancesError (181) */
+  /** @name PalletBalancesError (203) */
   interface PalletBalancesError extends Enum {
     readonly isVestingBalance: boolean;
     readonly isLiquidityRestrictions: boolean;
@@ -1785,7 +1922,7 @@
     readonly type: 'VestingBalance' | 'LiquidityRestrictions' | 'InsufficientBalance' | 'ExistentialDeposit' | 'KeepAlive' | 'ExistingVestingSchedule' | 'DeadAccount' | 'TooManyReserves';
   }
 
-  /** @name PalletTimestampCall (183) */
+  /** @name PalletTimestampCall (205) */
   interface PalletTimestampCall extends Enum {
     readonly isSet: boolean;
     readonly asSet: {
@@ -1794,14 +1931,14 @@
     readonly type: 'Set';
   }
 
-  /** @name PalletTransactionPaymentReleases (185) */
+  /** @name PalletTransactionPaymentReleases (207) */
   interface PalletTransactionPaymentReleases extends Enum {
     readonly isV1Ancient: boolean;
     readonly isV2: boolean;
     readonly type: 'V1Ancient' | 'V2';
   }
 
-  /** @name PalletTreasuryProposal (186) */
+  /** @name PalletTreasuryProposal (208) */
   interface PalletTreasuryProposal extends Struct {
     readonly proposer: AccountId32;
     readonly value: u128;
@@ -1809,7 +1946,7 @@
     readonly bond: u128;
   }
 
-  /** @name PalletTreasuryCall (189) */
+  /** @name PalletTreasuryCall (210) */
   interface PalletTreasuryCall extends Enum {
     readonly isProposeSpend: boolean;
     readonly asProposeSpend: {
@@ -1836,10 +1973,10 @@
     readonly type: 'ProposeSpend' | 'RejectProposal' | 'ApproveProposal' | 'Spend' | 'RemoveApproval';
   }
 
-  /** @name FrameSupportPalletId (191) */
+  /** @name FrameSupportPalletId (212) */
   interface FrameSupportPalletId extends U8aFixed {}
 
-  /** @name PalletTreasuryError (192) */
+  /** @name PalletTreasuryError (213) */
   interface PalletTreasuryError extends Enum {
     readonly isInsufficientProposersBalance: boolean;
     readonly isInvalidIndex: boolean;
@@ -1849,7 +1986,7 @@
     readonly type: 'InsufficientProposersBalance' | 'InvalidIndex' | 'TooManyApprovals' | 'InsufficientPermission' | 'ProposalNotApproved';
   }
 
-  /** @name PalletSudoCall (193) */
+  /** @name PalletSudoCall (214) */
   interface PalletSudoCall extends Enum {
     readonly isSudo: boolean;
     readonly asSudo: {
@@ -1872,7 +2009,7 @@
     readonly type: 'Sudo' | 'SudoUncheckedWeight' | 'SetKey' | 'SudoAs';
   }
 
-  /** @name OrmlVestingModuleCall (195) */
+  /** @name OrmlVestingModuleCall (216) */
   interface OrmlVestingModuleCall extends Enum {
     readonly isClaim: boolean;
     readonly isVestedTransfer: boolean;
@@ -1892,7 +2029,7 @@
     readonly type: 'Claim' | 'VestedTransfer' | 'UpdateVestingSchedules' | 'ClaimFor';
   }
 
-  /** @name OrmlXtokensModuleCall (197) */
+  /** @name OrmlXtokensModuleCall (218) */
   interface OrmlXtokensModuleCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1939,7 +2076,7 @@
     readonly type: 'Transfer' | 'TransferMultiasset' | 'TransferWithFee' | 'TransferMultiassetWithFee' | 'TransferMulticurrencies' | 'TransferMultiassets';
   }
 
-  /** @name XcmVersionedMultiAsset (198) */
+  /** @name XcmVersionedMultiAsset (219) */
   interface XcmVersionedMultiAsset extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0MultiAsset;
@@ -1948,7 +2085,7 @@
     readonly type: 'V0' | 'V1';
   }
 
-  /** @name OrmlTokensModuleCall (201) */
+  /** @name OrmlTokensModuleCall (222) */
   interface OrmlTokensModuleCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1985,7 +2122,166 @@
     readonly type: 'Transfer' | 'TransferAll' | 'TransferKeepAlive' | 'ForceTransfer' | 'SetBalance';
   }
 
-  /** @name CumulusPalletXcmpQueueCall (202) */
+  /** @name PalletIdentityCall (223) */
+  interface PalletIdentityCall extends Enum {
+    readonly isAddRegistrar: boolean;
+    readonly asAddRegistrar: {
+      readonly account: MultiAddress;
+    } & Struct;
+    readonly isSetIdentity: boolean;
+    readonly asSetIdentity: {
+      readonly info: PalletIdentityIdentityInfo;
+    } & Struct;
+    readonly isSetSubs: boolean;
+    readonly asSetSubs: {
+      readonly subs: Vec<ITuple<[AccountId32, Data]>>;
+    } & Struct;
+    readonly isClearIdentity: boolean;
+    readonly isRequestJudgement: boolean;
+    readonly asRequestJudgement: {
+      readonly regIndex: Compact<u32>;
+      readonly maxFee: Compact<u128>;
+    } & Struct;
+    readonly isCancelRequest: boolean;
+    readonly asCancelRequest: {
+      readonly regIndex: u32;
+    } & Struct;
+    readonly isSetFee: boolean;
+    readonly asSetFee: {
+      readonly index: Compact<u32>;
+      readonly fee: Compact<u128>;
+    } & Struct;
+    readonly isSetAccountId: boolean;
+    readonly asSetAccountId: {
+      readonly index: Compact<u32>;
+      readonly new_: MultiAddress;
+    } & Struct;
+    readonly isSetFields: boolean;
+    readonly asSetFields: {
+      readonly index: Compact<u32>;
+      readonly fields: PalletIdentityBitFlags;
+    } & Struct;
+    readonly isProvideJudgement: boolean;
+    readonly asProvideJudgement: {
+      readonly regIndex: Compact<u32>;
+      readonly target: MultiAddress;
+      readonly judgement: PalletIdentityJudgement;
+      readonly identity: H256;
+    } & Struct;
+    readonly isKillIdentity: boolean;
+    readonly asKillIdentity: {
+      readonly target: MultiAddress;
+    } & Struct;
+    readonly isAddSub: boolean;
+    readonly asAddSub: {
+      readonly sub: MultiAddress;
+      readonly data: Data;
+    } & Struct;
+    readonly isRenameSub: boolean;
+    readonly asRenameSub: {
+      readonly sub: MultiAddress;
+      readonly data: Data;
+    } & Struct;
+    readonly isRemoveSub: boolean;
+    readonly asRemoveSub: {
+      readonly sub: MultiAddress;
+    } & Struct;
+    readonly isQuitSub: boolean;
+    readonly isForceInsertIdentities: boolean;
+    readonly asForceInsertIdentities: {
+      readonly identities: Vec<ITuple<[AccountId32, PalletIdentityRegistration]>>;
+    } & Struct;
+    readonly isForceRemoveIdentities: boolean;
+    readonly asForceRemoveIdentities: {
+      readonly identities: Vec<AccountId32>;
+    } & Struct;
+    readonly isForceSetSubs: boolean;
+    readonly asForceSetSubs: {
+      readonly subs: Vec<ITuple<[AccountId32, ITuple<[u128, Vec<ITuple<[AccountId32, Data]>>]>]>>;
+    } & Struct;
+    readonly type: 'AddRegistrar' | 'SetIdentity' | 'SetSubs' | 'ClearIdentity' | 'RequestJudgement' | 'CancelRequest' | 'SetFee' | 'SetAccountId' | 'SetFields' | 'ProvideJudgement' | 'KillIdentity' | 'AddSub' | 'RenameSub' | 'RemoveSub' | 'QuitSub' | 'ForceInsertIdentities' | 'ForceRemoveIdentities' | 'ForceSetSubs';
+  }
+
+  /** @name PalletIdentityIdentityInfo (224) */
+  interface PalletIdentityIdentityInfo extends Struct {
+    readonly additional: Vec<ITuple<[Data, Data]>>;
+    readonly display: Data;
+    readonly legal: Data;
+    readonly web: Data;
+    readonly riot: Data;
+    readonly email: Data;
+    readonly pgpFingerprint: Option<U8aFixed>;
+    readonly image: Data;
+    readonly twitter: Data;
+  }
+
+  /** @name PalletIdentityBitFlags (260) */
+  interface PalletIdentityBitFlags extends Set {
+    readonly isDisplay: boolean;
+    readonly isLegal: boolean;
+    readonly isWeb: boolean;
+    readonly isRiot: boolean;
+    readonly isEmail: boolean;
+    readonly isPgpFingerprint: boolean;
+    readonly isImage: boolean;
+    readonly isTwitter: boolean;
+  }
+
+  /** @name PalletIdentityIdentityField (261) */
+  interface PalletIdentityIdentityField extends Enum {
+    readonly isDisplay: boolean;
+    readonly isLegal: boolean;
+    readonly isWeb: boolean;
+    readonly isRiot: boolean;
+    readonly isEmail: boolean;
+    readonly isPgpFingerprint: boolean;
+    readonly isImage: boolean;
+    readonly isTwitter: boolean;
+    readonly type: 'Display' | 'Legal' | 'Web' | 'Riot' | 'Email' | 'PgpFingerprint' | 'Image' | 'Twitter';
+  }
+
+  /** @name PalletIdentityJudgement (262) */
+  interface PalletIdentityJudgement extends Enum {
+    readonly isUnknown: boolean;
+    readonly isFeePaid: boolean;
+    readonly asFeePaid: u128;
+    readonly isReasonable: boolean;
+    readonly isKnownGood: boolean;
+    readonly isOutOfDate: boolean;
+    readonly isLowQuality: boolean;
+    readonly isErroneous: boolean;
+    readonly type: 'Unknown' | 'FeePaid' | 'Reasonable' | 'KnownGood' | 'OutOfDate' | 'LowQuality' | 'Erroneous';
+  }
+
+  /** @name PalletIdentityRegistration (265) */
+  interface PalletIdentityRegistration extends Struct {
+    readonly judgements: Vec<ITuple<[u32, PalletIdentityJudgement]>>;
+    readonly deposit: u128;
+    readonly info: PalletIdentityIdentityInfo;
+  }
+
+  /** @name PalletPreimageCall (273) */
+  interface PalletPreimageCall extends Enum {
+    readonly isNotePreimage: boolean;
+    readonly asNotePreimage: {
+      readonly bytes: Bytes;
+    } & Struct;
+    readonly isUnnotePreimage: boolean;
+    readonly asUnnotePreimage: {
+      readonly hash_: H256;
+    } & Struct;
+    readonly isRequestPreimage: boolean;
+    readonly asRequestPreimage: {
+      readonly hash_: H256;
+    } & Struct;
+    readonly isUnrequestPreimage: boolean;
+    readonly asUnrequestPreimage: {
+      readonly hash_: H256;
+    } & Struct;
+    readonly type: 'NotePreimage' | 'UnnotePreimage' | 'RequestPreimage' | 'UnrequestPreimage';
+  }
+
+  /** @name CumulusPalletXcmpQueueCall (274) */
   interface CumulusPalletXcmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -2021,7 +2317,7 @@
     readonly type: 'ServiceOverweight' | 'SuspendXcmExecution' | 'ResumeXcmExecution' | 'UpdateSuspendThreshold' | 'UpdateDropThreshold' | 'UpdateResumeThreshold' | 'UpdateThresholdWeight' | 'UpdateWeightRestrictDecay' | 'UpdateXcmpMaxIndividualWeight';
   }
 
-  /** @name PalletXcmCall (203) */
+  /** @name PalletXcmCall (275) */
   interface PalletXcmCall extends Enum {
     readonly isSend: boolean;
     readonly asSend: {
@@ -2083,7 +2379,7 @@
     readonly type: 'Send' | 'TeleportAssets' | 'ReserveTransferAssets' | 'Execute' | 'ForceXcmVersion' | 'ForceDefaultXcmVersion' | 'ForceSubscribeVersionNotify' | 'ForceUnsubscribeVersionNotify' | 'LimitedReserveTransferAssets' | 'LimitedTeleportAssets';
   }
 
-  /** @name XcmVersionedXcm (204) */
+  /** @name XcmVersionedXcm (276) */
   interface XcmVersionedXcm extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0Xcm;
@@ -2094,7 +2390,7 @@
     readonly type: 'V0' | 'V1' | 'V2';
   }
 
-  /** @name XcmV0Xcm (205) */
+  /** @name XcmV0Xcm (277) */
   interface XcmV0Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -2157,7 +2453,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposit' | 'TeleportAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom';
   }
 
-  /** @name XcmV0Order (207) */
+  /** @name XcmV0Order (279) */
   interface XcmV0Order extends Enum {
     readonly isNull: boolean;
     readonly isDepositAsset: boolean;
@@ -2205,14 +2501,14 @@
     readonly type: 'Null' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV0Response (209) */
+  /** @name XcmV0Response (281) */
   interface XcmV0Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: Vec<XcmV0MultiAsset>;
     readonly type: 'Assets';
   }
 
-  /** @name XcmV1Xcm (210) */
+  /** @name XcmV1Xcm (282) */
   interface XcmV1Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -2281,7 +2577,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom' | 'SubscribeVersion' | 'UnsubscribeVersion';
   }
 
-  /** @name XcmV1Order (212) */
+  /** @name XcmV1Order (284) */
   interface XcmV1Order extends Enum {
     readonly isNoop: boolean;
     readonly isDepositAsset: boolean;
@@ -2331,7 +2627,7 @@
     readonly type: 'Noop' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV1Response (214) */
+  /** @name XcmV1Response (286) */
   interface XcmV1Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: XcmV1MultiassetMultiAssets;
@@ -2340,10 +2636,10 @@
     readonly type: 'Assets' | 'Version';
   }
 
-  /** @name CumulusPalletXcmCall (228) */
+  /** @name CumulusPalletXcmCall (300) */
   type CumulusPalletXcmCall = Null;
 
-  /** @name CumulusPalletDmpQueueCall (229) */
+  /** @name CumulusPalletDmpQueueCall (301) */
   interface CumulusPalletDmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -2353,7 +2649,7 @@
     readonly type: 'ServiceOverweight';
   }
 
-  /** @name PalletInflationCall (230) */
+  /** @name PalletInflationCall (302) */
   interface PalletInflationCall extends Enum {
     readonly isStartInflation: boolean;
     readonly asStartInflation: {
@@ -2362,7 +2658,7 @@
     readonly type: 'StartInflation';
   }
 
-  /** @name PalletUniqueCall (231) */
+  /** @name PalletUniqueCall (303) */
   interface PalletUniqueCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -2543,7 +2839,7 @@
     readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'ApproveFrom' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll' | 'ForceRepairCollection' | 'ForceRepairItem';
   }
 
-  /** @name UpDataStructsCollectionMode (236) */
+  /** @name UpDataStructsCollectionMode (308) */
   interface UpDataStructsCollectionMode extends Enum {
     readonly isNft: boolean;
     readonly isFungible: boolean;
@@ -2552,7 +2848,7 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateCollectionData (237) */
+  /** @name UpDataStructsCreateCollectionData (309) */
   interface UpDataStructsCreateCollectionData extends Struct {
     readonly mode: UpDataStructsCollectionMode;
     readonly access: Option<UpDataStructsAccessMode>;
@@ -2566,14 +2862,14 @@
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsAccessMode (239) */
+  /** @name UpDataStructsAccessMode (311) */
   interface UpDataStructsAccessMode extends Enum {
     readonly isNormal: boolean;
     readonly isAllowList: boolean;
     readonly type: 'Normal' | 'AllowList';
   }
 
-  /** @name UpDataStructsCollectionLimits (241) */
+  /** @name UpDataStructsCollectionLimits (313) */
   interface UpDataStructsCollectionLimits extends Struct {
     readonly accountTokenOwnershipLimit: Option<u32>;
     readonly sponsoredDataSize: Option<u32>;
@@ -2586,7 +2882,7 @@
     readonly transfersEnabled: Option<bool>;
   }
 
-  /** @name UpDataStructsSponsoringRateLimit (243) */
+  /** @name UpDataStructsSponsoringRateLimit (315) */
   interface UpDataStructsSponsoringRateLimit extends Enum {
     readonly isSponsoringDisabled: boolean;
     readonly isBlocks: boolean;
@@ -2594,43 +2890,43 @@
     readonly type: 'SponsoringDisabled' | 'Blocks';
   }
 
-  /** @name UpDataStructsCollectionPermissions (246) */
+  /** @name UpDataStructsCollectionPermissions (318) */
   interface UpDataStructsCollectionPermissions extends Struct {
     readonly access: Option<UpDataStructsAccessMode>;
     readonly mintMode: Option<bool>;
     readonly nesting: Option<UpDataStructsNestingPermissions>;
   }
 
-  /** @name UpDataStructsNestingPermissions (248) */
+  /** @name UpDataStructsNestingPermissions (320) */
   interface UpDataStructsNestingPermissions extends Struct {
     readonly tokenOwner: bool;
     readonly collectionAdmin: bool;
     readonly restricted: Option<UpDataStructsOwnerRestrictedSet>;
   }
 
-  /** @name UpDataStructsOwnerRestrictedSet (250) */
+  /** @name UpDataStructsOwnerRestrictedSet (322) */
   interface UpDataStructsOwnerRestrictedSet extends BTreeSet<u32> {}
 
-  /** @name UpDataStructsPropertyKeyPermission (255) */
+  /** @name UpDataStructsPropertyKeyPermission (327) */
   interface UpDataStructsPropertyKeyPermission extends Struct {
     readonly key: Bytes;
     readonly permission: UpDataStructsPropertyPermission;
   }
 
-  /** @name UpDataStructsPropertyPermission (256) */
+  /** @name UpDataStructsPropertyPermission (328) */
   interface UpDataStructsPropertyPermission extends Struct {
     readonly mutable: bool;
     readonly collectionAdmin: bool;
     readonly tokenOwner: bool;
   }
 
-  /** @name UpDataStructsProperty (259) */
+  /** @name UpDataStructsProperty (331) */
   interface UpDataStructsProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name UpDataStructsCreateItemData (262) */
+  /** @name UpDataStructsCreateItemData (334) */
   interface UpDataStructsCreateItemData extends Enum {
     readonly isNft: boolean;
     readonly asNft: UpDataStructsCreateNftData;
@@ -2641,23 +2937,23 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateNftData (263) */
+  /** @name UpDataStructsCreateNftData (335) */
   interface UpDataStructsCreateNftData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateFungibleData (264) */
+  /** @name UpDataStructsCreateFungibleData (336) */
   interface UpDataStructsCreateFungibleData extends Struct {
     readonly value: u128;
   }
 
-  /** @name UpDataStructsCreateReFungibleData (265) */
+  /** @name UpDataStructsCreateReFungibleData (337) */
   interface UpDataStructsCreateReFungibleData extends Struct {
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateItemExData (268) */
+  /** @name UpDataStructsCreateItemExData (340) */
   interface UpDataStructsCreateItemExData extends Enum {
     readonly isNft: boolean;
     readonly asNft: Vec<UpDataStructsCreateNftExData>;
@@ -2670,26 +2966,26 @@
     readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners';
   }
 
-  /** @name UpDataStructsCreateNftExData (270) */
+  /** @name UpDataStructsCreateNftExData (342) */
   interface UpDataStructsCreateNftExData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsCreateRefungibleExSingleOwner (277) */
+  /** @name UpDataStructsCreateRefungibleExSingleOwner (349) */
   interface UpDataStructsCreateRefungibleExSingleOwner extends Struct {
     readonly user: PalletEvmAccountBasicCrossAccountIdRepr;
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateRefungibleExMultipleOwners (279) */
+  /** @name UpDataStructsCreateRefungibleExMultipleOwners (351) */
   interface UpDataStructsCreateRefungibleExMultipleOwners extends Struct {
     readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name PalletConfigurationCall (280) */
+  /** @name PalletConfigurationCall (352) */
   interface PalletConfigurationCall extends Enum {
     readonly isSetWeightToFeeCoefficientOverride: boolean;
     readonly asSetWeightToFeeCoefficientOverride: {
@@ -2722,7 +3018,7 @@
     readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride' | 'SetXcmAllowedLocations' | 'SetAppPromotionConfigurationOverride' | 'SetCollatorSelectionDesiredCollators' | 'SetCollatorSelectionLicenseBond' | 'SetCollatorSelectionKickThreshold';
   }
 
-  /** @name PalletConfigurationAppPromotionConfiguration (285) */
+  /** @name PalletConfigurationAppPromotionConfiguration (357) */
   interface PalletConfigurationAppPromotionConfiguration extends Struct {
     readonly recalculationInterval: Option<u32>;
     readonly pendingInterval: Option<u32>;
@@ -2730,226 +3026,13 @@
     readonly maxStakersPerCalculation: Option<u8>;
   }
 
-  /** @name PalletTemplateTransactionPaymentCall (289) */
+  /** @name PalletTemplateTransactionPaymentCall (361) */
   type PalletTemplateTransactionPaymentCall = Null;
 
-  /** @name PalletStructureCall (290) */
+  /** @name PalletStructureCall (362) */
   type PalletStructureCall = Null;
 
-  /** @name PalletRmrkCoreCall (291) */
-  interface PalletRmrkCoreCall extends Enum {
-    readonly isCreateCollection: boolean;
-    readonly asCreateCollection: {
-      readonly metadata: Bytes;
-      readonly max: Option<u32>;
-      readonly symbol: Bytes;
-    } & Struct;
-    readonly isDestroyCollection: boolean;
-    readonly asDestroyCollection: {
-      readonly collectionId: u32;
-    } & Struct;
-    readonly isChangeCollectionIssuer: boolean;
-    readonly asChangeCollectionIssuer: {
-      readonly collectionId: u32;
-      readonly newIssuer: MultiAddress;
-    } & Struct;
-    readonly isLockCollection: boolean;
-    readonly asLockCollection: {
-      readonly collectionId: u32;
-    } & Struct;
-    readonly isMintNft: boolean;
-    readonly asMintNft: {
-      readonly owner: Option<AccountId32>;
-      readonly collectionId: u32;
-      readonly recipient: Option<AccountId32>;
-      readonly royaltyAmount: Option<Permill>;
-      readonly metadata: Bytes;
-      readonly transferable: bool;
-      readonly resources: Option<Vec<RmrkTraitsResourceResourceTypes>>;
-    } & Struct;
-    readonly isBurnNft: boolean;
-    readonly asBurnNft: {
-      readonly collectionId: u32;
-      readonly nftId: u32;
-      readonly maxBurns: u32;
-    } & Struct;
-    readonly isSend: boolean;
-    readonly asSend: {
-      readonly rmrkCollectionId: u32;
-      readonly rmrkNftId: u32;
-      readonly newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-    } & Struct;
-    readonly isAcceptNft: boolean;
-    readonly asAcceptNft: {
-      readonly rmrkCollectionId: u32;
-      readonly rmrkNftId: u32;
-      readonly newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-    } & Struct;
-    readonly isRejectNft: boolean;
-    readonly asRejectNft: {
-      readonly rmrkCollectionId: u32;
-      readonly rmrkNftId: u32;
-    } & Struct;
-    readonly isAcceptResource: boolean;
-    readonly asAcceptResource: {
-      readonly rmrkCollectionId: u32;
-      readonly rmrkNftId: u32;
-      readonly resourceId: u32;
-    } & Struct;
-    readonly isAcceptResourceRemoval: boolean;
-    readonly asAcceptResourceRemoval: {
-      readonly rmrkCollectionId: u32;
-      readonly rmrkNftId: u32;
-      readonly resourceId: u32;
-    } & Struct;
-    readonly isSetProperty: boolean;
-    readonly asSetProperty: {
-      readonly rmrkCollectionId: Compact<u32>;
-      readonly maybeNftId: Option<u32>;
-      readonly key: Bytes;
-      readonly value: Bytes;
-    } & Struct;
-    readonly isSetPriority: boolean;
-    readonly asSetPriority: {
-      readonly rmrkCollectionId: u32;
-      readonly rmrkNftId: u32;
-      readonly priorities: Vec<u32>;
-    } & Struct;
-    readonly isAddBasicResource: boolean;
-    readonly asAddBasicResource: {
-      readonly rmrkCollectionId: u32;
-      readonly nftId: u32;
-      readonly resource: RmrkTraitsResourceBasicResource;
-    } & Struct;
-    readonly isAddComposableResource: boolean;
-    readonly asAddComposableResource: {
-      readonly rmrkCollectionId: u32;
-      readonly nftId: u32;
-      readonly resource: RmrkTraitsResourceComposableResource;
-    } & Struct;
-    readonly isAddSlotResource: boolean;
-    readonly asAddSlotResource: {
-      readonly rmrkCollectionId: u32;
-      readonly nftId: u32;
-      readonly resource: RmrkTraitsResourceSlotResource;
-    } & Struct;
-    readonly isRemoveResource: boolean;
-    readonly asRemoveResource: {
-      readonly rmrkCollectionId: u32;
-      readonly nftId: u32;
-      readonly resourceId: u32;
-    } & Struct;
-    readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource';
-  }
-
-  /** @name RmrkTraitsResourceResourceTypes (297) */
-  interface RmrkTraitsResourceResourceTypes extends Enum {
-    readonly isBasic: boolean;
-    readonly asBasic: RmrkTraitsResourceBasicResource;
-    readonly isComposable: boolean;
-    readonly asComposable: RmrkTraitsResourceComposableResource;
-    readonly isSlot: boolean;
-    readonly asSlot: RmrkTraitsResourceSlotResource;
-    readonly type: 'Basic' | 'Composable' | 'Slot';
-  }
-
-  /** @name RmrkTraitsResourceBasicResource (299) */
-  interface RmrkTraitsResourceBasicResource extends Struct {
-    readonly src: Option<Bytes>;
-    readonly metadata: Option<Bytes>;
-    readonly license: Option<Bytes>;
-    readonly thumb: Option<Bytes>;
-  }
-
-  /** @name RmrkTraitsResourceComposableResource (301) */
-  interface RmrkTraitsResourceComposableResource extends Struct {
-    readonly parts: Vec<u32>;
-    readonly base: u32;
-    readonly src: Option<Bytes>;
-    readonly metadata: Option<Bytes>;
-    readonly license: Option<Bytes>;
-    readonly thumb: Option<Bytes>;
-  }
-
-  /** @name RmrkTraitsResourceSlotResource (302) */
-  interface RmrkTraitsResourceSlotResource extends Struct {
-    readonly base: u32;
-    readonly src: Option<Bytes>;
-    readonly metadata: Option<Bytes>;
-    readonly slot: u32;
-    readonly license: Option<Bytes>;
-    readonly thumb: Option<Bytes>;
-  }
-
-  /** @name PalletRmrkEquipCall (305) */
-  interface PalletRmrkEquipCall extends Enum {
-    readonly isCreateBase: boolean;
-    readonly asCreateBase: {
-      readonly baseType: Bytes;
-      readonly symbol: Bytes;
-      readonly parts: Vec<RmrkTraitsPartPartType>;
-    } & Struct;
-    readonly isThemeAdd: boolean;
-    readonly asThemeAdd: {
-      readonly baseId: u32;
-      readonly theme: RmrkTraitsTheme;
-    } & Struct;
-    readonly isEquippable: boolean;
-    readonly asEquippable: {
-      readonly baseId: u32;
-      readonly slotId: u32;
-      readonly equippables: RmrkTraitsPartEquippableList;
-    } & Struct;
-    readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable';
-  }
-
-  /** @name RmrkTraitsPartPartType (308) */
-  interface RmrkTraitsPartPartType extends Enum {
-    readonly isFixedPart: boolean;
-    readonly asFixedPart: RmrkTraitsPartFixedPart;
-    readonly isSlotPart: boolean;
-    readonly asSlotPart: RmrkTraitsPartSlotPart;
-    readonly type: 'FixedPart' | 'SlotPart';
-  }
-
-  /** @name RmrkTraitsPartFixedPart (310) */
-  interface RmrkTraitsPartFixedPart extends Struct {
-    readonly id: u32;
-    readonly z: u32;
-    readonly src: Bytes;
-  }
-
-  /** @name RmrkTraitsPartSlotPart (311) */
-  interface RmrkTraitsPartSlotPart extends Struct {
-    readonly id: u32;
-    readonly equippable: RmrkTraitsPartEquippableList;
-    readonly src: Bytes;
-    readonly z: u32;
-  }
-
-  /** @name RmrkTraitsPartEquippableList (312) */
-  interface RmrkTraitsPartEquippableList extends Enum {
-    readonly isAll: boolean;
-    readonly isEmpty: boolean;
-    readonly isCustom: boolean;
-    readonly asCustom: Vec<u32>;
-    readonly type: 'All' | 'Empty' | 'Custom';
-  }
-
-  /** @name RmrkTraitsTheme (314) */
-  interface RmrkTraitsTheme extends Struct {
-    readonly name: Bytes;
-    readonly properties: Vec<RmrkTraitsThemeThemeProperty>;
-    readonly inherit: bool;
-  }
-
-  /** @name RmrkTraitsThemeThemeProperty (316) */
-  interface RmrkTraitsThemeThemeProperty extends Struct {
-    readonly key: Bytes;
-    readonly value: Bytes;
-  }
-
-  /** @name PalletAppPromotionCall (318) */
+  /** @name PalletAppPromotionCall (363) */
   interface PalletAppPromotionCall extends Enum {
     readonly isSetAdminAddress: boolean;
     readonly asSetAdminAddress: {
@@ -2959,7 +3042,7 @@
     readonly asStake: {
       readonly amount: u128;
     } & Struct;
-    readonly isUnstake: boolean;
+    readonly isUnstakeAll: boolean;
     readonly isSponsorCollection: boolean;
     readonly asSponsorCollection: {
       readonly collectionId: u32;
@@ -2980,10 +3063,14 @@
     readonly asPayoutStakers: {
       readonly stakersNumber: Option<u8>;
     } & Struct;
-    readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers';
+    readonly isUnstakePartial: boolean;
+    readonly asUnstakePartial: {
+      readonly amount: u128;
+    } & Struct;
+    readonly type: 'SetAdminAddress' | 'Stake' | 'UnstakeAll' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers' | 'UnstakePartial';
   }
 
-  /** @name PalletForeignAssetsModuleCall (319) */
+  /** @name PalletForeignAssetsModuleCall (364) */
   interface PalletForeignAssetsModuleCall extends Enum {
     readonly isRegisterForeignAsset: boolean;
     readonly asRegisterForeignAsset: {
@@ -3000,7 +3087,7 @@
     readonly type: 'RegisterForeignAsset' | 'UpdateForeignAsset';
   }
 
-  /** @name PalletEvmCall (320) */
+  /** @name PalletEvmCall (365) */
   interface PalletEvmCall extends Enum {
     readonly isWithdraw: boolean;
     readonly asWithdraw: {
@@ -3045,7 +3132,7 @@
     readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2';
   }
 
-  /** @name PalletEthereumCall (326) */
+  /** @name PalletEthereumCall (371) */
   interface PalletEthereumCall extends Enum {
     readonly isTransact: boolean;
     readonly asTransact: {
@@ -3054,7 +3141,7 @@
     readonly type: 'Transact';
   }
 
-  /** @name EthereumTransactionTransactionV2 (327) */
+  /** @name EthereumTransactionTransactionV2 (372) */
   interface EthereumTransactionTransactionV2 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumTransactionLegacyTransaction;
@@ -3065,7 +3152,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumTransactionLegacyTransaction (328) */
+  /** @name EthereumTransactionLegacyTransaction (373) */
   interface EthereumTransactionLegacyTransaction extends Struct {
     readonly nonce: U256;
     readonly gasPrice: U256;
@@ -3076,7 +3163,7 @@
     readonly signature: EthereumTransactionTransactionSignature;
   }
 
-  /** @name EthereumTransactionTransactionAction (329) */
+  /** @name EthereumTransactionTransactionAction (374) */
   interface EthereumTransactionTransactionAction extends Enum {
     readonly isCall: boolean;
     readonly asCall: H160;
@@ -3084,14 +3171,14 @@
     readonly type: 'Call' | 'Create';
   }
 
-  /** @name EthereumTransactionTransactionSignature (330) */
+  /** @name EthereumTransactionTransactionSignature (375) */
   interface EthereumTransactionTransactionSignature extends Struct {
     readonly v: u64;
     readonly r: H256;
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionEip2930Transaction (332) */
+  /** @name EthereumTransactionEip2930Transaction (377) */
   interface EthereumTransactionEip2930Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -3106,13 +3193,13 @@
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionAccessListItem (334) */
+  /** @name EthereumTransactionAccessListItem (379) */
   interface EthereumTransactionAccessListItem extends Struct {
     readonly address: H160;
     readonly storageKeys: Vec<H256>;
   }
 
-  /** @name EthereumTransactionEip1559Transaction (335) */
+  /** @name EthereumTransactionEip1559Transaction (380) */
   interface EthereumTransactionEip1559Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -3128,7 +3215,7 @@
     readonly s: H256;
   }
 
-  /** @name PalletEvmMigrationCall (336) */
+  /** @name PalletEvmMigrationCall (381) */
   interface PalletEvmMigrationCall extends Enum {
     readonly isBegin: boolean;
     readonly asBegin: {
@@ -3152,17 +3239,23 @@
     readonly asInsertEvents: {
       readonly events: Vec<Bytes>;
     } & Struct;
-    readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents';
+    readonly isRemoveRmrkData: boolean;
+    readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents' | 'RemoveRmrkData';
   }
 
-  /** @name PalletMaintenanceCall (340) */
+  /** @name PalletMaintenanceCall (385) */
   interface PalletMaintenanceCall extends Enum {
     readonly isEnable: boolean;
     readonly isDisable: boolean;
-    readonly type: 'Enable' | 'Disable';
+    readonly isExecutePreimage: boolean;
+    readonly asExecutePreimage: {
+      readonly hash_: H256;
+      readonly weightBound: SpWeightsWeightV2Weight;
+    } & Struct;
+    readonly type: 'Enable' | 'Disable' | 'ExecutePreimage';
   }
 
-  /** @name PalletTestUtilsCall (341) */
+  /** @name PalletTestUtilsCall (386) */
   interface PalletTestUtilsCall extends Enum {
     readonly isEnable: boolean;
     readonly isSetTestValue: boolean;
@@ -3182,13 +3275,13 @@
     readonly type: 'Enable' | 'SetTestValue' | 'SetTestValueAndRollback' | 'IncTestValue' | 'JustTakeFee' | 'BatchAll';
   }
 
-  /** @name PalletSudoError (343) */
+  /** @name PalletSudoError (388) */
   interface PalletSudoError extends Enum {
     readonly isRequireSudo: boolean;
     readonly type: 'RequireSudo';
   }
 
-  /** @name OrmlVestingModuleError (345) */
+  /** @name OrmlVestingModuleError (390) */
   interface OrmlVestingModuleError extends Enum {
     readonly isZeroVestingPeriod: boolean;
     readonly isZeroVestingPeriodCount: boolean;
@@ -3199,7 +3292,7 @@
     readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded';
   }
 
-  /** @name OrmlXtokensModuleError (346) */
+  /** @name OrmlXtokensModuleError (391) */
   interface OrmlXtokensModuleError extends Enum {
     readonly isAssetHasNoReserve: boolean;
     readonly isNotCrossChainTransfer: boolean;
@@ -3223,26 +3316,26 @@
     readonly type: 'AssetHasNoReserve' | 'NotCrossChainTransfer' | 'InvalidDest' | 'NotCrossChainTransferableCurrency' | 'UnweighableMessage' | 'XcmExecutionFailed' | 'CannotReanchor' | 'InvalidAncestry' | 'InvalidAsset' | 'DestinationNotInvertible' | 'BadVersion' | 'DistinctReserveForAssetAndFee' | 'ZeroFee' | 'ZeroAmount' | 'TooManyAssetsBeingSent' | 'AssetIndexNonExistent' | 'FeeNotEnough' | 'NotSupportedMultiLocation' | 'MinXcmFeeNotDefined';
   }
 
-  /** @name OrmlTokensBalanceLock (349) */
+  /** @name OrmlTokensBalanceLock (394) */
   interface OrmlTokensBalanceLock extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
   }
 
-  /** @name OrmlTokensAccountData (351) */
+  /** @name OrmlTokensAccountData (396) */
   interface OrmlTokensAccountData extends Struct {
     readonly free: u128;
     readonly reserved: u128;
     readonly frozen: u128;
   }
 
-  /** @name OrmlTokensReserveData (353) */
+  /** @name OrmlTokensReserveData (398) */
   interface OrmlTokensReserveData extends Struct {
     readonly id: Null;
     readonly amount: u128;
   }
 
-  /** @name OrmlTokensModuleError (355) */
+  /** @name OrmlTokensModuleError (400) */
   interface OrmlTokensModuleError extends Enum {
     readonly isBalanceTooLow: boolean;
     readonly isAmountIntoBalanceFailed: boolean;
@@ -3255,21 +3348,78 @@
     readonly type: 'BalanceTooLow' | 'AmountIntoBalanceFailed' | 'LiquidityRestrictions' | 'MaxLocksExceeded' | 'KeepAlive' | 'ExistentialDeposit' | 'DeadAccount' | 'TooManyReserves';
   }
 
-  /** @name CumulusPalletXcmpQueueInboundChannelDetails (357) */
+  /** @name PalletIdentityRegistrarInfo (405) */
+  interface PalletIdentityRegistrarInfo extends Struct {
+    readonly account: AccountId32;
+    readonly fee: u128;
+    readonly fields: PalletIdentityBitFlags;
+  }
+
+  /** @name PalletIdentityError (407) */
+  interface PalletIdentityError extends Enum {
+    readonly isTooManySubAccounts: boolean;
+    readonly isNotFound: boolean;
+    readonly isNotNamed: boolean;
+    readonly isEmptyIndex: boolean;
+    readonly isFeeChanged: boolean;
+    readonly isNoIdentity: boolean;
+    readonly isStickyJudgement: boolean;
+    readonly isJudgementGiven: boolean;
+    readonly isInvalidJudgement: boolean;
+    readonly isInvalidIndex: boolean;
+    readonly isInvalidTarget: boolean;
+    readonly isTooManyFields: boolean;
+    readonly isTooManyRegistrars: boolean;
+    readonly isAlreadyClaimed: boolean;
+    readonly isNotSub: boolean;
+    readonly isNotOwned: boolean;
+    readonly isJudgementForDifferentIdentity: boolean;
+    readonly isJudgementPaymentFailed: boolean;
+    readonly type: 'TooManySubAccounts' | 'NotFound' | 'NotNamed' | 'EmptyIndex' | 'FeeChanged' | 'NoIdentity' | 'StickyJudgement' | 'JudgementGiven' | 'InvalidJudgement' | 'InvalidIndex' | 'InvalidTarget' | 'TooManyFields' | 'TooManyRegistrars' | 'AlreadyClaimed' | 'NotSub' | 'NotOwned' | 'JudgementForDifferentIdentity' | 'JudgementPaymentFailed';
+  }
+
+  /** @name PalletPreimageRequestStatus (408) */
+  interface PalletPreimageRequestStatus extends Enum {
+    readonly isUnrequested: boolean;
+    readonly asUnrequested: {
+      readonly deposit: ITuple<[AccountId32, u128]>;
+      readonly len: u32;
+    } & Struct;
+    readonly isRequested: boolean;
+    readonly asRequested: {
+      readonly deposit: Option<ITuple<[AccountId32, u128]>>;
+      readonly count: u32;
+      readonly len: Option<u32>;
+    } & Struct;
+    readonly type: 'Unrequested' | 'Requested';
+  }
+
+  /** @name PalletPreimageError (413) */
+  interface PalletPreimageError extends Enum {
+    readonly isTooBig: boolean;
+    readonly isAlreadyNoted: boolean;
+    readonly isNotAuthorized: boolean;
+    readonly isNotNoted: boolean;
+    readonly isRequested: boolean;
+    readonly isNotRequested: boolean;
+    readonly type: 'TooBig' | 'AlreadyNoted' | 'NotAuthorized' | 'NotNoted' | 'Requested' | 'NotRequested';
+  }
+
+  /** @name CumulusPalletXcmpQueueInboundChannelDetails (415) */
   interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct {
     readonly sender: u32;
     readonly state: CumulusPalletXcmpQueueInboundState;
     readonly messageMetadata: Vec<ITuple<[u32, PolkadotParachainPrimitivesXcmpMessageFormat]>>;
   }
 
-  /** @name CumulusPalletXcmpQueueInboundState (358) */
+  /** @name CumulusPalletXcmpQueueInboundState (416) */
   interface CumulusPalletXcmpQueueInboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (361) */
+  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (419) */
   interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum {
     readonly isConcatenatedVersionedXcm: boolean;
     readonly isConcatenatedEncodedBlob: boolean;
@@ -3277,7 +3427,7 @@
     readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals';
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (364) */
+  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (422) */
   interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct {
     readonly recipient: u32;
     readonly state: CumulusPalletXcmpQueueOutboundState;
@@ -3286,14 +3436,14 @@
     readonly lastIndex: u16;
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundState (365) */
+  /** @name CumulusPalletXcmpQueueOutboundState (423) */
   interface CumulusPalletXcmpQueueOutboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name CumulusPalletXcmpQueueQueueConfigData (367) */
+  /** @name CumulusPalletXcmpQueueQueueConfigData (425) */
   interface CumulusPalletXcmpQueueQueueConfigData extends Struct {
     readonly suspendThreshold: u32;
     readonly dropThreshold: u32;
@@ -3303,7 +3453,7 @@
     readonly xcmpMaxIndividualWeight: SpWeightsWeightV2Weight;
   }
 
-  /** @name CumulusPalletXcmpQueueError (369) */
+  /** @name CumulusPalletXcmpQueueError (427) */
   interface CumulusPalletXcmpQueueError extends Enum {
     readonly isFailedToSend: boolean;
     readonly isBadXcmOrigin: boolean;
@@ -3313,7 +3463,7 @@
     readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit';
   }
 
-  /** @name PalletXcmError (370) */
+  /** @name PalletXcmError (428) */
   interface PalletXcmError extends Enum {
     readonly isUnreachable: boolean;
     readonly isSendFailure: boolean;
@@ -3331,29 +3481,29 @@
     readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed';
   }
 
-  /** @name CumulusPalletXcmError (371) */
+  /** @name CumulusPalletXcmError (429) */
   type CumulusPalletXcmError = Null;
 
-  /** @name CumulusPalletDmpQueueConfigData (372) */
+  /** @name CumulusPalletDmpQueueConfigData (430) */
   interface CumulusPalletDmpQueueConfigData extends Struct {
     readonly maxIndividual: SpWeightsWeightV2Weight;
   }
 
-  /** @name CumulusPalletDmpQueuePageIndexData (373) */
+  /** @name CumulusPalletDmpQueuePageIndexData (431) */
   interface CumulusPalletDmpQueuePageIndexData extends Struct {
     readonly beginUsed: u32;
     readonly endUsed: u32;
     readonly overweightCount: u64;
   }
 
-  /** @name CumulusPalletDmpQueueError (376) */
+  /** @name CumulusPalletDmpQueueError (434) */
   interface CumulusPalletDmpQueueError extends Enum {
     readonly isUnknown: boolean;
     readonly isOverLimit: boolean;
     readonly type: 'Unknown' | 'OverLimit';
   }
 
-  /** @name PalletUniqueError (380) */
+  /** @name PalletUniqueError (438) */
   interface PalletUniqueError extends Enum {
     readonly isCollectionDecimalPointLimitExceeded: boolean;
     readonly isEmptyArgument: boolean;
@@ -3361,13 +3511,13 @@
     readonly type: 'CollectionDecimalPointLimitExceeded' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
   }
 
-  /** @name PalletConfigurationError (381) */
+  /** @name PalletConfigurationError (439) */
   interface PalletConfigurationError extends Enum {
     readonly isInconsistentConfiguration: boolean;
     readonly type: 'InconsistentConfiguration';
   }
 
-  /** @name UpDataStructsCollection (382) */
+  /** @name UpDataStructsCollection (440) */
   interface UpDataStructsCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -3380,7 +3530,7 @@
     readonly flags: U8aFixed;
   }
 
-  /** @name UpDataStructsSponsorshipStateAccountId32 (383) */
+  /** @name UpDataStructsSponsorshipStateAccountId32 (441) */
   interface UpDataStructsSponsorshipStateAccountId32 extends Enum {
     readonly isDisabled: boolean;
     readonly isUnconfirmed: boolean;
@@ -3390,43 +3540,43 @@
     readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
   }
 
-  /** @name UpDataStructsProperties (385) */
+  /** @name UpDataStructsProperties (442) */
   interface UpDataStructsProperties extends Struct {
     readonly map: UpDataStructsPropertiesMapBoundedVec;
     readonly consumedSpace: u32;
     readonly spaceLimit: u32;
   }
 
-  /** @name UpDataStructsPropertiesMapBoundedVec (386) */
+  /** @name UpDataStructsPropertiesMapBoundedVec (443) */
   interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap<Bytes, Bytes> {}
 
-  /** @name UpDataStructsPropertiesMapPropertyPermission (391) */
+  /** @name UpDataStructsPropertiesMapPropertyPermission (448) */
   interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap<Bytes, UpDataStructsPropertyPermission> {}
 
-  /** @name UpDataStructsCollectionStats (398) */
+  /** @name UpDataStructsCollectionStats (455) */
   interface UpDataStructsCollectionStats extends Struct {
     readonly created: u32;
     readonly destroyed: u32;
     readonly alive: u32;
   }
 
-  /** @name UpDataStructsTokenChild (399) */
+  /** @name UpDataStructsTokenChild (456) */
   interface UpDataStructsTokenChild extends Struct {
     readonly token: u32;
     readonly collection: u32;
   }
 
-  /** @name PhantomTypeUpDataStructs (400) */
-  interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsPropertyPropertyInfo, RmrkTraitsBaseBaseInfo, RmrkTraitsPartPartType, RmrkTraitsTheme, RmrkTraitsNftNftChild, UpPovEstimateRpcPovInfo]>> {}
+  /** @name PhantomTypeUpDataStructs (457) */
+  interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, UpPovEstimateRpcPovInfo]>> {}
 
-  /** @name UpDataStructsTokenData (402) */
+  /** @name UpDataStructsTokenData (459) */
   interface UpDataStructsTokenData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: Option<PalletEvmAccountBasicCrossAccountIdRepr>;
     readonly pieces: u128;
   }
 
-  /** @name UpDataStructsRpcCollection (404) */
+  /** @name UpDataStructsRpcCollection (461) */
   interface UpDataStructsRpcCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -3442,64 +3592,13 @@
     readonly flags: UpDataStructsRpcCollectionFlags;
   }
 
-  /** @name UpDataStructsRpcCollectionFlags (405) */
+  /** @name UpDataStructsRpcCollectionFlags (462) */
   interface UpDataStructsRpcCollectionFlags extends Struct {
     readonly foreign: bool;
     readonly erc721metadata: bool;
   }
 
-  /** @name RmrkTraitsCollectionCollectionInfo (406) */
-  interface RmrkTraitsCollectionCollectionInfo extends Struct {
-    readonly issuer: AccountId32;
-    readonly metadata: Bytes;
-    readonly max: Option<u32>;
-    readonly symbol: Bytes;
-    readonly nftsCount: u32;
-  }
-
-  /** @name RmrkTraitsNftNftInfo (407) */
-  interface RmrkTraitsNftNftInfo extends Struct {
-    readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
-    readonly royalty: Option<RmrkTraitsNftRoyaltyInfo>;
-    readonly metadata: Bytes;
-    readonly equipped: bool;
-    readonly pending: bool;
-  }
-
-  /** @name RmrkTraitsNftRoyaltyInfo (409) */
-  interface RmrkTraitsNftRoyaltyInfo extends Struct {
-    readonly recipient: AccountId32;
-    readonly amount: Permill;
-  }
-
-  /** @name RmrkTraitsResourceResourceInfo (410) */
-  interface RmrkTraitsResourceResourceInfo extends Struct {
-    readonly id: u32;
-    readonly resource: RmrkTraitsResourceResourceTypes;
-    readonly pending: bool;
-    readonly pendingRemoval: bool;
-  }
-
-  /** @name RmrkTraitsPropertyPropertyInfo (411) */
-  interface RmrkTraitsPropertyPropertyInfo extends Struct {
-    readonly key: Bytes;
-    readonly value: Bytes;
-  }
-
-  /** @name RmrkTraitsBaseBaseInfo (412) */
-  interface RmrkTraitsBaseBaseInfo extends Struct {
-    readonly issuer: AccountId32;
-    readonly baseType: Bytes;
-    readonly symbol: Bytes;
-  }
-
-  /** @name RmrkTraitsNftNftChild (413) */
-  interface RmrkTraitsNftNftChild extends Struct {
-    readonly collectionId: u32;
-    readonly nftId: u32;
-  }
-
-  /** @name UpPovEstimateRpcPovInfo (414) */
+  /** @name UpPovEstimateRpcPovInfo (463) */
   interface UpPovEstimateRpcPovInfo extends Struct {
     readonly proofSize: u64;
     readonly compactProofSize: u64;
@@ -3508,7 +3607,7 @@
     readonly keyValues: Vec<UpPovEstimateRpcTrieKeyValue>;
   }
 
-  /** @name SpRuntimeTransactionValidityTransactionValidityError (417) */
+  /** @name SpRuntimeTransactionValidityTransactionValidityError (466) */
   interface SpRuntimeTransactionValidityTransactionValidityError extends Enum {
     readonly isInvalid: boolean;
     readonly asInvalid: SpRuntimeTransactionValidityInvalidTransaction;
@@ -3517,7 +3616,7 @@
     readonly type: 'Invalid' | 'Unknown';
   }
 
-  /** @name SpRuntimeTransactionValidityInvalidTransaction (418) */
+  /** @name SpRuntimeTransactionValidityInvalidTransaction (467) */
   interface SpRuntimeTransactionValidityInvalidTransaction extends Enum {
     readonly isCall: boolean;
     readonly isPayment: boolean;
@@ -3534,7 +3633,7 @@
     readonly type: 'Call' | 'Payment' | 'Future' | 'Stale' | 'BadProof' | 'AncientBirthBlock' | 'ExhaustsResources' | 'Custom' | 'BadMandatory' | 'MandatoryValidation' | 'BadSigner';
   }
 
-  /** @name SpRuntimeTransactionValidityUnknownTransaction (419) */
+  /** @name SpRuntimeTransactionValidityUnknownTransaction (468) */
   interface SpRuntimeTransactionValidityUnknownTransaction extends Enum {
     readonly isCannotLookup: boolean;
     readonly isNoUnsignedValidator: boolean;
@@ -3543,13 +3642,13 @@
     readonly type: 'CannotLookup' | 'NoUnsignedValidator' | 'Custom';
   }
 
-  /** @name UpPovEstimateRpcTrieKeyValue (421) */
+  /** @name UpPovEstimateRpcTrieKeyValue (470) */
   interface UpPovEstimateRpcTrieKeyValue extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PalletCommonError (423) */
+  /** @name PalletCommonError (472) */
   interface PalletCommonError extends Enum {
     readonly isCollectionNotFound: boolean;
     readonly isMustBeTokenOwner: boolean;
@@ -3591,7 +3690,7 @@
     readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsNotEthMirror' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal' | 'ConfirmSponsorshipFail' | 'UserIsNotCollectionAdmin';
   }
 
-  /** @name PalletFungibleError (425) */
+  /** @name PalletFungibleError (474) */
   interface PalletFungibleError extends Enum {
     readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isFungibleItemsHaveNoId: boolean;
@@ -3603,7 +3702,7 @@
     readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed' | 'SettingAllowanceForAllNotAllowed' | 'FungibleTokensAreAlwaysValid';
   }
 
-  /** @name PalletRefungibleError (429) */
+  /** @name PalletRefungibleError (478) */
   interface PalletRefungibleError extends Enum {
     readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isWrongRefungiblePieces: boolean;
@@ -3613,19 +3712,19 @@
     readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletNonfungibleItemData (430) */
+  /** @name PalletNonfungibleItemData (479) */
   interface PalletNonfungibleItemData extends Struct {
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsPropertyScope (432) */
+  /** @name UpDataStructsPropertyScope (481) */
   interface UpDataStructsPropertyScope extends Enum {
     readonly isNone: boolean;
     readonly isRmrk: boolean;
     readonly type: 'None' | 'Rmrk';
   }
 
-  /** @name PalletNonfungibleError (435) */
+  /** @name PalletNonfungibleError (484) */
   interface PalletNonfungibleError extends Enum {
     readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isNonfungibleItemsHaveNoAmount: boolean;
@@ -3633,52 +3732,17 @@
     readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren';
   }
 
-  /** @name PalletStructureError (436) */
+  /** @name PalletStructureError (485) */
   interface PalletStructureError extends Enum {
     readonly isOuroborosDetected: boolean;
     readonly isDepthLimit: boolean;
     readonly isBreadthLimit: boolean;
     readonly isTokenNotFound: boolean;
-    readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
+    readonly isCantNestTokenUnderCollection: boolean;
+    readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound' | 'CantNestTokenUnderCollection';
   }
 
-  /** @name PalletRmrkCoreError (437) */
-  interface PalletRmrkCoreError extends Enum {
-    readonly isCorruptedCollectionType: boolean;
-    readonly isRmrkPropertyKeyIsTooLong: boolean;
-    readonly isRmrkPropertyValueIsTooLong: boolean;
-    readonly isRmrkPropertyIsNotFound: boolean;
-    readonly isUnableToDecodeRmrkData: boolean;
-    readonly isCollectionNotEmpty: boolean;
-    readonly isNoAvailableCollectionId: boolean;
-    readonly isNoAvailableNftId: boolean;
-    readonly isCollectionUnknown: boolean;
-    readonly isNoPermission: boolean;
-    readonly isNonTransferable: boolean;
-    readonly isCollectionFullOrLocked: boolean;
-    readonly isResourceDoesntExist: boolean;
-    readonly isCannotSendToDescendentOrSelf: boolean;
-    readonly isCannotAcceptNonOwnedNft: boolean;
-    readonly isCannotRejectNonOwnedNft: boolean;
-    readonly isCannotRejectNonPendingNft: boolean;
-    readonly isResourceNotPending: boolean;
-    readonly isNoAvailableResourceId: boolean;
-    readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
-  }
-
-  /** @name PalletRmrkEquipError (439) */
-  interface PalletRmrkEquipError extends Enum {
-    readonly isPermissionError: boolean;
-    readonly isNoAvailableBaseId: boolean;
-    readonly isNoAvailablePartId: boolean;
-    readonly isBaseDoesntExist: boolean;
-    readonly isNeedsDefaultThemeFirst: boolean;
-    readonly isPartDoesntExist: boolean;
-    readonly isNoEquippableOnFixedPart: boolean;
-    readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart';
-  }
-
-  /** @name PalletAppPromotionError (445) */
+  /** @name PalletAppPromotionError (490) */
   interface PalletAppPromotionError extends Enum {
     readonly isAdminNotSet: boolean;
     readonly isNoPermission: boolean;
@@ -3686,10 +3750,11 @@
     readonly isPendingForBlockOverflow: boolean;
     readonly isSponsorNotSet: boolean;
     readonly isIncorrectLockedBalanceOperation: boolean;
-    readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation';
+    readonly isInsufficientStakedBalance: boolean;
+    readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation' | 'InsufficientStakedBalance';
   }
 
-  /** @name PalletForeignAssetsModuleError (446) */
+  /** @name PalletForeignAssetsModuleError (491) */
   interface PalletForeignAssetsModuleError extends Enum {
     readonly isBadLocation: boolean;
     readonly isMultiLocationExisted: boolean;
@@ -3698,7 +3763,7 @@
     readonly type: 'BadLocation' | 'MultiLocationExisted' | 'AssetIdNotExists' | 'AssetIdExisted';
   }
 
-  /** @name PalletEvmError (448) */
+  /** @name PalletEvmError (493) */
   interface PalletEvmError extends Enum {
     readonly isBalanceLow: boolean;
     readonly isFeeOverflow: boolean;
@@ -3714,7 +3779,7 @@
     readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce' | 'GasLimitTooLow' | 'GasLimitTooHigh' | 'Undefined' | 'Reentrancy' | 'TransactionMustComeFromEOA';
   }
 
-  /** @name FpRpcTransactionStatus (451) */
+  /** @name FpRpcTransactionStatus (496) */
   interface FpRpcTransactionStatus extends Struct {
     readonly transactionHash: H256;
     readonly transactionIndex: u32;
@@ -3725,10 +3790,10 @@
     readonly logsBloom: EthbloomBloom;
   }
 
-  /** @name EthbloomBloom (453) */
+  /** @name EthbloomBloom (498) */
   interface EthbloomBloom extends U8aFixed {}
 
-  /** @name EthereumReceiptReceiptV3 (455) */
+  /** @name EthereumReceiptReceiptV3 (500) */
   interface EthereumReceiptReceiptV3 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumReceiptEip658ReceiptData;
@@ -3739,7 +3804,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumReceiptEip658ReceiptData (456) */
+  /** @name EthereumReceiptEip658ReceiptData (501) */
   interface EthereumReceiptEip658ReceiptData extends Struct {
     readonly statusCode: u8;
     readonly usedGas: U256;
@@ -3747,14 +3812,14 @@
     readonly logs: Vec<EthereumLog>;
   }
 
-  /** @name EthereumBlock (457) */
+  /** @name EthereumBlock (502) */
   interface EthereumBlock extends Struct {
     readonly header: EthereumHeader;
     readonly transactions: Vec<EthereumTransactionTransactionV2>;
     readonly ommers: Vec<EthereumHeader>;
   }
 
-  /** @name EthereumHeader (458) */
+  /** @name EthereumHeader (503) */
   interface EthereumHeader extends Struct {
     readonly parentHash: H256;
     readonly ommersHash: H256;
@@ -3773,24 +3838,24 @@
     readonly nonce: EthereumTypesHashH64;
   }
 
-  /** @name EthereumTypesHashH64 (459) */
+  /** @name EthereumTypesHashH64 (504) */
   interface EthereumTypesHashH64 extends U8aFixed {}
 
-  /** @name PalletEthereumError (464) */
+  /** @name PalletEthereumError (509) */
   interface PalletEthereumError extends Enum {
     readonly isInvalidSignature: boolean;
     readonly isPreLogExists: boolean;
     readonly type: 'InvalidSignature' | 'PreLogExists';
   }
 
-  /** @name PalletEvmCoderSubstrateError (465) */
+  /** @name PalletEvmCoderSubstrateError (510) */
   interface PalletEvmCoderSubstrateError extends Enum {
     readonly isOutOfGas: boolean;
     readonly isOutOfFund: boolean;
     readonly type: 'OutOfGas' | 'OutOfFund';
   }
 
-  /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (466) */
+  /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (511) */
   interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum {
     readonly isDisabled: boolean;
     readonly isUnconfirmed: boolean;
@@ -3800,7 +3865,7 @@
     readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
   }
 
-  /** @name PalletEvmContractHelpersSponsoringModeT (467) */
+  /** @name PalletEvmContractHelpersSponsoringModeT (512) */
   interface PalletEvmContractHelpersSponsoringModeT extends Enum {
     readonly isDisabled: boolean;
     readonly isAllowlisted: boolean;
@@ -3808,7 +3873,7 @@
     readonly type: 'Disabled' | 'Allowlisted' | 'Generous';
   }
 
-  /** @name PalletEvmContractHelpersError (473) */
+  /** @name PalletEvmContractHelpersError (518) */
   interface PalletEvmContractHelpersError extends Enum {
     readonly isNoPermission: boolean;
     readonly isNoPendingSponsor: boolean;
@@ -3816,7 +3881,7 @@
     readonly type: 'NoPermission' | 'NoPendingSponsor' | 'TooManyMethodsHaveSponsoredLimit';
   }
 
-  /** @name PalletEvmMigrationError (474) */
+  /** @name PalletEvmMigrationError (519) */
   interface PalletEvmMigrationError extends Enum {
     readonly isAccountNotEmpty: boolean;
     readonly isAccountIsNotMigrating: boolean;
@@ -3824,17 +3889,17 @@
     readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating' | 'BadEvent';
   }
 
-  /** @name PalletMaintenanceError (475) */
+  /** @name PalletMaintenanceError (520) */
   type PalletMaintenanceError = Null;
 
-  /** @name PalletTestUtilsError (476) */
+  /** @name PalletTestUtilsError (521) */
   interface PalletTestUtilsError extends Enum {
     readonly isTestPalletDisabled: boolean;
     readonly isTriggerRollback: boolean;
     readonly type: 'TestPalletDisabled' | 'TriggerRollback';
   }
 
-  /** @name SpRuntimeMultiSignature (478) */
+  /** @name SpRuntimeMultiSignature (523) */
   interface SpRuntimeMultiSignature extends Enum {
     readonly isEd25519: boolean;
     readonly asEd25519: SpCoreEd25519Signature;
@@ -3845,43 +3910,43 @@
     readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa';
   }
 
-  /** @name SpCoreEd25519Signature (479) */
+  /** @name SpCoreEd25519Signature (524) */
   interface SpCoreEd25519Signature extends U8aFixed {}
 
-  /** @name SpCoreSr25519Signature (481) */
+  /** @name SpCoreSr25519Signature (526) */
   interface SpCoreSr25519Signature extends U8aFixed {}
 
-  /** @name SpCoreEcdsaSignature (482) */
+  /** @name SpCoreEcdsaSignature (527) */
   interface SpCoreEcdsaSignature extends U8aFixed {}
 
-  /** @name FrameSystemExtensionsCheckSpecVersion (485) */
+  /** @name FrameSystemExtensionsCheckSpecVersion (530) */
   type FrameSystemExtensionsCheckSpecVersion = Null;
 
-  /** @name FrameSystemExtensionsCheckTxVersion (486) */
+  /** @name FrameSystemExtensionsCheckTxVersion (531) */
   type FrameSystemExtensionsCheckTxVersion = Null;
 
-  /** @name FrameSystemExtensionsCheckGenesis (487) */
+  /** @name FrameSystemExtensionsCheckGenesis (532) */
   type FrameSystemExtensionsCheckGenesis = Null;
 
-  /** @name FrameSystemExtensionsCheckNonce (490) */
+  /** @name FrameSystemExtensionsCheckNonce (535) */
   interface FrameSystemExtensionsCheckNonce extends Compact<u32> {}
 
-  /** @name FrameSystemExtensionsCheckWeight (491) */
+  /** @name FrameSystemExtensionsCheckWeight (536) */
   type FrameSystemExtensionsCheckWeight = Null;
 
-  /** @name OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance (492) */
+  /** @name OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance (537) */
   type OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance = Null;
 
-  /** @name OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls (493) */
+  /** @name OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls (538) */
   type OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls = Null;
 
-  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (494) */
+  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (539) */
   interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact<u128> {}
 
-  /** @name OpalRuntimeRuntime (495) */
+  /** @name OpalRuntimeRuntime (540) */
   type OpalRuntimeRuntime = Null;
 
-  /** @name PalletEthereumFakeTransactionFinalizer (496) */
+  /** @name PalletEthereumFakeTransactionFinalizer (541) */
   type PalletEthereumFakeTransactionFinalizer = Null;
 
 } // declare module
modifiedtests/src/interfaces/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types.ts
+++ b/tests/src/interfaces/types.ts
@@ -3,6 +3,5 @@
 
 export * from './unique/types';
 export * from './appPromotion/types';
-export * from './rmrk/types';
 export * from './povinfo/types';
 export * from './default/types';
addedtests/src/maintenance.seqtest.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/maintenance.seqtest.ts
@@ -0,0 +1,368 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// 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 {IKeyringPair} from '@polkadot/types/types';
+import {ApiPromise} from '@polkadot/api';
+import {expect, itSched, itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds} from './util';
+import {itEth} from './eth/util';
+import {UniqueHelper} from './util/playgrounds/unique';
+
+async function maintenanceEnabled(api: ApiPromise): Promise<boolean> {
+  return (await api.query.maintenance.enabled()).toJSON() as boolean;
+}
+
+describe('Integration Test: Maintenance Functionality', () => {
+  let superuser: IKeyringPair;
+  let donor: IKeyringPair;
+  let bob: IKeyringPair;
+
+  before(async function() {
+    await usingPlaygrounds(async (helper, privateKey) => {
+      requirePalletsOrSkip(this, helper, [Pallets.Maintenance]);
+      superuser = await privateKey('//Alice');
+      donor = await privateKey({filename: __filename});
+      [bob] = await helper.arrange.createAccounts([10000n], donor);
+
+    });
+  });
+
+  describe('Maintenance Mode', () => {
+    before(async function() {
+      await usingPlaygrounds(async (helper) => {
+        if (await maintenanceEnabled(helper.getApi())) {
+          console.warn('\tMaintenance mode was left enabled BEFORE the test suite! Disabling it now.');
+          await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', [])).to.be.fulfilled;
+        }
+      });
+    });
+
+    itSub('Allows superuser to enable and disable maintenance mode - and disallows anyone else', async ({helper}) => {
+      // Make sure non-sudo can't enable maintenance mode
+      await expect(helper.executeExtrinsic(superuser, 'api.tx.maintenance.enable', []), 'on commoner enabling MM')
+        .to.be.rejectedWith(/BadOrigin/);
+
+      // Set maintenance mode
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
+
+      // Make sure non-sudo can't disable maintenance mode
+      await expect(helper.executeExtrinsic(bob, 'api.tx.maintenance.disable', []), 'on commoner disabling MM')
+        .to.be.rejectedWith(/BadOrigin/);
+
+      // Disable maintenance mode
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
+    });
+
+    itSub('MM blocks unique pallet calls', async ({helper}) => {
+      // Can create an NFT collection before enabling the MM
+      const nftCollection = await helper.nft.mintCollection(bob, {
+        tokenPropertyPermissions: [{key: 'test', permission: {
+          collectionAdmin: true,
+          tokenOwner: true,
+          mutable: true,
+        }}],
+      });
+
+      // Can mint an NFT before enabling the MM
+      const nft = await nftCollection.mintToken(bob);
+
+      // Can create an FT collection before enabling the MM
+      const ftCollection = await helper.ft.mintCollection(superuser);
+
+      // Can mint an FT before enabling the MM
+      await expect(ftCollection.mint(superuser)).to.be.fulfilled;
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
+
+      // Unable to create a collection when the MM is enabled
+      await expect(helper.nft.mintCollection(superuser), 'cudo forbidden stuff')
+        .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
+
+      // Unable to set token properties when the MM is enabled
+      await expect(nft.setProperties(
+        bob,
+        [{key: 'test', value: 'test-val'}],
+      )).to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
+
+      // Unable to mint an NFT when the MM is enabled
+      await expect(nftCollection.mintToken(superuser))
+        .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
+
+      // Unable to mint an FT when the MM is enabled
+      await expect(ftCollection.mint(superuser))
+        .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
+
+      // Can create a collection after disabling the MM
+      await expect(helper.nft.mintCollection(bob), 'MM is disabled, the collection should be created').to.be.fulfilled;
+
+      // Can set token properties after disabling the MM
+      await nft.setProperties(bob, [{key: 'test', value: 'test-val'}]);
+
+      // Can mint an NFT after disabling the MM
+      await nftCollection.mintToken(bob);
+
+      // Can mint an FT after disabling the MM
+      await ftCollection.mint(superuser);
+    });
+
+    itSub.ifWithPallets('MM blocks unique pallet calls (Re-Fungible)', [Pallets.ReFungible], async ({helper}) => {
+      // Can create an RFT collection before enabling the MM
+      const rftCollection = await helper.rft.mintCollection(superuser);
+
+      // Can mint an RFT before enabling the MM
+      await expect(rftCollection.mintToken(superuser)).to.be.fulfilled;
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
+
+      // Unable to mint an RFT when the MM is enabled
+      await expect(rftCollection.mintToken(superuser))
+        .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
+
+      // Can mint an RFT after disabling the MM
+      await rftCollection.mintToken(superuser);
+    });
+
+    itSub('MM allows native token transfers and RPC calls', async ({helper}) => {
+      // We can use RPC before the MM is enabled
+      const totalCount = await helper.collection.getTotalCount();
+
+      // We can transfer funds before the MM is enabled
+      await expect(helper.balance.transferToSubstrate(superuser, bob.address, 2n)).to.be.fulfilled;
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
+
+      // RPCs work while in maintenance
+      expect(await helper.collection.getTotalCount()).to.be.deep.equal(totalCount);
+
+      // We still able to transfer funds
+      await expect(helper.balance.transferToSubstrate(bob, superuser.address, 1n)).to.be.fulfilled;
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
+
+      // RPCs work after maintenance
+      expect(await helper.collection.getTotalCount()).to.be.deep.equal(totalCount);
+
+      // Transfers work after maintenance
+      await expect(helper.balance.transferToSubstrate(bob, superuser.address, 1n)).to.be.fulfilled;
+    });
+
+    itSched.ifWithPallets('MM blocks scheduled calls and the scheduler itself', [Pallets.Scheduler], async (scheduleKind, {helper}) => {
+      const collection = await helper.nft.mintCollection(bob);
+
+      const nftBeforeMM = await collection.mintToken(bob);
+      const nftDuringMM = await collection.mintToken(bob);
+      const nftAfterMM = await collection.mintToken(bob);
+
+      const [
+        scheduledIdBeforeMM,
+        scheduledIdDuringMM,
+        scheduledIdBunkerThroughMM,
+        scheduledIdAttemptDuringMM,
+        scheduledIdAfterMM,
+      ] = scheduleKind == 'named'
+        ? helper.arrange.makeScheduledIds(5)
+        : new Array(5);
+
+      const blocksToWait = 6;
+
+      // Scheduling works before the maintenance
+      await nftBeforeMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdBeforeMM})
+        .transfer(bob, {Substrate: superuser.address});
+
+      await helper.wait.newBlocks(blocksToWait + 1);
+      expect(await nftBeforeMM.getOwner()).to.be.deep.equal({Substrate: superuser.address});
+
+      // Schedule a transaction that should occur *during* the maintenance
+      await nftDuringMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdDuringMM})
+        .transfer(bob, {Substrate: superuser.address});
+
+      // Schedule a transaction that should occur *after* the maintenance
+      await nftDuringMM.scheduleAfter(blocksToWait * 2, {scheduledId: scheduledIdBunkerThroughMM})
+        .transfer(bob, {Substrate: superuser.address});
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
+
+      await helper.wait.newBlocks(blocksToWait + 1);
+      // The owner should NOT change since the scheduled transaction should be rejected
+      expect(await nftDuringMM.getOwner()).to.be.deep.equal({Substrate: bob.address});
+
+      // Any attempts to schedule a tx during the MM should be rejected
+      await expect(nftDuringMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdAttemptDuringMM})
+        .transfer(bob, {Substrate: superuser.address}))
+        .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
+
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
+
+      // Scheduling works after the maintenance
+      await nftAfterMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdAfterMM})
+        .transfer(bob, {Substrate: superuser.address});
+
+      await helper.wait.newBlocks(blocksToWait + 1);
+
+      expect(await nftAfterMM.getOwner()).to.be.deep.equal({Substrate: superuser.address});
+      // The owner of the token scheduled for transaction *before* maintenance should now change *after* maintenance
+      expect(await nftDuringMM.getOwner()).to.be.deep.equal({Substrate: superuser.address});
+    });
+
+    itEth('Disallows Ethereum transactions to execute while in maintenance', async ({helper}) => {
+      const owner = await helper.eth.createAccountWithBalance(donor);
+      const receiver = helper.eth.createAccount();
+
+      const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'A', 'B', 'C', '');
+
+      // Set maintenance mode
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
+
+      const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+      const tokenId = await contract.methods.nextTokenId().call();
+      expect(tokenId).to.be.equal('1');
+
+      await expect(contract.methods.mintWithTokenURI(receiver, 'Test URI').send())
+        .to.be.rejectedWith(/Returned error: unknown error/);
+
+      await expect(contract.methods.ownerOf(tokenId).call()).rejectedWith(/token not found/);
+
+      // Disable maintenance mode
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
+    });
+
+    itSub('Allows to enable and disable MM repeatedly', async ({helper}) => {
+      // Set maintenance mode
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
+
+      // Disable maintenance mode
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+      expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
+    });
+
+    afterEach(async () => {
+      await usingPlaygrounds(async helper => {
+        if (helper.fetchMissingPalletNames([Pallets.Maintenance]).length != 0) return;
+        if (await maintenanceEnabled(helper.getApi())) {
+          console.warn('\tMaintenance mode was left enabled AFTER a test has finished! Be careful. Disabling it now.');
+          await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
+        }
+        expect(await maintenanceEnabled(helper.getApi()), 'Disastrous! Exited the test suite with maintenance mode on.').to.be.false;
+      });
+    });
+  });
+
+  describe('Preimage Execution', () => {
+    const preimageHashes: string[] = [];
+
+    async function notePreimage(helper: UniqueHelper, preimage: any): Promise<string> {
+      const result = await helper.preimage.notePreimage(bob, preimage);
+      const events = result.result.events.filter(x => x.event.method === 'Noted' && x.event.section === 'preimage');
+      const preimageHash = events[0].event.data[0].toHuman();
+      return preimageHash;
+    }
+
+    before(async function() {
+      await usingPlaygrounds(async (helper) => {
+        requirePalletsOrSkip(this, helper, [Pallets.Preimage, Pallets.Maintenance]);
+
+        // create a preimage to be operated with in the tests
+        const randomAccounts = await helper.arrange.createCrowd(10, 0n, superuser);
+        const randomIdentities = randomAccounts.map((acc, i) => [
+          acc.address, {
+            deposit: 0n,
+            judgements: [],
+            info: {
+              display: {
+                raw: `Random Account #${i}`,
+              },
+            },
+          },
+        ]);
+        const preimage = helper.constructApiCall('api.tx.identity.forceInsertIdentities', [randomIdentities]).method.toHex();
+        preimageHashes.push(await notePreimage(helper, preimage));
+      });
+    });
+
+    itSub('Successfully executes call in a preimage', async ({helper}) => {
+      const result = await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.executePreimage', [
+        preimageHashes[0], {refTime: 10000000000, proofSize: 10000},
+      ])).to.be.fulfilled;
+
+      // preimage is executed, and an appropriate event is present
+      const events = result.result.events.filter((x: any) => x.event.method === 'IdentitiesInserted' && x.event.section === 'identity');
+      expect(events.length).to.be.equal(1);
+
+      // the preimage goes back to being unrequested
+      expect(await helper.preimage.getPreimageInfo(preimageHashes[0])).to.have.property('unrequested');
+    });
+
+    itSub('Does not allow execution of a preimage that would fail', async ({helper}) => {
+      const [zeroAccount] = await helper.arrange.createAccounts([0n], superuser);
+
+      const preimage = helper.constructApiCall('api.tx.balances.forceTransfer', [
+        {Id: zeroAccount.address}, {Id: superuser.address}, 1000n,
+      ]).method.toHex();
+      const preimageHash = await notePreimage(helper, preimage);
+      preimageHashes.push(preimageHash);
+
+      await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.executePreimage', [
+        preimageHash, {refTime: 10000000000, proofSize: 10000},
+      ])).to.be.rejectedWith(/balances\.InsufficientBalance/);
+    });
+
+    itSub('Does not allow preimage execution with non-root', async ({helper}) => {
+      await expect(helper.executeExtrinsic(bob, 'api.tx.maintenance.executePreimage', [
+        preimageHashes[0], {refTime: 10000000000, proofSize: 10000},
+      ])).to.be.rejectedWith(/BadOrigin/);
+    });
+
+    itSub('Does not allow execution of non-existent preimages', async ({helper}) => {
+      await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.executePreimage', [
+        '0x1010101010101010101010101010101010101010101010101010101010101010', {refTime: 10000000000, proofSize: 10000},
+      ])).to.be.rejectedWith(/Unavailable/);
+    });
+
+    itSub('Does not allow preimage execution with less than minimum weights', async ({helper}) => {
+      await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.executePreimage', [
+        preimageHashes[0], {refTime: 1000, proofSize: 100},
+      ])).to.be.rejectedWith(/Exhausted/);
+    });
+
+    after(async function() {
+      await usingPlaygrounds(async (helper) => {
+        if (helper.fetchMissingPalletNames([Pallets.Preimage, Pallets.Maintenance]).length != 0) return;
+
+        for (const hash of preimageHashes) {
+          await helper.preimage.unnotePreimage(bob, hash);
+        }
+      });
+    });
+  });
+});
deletedtests/src/maintenanceMode.seqtest.tsdiffbeforeafterboth
--- a/tests/src/maintenanceMode.seqtest.ts
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// 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 {IKeyringPair} from '@polkadot/types/types';
-import {ApiPromise} from '@polkadot/api';
-import {expect, itSched, itSub, Pallets, usingPlaygrounds} from './util';
-import {itEth} from './eth/util';
-
-async function maintenanceEnabled(api: ApiPromise): Promise<boolean> {
-  return (await api.query.maintenance.enabled()).toJSON() as boolean;
-}
-
-describe('Integration Test: Maintenance Mode', () => {
-  let superuser: IKeyringPair;
-  let donor: IKeyringPair;
-  let bob: IKeyringPair;
-
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      superuser = await privateKey('//Alice');
-      donor = await privateKey({filename: __filename});
-      [bob] = await helper.arrange.createAccounts([100n], donor);
-
-      if (await maintenanceEnabled(helper.getApi())) {
-        console.warn('\tMaintenance mode was left enabled BEFORE the test suite! Disabling it now.');
-        await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', [])).to.be.fulfilled;
-      }
-    });
-  });
-
-  itSub('Allows superuser to enable and disable maintenance mode - and disallows anyone else', async ({helper}) => {
-    // Make sure non-sudo can't enable maintenance mode
-    await expect(helper.executeExtrinsic(superuser, 'api.tx.maintenance.enable', []), 'on commoner enabling MM')
-      .to.be.rejectedWith(/BadOrigin/);
-
-    // Set maintenance mode
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
-
-    // Make sure non-sudo can't disable maintenance mode
-    await expect(helper.executeExtrinsic(bob, 'api.tx.maintenance.disable', []), 'on commoner disabling MM')
-      .to.be.rejectedWith(/BadOrigin/);
-
-    // Disable maintenance mode
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
-  });
-
-  itSub('MM blocks unique pallet calls', async ({helper}) => {
-    // Can create an NFT collection before enabling the MM
-    const nftCollection = await helper.nft.mintCollection(bob, {
-      tokenPropertyPermissions: [{key: 'test', permission: {
-        collectionAdmin: true,
-        tokenOwner: true,
-        mutable: true,
-      }}],
-    });
-
-    // Can mint an NFT before enabling the MM
-    const nft = await nftCollection.mintToken(bob);
-
-    // Can create an FT collection before enabling the MM
-    const ftCollection = await helper.ft.mintCollection(superuser);
-
-    // Can mint an FT before enabling the MM
-    await expect(ftCollection.mint(superuser)).to.be.fulfilled;
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
-
-    // Unable to create a collection when the MM is enabled
-    await expect(helper.nft.mintCollection(superuser), 'cudo forbidden stuff')
-      .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
-
-    // Unable to set token properties when the MM is enabled
-    await expect(nft.setProperties(
-      bob,
-      [{key: 'test', value: 'test-val'}],
-    )).to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
-
-    // Unable to mint an NFT when the MM is enabled
-    await expect(nftCollection.mintToken(superuser))
-      .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
-
-    // Unable to mint an FT when the MM is enabled
-    await expect(ftCollection.mint(superuser))
-      .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
-
-    // Can create a collection after disabling the MM
-    await expect(helper.nft.mintCollection(bob), 'MM is disabled, the collection should be created').to.be.fulfilled;
-
-    // Can set token properties after disabling the MM
-    await nft.setProperties(bob, [{key: 'test', value: 'test-val'}]);
-
-    // Can mint an NFT after disabling the MM
-    await nftCollection.mintToken(bob);
-
-    // Can mint an FT after disabling the MM
-    await ftCollection.mint(superuser);
-  });
-
-  itSub.ifWithPallets('MM blocks unique pallet calls (Re-Fungible)', [Pallets.ReFungible], async ({helper}) => {
-    // Can create an RFT collection before enabling the MM
-    const rftCollection = await helper.rft.mintCollection(superuser);
-
-    // Can mint an RFT before enabling the MM
-    await expect(rftCollection.mintToken(superuser)).to.be.fulfilled;
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
-
-    // Unable to mint an RFT when the MM is enabled
-    await expect(rftCollection.mintToken(superuser))
-      .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
-
-    // Can mint an RFT after disabling the MM
-    await rftCollection.mintToken(superuser);
-  });
-
-  itSub('MM allows native token transfers and RPC calls', async ({helper}) => {
-    // We can use RPC before the MM is enabled
-    const totalCount = await helper.collection.getTotalCount();
-
-    // We can transfer funds before the MM is enabled
-    await expect(helper.balance.transferToSubstrate(superuser, bob.address, 2n)).to.be.fulfilled;
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
-
-    // RPCs work while in maintenance
-    expect(await helper.collection.getTotalCount()).to.be.deep.equal(totalCount);
-
-    // We still able to transfer funds
-    await expect(helper.balance.transferToSubstrate(bob, superuser.address, 1n)).to.be.fulfilled;
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
-
-    // RPCs work after maintenance
-    expect(await helper.collection.getTotalCount()).to.be.deep.equal(totalCount);
-
-    // Transfers work after maintenance
-    await expect(helper.balance.transferToSubstrate(bob, superuser.address, 1n)).to.be.fulfilled;
-  });
-
-  itSched.ifWithPallets('MM blocks scheduled calls and the scheduler itself', [Pallets.Scheduler], async (scheduleKind, {helper}) => {
-    const collection = await helper.nft.mintCollection(bob);
-
-    const nftBeforeMM = await collection.mintToken(bob);
-    const nftDuringMM = await collection.mintToken(bob);
-    const nftAfterMM = await collection.mintToken(bob);
-
-    const [
-      scheduledIdBeforeMM,
-      scheduledIdDuringMM,
-      scheduledIdBunkerThroughMM,
-      scheduledIdAttemptDuringMM,
-      scheduledIdAfterMM,
-    ] = scheduleKind == 'named'
-      ? helper.arrange.makeScheduledIds(5)
-      : new Array(5);
-
-    const blocksToWait = 6;
-
-    // Scheduling works before the maintenance
-    await nftBeforeMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdBeforeMM})
-      .transfer(bob, {Substrate: superuser.address});
-
-    await helper.wait.newBlocks(blocksToWait + 1);
-    expect(await nftBeforeMM.getOwner()).to.be.deep.equal({Substrate: superuser.address});
-
-    // Schedule a transaction that should occur *during* the maintenance
-    await nftDuringMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdDuringMM})
-      .transfer(bob, {Substrate: superuser.address});
-
-    // Schedule a transaction that should occur *after* the maintenance
-    await nftDuringMM.scheduleAfter(blocksToWait * 2, {scheduledId: scheduledIdBunkerThroughMM})
-      .transfer(bob, {Substrate: superuser.address});
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
-
-    await helper.wait.newBlocks(blocksToWait + 1);
-    // The owner should NOT change since the scheduled transaction should be rejected
-    expect(await nftDuringMM.getOwner()).to.be.deep.equal({Substrate: bob.address});
-
-    // Any attempts to schedule a tx during the MM should be rejected
-    await expect(nftDuringMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdAttemptDuringMM})
-      .transfer(bob, {Substrate: superuser.address}))
-      .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
-
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
-
-    // Scheduling works after the maintenance
-    await nftAfterMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdAfterMM})
-      .transfer(bob, {Substrate: superuser.address});
-
-    await helper.wait.newBlocks(blocksToWait + 1);
-
-    expect(await nftAfterMM.getOwner()).to.be.deep.equal({Substrate: superuser.address});
-    // The owner of the token scheduled for transaction *before* maintenance should now change *after* maintenance
-    expect(await nftDuringMM.getOwner()).to.be.deep.equal({Substrate: superuser.address});
-  });
-
-  itEth('Disallows Ethereum transactions to execute while in maintenance', async ({helper}) => {
-    const owner = await helper.eth.createAccountWithBalance(donor);
-    const receiver = helper.eth.createAccount();
-
-    const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'A', 'B', 'C', '');
-
-    // Set maintenance mode
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
-
-    const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
-    const tokenId = await contract.methods.nextTokenId().call();
-    expect(tokenId).to.be.equal('1');
-
-    await expect(contract.methods.mintWithTokenURI(receiver, 'Test URI').send())
-      .to.be.rejectedWith(/Returned error: unknown error/);
-
-    await expect(contract.methods.ownerOf(tokenId).call()).rejectedWith(/token not found/);
-
-    // Disable maintenance mode
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
-  });
-
-  itSub('Allows to enable and disable MM repeatedly', async ({helper}) => {
-    // Set maintenance mode
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true;
-
-    // Disable maintenance mode
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-    expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
-  });
-
-  afterEach(async () => {
-    await usingPlaygrounds(async helper => {
-      if (await maintenanceEnabled(helper.getApi())) {
-        console.warn('\tMaintenance mode was left enabled AFTER a test has finished! Be careful. Disabling it now.');
-        await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []);
-      }
-      expect(await maintenanceEnabled(helper.getApi()), 'Disastrous! Exited the test suite with maintenance mode on.').to.be.false;
-    });
-  });
-});
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -66,6 +66,7 @@
       const foreignAssets = 'foreignassets';
       const appPromotion = 'apppromotion';
       const collatorSelection = ['authorship', 'session', 'collatorselection', 'identity'];
+      const preimage = ['preimage'];
       const testUtils = 'testutils';
 
       if (chain.eq('OPAL by UNIQUE')) {
@@ -75,6 +76,7 @@
           appPromotion,
           testUtils,
           ...collatorSelection,
+          ...preimage,
         );
       } else if (chain.eq('QUARTZ by UNIQUE') || chain.eq('SAPPHIRE by UNIQUE')) {
         requiredPallets.push(
@@ -82,6 +84,7 @@
           appPromotion,
           foreignAssets,
           ...collatorSelection,
+          ...preimage,
         );
       } else if (chain.eq('UNIQUE')) {
         // Insert Unique additional pallets here
modifiedtests/src/util/identitySetter.tsdiffbeforeafterboth
--- a/tests/src/util/identitySetter.ts
+++ b/tests/src/util/identitySetter.ts
@@ -1,13 +1,14 @@
 // Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
 // SPDX-License-Identifier: Apache-2.0
 //
-// Pulls identities and sub-identities from a chain and then uses sudo to force upload them into another.
+// Pulls identities and sub-identities from a chain and then makes a preimage to later force upload them into another.
 // Only changed or previously non-existent data are inserted.
 //
-// Usage: `yarn setIdentities [relay WS URL] [parachain WS URL] [sudo key]`
+// Usage: `yarn setIdentities [relay WS URL] [parachain WS URL] [user key]
 // Example: `yarn setIdentities wss://polkadot-rpc.dwellir.com ws://localhost:9944 escape pattern miracle train sudden cart adapt embark wedding alien lamp mesh`
 
 import {encodeAddress} from '@polkadot/keyring';
+import {IKeyringPair} from '@polkadot/types/types';
 import {usingPlaygrounds, Pallets} from './index';
 import {ChainHelperBase} from './playgrounds/unique';
 
@@ -81,6 +82,18 @@
   return (await helper.getApi().query.identity.superOf.entries()).map(([key, value]) => [extractAccountId(key), value as any]);
 }
 
+async function uploadPreimage(helper: ChainHelperBase, preimageMaker: IKeyringPair, preimage: string) {
+  try {
+    await helper.executeExtrinsic(preimageMaker, 'api.tx.preimage.notePreimage', [preimage]);
+  } catch(e: any) {
+    if (e.message.includes('AlreadyNoted')) {
+      console.warn('Warning: The same preimage already exists on the chain. Nothing was uploaded.');
+    } else {
+      console.error(e);
+    }
+  }
+}
+
 // The utility for pulling identity and sub-identity data
 const forceInsertIdentities = async (): Promise<void> => {
   let relaySS58Prefix = 0;
@@ -128,8 +141,10 @@
 
   await usingPlaygrounds(async (helper, privateKey) => {
     if (helper.fetchMissingPalletNames([Pallets.Identity]).length != 0) console.error('pallet-identity is not included in parachain.');
+    if (helper.fetchMissingPalletNames([Pallets.Preimage]).length != 0) console.error('pallet-preimage is not included in parachain.');
+
     try {
-      const superuser = await privateKey(key);
+      const preimageMaker = await privateKey(key);
       const ss58Format = helper.chain.getChainProperties().ss58Format;
       const paraIdentities = await getIdentities(helper);
       const identitiesToAdd: any[] = [];
@@ -158,13 +173,21 @@
       }
 
       if (identitiesToRemove.length != 0)
-        await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceRemoveIdentities', [identitiesToRemove]);
+        await uploadPreimage(
+          helper,
+          preimageMaker,
+          helper.constructApiCall('api.tx.identity.forceRemoveIdentities', [identitiesToRemove]).method.toHex(),
+        );
       if (identitiesToAdd.length != 0)
-        await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identitiesToAdd]);
+        await uploadPreimage(
+          helper,
+          preimageMaker,
+          helper.constructApiCall('api.tx.identity.forceInsertIdentities', [identitiesToAdd]).method.toHex(),
+        );
 
-      console.log(`Tried to upload ${identitiesToAdd.length} identities`
+      console.log(`Tried to push ${identitiesToAdd.length} identities`
         + ` and found ${identitiesToRemove.length} identities for potential removal.`
-        + ` Now there are ${(await helper.getApi().query.identity.identityOf.keys()).length}.`);
+        + ` Currently there are ${(await helper.getApi().query.identity.identityOf.keys()).length} identities on the chain.`);
 
       // fill sub-identities
       const paraSubs = await getSubs(helper);
@@ -187,10 +210,14 @@
       }
 
       if (subsToUpdate.length != 0)
-        await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsToUpdate]);
+        await uploadPreimage(
+          helper,
+          preimageMaker,
+          helper.constructApiCall('api.tx.identity.forceSetSubs', [subsToUpdate]).method.toHex(),
+        );
 
-      console.log(`Also tried to update ${subsToUpdate.length} identities with their sub-identities.`
-        + ` Now there are ${(await helper.getApi().query.identity.subsOf.keys()).length} identities with subs.`);
+      console.log(`Also tried to push ${subsToUpdate.length} identities with their sub-identities.`
+        + ` Currently there are ${(await helper.getApi().query.identity.subsOf.keys()).length} identities with subs.`);
     } catch (error) {
       console.error(error);
       throw Error('Error during setting identities');
modifiedtests/src/util/index.tsdiffbeforeafterboth
--- a/tests/src/util/index.ts
+++ b/tests/src/util/index.ts
@@ -114,6 +114,8 @@
   CollatorSelection = 'collatorselection',
   Session = 'session',
   Identity = 'identity',
+  Preimage = 'preimage',
+  Maintenance = 'maintenance',
   TestUtils = 'testutils',
 }
 
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
before · tests/src/util/playgrounds/unique.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034/* eslint-disable @typescript-eslint/no-var-requires */5/* eslint-disable function-call-argument-newline */6/* eslint-disable no-prototype-builtins */78import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';9import {SignerOptions} from '@polkadot/api/types/submittable';10import {ApiInterfaceEvents} from '@polkadot/api/types';11import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';12import {IKeyringPair} from '@polkadot/types/types';13import {hexToU8a} from '@polkadot/util/hex';14import {u8aConcat} from '@polkadot/util/u8a';15import {16  IApiListeners,17  IBlock,18  IEvent,19  IChainProperties,20  ICollectionCreationOptions,21  ICollectionLimits,22  ICollectionPermissions,23  ICrossAccountId,24  ICrossAccountIdLower,25  ILogger,26  INestingPermissions,27  IProperty,28  IStakingInfo,29  ISchedulerOptions,30  ISubstrateBalance,31  IToken,32  ITokenPropertyPermission,33  ITransactionResult,34  IUniqueHelperLog,35  TApiAllowedListeners,36  TEthereumAccount,37  TSigner,38  TSubstrateAccount,39  TNetworks,40  IForeignAssetMetadata,41  AcalaAssetMetadata,42  MoonbeamAssetInfo,43  DemocracyStandardAccountVote,44  IEthCrossAccountId,45} from './types';46import {RuntimeDispatchInfo} from '@polkadot/types/interfaces';47import type {Vec} from '@polkadot/types-codec';48import {FrameSystemEventRecord} from '@polkadot/types/lookup';4950export class CrossAccountId implements ICrossAccountId {51  Substrate?: TSubstrateAccount;52  Ethereum?: TEthereumAccount;5354  constructor(account: ICrossAccountId) {55    if (account.Substrate) this.Substrate = account.Substrate;56    if (account.Ethereum) this.Ethereum = account.Ethereum;57  }5859  static fromKeyring(account: IKeyringPair, domain: 'Substrate' | 'Ethereum' = 'Substrate') {60    switch (domain) {61      case 'Substrate': return new CrossAccountId({Substrate: account.address});62      case 'Ethereum': return new CrossAccountId({Substrate: account.address}).toEthereum();63    }64  }6566  static fromLowerCaseKeys(address: ICrossAccountIdLower): CrossAccountId {67    return new CrossAccountId({Substrate: address.substrate, Ethereum: address.ethereum});68  }6970  static normalizeSubstrateAddress(address: TSubstrateAccount, ss58Format = 42): TSubstrateAccount {71    return encodeAddress(decodeAddress(address), ss58Format);72  }7374  static withNormalizedSubstrate(address: TSubstrateAccount, ss58Format = 42): CrossAccountId {75    return new CrossAccountId({Substrate: CrossAccountId.normalizeSubstrateAddress(address, ss58Format)});76  }7778  withNormalizedSubstrate(ss58Format = 42): CrossAccountId {79    if (this.Substrate) return CrossAccountId.withNormalizedSubstrate(this.Substrate, ss58Format);80    return this;81  }8283  static translateSubToEth(address: TSubstrateAccount): TEthereumAccount {84    return nesting.toChecksumAddress('0x' + Array.from(addressToEvm(address), i => i.toString(16).padStart(2, '0')).join(''));85  }8687  toEthereum(): CrossAccountId {88    if (this.Substrate) return new CrossAccountId({Ethereum: CrossAccountId.translateSubToEth(this.Substrate)});89    return this;90  }9192  static translateEthToSub(address: TEthereumAccount, ss58Format?: number): TSubstrateAccount {93    return evmToAddress(address, ss58Format);94  }9596  toSubstrate(ss58Format?: number): CrossAccountId {97    if (this.Ethereum) return new CrossAccountId({Substrate: CrossAccountId.translateEthToSub(this.Ethereum, ss58Format)});98    return this;99  }100101  toLowerCase(): CrossAccountId {102    if (this.Substrate) this.Substrate = this.Substrate.toLowerCase();103    if (this.Ethereum) this.Ethereum = this.Ethereum.toLowerCase();104    return this;105  }106}107108const nesting = {109  toChecksumAddress(address: string): string {110    if (typeof address === 'undefined') return '';111112    if(!/^(0x)?[0-9a-f]{40}$/i.test(address)) throw new Error(`Given address "${address}" is not a valid Ethereum address.`);113114    address = address.toLowerCase().replace(/^0x/i,'');115    const addressHash = keccakAsHex(address).replace(/^0x/i,'');116    const checksumAddress = ['0x'];117118    for (let i = 0; i < address.length; i++) {119      // If ith character is 8 to f then make it uppercase120      if (parseInt(addressHash[i], 16) > 7) {121        checksumAddress.push(address[i].toUpperCase());122      } else {123        checksumAddress.push(address[i]);124      }125    }126    return checksumAddress.join('');127  },128  tokenIdToAddress(collectionId: number, tokenId: number) {129    return this.toChecksumAddress(`0xf8238ccfff8ed887463fd5e0${collectionId.toString(16).padStart(8, '0')}${tokenId.toString(16).padStart(8, '0')}`);130  },131};132133class UniqueUtil {134  static transactionStatus = {135    NOT_READY: 'NotReady',136    FAIL: 'Fail',137    SUCCESS: 'Success',138  };139140  static chainLogType = {141    EXTRINSIC: 'extrinsic',142    RPC: 'rpc',143  };144145  static getTokenAccount(token: IToken): CrossAccountId {146    return new CrossAccountId({Ethereum: this.getTokenAddress(token)});147  }148149  static getTokenAddress(token: IToken): string {150    return nesting.tokenIdToAddress(token.collectionId, token.tokenId);151  }152153  static getDefaultLogger(): ILogger {154    return {155      log(msg: any, level = 'INFO') {156        console[level.toLocaleLowerCase() === 'error' ? 'error' : 'log'](...(Array.isArray(msg) ? msg : [msg]));157      },158      level: {159        ERROR: 'ERROR',160        WARNING: 'WARNING',161        INFO: 'INFO',162      },163    };164  }165166  static vec2str(arr: string[] | number[]) {167    return arr.map(x => String.fromCharCode(parseInt(x.toString()))).join('');168  }169170  static str2vec(string: string) {171    if (typeof string !== 'string') return string;172    return Array.from(string).map(x => x.charCodeAt(0));173  }174175  static fromSeed(seed: string, ss58Format = 42) {176    const keyring = new Keyring({type: 'sr25519', ss58Format});177    return keyring.addFromUri(seed);178  }179180  static extractCollectionIdFromCreationResult(creationResult: ITransactionResult): number {181    if (creationResult.status !== this.transactionStatus.SUCCESS) {182      throw Error('Unable to create collection!');183    }184185    let collectionId = null;186    creationResult.result.events.forEach(({event: {data, method, section}}) => {187      if ((section === 'common') && (method === 'CollectionCreated')) {188        collectionId = parseInt(data[0].toString(), 10);189      }190    });191192    if (collectionId === null) {193      throw Error('No CollectionCreated event was found!');194    }195196    return collectionId;197  }198199  static extractTokensFromCreationResult(creationResult: ITransactionResult): {200    success: boolean,201    tokens: {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[],202  } {203    if (creationResult.status !== this.transactionStatus.SUCCESS) {204      throw Error('Unable to create tokens!');205    }206    let success = false;207    const tokens = [] as {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[];208    creationResult.result.events.forEach(({event: {data, method, section}}) => {209      if (method === 'ExtrinsicSuccess') {210        success = true;211      } else if ((section === 'common') && (method === 'ItemCreated')) {212        tokens.push({213          collectionId: parseInt(data[0].toString(), 10),214          tokenId: parseInt(data[1].toString(), 10),215          owner: data[2].toHuman(),216          amount: data[3].toBigInt(),217        });218      }219    });220    return {success, tokens};221  }222223  static extractTokensFromBurnResult(burnResult: ITransactionResult): {224    success: boolean,225    tokens: {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[],226  } {227    if (burnResult.status !== this.transactionStatus.SUCCESS) {228      throw Error('Unable to burn tokens!');229    }230    let success = false;231    const tokens = [] as {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[];232    burnResult.result.events.forEach(({event: {data, method, section}}) => {233      if (method === 'ExtrinsicSuccess') {234        success = true;235      } else if ((section === 'common') && (method === 'ItemDestroyed')) {236        tokens.push({237          collectionId: parseInt(data[0].toString(), 10),238          tokenId: parseInt(data[1].toString(), 10),239          owner: data[2].toHuman(),240          amount: data[3].toBigInt(),241        });242      }243    });244    return {success, tokens};245  }246247  static findCollectionInEvents(events: {event: IEvent}[], collectionId: number, expectedSection: string, expectedMethod: string): boolean {248    let eventId = null;249    events.forEach(({event: {data, method, section}}) => {250      if ((section === expectedSection) && (method === expectedMethod)) {251        eventId = parseInt(data[0].toString(), 10);252      }253    });254255    if (eventId === null) {256      throw Error(`No ${expectedMethod} event was found!`);257    }258    return eventId === collectionId;259  }260261  static isTokenTransferSuccess(events: {event: IEvent}[], collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {262    const normalizeAddress = (address: string | ICrossAccountId) => {263      if(typeof address === 'string') return address;264      const obj = {} as any;265      Object.keys(address).forEach(k => {266        obj[k.toLocaleLowerCase()] = address[k as 'Substrate' | 'Ethereum'];267      });268      if(obj.substrate) return CrossAccountId.withNormalizedSubstrate(obj.substrate);269      if(obj.ethereum) return CrossAccountId.fromLowerCaseKeys(obj).toLowerCase();270      return address;271    };272    let transfer = {collectionId: null, tokenId: null, from: null, to: null, amount: 1} as any;273    events.forEach(({event: {data, method, section}}) => {274      if ((section === 'common') && (method === 'Transfer')) {275        const hData = (data as any).toJSON();276        transfer = {277          collectionId: hData[0],278          tokenId: hData[1],279          from: normalizeAddress(hData[2]),280          to: normalizeAddress(hData[3]),281          amount: BigInt(hData[4]),282        };283      }284    });285    let isSuccess = parseInt(collectionId.toString()) === transfer.collectionId && parseInt(tokenId.toString()) === transfer.tokenId;286    isSuccess = isSuccess && JSON.stringify(normalizeAddress(fromAddressObj)) === JSON.stringify(transfer.from);287    isSuccess = isSuccess && JSON.stringify(normalizeAddress(toAddressObj)) === JSON.stringify(transfer.to);288    isSuccess = isSuccess && amount === transfer.amount;289    return isSuccess;290  }291292  static bigIntToDecimals(number: bigint, decimals = 18) {293    const numberStr = number.toString();294    const dotPos = numberStr.length - decimals;295296    if (dotPos <= 0) {297      return '0.' + '0'.repeat(Math.abs(dotPos)) + numberStr;298    } else {299      const intPart = numberStr.substring(0, dotPos);300      const fractPart = numberStr.substring(dotPos);301      return intPart + '.' + fractPart;302    }303  }304}305306class UniqueEventHelper {307  private static extractIndex(index: any): [number, number] | string {308    if(index.toRawType() === '[u8;2]') return [index[0], index[1]];309    return index.toJSON();310  }311312  private static extractSub(data: any, subTypes: any): {[key: string]: any} {313    let obj: any = {};314    let index = 0;315316    if (data.entries) {317      for(const [key, value] of data.entries()) {318        obj[key] = this.extractData(value, subTypes[index]);319        index++;320      }321    } else obj = data.toJSON();322323    return obj;324  }325326  private static toHuman(data: any) {327    return data && data.toHuman ? data.toHuman() : `${data}`;328  }329330  private static extractData(data: any, type: any): any {331    if(!type) return this.toHuman(data);332    if (['u16', 'u32'].indexOf(type.type) > -1) return data.toNumber();333    if (['u64', 'u128', 'u256'].indexOf(type.type) > -1) return data.toBigInt();334    if(type.hasOwnProperty('sub')) return this.extractSub(data, type.sub);335    return this.toHuman(data);336  }337338  public static extractEvents(events: {event: any, phase: any}[]): IEvent[] {339    const parsedEvents: IEvent[] = [];340341    events.forEach((record) => {342      const {event, phase} = record;343      const types = event.typeDef;344345      const eventData: IEvent = {346        section: event.section.toString(),347        method: event.method.toString(),348        index: this.extractIndex(event.index),349        data: [],350        phase: phase.toJSON(),351      };352353      event.data.forEach((val: any, index: number) => {354        eventData.data.push(this.extractData(val, types[index]));355      });356357      parsedEvents.push(eventData);358    });359360    return parsedEvents;361  }362}363364export class ChainHelperBase {365  helperBase: any;366367  transactionStatus = UniqueUtil.transactionStatus;368  chainLogType = UniqueUtil.chainLogType;369  util: typeof UniqueUtil;370  eventHelper: typeof UniqueEventHelper;371  logger: ILogger;372  api: ApiPromise | null;373  forcedNetwork: TNetworks | null;374  network: TNetworks | null;375  wsEndpoint: string | null;376  chainLog: IUniqueHelperLog[];377  children: ChainHelperBase[];378  address: AddressGroup;379  chain: ChainGroup;380381  constructor(logger?: ILogger, helperBase?: any) {382    this.helperBase = helperBase;383384    this.util = UniqueUtil;385    this.eventHelper = UniqueEventHelper;386    if (typeof logger == 'undefined') logger = this.util.getDefaultLogger();387    this.logger = logger;388    this.api = null;389    this.forcedNetwork = null;390    this.network = null;391    this.wsEndpoint = null;392    this.chainLog = [];393    this.children = [];394    this.address = new AddressGroup(this);395    this.chain = new ChainGroup(this);396  }397398  clone(helperCls: ChainHelperBaseConstructor, options: {[key: string]: any} = {}) {399    Object.setPrototypeOf(helperCls.prototype, this);400    const newHelper = new helperCls(this.logger, options);401402    newHelper.api = this.api;403    newHelper.network = this.network;404    newHelper.forceNetwork = this.forceNetwork;405406    this.children.push(newHelper);407408    return newHelper;409  }410411  getEndpoint(): string {412    if (this.wsEndpoint === null) throw Error('No connection was established');413    return this.wsEndpoint;414  }415416  getApi(): ApiPromise {417    if(this.api === null) throw Error('API not initialized');418    return this.api;419  }420421  async subscribeEvents(expectedEvents: {section: string, names: string[]}[]) {422    const collectedEvents: IEvent[] = [];423    const unsubscribe = await this.getApi().query.system.events((events: Vec<FrameSystemEventRecord>) => {424      const ievents = this.eventHelper.extractEvents(events);425      ievents.forEach((event) => {426        expectedEvents.forEach((e => {427          if (event.section === e.section && e.names.includes(event.method)) {428            collectedEvents.push(event);429          }430        }));431      });432    });433    return {unsubscribe: unsubscribe as any, collectedEvents};434  }435436  clearChainLog(): void {437    this.chainLog = [];438  }439440  forceNetwork(value: TNetworks): void {441    this.forcedNetwork = value;442  }443444  async connect(wsEndpoint: string, listeners?: IApiListeners) {445    if (this.api !== null) throw Error('Already connected');446    const {api, network} = await ChainHelperBase.createConnection(wsEndpoint, listeners, this.forcedNetwork);447    this.wsEndpoint = wsEndpoint;448    this.api = api;449    this.network = network;450  }451452  async disconnect() {453    for (const child of this.children) {454      child.clearApi();455    }456457    if (this.api === null) return;458    await this.api.disconnect();459    this.clearApi();460  }461462  clearApi() {463    this.api = null;464    this.network = null;465  }466467  static async detectNetwork(api: ApiPromise): Promise<TNetworks> {468    const spec = (await api.query.system.lastRuntimeUpgrade()).toJSON() as any;469    const xcmChains = ['rococo', 'westend', 'westmint', 'acala', 'karura', 'moonbeam', 'moonriver'];470471    if(xcmChains.indexOf(spec.specName) > -1) return spec.specName;472473    if(['quartz', 'unique'].indexOf(spec.specName) > -1) return spec.specName;474    return 'opal';475  }476477  static async detectNetworkByWsEndpoint(wsEndpoint: string): Promise<TNetworks> {478    const api = new ApiPromise({provider: new WsProvider(wsEndpoint)});479    await api.isReady;480481    const network = await this.detectNetwork(api);482483    await api.disconnect();484485    return network;486  }487488  static async createConnection(wsEndpoint: string, listeners?: IApiListeners, network?: TNetworks | null): Promise<{489    api: ApiPromise;490    network: TNetworks;491  }> {492    if(typeof network === 'undefined' || network === null) network = 'opal';493    const supportedRPC = {494      opal: {495        unique: require('@unique-nft/opal-testnet-types/definitions').unique.rpc,496      },497      quartz: {498        unique: require('@unique-nft/quartz-mainnet-types/definitions').unique.rpc,499      },500      unique: {501        unique: require('@unique-nft/unique-mainnet-types/definitions').unique.rpc,502      },503      rococo: {},504      westend: {},505      moonbeam: {},506      moonriver: {},507      acala: {},508      karura: {},509      westmint: {},510    };511    if(!supportedRPC.hasOwnProperty(network)) network = await this.detectNetworkByWsEndpoint(wsEndpoint);512    const rpc = supportedRPC[network];513514    // TODO: investigate how to replace rpc in runtime515    // api._rpcCore.addUserInterfaces(rpc);516517    const api = new ApiPromise({provider: new WsProvider(wsEndpoint), rpc});518519    await api.isReadyOrError;520521    if (typeof listeners === 'undefined') listeners = {};522    for (const event of ['connected', 'disconnected', 'error', 'ready', 'decorated']) {523      if (!listeners.hasOwnProperty(event) || typeof listeners[event as TApiAllowedListeners] === 'undefined') continue;524      api.on(event as ApiInterfaceEvents, listeners[event as TApiAllowedListeners] as (...args: any[]) => any);525    }526527    return {api, network};528  }529530  getTransactionStatus(data: {events: {event: IEvent}[], status: any}) {531    const {events, status} = data;532    if (status.isReady) {533      return this.transactionStatus.NOT_READY;534    }535    if (status.isBroadcast) {536      return this.transactionStatus.NOT_READY;537    }538    if (status.isInBlock || status.isFinalized) {539      const errors = events.filter(e => e.event.method === 'ExtrinsicFailed');540      if (errors.length > 0) {541        return this.transactionStatus.FAIL;542      }543      if (events.filter(e => e.event.method === 'ExtrinsicSuccess').length > 0) {544        return this.transactionStatus.SUCCESS;545      }546    }547548    return this.transactionStatus.FAIL;549  }550551  signTransaction(sender: TSigner, transaction: any, options: Partial<SignerOptions> | null = null, label = 'transaction') {552    const sign = (callback: any) => {553      if(options !== null) return transaction.signAndSend(sender, options, callback);554      return transaction.signAndSend(sender, callback);555    };556    // eslint-disable-next-line no-async-promise-executor557    return new Promise(async (resolve, reject) => {558      try {559        const unsub = await sign((result: any) => {560          const status = this.getTransactionStatus(result);561562          if (status === this.transactionStatus.SUCCESS) {563            this.logger.log(`${label} successful`);564            unsub();565            resolve({result, status, blockHash: result.status.asInBlock.toHuman()});566          } else if (status === this.transactionStatus.FAIL) {567            let moduleError = null;568569            if (result.hasOwnProperty('dispatchError')) {570              const dispatchError = result['dispatchError'];571572              if (dispatchError) {573                if (dispatchError.isModule) {574                  const modErr = dispatchError.asModule;575                  const errorMeta = dispatchError.registry.findMetaError(modErr);576577                  moduleError = `${errorMeta.section}.${errorMeta.name}`;578                } else {579                  moduleError = dispatchError.toHuman();580                }581              } else {582                this.logger.log(result, this.logger.level.ERROR);583              }584            }585586            this.logger.log(`Something went wrong with ${label}. Status: ${status}`, this.logger.level.ERROR);587            unsub();588            reject({status, moduleError, result});589          }590        });591      } catch (e) {592        this.logger.log(e, this.logger.level.ERROR);593        reject(e);594      }595    });596  }597598  async signTransactionWithoutSending(signer: TSigner, tx: any) {599    const api = this.getApi();600    const signingInfo = await api.derive.tx.signingInfo(signer.address);601602    tx.sign(signer, {603      blockHash: api.genesisHash,604      genesisHash: api.genesisHash,605      runtimeVersion: api.runtimeVersion,606      nonce: signingInfo.nonce,607    });608609    return tx.toHex();610  }611612  async getPaymentInfo(signer: TSigner, tx: any, len: number | null) {613    const api = this.getApi();614    const signingInfo = await api.derive.tx.signingInfo(signer.address);615616    // We need to sign the tx because617    // unsigned transactions does not have an inclusion fee618    tx.sign(signer, {619      blockHash: api.genesisHash,620      genesisHash: api.genesisHash,621      runtimeVersion: api.runtimeVersion,622      nonce: signingInfo.nonce,623    });624625    if (len === null) {626      return (await this.callRpc('api.rpc.payment.queryInfo', [tx.toHex()])) as RuntimeDispatchInfo;627    } else {628      return (await api.call.transactionPaymentApi.queryInfo(tx, len)) as RuntimeDispatchInfo;629    }630  }631632  constructApiCall(apiCall: string, params: any[]) {633    if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);634    let call = this.getApi() as any;635    for(const part of apiCall.slice(4).split('.')) {636      call = call[part];637      if (!call) {638        const advice = part.includes('_') ? ' Looks like it needs to be converted to camel case.' : '';639        throw Error(`Function ${part} of api call ${apiCall} not found.${advice}`);640      }641    }642    return call(...params);643  }644645  async executeExtrinsic(sender: TSigner, extrinsic: string, params: any[], expectSuccess=true, options: Partial<SignerOptions>|null = null/*, failureMessage='expected success'*/) {646    if(this.api === null) throw Error('API not initialized');647    if(!extrinsic.startsWith('api.tx.')) throw Error(`${extrinsic} is not transaction`);648649    const startTime = (new Date()).getTime();650    let result: ITransactionResult;651    let events: IEvent[] = [];652    try {653      result = await this.signTransaction(sender, this.constructApiCall(extrinsic, params), options, extrinsic) as ITransactionResult;654      events = this.eventHelper.extractEvents(result.result.events);655      const errorEvent = events.find((event) => event.method == 'ExecutedFailed' || event.method == 'CreatedFailed');656      if (errorEvent)657        throw Error(errorEvent.method + ': ' + extrinsic);658    }659    catch(e) {660      if(!(e as object).hasOwnProperty('status')) throw e;661      result = e as ITransactionResult;662    }663664    const endTime = (new Date()).getTime();665666    const log = {667      executedAt: endTime,668      executionTime: endTime - startTime,669      type: this.chainLogType.EXTRINSIC,670      status: result.status,671      call: extrinsic,672      signer: this.getSignerAddress(sender),673      params,674    } as IUniqueHelperLog;675676    let errorMessage = '';677678    if(result.status !== this.transactionStatus.SUCCESS) {679      if (result.moduleError) {680        errorMessage = typeof result.moduleError === 'string'681          ? result.moduleError682          : `${Object.keys(result.moduleError)[0]}: ${Object.values(result.moduleError)[0]}`;683        log.moduleError = errorMessage;684      }685      else if (result.result.dispatchError) log.dispatchError = result.result.dispatchError;686    }687    if(events.length > 0) log.events = events;688689    this.chainLog.push(log);690691    if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) {692      if (result.moduleError) throw Error(`${errorMessage}`);693      else if (result.result.dispatchError) throw Error(JSON.stringify(result.result.dispatchError));694    }695    return result;696  }697698  async callRpc(rpc: string, params?: any[]) {699    if(typeof params === 'undefined') params = [];700    if(this.api === null) throw Error('API not initialized');701    if(!rpc.startsWith('api.rpc.') && !rpc.startsWith('api.query.')) throw Error(`${rpc} is not RPC call`);702703    const startTime = (new Date()).getTime();704    let result;705    let error = null;706    const log = {707      type: this.chainLogType.RPC,708      call: rpc,709      params,710    } as IUniqueHelperLog;711712    try {713      result = await this.constructApiCall(rpc, params);714    }715    catch(e) {716      error = e;717    }718719    const endTime = (new Date()).getTime();720721    log.executedAt = endTime;722    log.status = (error === null ? this.transactionStatus.SUCCESS : this.transactionStatus.FAIL) as 'Fail' | 'Success';723    log.executionTime = endTime - startTime;724725    this.chainLog.push(log);726727    if(error !== null) throw error;728729    return result;730  }731732  getSignerAddress(signer: IKeyringPair | string): string {733    if(typeof signer === 'string') return signer;734    return signer.address;735  }736737  fetchAllPalletNames(): string[] {738    if(this.api === null) throw Error('API not initialized');739    return this.api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());740  }741742  fetchMissingPalletNames(requiredPallets: string[]): string[] {743    const palletNames = this.fetchAllPalletNames();744    return requiredPallets.filter(p => !palletNames.includes(p));745  }746}747748749class HelperGroup<T extends ChainHelperBase> {750  helper: T;751752  constructor(uniqueHelper: T) {753    this.helper = uniqueHelper;754  }755}756757758class CollectionGroup extends HelperGroup<UniqueHelper> {759  /**760 * Get number of blocks when sponsored transaction is available.761 *762 * @param collectionId ID of collection763 * @param tokenId ID of token764 * @param addressObj address for which the sponsorship is checked765 * @example await getTokenNextSponsored(1, 2, {Substrate: '5DfhbVfww7ThF8q6f3...'});766 * @returns number of blocks or null if sponsorship hasn't been set767 */768  async getTokenNextSponsored(collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<number | null> {769    return (await this.helper.callRpc('api.rpc.unique.nextSponsored', [collectionId, addressObj, tokenId])).toJSON();770  }771772  /**773   * Get the number of created collections.774   *775   * @returns number of created collections776   */777  async getTotalCount(): Promise<number> {778    return (await this.helper.callRpc('api.rpc.unique.collectionStats')).created.toNumber();779  }780781  /**782   * Get information about the collection with additional data,783   * including the number of tokens it contains, its administrators,784   * the normalized address of the collection's owner, and decoded name and description.785   *786   * @param collectionId ID of collection787   * @example await getData(2)788   * @returns collection information object789   */790  async getData(collectionId: number): Promise<{791    id: number;792    name: string;793    description: string;794    tokensCount: number;795    admins: CrossAccountId[];796    normalizedOwner: TSubstrateAccount;797    raw: any798  } | null> {799    const collection = await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId]);800    const humanCollection = collection.toHuman(), collectionData = {801      id: collectionId, name: null, description: null, tokensCount: 0, admins: [],802      raw: humanCollection,803    } as any, jsonCollection = collection.toJSON();804    if (humanCollection === null) return null;805    collectionData.raw.limits = jsonCollection.limits;806    collectionData.raw.permissions = jsonCollection.permissions;807    collectionData.normalizedOwner = this.helper.address.normalizeSubstrate(collectionData.raw.owner);808    for (const key of ['name', 'description']) {809      collectionData[key] = this.helper.util.vec2str(humanCollection[key]);810    }811812    collectionData.tokensCount = (['RFT', 'NFT'].includes(humanCollection.mode))813      ? await this.helper[humanCollection.mode.toLocaleLowerCase() as 'nft' | 'rft'].getLastTokenId(collectionId)814      : 0;815    collectionData.admins = await this.getAdmins(collectionId);816817    return collectionData;818  }819820  /**821   * Get the addresses of the collection's administrators, optionally normalized.822   *823   * @param collectionId ID of collection824   * @param normalize whether to normalize the addresses to the default ss58 format825   * @example await getAdmins(1)826   * @returns array of administrators827   */828  async getAdmins(collectionId: number, normalize = false): Promise<CrossAccountId[]> {829    const admins = (await this.helper.callRpc('api.rpc.unique.adminlist', [collectionId])).toHuman();830831    return normalize832      ? admins.map((address: CrossAccountId) => address.withNormalizedSubstrate())833      : admins;834  }835836  /**837   * Get the addresses added to the collection allow-list, optionally normalized.838   * @param collectionId ID of collection839   * @param normalize whether to normalize the addresses to the default ss58 format840   * @example await getAllowList(1)841   * @returns array of allow-listed addresses842   */843  async getAllowList(collectionId: number, normalize = false): Promise<CrossAccountId[]> {844    const allowListed = (await this.helper.callRpc('api.rpc.unique.allowlist', [collectionId])).toHuman();845    return normalize846      ? allowListed.map((address: CrossAccountId) => address.withNormalizedSubstrate())847      : allowListed;848  }849850  /**851   * Get the effective limits of the collection instead of null for default values852   *853   * @param collectionId ID of collection854   * @example await getEffectiveLimits(2)855   * @returns object of collection limits856   */857  async getEffectiveLimits(collectionId: number): Promise<ICollectionLimits> {858    return (await this.helper.callRpc('api.rpc.unique.effectiveCollectionLimits', [collectionId])).toJSON();859  }860861  /**862   * Burns the collection if the signer has sufficient permissions and collection is empty.863   *864   * @param signer keyring of signer865   * @param collectionId ID of collection866   * @example await helper.collection.burn(aliceKeyring, 3);867   * @returns ```true``` if extrinsic success, otherwise ```false```868   */869  async burn(signer: TSigner, collectionId: number): Promise<boolean> {870    const result = await this.helper.executeExtrinsic(871      signer,872      'api.tx.unique.destroyCollection', [collectionId],873      true,874    );875876    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionDestroyed');877  }878879  /**880   * Sets the sponsor for the collection (Requires the Substrate address). Needs confirmation by the sponsor.881   *882   * @param signer keyring of signer883   * @param collectionId ID of collection884   * @param sponsorAddress Sponsor substrate address885   * @example setSponsor(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")886   * @returns ```true``` if extrinsic success, otherwise ```false```887   */888  async setSponsor(signer: TSigner, collectionId: number, sponsorAddress: TSubstrateAccount): Promise<boolean> {889    const result = await this.helper.executeExtrinsic(890      signer,891      'api.tx.unique.setCollectionSponsor', [collectionId, sponsorAddress],892      true,893    );894895    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionSponsorSet');896  }897898  /**899   * Confirms consent to sponsor the collection on behalf of the signer.900   *901   * @param signer keyring of signer902   * @param collectionId ID of collection903   * @example confirmSponsorship(aliceKeyring, 10)904   * @returns ```true``` if extrinsic success, otherwise ```false```905   */906  async confirmSponsorship(signer: TSigner, collectionId: number): Promise<boolean> {907    const result = await this.helper.executeExtrinsic(908      signer,909      'api.tx.unique.confirmSponsorship', [collectionId],910      true,911    );912913    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'SponsorshipConfirmed');914  }915916  /**917   * Removes the sponsor of a collection, regardless if it consented or not.918   *919   * @param signer keyring of signer920   * @param collectionId ID of collection921   * @example removeSponsor(aliceKeyring, 10)922   * @returns ```true``` if extrinsic success, otherwise ```false```923   */924  async removeSponsor(signer: TSigner, collectionId: number): Promise<boolean> {925    const result = await this.helper.executeExtrinsic(926      signer,927      'api.tx.unique.removeCollectionSponsor', [collectionId],928      true,929    );930931    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionSponsorRemoved');932  }933934  /**935   * Sets the limits of the collection. At least one limit must be specified for a correct call.936   *937   * @param signer keyring of signer938   * @param collectionId ID of collection939   * @param limits collection limits object940   * @example941   * await setLimits(942   *   aliceKeyring,943   *   10,944   *   {945   *     sponsorTransferTimeout: 0,946   *     ownerCanDestroy: false947   *   }948   * )949   * @returns ```true``` if extrinsic success, otherwise ```false```950   */951  async setLimits(signer: TSigner, collectionId: number, limits: ICollectionLimits): Promise<boolean> {952    const result = await this.helper.executeExtrinsic(953      signer,954      'api.tx.unique.setCollectionLimits', [collectionId, limits],955      true,956    );957958    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionLimitSet');959  }960961  /**962   * Changes the owner of the collection to the new Substrate address.963   *964   * @param signer keyring of signer965   * @param collectionId ID of collection966   * @param ownerAddress substrate address of new owner967   * @example changeOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")968   * @returns ```true``` if extrinsic success, otherwise ```false```969   */970  async changeOwner(signer: TSigner, collectionId: number, ownerAddress: TSubstrateAccount): Promise<boolean> {971    const result = await this.helper.executeExtrinsic(972      signer,973      'api.tx.unique.changeCollectionOwner', [collectionId, ownerAddress],974      true,975    );976977    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionOwnerChanged');978  }979980  /**981   * Adds a collection administrator.982   *983   * @param signer keyring of signer984   * @param collectionId ID of collection985   * @param adminAddressObj Administrator address (substrate or ethereum)986   * @example addAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})987   * @returns ```true``` if extrinsic success, otherwise ```false```988   */989  async addAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {990    const result = await this.helper.executeExtrinsic(991      signer,992      'api.tx.unique.addCollectionAdmin', [collectionId, adminAddressObj],993      true,994    );995996    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionAdminAdded');997  }998999  /**1000   * Removes a collection administrator.1001   *1002   * @param signer keyring of signer1003   * @param collectionId ID of collection1004   * @param adminAddressObj Administrator address (substrate or ethereum)1005   * @example removeAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})1006   * @returns ```true``` if extrinsic success, otherwise ```false```1007   */1008  async removeAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {1009    const result = await this.helper.executeExtrinsic(1010      signer,1011      'api.tx.unique.removeCollectionAdmin', [collectionId, adminAddressObj],1012      true,1013    );10141015    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionAdminRemoved');1016  }10171018  /**1019   * Check if user is in allow list.1020   *1021   * @param collectionId ID of collection1022   * @param user Account to check1023   * @example await getAdmins(1)1024   * @returns is user in allow list1025   */1026  async allowed(collectionId: number, user: ICrossAccountId): Promise<boolean> {1027    return (await this.helper.callRpc('api.rpc.unique.allowed', [collectionId, user])).toJSON();1028  }10291030  /**1031   * Adds an address to allow list1032   * @param signer keyring of signer1033   * @param collectionId ID of collection1034   * @param addressObj address to add to the allow list1035   * @returns ```true``` if extrinsic success, otherwise ```false```1036   */1037  async addToAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {1038    const result = await this.helper.executeExtrinsic(1039      signer,1040      'api.tx.unique.addToAllowList', [collectionId, addressObj],1041      true,1042    );10431044    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'AllowListAddressAdded');1045  }10461047  /**1048   * Removes an address from allow list1049   *1050   * @param signer keyring of signer1051   * @param collectionId ID of collection1052   * @param addressObj address to remove from the allow list1053   * @returns ```true``` if extrinsic success, otherwise ```false```1054   */1055  async removeFromAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {1056    const result = await this.helper.executeExtrinsic(1057      signer,1058      'api.tx.unique.removeFromAllowList', [collectionId, addressObj],1059      true,1060    );10611062    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'AllowListAddressRemoved');1063  }10641065  /**1066   * Sets onchain permissions for selected collection.1067   *1068   * @param signer keyring of signer1069   * @param collectionId ID of collection1070   * @param permissions collection permissions object1071   * @example setPermissions(aliceKeyring, 10, {access:'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true}});1072   * @returns ```true``` if extrinsic success, otherwise ```false```1073   */1074  async setPermissions(signer: TSigner, collectionId: number, permissions: ICollectionPermissions): Promise<boolean> {1075    const result = await this.helper.executeExtrinsic(1076      signer,1077      'api.tx.unique.setCollectionPermissions', [collectionId, permissions],1078      true,1079    );10801081    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPermissionSet');1082  }10831084  /**1085   * Enables nesting for selected collection. If `restricted` set, you can nest only tokens from specified collections.1086   *1087   * @param signer keyring of signer1088   * @param collectionId ID of collection1089   * @param permissions nesting permissions object1090   * @example enableNesting(aliceKeyring, 10, {collectionAdmin: true, tokenOwner: true});1091   * @returns ```true``` if extrinsic success, otherwise ```false```1092   */1093  async enableNesting(signer: TSigner, collectionId: number, permissions: INestingPermissions): Promise<boolean> {1094    return await this.setPermissions(signer, collectionId, {nesting: permissions});1095  }10961097  /**1098   * Disables nesting for selected collection.1099   *1100   * @param signer keyring of signer1101   * @param collectionId ID of collection1102   * @example disableNesting(aliceKeyring, 10);1103   * @returns ```true``` if extrinsic success, otherwise ```false```1104   */1105  async disableNesting(signer: TSigner, collectionId: number): Promise<boolean> {1106    return await this.setPermissions(signer, collectionId, {nesting: {tokenOwner: false, collectionAdmin: false}});1107  }11081109  /**1110   * Sets onchain properties to the collection.1111   *1112   * @param signer keyring of signer1113   * @param collectionId ID of collection1114   * @param properties array of property objects1115   * @example setProperties(aliceKeyring, 10, [{key: "gender", value: "male"}]);1116   * @returns ```true``` if extrinsic success, otherwise ```false```1117   */1118  async setProperties(signer: TSigner, collectionId: number, properties: IProperty[]): Promise<boolean> {1119    const result = await this.helper.executeExtrinsic(1120      signer,1121      'api.tx.unique.setCollectionProperties', [collectionId, properties],1122      true,1123    );11241125    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet');1126  }11271128  /**1129   * Get collection properties.1130   *1131   * @param collectionId ID of collection1132   * @param propertyKeys optionally filter the returned properties to only these keys1133   * @example getProperties(1219, ['location', 'date', 'time', 'isParadise']);1134   * @returns array of key-value pairs1135   */1136  async getProperties(collectionId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {1137    return (await this.helper.callRpc('api.rpc.unique.collectionProperties', [collectionId, propertyKeys])).toHuman();1138  }11391140  async getPropertiesConsumedSpace(collectionId: number): Promise<number> {1141    const api = this.helper.getApi();1142    const props = (await api.query.common.collectionProperties(collectionId)).toJSON();11431144    return (props! as any).consumedSpace;1145  }11461147  async getCollectionOptions(collectionId: number) {1148    return (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();1149  }11501151  /**1152   * Deletes onchain properties from the collection.1153   *1154   * @param signer keyring of signer1155   * @param collectionId ID of collection1156   * @param propertyKeys array of property keys to delete1157   * @example deleteProperties(aliceKeyring, 10, ["gender", "age"]);1158   * @returns ```true``` if extrinsic success, otherwise ```false```1159   */1160  async deleteProperties(signer: TSigner, collectionId: number, propertyKeys: string[]): Promise<boolean> {1161    const result = await this.helper.executeExtrinsic(1162      signer,1163      'api.tx.unique.deleteCollectionProperties', [collectionId, propertyKeys],1164      true,1165    );11661167    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertyDeleted');1168  }11691170  /**1171   * Changes the owner of the token.1172   *1173   * @param signer keyring of signer1174   * @param collectionId ID of collection1175   * @param tokenId ID of token1176   * @param addressObj address of a new owner1177   * @param amount amount of tokens to be transfered. For NFT must be set to 1n1178   * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1179   * @returns true if the token success, otherwise false1180   */1181  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {1182    const result = await this.helper.executeExtrinsic(1183      signer,1184      'api.tx.unique.transfer', [addressObj, collectionId, tokenId, amount],1185      true, // `Unable to transfer token #${tokenId} from collection #${collectionId}`,1186    );11871188    return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, {Substrate: typeof signer === 'string' ? signer : signer.address}, addressObj, amount);1189  }11901191  /**1192   *1193   * Change ownership of a token(s) on behalf of the owner.1194   *1195   * @param signer keyring of signer1196   * @param collectionId ID of collection1197   * @param tokenId ID of token1198   * @param fromAddressObj address on behalf of which the token will be sent1199   * @param toAddressObj new token owner1200   * @param amount amount of tokens to be transfered. For NFT must be set to 1n1201   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg"}, {Ethereum: "0x9F0583DbB85..."})1202   * @returns true if the token success, otherwise false1203   */1204  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1205    const result = await this.helper.executeExtrinsic(1206      signer,1207      'api.tx.unique.transferFrom', [fromAddressObj, toAddressObj, collectionId, tokenId, amount],1208      true, // `Unable to transfer token #${tokenId} from collection #${collectionId}`,1209    );1210    return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1211  }12121213  /**1214   *1215   * Destroys a concrete instance of NFT/RFT or burns a specified amount of fungible tokens.1216   *1217   * @param signer keyring of signer1218   * @param collectionId ID of collection1219   * @param tokenId ID of token1220   * @param amount amount of tokens to be burned. For NFT must be set to 1n1221   * @example burnToken(aliceKeyring, 10, 5);1222   * @returns ```true``` if the extrinsic is successful, otherwise ```false```1223   */1224  async burnToken(signer: TSigner, collectionId: number, tokenId: number, amount=1n): Promise<boolean> {1225    const burnResult = await this.helper.executeExtrinsic(1226      signer,1227      'api.tx.unique.burnItem', [collectionId, tokenId, amount],1228      true, // `Unable to burn token for ${label}`,1229    );1230    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);1231    if (burnedTokens.tokens.length > 1) throw Error('Burned multiple tokens');1232    return burnedTokens.success;1233  }12341235  /**1236   * Destroys a concrete instance of NFT on behalf of the owner1237   *1238   * @param signer keyring of signer1239   * @param collectionId ID of collection1240   * @param tokenId ID of token1241   * @param fromAddressObj address on behalf of which the token will be burnt1242   * @param amount amount of tokens to be burned. For NFT must be set to 1n1243   * @example burnTokenFrom(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."}, 5, {Ethereum: "0x9F0583DbB85..."})1244   * @returns ```true``` if extrinsic success, otherwise ```false```1245   */1246  async burnTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1247    const burnResult = await this.helper.executeExtrinsic(1248      signer,1249      'api.tx.unique.burnFrom', [collectionId, fromAddressObj, tokenId, amount],1250      true, // `Unable to burn token from for ${label}`,1251    );1252    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);1253    return burnedTokens.success && burnedTokens.tokens.length > 0;1254  }12551256  /**1257   * Set, change, or remove approved address to transfer the ownership of the NFT.1258   *1259   * @param signer keyring of signer1260   * @param collectionId ID of collection1261   * @param tokenId ID of token1262   * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens1263   * @param amount amount of token to be approved. For NFT must be set to 1n1264   * @returns ```true``` if extrinsic success, otherwise ```false```1265   */1266  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1267    const approveResult = await this.helper.executeExtrinsic(1268      signer,1269      'api.tx.unique.approve', [toAddressObj, collectionId, tokenId, amount],1270      true, // `Unable to approve token for ${label}`,1271    );12721273    return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');1274  }12751276  /**1277   * Set, change, or remove approved address to transfer the ownership of the NFT from eth mirror.1278   *1279   * @param signer keyring of signer1280   * @param collectionId ID of collection1281   * @param tokenId ID of token1282   * @param fromAddressObj Signer's Ethereum address containing her tokens1283   * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens1284   * @param amount amount of token to be approved. For NFT must be set to 1n1285   * @returns ```true``` if extrinsic success, otherwise ```false```1286   */1287  async approveTokenFrom(signer: IKeyringPair, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {1288    const approveResult = await this.helper.executeExtrinsic(1289      signer,1290      'api.tx.unique.approveFrom', [fromAddressObj, toAddressObj, collectionId, tokenId, amount],1291      true, // `Unable to approve token for ${label}`,1292    );12931294    return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');1295  }12961297  /**1298   * Set, change, or remove approved address to transfer the ownership of the NFT from eth mirror.1299   *1300   * @param signer keyring of signer1301   * @param collectionId ID of collection1302   * @param tokenId ID of token1303   * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens1304   * @param amount amount of token to be approved. For NFT must be set to 1n1305   * @returns ```true``` if extrinsic success, otherwise ```false```1306   */1307  async approveTokenFromEth(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1308    const ethMirror = CrossAccountId.fromKeyring(signer).toEthereum();1309    return await this.approveTokenFrom(signer, collectionId, tokenId, ethMirror, toAddressObj, amount);1310  }13111312  /**1313   * Get the amount of token pieces approved to transfer or burn. Normally 0.1314   *1315   * @param collectionId ID of collection1316   * @param tokenId ID of token1317   * @param toAccountObj address which is approved to use token pieces1318   * @param fromAccountObj address which may have allowed the use of its owned tokens1319   * @example getTokenApprovedPieces(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5ERZNF88Mm7UGfPP3mdG..."})1320   * @returns number of approved to transfer pieces1321   */1322  async getTokenApprovedPieces(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId, fromAccountObj: ICrossAccountId): Promise<bigint> {1323    return (await this.helper.callRpc('api.rpc.unique.allowance', [collectionId, fromAccountObj, toAccountObj, tokenId])).toBigInt();1324  }13251326  /**1327   * Get the last created token ID in a collection1328   *1329   * @param collectionId ID of collection1330   * @example getLastTokenId(10);1331   * @returns id of the last created token1332   */1333  async getLastTokenId(collectionId: number): Promise<number> {1334    return (await this.helper.callRpc('api.rpc.unique.lastTokenId', [collectionId])).toNumber();1335  }13361337  /**1338   * Check if token exists1339   *1340   * @param collectionId ID of collection1341   * @param tokenId ID of token1342   * @example doesTokenExist(10, 20);1343   * @returns true if the token exists, otherwise false1344   */1345  async doesTokenExist(collectionId: number, tokenId: number): Promise<boolean> {1346    return (await this.helper.callRpc('api.rpc.unique.tokenExists', [collectionId, tokenId])).toJSON();1347  }1348}13491350class NFTnRFT extends CollectionGroup {1351  /**1352   * Get tokens owned by account1353   *1354   * @param collectionId ID of collection1355   * @param addressObj tokens owner1356   * @example getTokensByAddress(10, {Substrate: "5DyN4Y92vZCjv38fg..."})1357   * @returns array of token ids owned by account1358   */1359  async getTokensByAddress(collectionId: number, addressObj: ICrossAccountId): Promise<number[]> {1360    return (await this.helper.callRpc('api.rpc.unique.accountTokens', [collectionId, addressObj])).toJSON();1361  }13621363  /**1364   * Get token data1365   *1366   * @param collectionId ID of collection1367   * @param tokenId ID of token1368   * @param propertyKeys optionally filter the token properties to only these keys1369   * @param blockHashAt optionally query the data at some block with this hash1370   * @example getToken(10, 5);1371   * @returns human readable token data1372   */1373  async getToken(collectionId: number, tokenId: number, propertyKeys: string[] = [], blockHashAt?: string): Promise<{1374    properties: IProperty[];1375    owner: CrossAccountId;1376    normalizedOwner: CrossAccountId;1377  }| null> {1378    let tokenData;1379    if(typeof blockHashAt === 'undefined') {1380      tokenData = await this.helper.callRpc('api.rpc.unique.tokenData', [collectionId, tokenId]);1381    }1382    else {1383      if(propertyKeys.length == 0) {1384        const collection = (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();1385        if(!collection) return null;1386        propertyKeys = collection.tokenPropertyPermissions.map((x: ITokenPropertyPermission) => x.key);1387      }1388      tokenData = await this.helper.callRpc('api.rpc.unique.tokenData', [collectionId, tokenId, propertyKeys, blockHashAt]);1389    }1390    tokenData = tokenData.toHuman();1391    if (tokenData === null || tokenData.owner === null) return null;1392    const owner = {} as any;1393    for (const key of Object.keys(tokenData.owner)) {1394      owner[key.toLocaleLowerCase()] = key.toLocaleLowerCase() == 'substrate'1395        ? CrossAccountId.normalizeSubstrateAddress(tokenData.owner[key])1396        : tokenData.owner[key];1397    }1398    tokenData.normalizedOwner = CrossAccountId.fromLowerCaseKeys(owner);1399    return tokenData;1400  }14011402  /**1403   * Get token's owner1404   * @param collectionId ID of collection1405   * @param tokenId ID of token1406   * @param blockHashAt optionally query the data at the block with this hash1407   * @example getTokenOwner(10, 5);1408   * @returns Address in CrossAccountId format, e.g. {Substrate: "5DnSF6RRjwteE3BrCj..."}1409   */1410  async getTokenOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<CrossAccountId> {1411    let owner;1412    if (typeof blockHashAt === 'undefined') {1413      owner = await this.helper.callRpc('api.rpc.unique.tokenOwner', [collectionId, tokenId]);1414    } else {1415      owner = await this.helper.callRpc('api.rpc.unique.tokenOwner', [collectionId, tokenId, blockHashAt]);1416    }1417    return CrossAccountId.fromLowerCaseKeys(owner.toJSON());1418  }14191420  /**1421   * Recursively find the address that owns the token1422   * @param collectionId ID of collection1423   * @param tokenId ID of token1424   * @param blockHashAt1425   * @example getTokenTopmostOwner(10, 5);1426   * @returns address in CrossAccountId format, e.g. {Substrate: "5DyN4Y92vZCjv38fg..."}1427   */1428  async getTokenTopmostOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<CrossAccountId | null> {1429    let owner;1430    if (typeof blockHashAt === 'undefined') {1431      owner = await this.helper.callRpc('api.rpc.unique.topmostTokenOwner', [collectionId, tokenId]);1432    } else {1433      owner = await this.helper.callRpc('api.rpc.unique.topmostTokenOwner', [collectionId, tokenId, blockHashAt]);1434    }14351436    if (owner === null) return null;14371438    return owner.toHuman();1439  }14401441  /**1442   * Nest one token into another1443   * @param signer keyring of signer1444   * @param tokenObj token to be nested1445   * @param rootTokenObj token to be parent1446   * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});1447   * @returns ```true``` if extrinsic success, otherwise ```false```1448   */1449  async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken): Promise<boolean> {1450    const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1451    const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);1452    if(!result) {1453      throw Error('Unable to nest token!');1454    }1455    return result;1456  }14571458  /**1459     * Remove token from nested state1460     * @param signer keyring of signer1461     * @param tokenObj token to unnest1462     * @param rootTokenObj parent of a token1463     * @param toAddressObj address of a new token owner1464     * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});1465     * @returns ```true``` if extrinsic success, otherwise ```false```1466     */1467  async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {1468    const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1469    const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);1470    if(!result) {1471      throw Error('Unable to unnest token!');1472    }1473    return result;1474  }14751476  /**1477   * Set permissions to change token properties1478   *1479   * @param signer keyring of signer1480   * @param collectionId ID of collection1481   * @param permissions permissions to change a property by the collection admin or token owner1482   * @example setTokenPropertyPermissions(1483   *   aliceKeyring, 10, [{key: "gender", permission: {tokenOwner: true, mutable: true, collectionAdmin: true}}]1484   * )1485   * @returns true if extrinsic success otherwise false1486   */1487  async setTokenPropertyPermissions(signer: TSigner, collectionId: number, permissions: ITokenPropertyPermission[]): Promise<boolean> {1488    const result = await this.helper.executeExtrinsic(1489      signer,1490      'api.tx.unique.setTokenPropertyPermissions', [collectionId, permissions],1491      true,1492    );14931494    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet');1495  }14961497  /**1498   * Get token property permissions.1499   *1500   * @param collectionId ID of collection1501   * @param propertyKeys optionally filter the returned property permissions to only these keys1502   * @example getPropertyPermissions(1219, ['location', 'date', 'time', 'isParadise']);1503   * @returns array of key-permission pairs1504   */1505  async getPropertyPermissions(collectionId: number, propertyKeys: string[] | null = null): Promise<ITokenPropertyPermission[]> {1506    return (await this.helper.callRpc('api.rpc.unique.propertyPermissions', [collectionId, ...(propertyKeys === null ? [] : [propertyKeys])])).toHuman();1507  }15081509  /**1510   * Set token properties1511   *1512   * @param signer keyring of signer1513   * @param collectionId ID of collection1514   * @param tokenId ID of token1515   * @param properties key-value pairs of metadata which to add to a token. Keys must be permitted in the collection1516   * @example setTokenProperties(aliceKeyring, 10, 5, [{key: "gender", value: "female"}, {key: "age", value: "23"}])1517   * @returns ```true``` if extrinsic success, otherwise ```false```1518   */1519  async setTokenProperties(signer: TSigner, collectionId: number, tokenId: number, properties: IProperty[]): Promise<boolean> {1520    const result = await this.helper.executeExtrinsic(1521      signer,1522      'api.tx.unique.setTokenProperties', [collectionId, tokenId, properties],1523      true,1524    );15251526    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet');1527  }15281529  /**1530   * Get properties, metadata assigned to a token.1531   *1532   * @param collectionId ID of collection1533   * @param tokenId ID of token1534   * @param propertyKeys optionally filter the returned properties to only these keys1535   * @example getTokenProperties(1219, ['location', 'date', 'time', 'isParadise']);1536   * @returns array of key-value pairs1537   */1538  async getTokenProperties(collectionId: number, tokenId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {1539    return (await this.helper.callRpc('api.rpc.unique.tokenProperties', [collectionId, tokenId, propertyKeys])).toHuman();1540  }15411542  /**1543   * Delete the provided properties of a token1544   * @param signer keyring of signer1545   * @param collectionId ID of collection1546   * @param tokenId ID of token1547   * @param propertyKeys property keys to be deleted1548   * @example deleteTokenProperties(aliceKeyring, 10, 5, ["gender", "age"])1549   * @returns ```true``` if extrinsic success, otherwise ```false```1550   */1551  async deleteTokenProperties(signer: TSigner, collectionId: number, tokenId: number, propertyKeys: string[]): Promise<boolean> {1552    const result = await this.helper.executeExtrinsic(1553      signer,1554      'api.tx.unique.deleteTokenProperties', [collectionId, tokenId, propertyKeys],1555      true,1556    );15571558    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertyDeleted');1559  }15601561  /**1562   * Mint new collection1563   *1564   * @param signer keyring of signer1565   * @param collectionOptions basic collection options and properties1566   * @param mode NFT or RFT type of a collection1567   * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")1568   * @returns object of the created collection1569   */1570  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueBaseCollection> {1571    collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1572    collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};1573    for (const key of ['name', 'description', 'tokenPrefix']) {1574      if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);1575    }1576    const creationResult = await this.helper.executeExtrinsic(1577      signer,1578      'api.tx.unique.createCollectionEx', [collectionOptions],1579      true, // errorLabel,1580    );1581    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));1582  }15831584  getCollectionObject(_collectionId: number): any {1585    return null;1586  }15871588  getTokenObject(_collectionId: number, _tokenId: number): any {1589    return null;1590  }15911592  /**1593   * Tells whether the given `owner` approves the `operator`.1594   * @param collectionId ID of collection1595   * @param owner owner address1596   * @param operator operator addrees1597   * @returns true if operator is enabled1598   */1599  async allowanceForAll(collectionId: number, owner: ICrossAccountId, operator: ICrossAccountId): Promise<boolean> {1600    return (await this.helper.callRpc('api.rpc.unique.allowanceForAll', [collectionId, owner, operator])).toJSON();1601  }16021603  /** Sets or unsets the approval of a given operator.1604   *  The `operator` is allowed to transfer all tokens of the `caller` on their behalf.1605   *  @param operator Operator1606   *  @param approved Should operator status be granted or revoked?1607   *  @returns ```true``` if extrinsic success, otherwise ```false```1608   */1609  async setAllowanceForAll(signer: TSigner, collectionId: number, operator: ICrossAccountId, approved: boolean): Promise<boolean> {1610    const result = await this.helper.executeExtrinsic(1611      signer,1612      'api.tx.unique.setAllowanceForAll', [collectionId, operator, approved],1613      true,1614    );1615    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'ApprovedForAll');1616  }1617}161816191620class NFTGroup extends NFTnRFT {1621  /**1622   * Get collection object1623   * @param collectionId ID of collection1624   * @example getCollectionObject(2);1625   * @returns instance of UniqueNFTCollection1626   */1627  getCollectionObject(collectionId: number): UniqueNFTCollection {1628    return new UniqueNFTCollection(collectionId, this.helper);1629  }16301631  /**1632   * Get token object1633   * @param collectionId ID of collection1634   * @param tokenId ID of token1635   * @example getTokenObject(10, 5);1636   * @returns instance of UniqueNFTToken1637   */1638  getTokenObject(collectionId: number, tokenId: number): UniqueNFToken {1639    return new UniqueNFToken(tokenId, this.getCollectionObject(collectionId));1640  }16411642  /**1643   * Is token approved to transfer1644   * @param collectionId ID of collection1645   * @param tokenId ID of token1646   * @param toAccountObj address to be approved1647   * @returns ```true``` if extrinsic success, otherwise ```false```1648   */1649  async isTokenApproved(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId): Promise<boolean> {1650    return (await this.getTokenApprovedPieces(collectionId, tokenId, toAccountObj, await this.getTokenOwner(collectionId, tokenId))) === 1n;1651  }16521653  /**1654   * Changes the owner of the token.1655   *1656   * @param signer keyring of signer1657   * @param collectionId ID of collection1658   * @param tokenId ID of token1659   * @param addressObj address of a new owner1660   * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1661   * @returns ```true``` if extrinsic success, otherwise ```false```1662   */1663  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<boolean> {1664    return await super.transferToken(signer, collectionId, tokenId, addressObj, 1n);1665  }16661667  /**1668   *1669   * Change ownership of a NFT on behalf of the owner.1670   *1671   * @param signer keyring of signer1672   * @param collectionId ID of collection1673   * @param tokenId ID of token1674   * @param fromAddressObj address on behalf of which the token will be sent1675   * @param toAddressObj new token owner1676   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Ethereum: "0x9F0583DbB85..."})1677   * @returns ```true``` if extrinsic success, otherwise ```false```1678   */1679  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId): Promise<boolean> {1680    return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, 1n);1681  }16821683  /**1684   * Get tokens nested in the provided token1685   * @param collectionId ID of collection1686   * @param tokenId ID of token1687   * @param blockHashAt optionally query the data at the block with this hash1688   * @example getTokenChildren(10, 5);1689   * @returns tokens whose depth of nesting is <= 51690   */1691  async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<IToken[]> {1692    let children;1693    if(typeof blockHashAt === 'undefined') {1694      children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId]);1695    } else {1696      children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId, blockHashAt]);1697    }16981699    return children.toJSON().map((x: any) => {1700      return {collectionId: x.collection, tokenId: x.token};1701    });1702  }17031704  /**1705   * Mint new collection1706   * @param signer keyring of signer1707   * @param collectionOptions Collection options1708   * @example1709   * mintCollection(aliceKeyring, {1710   *   name: 'New',1711   *   description: 'New collection',1712   *   tokenPrefix: 'NEW',1713   * })1714   * @returns object of the created collection1715   */1716  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions = {}): Promise<UniqueNFTCollection> {1717    return await super.mintCollection(signer, collectionOptions, 'NFT') as UniqueNFTCollection;1718  }17191720  /**1721   * Mint new token1722   * @param signer keyring of signer1723   * @param data token data1724   * @returns created token object1725   */1726  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; properties?: IProperty[]; }): Promise<UniqueNFToken> {1727    const creationResult = await this.helper.executeExtrinsic(1728      signer,1729      'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1730        nft: {1731          properties: data.properties,1732        },1733      }],1734      true,1735    );1736    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult);1737    if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');1738    if (createdTokens.tokens.length < 1) throw Error('No tokens minted');1739    return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);1740  }17411742  /**1743   * Mint multiple NFT tokens1744   * @param signer keyring of signer1745   * @param collectionId ID of collection1746   * @param tokens array of tokens with owner and properties1747   * @example1748   * mintMultipleTokens(aliceKeyring, 10, [{1749   *     owner: {Substrate: "5DyN4Y92vZCjv38fg..."},1750   *     properties: [{key: "gender", value: "male"},{key: "age", value: "45"}],1751   *   },{1752   *     owner: {Ethereum: "0x9F0583DbB855d..."},1753   *     properties: [{key: "gender", value: "female"},{key: "age", value: "22"}],1754   * }]);1755   * @returns ```true``` if extrinsic success, otherwise ```false```1756   */1757  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]): Promise<UniqueNFToken[]> {1758    const creationResult = await this.helper.executeExtrinsic(1759      signer,1760      'api.tx.unique.createMultipleItemsEx', [collectionId, {NFT: tokens}],1761      true,1762    );1763    const collection = this.getCollectionObject(collectionId);1764    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1765  }17661767  /**1768   * Mint multiple NFT tokens with one owner1769   * @param signer keyring of signer1770   * @param collectionId ID of collection1771   * @param owner tokens owner1772   * @param tokens array of tokens with owner and properties1773   * @example1774   * mintMultipleTokensWithOneOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...", [{1775   *   properties: [{1776   *   key: "gender",1777   *   value: "female",1778   *  },{1779   *   key: "age",1780   *   value: "33",1781   *  }],1782   * }]);1783   * @returns array of newly created tokens1784   */1785  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {properties?: IProperty[]}[]): Promise<UniqueNFToken[]> {1786    const rawTokens = [];1787    for (const token of tokens) {1788      const raw = {NFT: {properties: token.properties}};1789      rawTokens.push(raw);1790    }1791    const creationResult = await this.helper.executeExtrinsic(1792      signer,1793      'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],1794      true,1795    );1796    const collection = this.getCollectionObject(collectionId);1797    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1798  }17991800  /**1801   * Set, change, or remove approved address to transfer the ownership of the NFT.1802   *1803   * @param signer keyring of signer1804   * @param collectionId ID of collection1805   * @param tokenId ID of token1806   * @param toAddressObj address to approve1807   * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1808   * @returns ```true``` if extrinsic success, otherwise ```false```1809   */1810  approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1811    return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);1812  }1813}181418151816class RFTGroup extends NFTnRFT {1817  /**1818   * Get collection object1819   * @param collectionId ID of collection1820   * @example getCollectionObject(2);1821   * @returns instance of UniqueRFTCollection1822   */1823  getCollectionObject(collectionId: number): UniqueRFTCollection {1824    return new UniqueRFTCollection(collectionId, this.helper);1825  }18261827  /**1828   * Get token object1829   * @param collectionId ID of collection1830   * @param tokenId ID of token1831   * @example getTokenObject(10, 5);1832   * @returns instance of UniqueNFTToken1833   */1834  getTokenObject(collectionId: number, tokenId: number): UniqueRFToken {1835    return new UniqueRFToken(tokenId, this.getCollectionObject(collectionId));1836  }18371838  /**1839   * Get top 10 token owners with the largest number of pieces1840   * @param collectionId ID of collection1841   * @param tokenId ID of token1842   * @example getTokenTop10Owners(10, 5);1843   * @returns array of top 10 owners1844   */1845  async getTokenTop10Owners(collectionId: number, tokenId: number): Promise<CrossAccountId[]> {1846    return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, tokenId])).toJSON().map(CrossAccountId.fromLowerCaseKeys);1847  }18481849  /**1850   * Get number of pieces owned by address1851   * @param collectionId ID of collection1852   * @param tokenId ID of token1853   * @param addressObj address token owner1854   * @example getTokenBalance(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."});1855   * @returns number of pieces ownerd by address1856   */1857  async getTokenBalance(collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<bigint> {1858    return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, tokenId])).toBigInt();1859  }18601861  /**1862   * Transfer pieces of token to another address1863   * @param signer keyring of signer1864   * @param collectionId ID of collection1865   * @param tokenId ID of token1866   * @param addressObj address of a new owner1867   * @param amount number of pieces to be transfered1868   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, 2000n)1869   * @returns ```true``` if extrinsic success, otherwise ```false```1870   */1871  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {1872    return await super.transferToken(signer, collectionId, tokenId, addressObj, amount);1873  }18741875  /**1876   * Change ownership of some pieces of RFT on behalf of the owner.1877   * @param signer keyring of signer1878   * @param collectionId ID of collection1879   * @param tokenId ID of token1880   * @param fromAddressObj address on behalf of which the token will be sent1881   * @param toAddressObj new token owner1882   * @param amount number of pieces to be transfered1883   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5DfhbVfww7ThF8q6f3i..."}, 2000n)1884   * @returns ```true``` if extrinsic success, otherwise ```false```1885   */1886  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1887    return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1888  }18891890  /**1891   * Mint new collection1892   * @param signer keyring of signer1893   * @param collectionOptions Collection options1894   * @example1895   * mintCollection(aliceKeyring, {1896   *   name: 'New',1897   *   description: 'New collection',1898   *   tokenPrefix: 'NEW',1899   * })1900   * @returns object of the created collection1901   */1902  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions = {}): Promise<UniqueRFTCollection> {1903    return await super.mintCollection(signer, collectionOptions, 'RFT') as UniqueRFTCollection;1904  }19051906  /**1907   * Mint new token1908   * @param signer keyring of signer1909   * @param data token data1910   * @example mintToken(aliceKeyring, {collectionId: 10, owner: {Substrate: '5GHoZe9c73RYbVzq...'}, pieces: 10000n});1911   * @returns created token object1912   */1913  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; pieces: bigint; properties?: IProperty[]; }): Promise<UniqueRFToken> {1914    const creationResult = await this.helper.executeExtrinsic(1915      signer,1916      'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1917        refungible: {1918          pieces: data.pieces,1919          properties: data.properties,1920        },1921      }],1922      true,1923    );1924    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult);1925    if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');1926    if (createdTokens.tokens.length < 1) throw Error('No tokens minted');1927    return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);1928  }19291930  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFToken[]> {1931    throw Error('Not implemented');1932    const creationResult = await this.helper.executeExtrinsic(1933      signer,1934      'api.tx.unique.createMultipleItemsEx', [collectionId, {RefungibleMultipleOwners: tokens}],1935      true, // `Unable to mint RFT tokens for ${label}`,1936    );1937    const collection = this.getCollectionObject(collectionId);1938    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1939  }19401941  /**1942   * Mint multiple RFT tokens with one owner1943   * @param signer keyring of signer1944   * @param collectionId ID of collection1945   * @param owner tokens owner1946   * @param tokens array of tokens with properties and pieces1947   * @example mintMultipleTokensWithOneOwner(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, [{pieces: 100000n, properties: [{key: "gender", value: "male"}]}]);1948   * @returns array of newly created RFT tokens1949   */1950  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFToken[]> {1951    const rawTokens = [];1952    for (const token of tokens) {1953      const raw = {ReFungible: {pieces: token.pieces, properties: token.properties}};1954      rawTokens.push(raw);1955    }1956    const creationResult = await this.helper.executeExtrinsic(1957      signer,1958      'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],1959      true,1960    );1961    const collection = this.getCollectionObject(collectionId);1962    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1963  }19641965  /**1966   * Destroys a concrete instance of RFT.1967   * @param signer keyring of signer1968   * @param collectionId ID of collection1969   * @param tokenId ID of token1970   * @param amount number of pieces to be burnt1971   * @example burnToken(aliceKeyring, 10, 5);1972   * @returns ```true``` if the extrinsic is successful, otherwise ```false```1973   */1974  async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, amount=1n): Promise<boolean> {1975    return await super.burnToken(signer, collectionId, tokenId, amount);1976  }19771978  /**1979   * Destroys a concrete instance of RFT on behalf of the owner.1980   * @param signer keyring of signer1981   * @param collectionId ID of collection1982   * @param tokenId ID of token1983   * @param fromAddressObj address on behalf of which the token will be burnt1984   * @param amount number of pieces to be burnt1985   * @example burnTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, 2n)1986   * @returns ```true``` if extrinsic success, otherwise ```false```1987   */1988  async burnTokenFrom(signer: IKeyringPair, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1989    return await super.burnTokenFrom(signer, collectionId, tokenId, fromAddressObj, amount);1990  }19911992  /**1993   * Set, change, or remove approved address to transfer the ownership of the RFT.1994   *1995   * @param signer keyring of signer1996   * @param collectionId ID of collection1997   * @param tokenId ID of token1998   * @param toAddressObj address to approve1999   * @param amount number of pieces to be approved2000   * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5GHoZe9c73RYbVzq..."}, "", 10000n);2001   * @returns true if the token success, otherwise false2002   */2003  approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {2004    return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);2005  }20062007  /**2008   * Get total number of pieces2009   * @param collectionId ID of collection2010   * @param tokenId ID of token2011   * @example getTokenTotalPieces(10, 5);2012   * @returns number of pieces2013   */2014  async getTokenTotalPieces(collectionId: number, tokenId: number): Promise<bigint> {2015    return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, tokenId])).unwrap().toBigInt();2016  }20172018  /**2019   * Change number of token pieces. Signer must be the owner of all token pieces.2020   * @param signer keyring of signer2021   * @param collectionId ID of collection2022   * @param tokenId ID of token2023   * @param amount new number of pieces2024   * @example repartitionToken(aliceKeyring, 10, 5, 12345n);2025   * @returns true if the repartion was success, otherwise false2026   */2027  async repartitionToken(signer: TSigner, collectionId: number, tokenId: number, amount: bigint): Promise<boolean> {2028    const currentAmount = await this.getTokenTotalPieces(collectionId, tokenId);2029    const repartitionResult = await this.helper.executeExtrinsic(2030      signer,2031      'api.tx.unique.repartition', [collectionId, tokenId, amount],2032      true,2033    );2034    if(currentAmount < amount) return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemCreated');2035    return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemDestroyed');2036  }2037}203820392040class FTGroup extends CollectionGroup {2041  /**2042   * Get collection object2043   * @param collectionId ID of collection2044   * @example getCollectionObject(2);2045   * @returns instance of UniqueFTCollection2046   */2047  getCollectionObject(collectionId: number): UniqueFTCollection {2048    return new UniqueFTCollection(collectionId, this.helper);2049  }20502051  /**2052   * Mint new fungible collection2053   * @param signer keyring of signer2054   * @param collectionOptions Collection options2055   * @param decimalPoints number of token decimals2056   * @example2057   * mintCollection(aliceKeyring, {2058   *   name: 'New',2059   *   description: 'New collection',2060   *   tokenPrefix: 'NEW',2061   * }, 18)2062   * @returns newly created fungible collection2063   */2064  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions = {}, decimalPoints = 0): Promise<UniqueFTCollection> {2065    collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object2066    if(collectionOptions.tokenPropertyPermissions) throw Error('Fungible collections has no tokenPropertyPermissions');2067    collectionOptions.mode = {fungible: decimalPoints};2068    for (const key of ['name', 'description', 'tokenPrefix']) {2069      if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);2070    }2071    const creationResult = await this.helper.executeExtrinsic(2072      signer,2073      'api.tx.unique.createCollectionEx', [collectionOptions],2074      true,2075    );2076    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));2077  }20782079  /**2080   * Mint tokens2081   * @param signer keyring of signer2082   * @param collectionId ID of collection2083   * @param owner address owner of new tokens2084   * @param amount amount of tokens to be meanted2085   * @example mintTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq"}, 1000n);2086   * @returns ```true``` if extrinsic success, otherwise ```false```2087   */2088  async mintTokens(signer: TSigner, collectionId: number, amount: bigint, owner: ICrossAccountId | string): Promise<boolean> {2089    const creationResult = await this.helper.executeExtrinsic(2090      signer,2091      'api.tx.unique.createItem', [collectionId, (typeof owner === 'string') ? {Substrate: owner} : owner, {2092        fungible: {2093          value: amount,2094        },2095      }],2096      true, // `Unable to mint fungible tokens for ${label}`,2097    );2098    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');2099  }21002101  /**2102   * Mint multiple Fungible tokens with one owner2103   * @param signer keyring of signer2104   * @param collectionId ID of collection2105   * @param owner tokens owner2106   * @param tokens array of tokens with properties and pieces2107   * @returns ```true``` if extrinsic success, otherwise ```false```2108   */2109  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, tokens: {value: bigint}[], owner: ICrossAccountId): Promise<boolean> {2110    const rawTokens = [];2111    for (const token of tokens) {2112      const raw = {Fungible: {Value: token.value}};2113      rawTokens.push(raw);2114    }2115    const creationResult = await this.helper.executeExtrinsic(2116      signer,2117      'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],2118      true,2119    );2120    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');2121  }21222123  /**2124   * Get the top 10 owners with the largest balance for the Fungible collection2125   * @param collectionId ID of collection2126   * @example getTop10Owners(10);2127   * @returns array of ```ICrossAccountId```2128   */2129  async getTop10Owners(collectionId: number): Promise<CrossAccountId[]> {2130    return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, 0])).toJSON().map(CrossAccountId.fromLowerCaseKeys);2131  }21322133  /**2134   * Get account balance2135   * @param collectionId ID of collection2136   * @param addressObj address of owner2137   * @example getBalance(10, {Substrate: "5GHoZe9c73RYbVzq..."})2138   * @returns amount of fungible tokens owned by address2139   */2140  async getBalance(collectionId: number, addressObj: ICrossAccountId): Promise<bigint> {2141    return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, 0])).toBigInt();2142  }21432144  /**2145   * Transfer tokens to address2146   * @param signer keyring of signer2147   * @param collectionId ID of collection2148   * @param toAddressObj address recipient2149   * @param amount amount of tokens to be sent2150   * @example transfer(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);2151   * @returns ```true``` if extrinsic success, otherwise ```false```2152   */2153  async transfer(signer: TSigner, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {2154    return await super.transferToken(signer, collectionId, 0, toAddressObj, amount);2155  }21562157  /**2158   * Transfer some tokens on behalf of the owner.2159   * @param signer keyring of signer2160   * @param collectionId ID of collection2161   * @param fromAddressObj address on behalf of which tokens will be sent2162   * @param toAddressObj address where token to be sent2163   * @param amount number of tokens to be sent2164   * @example transferFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, {Substrate: "5DfhbVfww7ThF8q6f3ij..."}, 10000n);2165   * @returns ```true``` if extrinsic success, otherwise ```false```2166   */2167  async transferFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {2168    return await super.transferTokenFrom(signer, collectionId, 0, fromAddressObj, toAddressObj, amount);2169  }21702171  /**2172   * Destroy some amount of tokens2173   * @param signer keyring of signer2174   * @param collectionId ID of collection2175   * @param amount amount of tokens to be destroyed2176   * @example burnTokens(aliceKeyring, 10, 1000n);2177   * @returns ```true``` if extrinsic success, otherwise ```false```2178   */2179  async burnTokens(signer: IKeyringPair, collectionId: number, amount=1n): Promise<boolean> {2180    return await super.burnToken(signer, collectionId, 0, amount);2181  }21822183  /**2184   * Burn some tokens on behalf of the owner.2185   * @param signer keyring of signer2186   * @param collectionId ID of collection2187   * @param fromAddressObj address on behalf of which tokens will be burnt2188   * @param amount amount of tokens to be burnt2189   * @example burnTokensFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);2190   * @returns ```true``` if extrinsic success, otherwise ```false```2191   */2192  async burnTokensFrom(signer: IKeyringPair, collectionId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {2193    return await super.burnTokenFrom(signer, collectionId, 0, fromAddressObj, amount);2194  }21952196  /**2197   * Get total collection supply2198   * @param collectionId2199   * @returns2200   */2201  async getTotalPieces(collectionId: number): Promise<bigint> {2202    return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, 0])).unwrap().toBigInt();2203  }22042205  /**2206   * Set, change, or remove approved address to transfer tokens.2207   *2208   * @param signer keyring of signer2209   * @param collectionId ID of collection2210   * @param toAddressObj address to be approved2211   * @param amount amount of tokens to be approved2212   * @example approveTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n)2213   * @returns ```true``` if extrinsic success, otherwise ```false```2214   */2215  approveTokens(signer: IKeyringPair, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {2216    return super.approveToken(signer, collectionId, 0, toAddressObj, amount);2217  }22182219  /**2220   * Get amount of fungible tokens approved to transfer2221   * @param collectionId ID of collection2222   * @param fromAddressObj owner of tokens2223   * @param toAddressObj the address approved for the transfer of tokens on behalf of the owner2224   * @returns number of tokens approved for the transfer2225   */2226  getApprovedTokens(collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {2227    return super.getTokenApprovedPieces(collectionId, 0, toAddressObj, fromAddressObj);2228  }2229}223022312232class ChainGroup extends HelperGroup<ChainHelperBase> {2233  /**2234   * Get system properties of a chain2235   * @example getChainProperties();2236   * @returns ss58Format, token decimals, and token symbol2237   */2238  getChainProperties(): IChainProperties {2239    const properties = (this.helper.getApi() as any).registry.getChainProperties().toJSON();2240    return {2241      ss58Format: properties.ss58Format.toJSON(),2242      tokenDecimals: properties.tokenDecimals.toJSON(),2243      tokenSymbol: properties.tokenSymbol.toJSON(),2244    };2245  }22462247  /**2248   * Get chain header2249   * @example getLatestBlockNumber();2250   * @returns the number of the last block2251   */2252  async getLatestBlockNumber(): Promise<number> {2253    return (await this.helper.callRpc('api.rpc.chain.getHeader')).number.toNumber();2254  }22552256  /**2257   * Get block hash by block number2258   * @param blockNumber number of block2259   * @example getBlockHashByNumber(12345);2260   * @returns hash of a block2261   */2262  async getBlockHashByNumber(blockNumber: number): Promise<string | null> {2263    const blockHash = (await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockNumber])).toJSON();2264    if(blockHash === '0x0000000000000000000000000000000000000000000000000000000000000000') return null;2265    return blockHash;2266  }22672268  // TODO add docs2269  async getBlock(blockHashOrNumber: string | number): Promise<IBlock | null> {2270    const blockHash = typeof blockHashOrNumber === 'string' ? blockHashOrNumber : await this.getBlockHashByNumber(blockHashOrNumber);2271    if (!blockHash) return null;2272    return (await this.helper.callRpc('api.rpc.chain.getBlock', [blockHash])).toHuman().block;2273  }22742275  /**2276   * Get latest relay block2277   * @returns {number} relay block2278   */2279  async getRelayBlockNumber(): Promise<bigint> {2280    const blockNumber = (await this.helper.callRpc('api.query.parachainSystem.validationData')).toJSON().relayParentNumber;2281    return BigInt(blockNumber);2282  }22832284  /**2285   * Get account nonce2286   * @param address substrate address2287   * @example getNonce("5GrwvaEF5zXb26Fz...");2288   * @returns number, account's nonce2289   */2290  async getNonce(address: TSubstrateAccount): Promise<number> {2291    return (await this.helper.callRpc('api.query.system.account', [address])).nonce.toNumber();2292  }2293}22942295class SubstrateBalanceGroup<T extends ChainHelperBase> extends HelperGroup<T> {2296  /**2297 * Get substrate address balance2298 * @param address substrate address2299 * @example getSubstrate("5GrwvaEF5zXb26Fz...")2300 * @returns amount of tokens on address2301 */2302  async getSubstrate(address: TSubstrateAccount): Promise<bigint> {2303    return (await this.helper.callRpc('api.query.system.account', [address])).data.free.toBigInt();2304  }23052306  /**2307   * Transfer tokens to substrate address2308   * @param signer keyring of signer2309   * @param address substrate address of a recipient2310   * @param amount amount of tokens to be transfered2311   * @example transferToSubstrate(aliceKeyring, "5GrwvaEF5zXb26Fz...", 100_000_000_000n);2312   * @returns ```true``` if extrinsic success, otherwise ```false```2313   */2314  async transferToSubstrate(signer: TSigner, address: TSubstrateAccount, amount: bigint | string): Promise<boolean> {2315    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.transfer', [address, amount], true/*, `Unable to transfer balance from ${this.helper.getSignerAddress(signer)} to ${address}`*/);23162317    let transfer = {from: null, to: null, amount: 0n} as any;2318    result.result.events.forEach(({event: {data, method, section}}) => {2319      if ((section === 'balances') && (method === 'Transfer')) {2320        transfer = {2321          from: this.helper.address.normalizeSubstrate(data[0]),2322          to: this.helper.address.normalizeSubstrate(data[1]),2323          amount: BigInt(data[2]),2324        };2325      }2326    });2327    const isSuccess = this.helper.address.normalizeSubstrate(typeof signer === 'string' ? signer : signer.address) === transfer.from2328      && this.helper.address.normalizeSubstrate(address) === transfer.to2329      && BigInt(amount) === transfer.amount;2330    return isSuccess;2331  }23322333  /**2334   * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved2335   * @param address substrate address2336   * @returns2337   */2338  async getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {2339    const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data;2340    return {free: accountInfo.free.toBigInt(), miscFrozen: accountInfo.miscFrozen.toBigInt(), feeFrozen: accountInfo.feeFrozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};2341  }23422343  async getLocked(address: TSubstrateAccount): Promise<[{id: string, amount: bigint, reason: string}]> {2344    const locks = (await this.helper.callRpc('api.query.balances.locks', [address])).toHuman();2345    return locks.map((lock: any) => {return {id: lock.id, amount: BigInt(lock.amount.replace(/,/g, '')), reasons: lock.reasons};});2346  }2347}23482349class EthereumBalanceGroup<T extends ChainHelperBase> extends HelperGroup<T> {2350  /**2351   * Get ethereum address balance2352   * @param address ethereum address2353   * @example getEthereum("0x9F0583DbB855d...")2354   * @returns amount of tokens on address2355   */2356  async getEthereum(address: TEthereumAccount): Promise<bigint> {2357    return (await this.helper.callRpc('api.rpc.eth.getBalance', [address])).toBigInt();2358  }23592360  /**2361   * Transfer tokens to address2362   * @param signer keyring of signer2363   * @param address Ethereum address of a recipient2364   * @param amount amount of tokens to be transfered2365   * @example transferToEthereum(alithKeyring, "0x9F0583DbB855d...", 100_000_000_000n);2366   * @returns ```true``` if extrinsic success, otherwise ```false```2367   */2368  async transferToEthereum(signer: TSigner, address: TEthereumAccount, amount: bigint | string): Promise<boolean> {2369    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.transfer', [address, amount], true);23702371    let transfer = {from: null, to: null, amount: 0n} as any;2372    result.result.events.forEach(({event: {data, method, section}}) => {2373      if ((section === 'balances') && (method === 'Transfer')) {2374        transfer = {2375          from: data[0].toString(),2376          to: data[1].toString(),2377          amount: BigInt(data[2]),2378        };2379      }2380    });2381    const isSuccess = (typeof signer === 'string' ? signer : signer.address) === transfer.from2382      && address === transfer.to2383      && BigInt(amount) === transfer.amount;2384    return isSuccess;2385  }2386}23872388class BalanceGroup<T extends ChainHelperBase> extends HelperGroup<T> {2389  subBalanceGroup: SubstrateBalanceGroup<T>;2390  ethBalanceGroup: EthereumBalanceGroup<T>;23912392  constructor(helper: T) {2393    super(helper);2394    this.subBalanceGroup = new SubstrateBalanceGroup(helper);2395    this.ethBalanceGroup = new EthereumBalanceGroup(helper);2396  }23972398  getCollectionCreationPrice(): bigint {2399    return 2n * this.getOneTokenNominal();2400  }2401  /**2402   * Representation of the native token in the smallest unit - one OPAL (OPL), QUARTZ (QTZ), or UNIQUE (UNQ).2403   * @example getOneTokenNominal()2404   * @returns ```BigInt``` representation of the native token in the smallest unit, e.g. ```1_000_000_000_000_000_000n``` for QTZ.2405   */2406  getOneTokenNominal(): bigint {2407    const chainProperties = this.helper.chain.getChainProperties();2408    return 10n ** BigInt((chainProperties.tokenDecimals || [18])[0]);2409  }24102411  /**2412   * Get substrate address balance2413   * @param address substrate address2414   * @example getSubstrate("5GrwvaEF5zXb26Fz...")2415   * @returns amount of tokens on address2416   */2417  getSubstrate(address: TSubstrateAccount): Promise<bigint> {2418    return this.subBalanceGroup.getSubstrate(address);2419  }24202421  /**2422   * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved2423   * @param address substrate address2424   * @returns2425   */2426  getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {2427    return this.subBalanceGroup.getSubstrateFull(address);2428  }24292430  /**2431   * Get locked balances2432   * @param address substrate address2433   * @returns locked balances with reason via api.query.balances.locks2434   */2435  getLocked(address: TSubstrateAccount) {2436    return this.subBalanceGroup.getLocked(address);2437  }24382439  /**2440   * Get ethereum address balance2441   * @param address ethereum address2442   * @example getEthereum("0x9F0583DbB855d...")2443   * @returns amount of tokens on address2444   */2445  getEthereum(address: TEthereumAccount): Promise<bigint> {2446    return this.ethBalanceGroup.getEthereum(address);2447  }24482449  /**2450   * Transfer tokens to substrate address2451   * @param signer keyring of signer2452   * @param address substrate address of a recipient2453   * @param amount amount of tokens to be transfered2454   * @example transferToSubstrate(aliceKeyring, "5GrwvaEF5zXb26Fz...", 100_000_000_000n);2455   * @returns ```true``` if extrinsic success, otherwise ```false```2456   */2457  transferToSubstrate(signer: TSigner, address: TSubstrateAccount, amount: bigint | string): Promise<boolean> {2458    return this.subBalanceGroup.transferToSubstrate(signer, address, amount);2459  }24602461  async forceTransferToSubstrate(signer: TSigner, from: TSubstrateAccount, to: TSubstrateAccount, amount: bigint | string): Promise<boolean> {2462    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.forceTransfer', [from, to, amount], true);24632464    let transfer = {from: null, to: null, amount: 0n} as any;2465    result.result.events.forEach(({event: {data, method, section}}) => {2466      if ((section === 'balances') && (method === 'Transfer')) {2467        transfer = {2468          from: this.helper.address.normalizeSubstrate(data[0]),2469          to: this.helper.address.normalizeSubstrate(data[1]),2470          amount: BigInt(data[2]),2471        };2472      }2473    });2474    let isSuccess = this.helper.address.normalizeSubstrate(from) === transfer.from;2475    isSuccess = isSuccess && this.helper.address.normalizeSubstrate(to) === transfer.to;2476    isSuccess = isSuccess && BigInt(amount) === transfer.amount;2477    return isSuccess;2478  }24792480  /**2481   * Transfer tokens with the unlock period2482   * @param signer signers Keyring2483   * @param address Substrate address of recipient2484   * @param schedule Schedule params2485   * @example vestedTransfer(signer, recepient.address, 20000, 100, 10, 50 * nominal); // total amount of vested tokens will be 100 * 50 = 50002486   */2487  async vestedTransfer(signer: TSigner, address: TSubstrateAccount, schedule: {start: bigint, period: bigint, periodCount: bigint, perPeriod: bigint}): Promise<void> {2488    const result = await this.helper.executeExtrinsic(signer, 'api.tx.vesting.vestedTransfer', [address, schedule]);2489    const event = result.result.events2490      .find(e => e.event.section === 'vesting' &&2491            e.event.method === 'VestingScheduleAdded' &&2492            e.event.data[0].toHuman() === signer.address);2493    if (!event) throw Error('Cannot find transfer in events');2494  }24952496  /**2497   * Get schedule for recepient of vested transfer2498   * @param address Substrate address of recipient2499   * @returns2500   */2501  async getVestingSchedules(address: TSubstrateAccount): Promise<{start: bigint, period: bigint, periodCount: bigint, perPeriod: bigint}[]> {2502    const schedule = (await this.helper.callRpc('api.query.vesting.vestingSchedules', [address])).toJSON();2503    return schedule.map((schedule: any) => {2504      return {2505        start: BigInt(schedule.start),2506        period: BigInt(schedule.period),2507        periodCount: BigInt(schedule.periodCount),2508        perPeriod: BigInt(schedule.perPeriod),2509      };2510    });2511  }25122513  /**2514   * Claim vested tokens2515   * @param signer signers Keyring2516   */2517  async claim(signer: TSigner) {2518    const result = await this.helper.executeExtrinsic(signer, 'api.tx.vesting.claim', []);2519    const event = result.result.events2520      .find(e => e.event.section === 'vesting' &&2521            e.event.method === 'Claimed' &&2522            e.event.data[0].toHuman() === signer.address);2523    if (!event) throw Error('Cannot find claim in events');2524  }2525}25262527class AddressGroup extends HelperGroup<ChainHelperBase> {2528  /**2529   * Normalizes the address to the specified ss58 format, by default ```42```.2530   * @param address substrate address2531   * @param ss58Format format for address conversion, by default ```42```2532   * @example normalizeSubstrate("unjKJQJrRd238pkUZZvzDQrfKuM39zBSnQ5zjAGAGcdRhaJTx") // returns 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY2533   * @returns substrate address converted to normalized (i.e., starting with 5) or specified explicitly representation2534   */2535  normalizeSubstrate(address: TSubstrateAccount, ss58Format = 42): TSubstrateAccount {2536    return CrossAccountId.normalizeSubstrateAddress(address, ss58Format);2537  }25382539  /**2540   * Get address in the connected chain format2541   * @param address substrate address2542   * @example normalizeSubstrateToChainFormat("5GrwvaEF5zXb26Fz...") // returns unjKJQJrRd238pkUZZ... for Unique Network2543   * @returns address in chain format2544   */2545  normalizeSubstrateToChainFormat(address: TSubstrateAccount): TSubstrateAccount {2546    return this.normalizeSubstrate(address, this.helper.chain.getChainProperties().ss58Format);2547  }25482549  /**2550   * Get substrate mirror of an ethereum address2551   * @param ethAddress ethereum address2552   * @param toChainFormat false for normalized account2553   * @example ethToSubstrate('0x9F0583DbB855d...')2554   * @returns substrate mirror of a provided ethereum address2555   */2556  ethToSubstrate(ethAddress: TEthereumAccount, toChainFormat=false): TSubstrateAccount {2557    return CrossAccountId.translateEthToSub(ethAddress, toChainFormat ? this.helper.chain.getChainProperties().ss58Format : undefined);2558  }25592560  /**2561   * Get ethereum mirror of a substrate address2562   * @param subAddress substrate account2563   * @example substrateToEth("5DnSF6RRjwteE3BrC...")2564   * @returns ethereum mirror of a provided substrate address2565   */2566  substrateToEth(subAddress: TSubstrateAccount): TEthereumAccount {2567    return CrossAccountId.translateSubToEth(subAddress);2568  }25692570  /**2571   * Encode key to substrate address2572   * @param key key for encoding address2573   * @param ss58Format prefix for encoding to the address of the corresponding network2574   * @returns encoded substrate address2575   */2576  encodeSubstrateAddress (key: Uint8Array | string | bigint, ss58Format = 42): string {2577    const u8a :Uint8Array = typeof key === 'string'2578      ? hexToU8a(key)2579      : typeof key === 'bigint'2580        ? hexToU8a(key.toString(16))2581        : key;25822583    if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) {2584      throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`);2585    }25862587    const allowedDecodedLengths = [1, 2, 4, 8, 32, 33];2588    if (!allowedDecodedLengths.includes(u8a.length)) {2589      throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(', ')}`);2590    }25912592    const u8aPrefix = ss58Format < 642593      ? new Uint8Array([ss58Format])2594      : new Uint8Array([2595        ((ss58Format & 0xfc) >> 2) | 0x40,2596        (ss58Format >> 8) | ((ss58Format & 0x03) << 6),2597      ]);25982599    const input = u8aConcat(u8aPrefix, u8a);26002601    return base58Encode(u8aConcat(2602      input,2603      blake2AsU8a(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1),2604    ));2605  }26062607  /**2608   * Restore substrate address from bigint representation2609   * @param number decimal representation of substrate address2610   * @returns substrate address2611   */2612  restoreCrossAccountFromBigInt(number: bigint): TSubstrateAccount {2613    if (this.helper.api === null) {2614      throw 'Not connected';2615    }2616    const res = this.helper.api.registry.createType('AccountId', '0x' + number.toString(16).padStart(64, '0')).toJSON();2617    if (res === undefined || res === null) {2618      throw 'Restore address error';2619    }2620    return res.toString();2621  }26222623  /**2624   * Convert etherium cross account id to substrate cross account id2625   * @param ethCrossAccount etherium cross account2626   * @returns substrate cross account id2627   */2628  convertCrossAccountFromEthCrossAccount(ethCrossAccount: IEthCrossAccountId): ICrossAccountId {2629    if (ethCrossAccount.sub === '0') {2630      return {Ethereum: ethCrossAccount.eth.toLocaleLowerCase()};2631    }26322633    const ss58 = this.restoreCrossAccountFromBigInt(BigInt(ethCrossAccount.sub));2634    return {Substrate: ss58};2635  }26362637  paraSiblingSovereignAccount(paraid: number) {2638    // We are getting a *sibling* parachain sovereign account,2639    // so we need a sibling prefix: encoded(b"sibl") == 0x7369626c2640    const siblingPrefix = '0x7369626c';26412642    const encodedParaId = this.helper.getApi().createType('u32', paraid).toHex(true).substring(2);2643    const suffix = '000000000000000000000000000000000000000000000000';26442645    return siblingPrefix + encodedParaId + suffix;2646  }2647}26482649class StakingGroup extends HelperGroup<UniqueHelper> {2650  /**2651   * Stake tokens for App Promotion2652   * @param signer keyring of signer2653   * @param amountToStake amount of tokens to stake2654   * @param label extra label for log2655   * @returns2656   */2657  async stake(signer: TSigner, amountToStake: bigint, label?: string): Promise<boolean> {2658    if(typeof label === 'undefined') label = `${signer.address} amount: ${amountToStake}`;2659    const _stakeResult = await this.helper.executeExtrinsic(2660      signer, 'api.tx.appPromotion.stake',2661      [amountToStake], true,2662    );2663    // TODO extract info from stakeResult2664    return true;2665  }26662667  /**2668   * Unstake all staked tokens2669   * @param signer keyring of signer2670   * @param amountToUnstake amount of tokens to unstake2671   * @param label extra label for log2672   * @returns block hash where unstake happened2673   */2674  async unstakeAll(signer: TSigner, label?: string): Promise<string> {2675    if(typeof label === 'undefined') label = `${signer.address}`;2676    const unstakeResult = await this.helper.executeExtrinsic(2677      signer, 'api.tx.appPromotion.unstakeAll',2678      [], true,2679    );2680    return unstakeResult.blockHash;2681  }26822683  /**2684   * Unstake the part of a staked tokens2685   * @param signer keyring of signer2686   * @param amount amount of tokens to unstake2687   * @param label extra label for log2688   * @returns block hash where unstake happened2689   */2690  async unstakePartial(signer: TSigner, amount: bigint, label?: string): Promise<string> {2691    if(typeof label === 'undefined') label = `${signer.address}`;2692    const unstakeResult = await this.helper.executeExtrinsic(2693      signer, 'api.tx.appPromotion.unstakePartial',2694      [amount], true,2695    );2696    return unstakeResult.blockHash;2697  }26982699  /**2700   * Get total number of active stakes2701   * @param address substrate address2702   * @returns {number}2703   */2704  async getStakesNumber(address: ICrossAccountId): Promise<number> {2705    if (address.Ethereum) throw Error('only substrate address');2706    return (await this.helper.callRpc('api.query.appPromotion.stakesPerAccount', [address.Substrate])).toNumber();2707  }27082709  /**2710   * Get total staked amount for address2711   * @param address substrate or ethereum address2712   * @returns total staked amount2713   */2714  async getTotalStaked(address?: ICrossAccountId): Promise<bigint> {2715    if (address) return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked', [address])).toBigInt();2716    return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked')).toBigInt();2717  }27182719  /**2720   * Get total staked per block2721   * @param address substrate or ethereum address2722   * @returns array of stakes. `block` – the number of the block in which the stake was made. `amount` - the number of tokens staked in the block2723   */2724  async getTotalStakedPerBlock(address: ICrossAccountId): Promise<IStakingInfo[]> {2725    const rawTotalStakerdPerBlock = await this.helper.callRpc('api.rpc.appPromotion.totalStakedPerBlock', [address]);2726    return rawTotalStakerdPerBlock.map(([block, amount]: any[]) => {2727      return {2728        block: block.toBigInt(),2729        amount: amount.toBigInt(),2730      };2731    });2732  }27332734  /**2735   * Get total pending unstake amount for address2736   * @param address substrate or ethereum address2737   * @returns total pending unstake amount2738   */2739  async getPendingUnstake(address: ICrossAccountId): Promise<bigint> {2740    return (await this.helper.callRpc('api.rpc.appPromotion.pendingUnstake', [address])).toBigInt();2741  }27422743  /**2744   * Get pending unstake amount per block for address2745   * @param address substrate or ethereum address2746   * @returns array of pending stakes. `block` – the number of the block in which the unstake was made. `amount` - the number of tokens unstaked in the block2747   */2748  async getPendingUnstakePerBlock(address: ICrossAccountId): Promise<IStakingInfo[]> {2749    const rawUnstakedPerBlock = await this.helper.callRpc('api.rpc.appPromotion.pendingUnstakePerBlock', [address]);2750    const result = rawUnstakedPerBlock.map(([block, amount]: any[]) => {2751      return {2752        block: block.toBigInt(),2753        amount: amount.toBigInt(),2754      };2755    });2756    return result;2757  }2758}27592760class SchedulerGroup extends HelperGroup<UniqueHelper> {2761  constructor(helper: UniqueHelper) {2762    super(helper);2763  }27642765  cancelScheduled(signer: TSigner, scheduledId: string) {2766    return this.helper.executeExtrinsic(2767      signer,2768      'api.tx.scheduler.cancelNamed',2769      [scheduledId],2770      true,2771    );2772  }27732774  changePriority(signer: TSigner, scheduledId: string, priority: number) {2775    return this.helper.executeExtrinsic(2776      signer,2777      'api.tx.scheduler.changeNamedPriority',2778      [scheduledId, priority],2779      true,2780    );2781  }27822783  scheduleAt<T extends UniqueHelper>(2784    executionBlockNumber: number,2785    options: ISchedulerOptions = {},2786  ) {2787    return this.schedule<T>('schedule', executionBlockNumber, options);2788  }27892790  scheduleAfter<T extends UniqueHelper>(2791    blocksBeforeExecution: number,2792    options: ISchedulerOptions = {},2793  ) {2794    return this.schedule<T>('scheduleAfter', blocksBeforeExecution, options);2795  }27962797  schedule<T extends UniqueHelper>(2798    scheduleFn: 'schedule' | 'scheduleAfter',2799    blocksNum: number,2800    options: ISchedulerOptions = {},2801  ) {2802    // eslint-disable-next-line @typescript-eslint/naming-convention2803    const ScheduledHelperType = ScheduledUniqueHelper(this.helper.helperBase);2804    return this.helper.clone(ScheduledHelperType, {2805      scheduleFn,2806      blocksNum,2807      options,2808    }) as T;2809  }2810}28112812class CollatorSelectionGroup extends HelperGroup<UniqueHelper> {2813  //todo:collator documentation2814  addInvulnerable(signer: TSigner, address: string) {2815    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.addInvulnerable', [address]);2816  }28172818  removeInvulnerable(signer: TSigner, address: string) {2819    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.removeInvulnerable', [address]);2820  }28212822  async getInvulnerables(): Promise<string[]> {2823    return (await this.helper.callRpc('api.query.collatorSelection.invulnerables')).map((x: any) => x.toHuman());2824  }28252826  /** and also total max invulnerables */2827  maxCollators(): number {2828    return (this.helper.getApi().consts.configuration.defaultCollatorSelectionMaxCollators.toJSON() as number);2829  }28302831  async getDesiredCollators(): Promise<number> {2832    return (await this.helper.callRpc('api.query.configuration.collatorSelectionDesiredCollatorsOverride')).toNumber();2833  }28342835  setLicenseBond(signer: TSigner, amount: bigint) {2836    return this.helper.executeExtrinsic(signer, 'api.tx.configuration.setCollatorSelectionLicenseBond', [amount]);2837  }28382839  async getLicenseBond(): Promise<bigint> {2840    return (await this.helper.callRpc('api.query.configuration.collatorSelectionLicenseBondOverride')).toBigInt();2841  }28422843  obtainLicense(signer: TSigner) {2844    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.getLicense', []);2845  }28462847  releaseLicense(signer: TSigner) {2848    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.releaseLicense', []);2849  }28502851  forceReleaseLicense(signer: TSigner, released: string) {2852    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.forceReleaseLicense', [released]);2853  }28542855  async hasLicense(address: string): Promise<bigint> {2856    return (await this.helper.callRpc('api.query.collatorSelection.licenseDepositOf', [address])).toBigInt();2857  }28582859  onboard(signer: TSigner) {2860    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.onboard', []);2861  }28622863  offboard(signer: TSigner) {2864    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.offboard', []);2865  }28662867  async getCandidates(): Promise<string[]> {2868    return (await this.helper.callRpc('api.query.collatorSelection.candidates')).map((x: any) => x.toHuman());2869  }2870}28712872class ForeignAssetsGroup extends HelperGroup<UniqueHelper> {2873  async register(signer: TSigner, ownerAddress: TSubstrateAccount, location: any, metadata: IForeignAssetMetadata) {2874    await this.helper.executeExtrinsic(2875      signer,2876      'api.tx.foreignAssets.registerForeignAsset',2877      [ownerAddress, location, metadata],2878      true,2879    );2880  }28812882  async update(signer: TSigner, foreignAssetId: number, location: any, metadata: IForeignAssetMetadata) {2883    await this.helper.executeExtrinsic(2884      signer,2885      'api.tx.foreignAssets.updateForeignAsset',2886      [foreignAssetId, location, metadata],2887      true,2888    );2889  }2890}28912892class XcmGroup<T extends ChainHelperBase> extends HelperGroup<T> {2893  palletName: string;28942895  constructor(helper: T, palletName: string) {2896    super(helper);28972898    this.palletName = palletName;2899  }29002901  async limitedReserveTransferAssets(signer: TSigner, destination: any, beneficiary: any, assets: any, feeAssetItem: number, weightLimit: any) {2902    await this.helper.executeExtrinsic(signer, `api.tx.${this.palletName}.limitedReserveTransferAssets`, [destination, beneficiary, assets, feeAssetItem, weightLimit], true);2903  }29042905  async teleportAssets(signer: TSigner, destination: any, beneficiary: any, assets: any, feeAssetItem: number) {2906    await this.helper.executeExtrinsic(signer, `api.tx.${this.palletName}.teleportAssets`, [destination, beneficiary, assets, feeAssetItem], true);2907  }29082909  async teleportNativeAsset(signer: TSigner, destinationParaId: number, targetAccount: Uint8Array, amount: bigint) {2910    const destination = {2911      V1: {2912        parents: 0,2913        interior: {2914          X1: {2915            Parachain: destinationParaId,2916          },2917        },2918      },2919    };29202921    const beneficiary = {2922      V1: {2923        parents: 0,2924        interior: {2925          X1: {2926            AccountId32: {2927              network: 'Any',2928              id: targetAccount,2929            },2930          },2931        },2932      },2933    };29342935    const assets = {2936      V1: [2937        {2938          id: {2939            Concrete: {2940              parents: 0,2941              interior: 'Here',2942            },2943          },2944          fun: {2945            Fungible: amount,2946          },2947        },2948      ],2949    };29502951    const feeAssetItem = 0;29522953    await this.teleportAssets(signer, destination, beneficiary, assets, feeAssetItem);2954  }2955}29562957class XTokensGroup<T extends ChainHelperBase> extends HelperGroup<T> {2958  async transfer(signer: TSigner, currencyId: any, amount: bigint, destination: any, destWeight: any) {2959    await this.helper.executeExtrinsic(signer, 'api.tx.xTokens.transfer', [currencyId, amount, destination, destWeight], true);2960  }29612962  async transferMultiasset(signer: TSigner, asset: any, destination: any, destWeight: any) {2963    await this.helper.executeExtrinsic(signer, 'api.tx.xTokens.transferMultiasset', [asset, destination, destWeight], true);2964  }29652966  async transferMulticurrencies(signer: TSigner, currencies: any[], feeItem: number, destLocation: any, destWeight: any) {2967    await this.helper.executeExtrinsic(signer, 'api.tx.xTokens.transferMulticurrencies', [currencies, feeItem, destLocation, destWeight], true);2968  }2969}29702971class TokensGroup<T extends ChainHelperBase> extends HelperGroup<T> {2972  async accounts(address: string, currencyId: any) {2973    const {free} = (await this.helper.callRpc('api.query.tokens.accounts', [address, currencyId])).toJSON() as any;2974    return BigInt(free);2975  }2976}29772978class AssetsGroup<T extends ChainHelperBase> extends HelperGroup<T> {2979  async create(signer: TSigner, assetId: number, admin: string, minimalBalance: bigint) {2980    await this.helper.executeExtrinsic(signer, 'api.tx.assets.create', [assetId, admin, minimalBalance], true);2981  }29822983  async setMetadata(signer: TSigner, assetId: number, name: string, symbol: string, decimals: number) {2984    await this.helper.executeExtrinsic(signer, 'api.tx.assets.setMetadata', [assetId, name, symbol, decimals], true);2985  }29862987  async mint(signer: TSigner, assetId: number, beneficiary: string, amount: bigint) {2988    await this.helper.executeExtrinsic(signer, 'api.tx.assets.mint', [assetId, beneficiary, amount], true);2989  }29902991  async account(assetId: string | number, address: string) {2992    const accountAsset = (2993      await this.helper.callRpc('api.query.assets.account', [assetId, address])2994    ).toJSON()! as any;29952996    if (accountAsset !== null) {2997      return BigInt(accountAsset['balance']);2998    } else {2999      return null;3000    }3001  }3002}30033004class AcalaAssetRegistryGroup extends HelperGroup<AcalaHelper> {3005  async registerForeignAsset(signer: TSigner, destination: any, metadata: AcalaAssetMetadata) {3006    await this.helper.executeExtrinsic(signer, 'api.tx.assetRegistry.registerForeignAsset', [destination, metadata], true);3007  }3008}30093010class MoonbeamAssetManagerGroup extends HelperGroup<MoonbeamHelper> {3011  makeRegisterForeignAssetProposal(assetInfo: MoonbeamAssetInfo) {3012    const apiPrefix = 'api.tx.assetManager.';30133014    const registerTx = this.helper.constructApiCall(3015      apiPrefix + 'registerForeignAsset',3016      [assetInfo.location, assetInfo.metadata, assetInfo.existentialDeposit, assetInfo.isSufficient],3017    );30183019    const setUnitsTx = this.helper.constructApiCall(3020      apiPrefix + 'setAssetUnitsPerSecond',3021      [assetInfo.location, assetInfo.unitsPerSecond, assetInfo.numAssetsWeightHint],3022    );30233024    const batchCall = this.helper.getApi().tx.utility.batchAll([registerTx, setUnitsTx]);3025    const encodedProposal = batchCall?.method.toHex() || '';3026    return encodedProposal;3027  }30283029  async assetTypeId(location: any) {3030    return await this.helper.callRpc('api.query.assetManager.assetTypeId', [location]);3031  }3032}30333034class MoonbeamDemocracyGroup extends HelperGroup<MoonbeamHelper> {3035  notePreimagePallet: string;30363037  constructor(helper: MoonbeamHelper, options: {[key: string]: any} = {}) {3038    super(helper);3039    this.notePreimagePallet = options.notePreimagePallet;3040  }30413042  async notePreimage(signer: TSigner, encodedProposal: string) {3043    await this.helper.executeExtrinsic(signer, `api.tx.${this.notePreimagePallet}.notePreimage`, [encodedProposal], true);3044  }30453046  externalProposeMajority(proposal: any) {3047    return this.helper.constructApiCall('api.tx.democracy.externalProposeMajority', [proposal]);3048  }30493050  fastTrack(proposalHash: string, votingPeriod: number, delayPeriod: number) {3051    return this.helper.constructApiCall('api.tx.democracy.fastTrack', [proposalHash, votingPeriod, delayPeriod]);3052  }30533054  async referendumVote(signer: TSigner, referendumIndex: number, accountVote: DemocracyStandardAccountVote) {3055    await this.helper.executeExtrinsic(signer, 'api.tx.democracy.vote', [referendumIndex, {Standard: accountVote}], true);3056  }3057}30583059class MoonbeamCollectiveGroup extends HelperGroup<MoonbeamHelper> {3060  collective: string;30613062  constructor(helper: MoonbeamHelper, collective: string) {3063    super(helper);30643065    this.collective = collective;3066  }30673068  async propose(signer: TSigner, threshold: number, proposalHash: string, lengthBound: number) {3069    await this.helper.executeExtrinsic(signer, `api.tx.${this.collective}.propose`, [threshold, proposalHash, lengthBound], true);3070  }30713072  async vote(signer: TSigner, proposalHash: string, proposalIndex: number, approve: boolean) {3073    await this.helper.executeExtrinsic(signer, `api.tx.${this.collective}.vote`, [proposalHash, proposalIndex, approve], true);3074  }30753076  async close(signer: TSigner, proposalHash: string, proposalIndex: number, weightBound: any, lengthBound: number) {3077    await this.helper.executeExtrinsic(signer, `api.tx.${this.collective}.close`, [proposalHash, proposalIndex, weightBound, lengthBound], true);3078  }30793080  async proposalCount() {3081    return Number(await this.helper.callRpc(`api.query.${this.collective}.proposalCount`, []));3082  }3083}30843085export type ChainHelperBaseConstructor = new(...args: any[]) => ChainHelperBase;3086export type UniqueHelperConstructor = new(...args: any[]) => UniqueHelper;30873088export class UniqueHelper extends ChainHelperBase {3089  balance: BalanceGroup<UniqueHelper>;3090  collection: CollectionGroup;3091  nft: NFTGroup;3092  rft: RFTGroup;3093  ft: FTGroup;3094  staking: StakingGroup;3095  scheduler: SchedulerGroup;3096  collatorSelection: CollatorSelectionGroup;3097  foreignAssets: ForeignAssetsGroup;3098  xcm: XcmGroup<UniqueHelper>;3099  xTokens: XTokensGroup<UniqueHelper>;3100  tokens: TokensGroup<UniqueHelper>;31013102  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3103    super(logger, options.helperBase ?? UniqueHelper);31043105    this.balance = new BalanceGroup(this);3106    this.collection = new CollectionGroup(this);3107    this.nft = new NFTGroup(this);3108    this.rft = new RFTGroup(this);3109    this.ft = new FTGroup(this);3110    this.staking = new StakingGroup(this);3111    this.scheduler = new SchedulerGroup(this);3112    this.collatorSelection = new CollatorSelectionGroup(this);3113    this.foreignAssets = new ForeignAssetsGroup(this);3114    this.xcm = new XcmGroup(this, 'polkadotXcm');3115    this.xTokens = new XTokensGroup(this);3116    this.tokens = new TokensGroup(this);3117  }31183119  getSudo<T extends UniqueHelper>() {3120    // eslint-disable-next-line @typescript-eslint/naming-convention3121    const SudoHelperType = SudoHelper(this.helperBase);3122    return this.clone(SudoHelperType) as T;3123  }3124}31253126export class XcmChainHelper extends ChainHelperBase {3127  async connect(wsEndpoint: string, _listeners?: any): Promise<void> {3128    const wsProvider = new WsProvider(wsEndpoint);3129    this.api = new ApiPromise({3130      provider: wsProvider,3131    });3132    await this.api.isReadyOrError;3133    this.network = await UniqueHelper.detectNetwork(this.api);3134  }3135}31363137export class RelayHelper extends XcmChainHelper {3138  balance: SubstrateBalanceGroup<RelayHelper>;3139  xcm: XcmGroup<RelayHelper>;31403141  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3142    super(logger, options.helperBase ?? RelayHelper);31433144    this.balance = new SubstrateBalanceGroup(this);3145    this.xcm = new XcmGroup(this, 'xcmPallet');3146  }3147}31483149export class WestmintHelper extends XcmChainHelper {3150  balance: SubstrateBalanceGroup<WestmintHelper>;3151  xcm: XcmGroup<WestmintHelper>;3152  assets: AssetsGroup<WestmintHelper>;3153  xTokens: XTokensGroup<WestmintHelper>;31543155  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3156    super(logger, options.helperBase ?? WestmintHelper);31573158    this.balance = new SubstrateBalanceGroup(this);3159    this.xcm = new XcmGroup(this, 'polkadotXcm');3160    this.assets = new AssetsGroup(this);3161    this.xTokens = new XTokensGroup(this);3162  }3163}31643165export class MoonbeamHelper extends XcmChainHelper {3166  balance: EthereumBalanceGroup<MoonbeamHelper>;3167  assetManager: MoonbeamAssetManagerGroup;3168  assets: AssetsGroup<MoonbeamHelper>;3169  xTokens: XTokensGroup<MoonbeamHelper>;3170  democracy: MoonbeamDemocracyGroup;3171  collective: {3172    council: MoonbeamCollectiveGroup,3173    techCommittee: MoonbeamCollectiveGroup,3174  };31753176  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3177    super(logger, options.helperBase ?? MoonbeamHelper);31783179    this.balance = new EthereumBalanceGroup(this);3180    this.assetManager = new MoonbeamAssetManagerGroup(this);3181    this.assets = new AssetsGroup(this);3182    this.xTokens = new XTokensGroup(this);3183    this.democracy = new MoonbeamDemocracyGroup(this, options);3184    this.collective = {3185      council: new MoonbeamCollectiveGroup(this, 'councilCollective'),3186      techCommittee: new MoonbeamCollectiveGroup(this, 'techCommitteeCollective'),3187    };3188  }3189}31903191export class AcalaHelper extends XcmChainHelper {3192  balance: SubstrateBalanceGroup<AcalaHelper>;3193  assetRegistry: AcalaAssetRegistryGroup;3194  xTokens: XTokensGroup<AcalaHelper>;3195  tokens: TokensGroup<AcalaHelper>;31963197  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3198    super(logger, options.helperBase ?? AcalaHelper);31993200    this.balance = new SubstrateBalanceGroup(this);3201    this.assetRegistry = new AcalaAssetRegistryGroup(this);3202    this.xTokens = new XTokensGroup(this);3203    this.tokens = new TokensGroup(this);3204  }32053206  getSudo<T extends AcalaHelper>() {3207    // eslint-disable-next-line @typescript-eslint/naming-convention3208    const SudoHelperType = SudoHelper(this.helperBase);3209    return this.clone(SudoHelperType) as T;3210  }3211}32123213// eslint-disable-next-line @typescript-eslint/naming-convention3214function ScheduledUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {3215  return class extends Base {3216    scheduleFn: 'schedule' | 'scheduleAfter';3217    blocksNum: number;3218    options: ISchedulerOptions;32193220    constructor(...args: any[]) {3221      const logger = args[0] as ILogger;3222      const options = args[1] as {3223        scheduleFn: 'schedule' | 'scheduleAfter',3224        blocksNum: number,3225        options: ISchedulerOptions3226      };32273228      super(logger);32293230      this.scheduleFn = options.scheduleFn;3231      this.blocksNum = options.blocksNum;3232      this.options = options.options;3233    }32343235    executeExtrinsic(sender: IKeyringPair, scheduledExtrinsic: string, scheduledParams: any[], expectSuccess?: boolean): Promise<ITransactionResult> {3236      const scheduledTx = this.constructApiCall(scheduledExtrinsic, scheduledParams);32373238      const mandatorySchedArgs = [3239        this.blocksNum,3240        this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,3241        this.options.priority ?? null,3242        scheduledTx,3243      ];32443245      let schedArgs;3246      let scheduleFn;32473248      if (this.options.scheduledId) {3249        schedArgs = [this.options.scheduledId!, ...mandatorySchedArgs];32503251        if (this.scheduleFn == 'schedule') {3252          scheduleFn = 'scheduleNamed';3253        } else if (this.scheduleFn == 'scheduleAfter') {3254          scheduleFn = 'scheduleNamedAfter';3255        }3256      } else {3257        schedArgs = mandatorySchedArgs;3258        scheduleFn = this.scheduleFn;3259      }32603261      const extrinsic = 'api.tx.scheduler.' +  scheduleFn;32623263      return super.executeExtrinsic(3264        sender,3265        extrinsic,3266        schedArgs,3267        expectSuccess,3268      );3269    }3270  };3271}32723273// eslint-disable-next-line @typescript-eslint/naming-convention3274function SudoHelper<T extends ChainHelperBaseConstructor>(Base: T) {3275  return class extends Base {3276    constructor(...args: any[]) {3277      super(...args);3278    }32793280    async executeExtrinsic(3281      sender: IKeyringPair,3282      extrinsic: string,3283      params: any[],3284      expectSuccess?: boolean,3285      options: Partial<SignerOptions>|null = null,3286    ): Promise<ITransactionResult> {3287      const call = this.constructApiCall(extrinsic, params);3288      const result = await super.executeExtrinsic(3289        sender,3290        'api.tx.sudo.sudo',3291        [call],3292        expectSuccess,3293        options,3294      );32953296      if (result.status === 'Fail') return result;32973298      const data = (result.result.events.find(x => x.event.section == 'sudo' && x.event.method == 'Sudid')?.event.data as any).sudoResult;3299      if (data.isErr) {3300        if (data.asErr.isModule) {3301          const error = (result.result.events[1].event.data as any).sudoResult.asErr.asModule;3302          const metaError = super.getApi()?.registry.findMetaError(error);3303          throw new Error(`${metaError.section}.${metaError.name}`);3304        } else {3305          throw new Error(data.asErr.toHuman());3306        }3307      }3308      return result;3309    }3310  };3311}33123313export class UniqueBaseCollection {3314  helper: UniqueHelper;3315  collectionId: number;33163317  constructor(collectionId: number, uniqueHelper: UniqueHelper) {3318    this.collectionId = collectionId;3319    this.helper = uniqueHelper;3320  }33213322  async getData() {3323    return await this.helper.collection.getData(this.collectionId);3324  }33253326  async getLastTokenId() {3327    return await this.helper.collection.getLastTokenId(this.collectionId);3328  }33293330  async doesTokenExist(tokenId: number) {3331    return await this.helper.collection.doesTokenExist(this.collectionId, tokenId);3332  }33333334  async getAdmins() {3335    return await this.helper.collection.getAdmins(this.collectionId);3336  }33373338  async getAllowList() {3339    return await this.helper.collection.getAllowList(this.collectionId);3340  }33413342  async getEffectiveLimits() {3343    return await this.helper.collection.getEffectiveLimits(this.collectionId);3344  }33453346  async getProperties(propertyKeys?: string[] | null) {3347    return await this.helper.collection.getProperties(this.collectionId, propertyKeys);3348  }33493350  async getPropertiesConsumedSpace() {3351    return await this.helper.collection.getPropertiesConsumedSpace(this.collectionId);3352  }33533354  async getTokenNextSponsored(tokenId: number, addressObj: ICrossAccountId) {3355    return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);3356  }33573358  async getOptions() {3359    return await this.helper.collection.getCollectionOptions(this.collectionId);3360  }33613362  async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {3363    return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);3364  }33653366  async confirmSponsorship(signer: TSigner) {3367    return await this.helper.collection.confirmSponsorship(signer, this.collectionId);3368  }33693370  async removeSponsor(signer: TSigner) {3371    return await this.helper.collection.removeSponsor(signer, this.collectionId);3372  }33733374  async setLimits(signer: TSigner, limits: ICollectionLimits) {3375    return await this.helper.collection.setLimits(signer, this.collectionId, limits);3376  }33773378  async changeOwner(signer: TSigner, ownerAddress: TSubstrateAccount) {3379    return await this.helper.collection.changeOwner(signer, this.collectionId, ownerAddress);3380  }33813382  async addAdmin(signer: TSigner, adminAddressObj: ICrossAccountId) {3383    return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj);3384  }33853386  async addToAllowList(signer: TSigner, addressObj: ICrossAccountId) {3387    return await this.helper.collection.addToAllowList(signer, this.collectionId, addressObj);3388  }33893390  async removeFromAllowList(signer: TSigner, addressObj: ICrossAccountId) {3391    return await this.helper.collection.removeFromAllowList(signer, this.collectionId, addressObj);3392  }33933394  async removeAdmin(signer: TSigner, adminAddressObj: ICrossAccountId) {3395    return await this.helper.collection.removeAdmin(signer, this.collectionId, adminAddressObj);3396  }33973398  async setProperties(signer: TSigner, properties: IProperty[]) {3399    return await this.helper.collection.setProperties(signer, this.collectionId, properties);3400  }34013402  async deleteProperties(signer: TSigner, propertyKeys: string[]) {3403    return await this.helper.collection.deleteProperties(signer, this.collectionId, propertyKeys);3404  }34053406  async setPermissions(signer: TSigner, permissions: ICollectionPermissions) {3407    return await this.helper.collection.setPermissions(signer, this.collectionId, permissions);3408  }34093410  async enableNesting(signer: TSigner, permissions: INestingPermissions) {3411    return await this.helper.collection.enableNesting(signer, this.collectionId, permissions);3412  }34133414  async disableNesting(signer: TSigner) {3415    return await this.helper.collection.disableNesting(signer, this.collectionId);3416  }34173418  async burn(signer: TSigner) {3419    return await this.helper.collection.burn(signer, this.collectionId);3420  }34213422  scheduleAt<T extends UniqueHelper>(3423    executionBlockNumber: number,3424    options: ISchedulerOptions = {},3425  ) {3426    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3427    return new UniqueBaseCollection(this.collectionId, scheduledHelper);3428  }34293430  scheduleAfter<T extends UniqueHelper>(3431    blocksBeforeExecution: number,3432    options: ISchedulerOptions = {},3433  ) {3434    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3435    return new UniqueBaseCollection(this.collectionId, scheduledHelper);3436  }34373438  getSudo<T extends UniqueHelper>() {3439    return new UniqueBaseCollection(this.collectionId, this.helper.getSudo<T>());3440  }3441}344234433444export class UniqueNFTCollection extends UniqueBaseCollection {3445  getTokenObject(tokenId: number) {3446    return new UniqueNFToken(tokenId, this);3447  }34483449  async getTokensByAddress(addressObj: ICrossAccountId) {3450    return await this.helper.nft.getTokensByAddress(this.collectionId, addressObj);3451  }34523453  async getToken(tokenId: number, blockHashAt?: string) {3454    return await this.helper.nft.getToken(this.collectionId, tokenId, [], blockHashAt);3455  }34563457  async getTokenOwner(tokenId: number, blockHashAt?: string) {3458    return await this.helper.nft.getTokenOwner(this.collectionId, tokenId, blockHashAt);3459  }34603461  async getTokenTopmostOwner(tokenId: number, blockHashAt?: string) {3462    return await this.helper.nft.getTokenTopmostOwner(this.collectionId, tokenId, blockHashAt);3463  }34643465  async getTokenChildren(tokenId: number, blockHashAt?: string) {3466    return await this.helper.nft.getTokenChildren(this.collectionId, tokenId, blockHashAt);3467  }34683469  async getPropertyPermissions(propertyKeys: string[] | null = null) {3470    return await this.helper.nft.getPropertyPermissions(this.collectionId, propertyKeys);3471  }34723473  async getTokenProperties(tokenId: number, propertyKeys?: string[] | null) {3474    return await this.helper.nft.getTokenProperties(this.collectionId, tokenId, propertyKeys);3475  }34763477  async getTokenPropertiesConsumedSpace(tokenId: number): Promise<number> {3478    const api = this.helper.getApi();3479    const props = (await api.query.nonfungible.tokenProperties(this.collectionId, tokenId)).toJSON();34803481    return (props! as any).consumedSpace;3482  }34833484  async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId) {3485    return await this.helper.nft.transferToken(signer, this.collectionId, tokenId, addressObj);3486  }34873488  async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3489    return await this.helper.nft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj);3490  }34913492  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId) {3493    return await this.helper.nft.approveToken(signer, this.collectionId, tokenId, toAddressObj);3494  }34953496  async isTokenApproved(tokenId: number, toAddressObj: ICrossAccountId) {3497    return await this.helper.nft.isTokenApproved(this.collectionId, tokenId, toAddressObj);3498  }34993500  async mintToken(signer: TSigner, owner: ICrossAccountId = {Substrate: signer.address}, properties?: IProperty[]) {3501    return await this.helper.nft.mintToken(signer, {collectionId: this.collectionId, owner, properties});3502  }35033504  async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]) {3505    return await this.helper.nft.mintMultipleTokens(signer, this.collectionId, tokens);3506  }35073508  async burnToken(signer: TSigner, tokenId: number) {3509    return await this.helper.nft.burnToken(signer, this.collectionId, tokenId);3510  }35113512  async burnTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId) {3513    return await this.helper.nft.burnTokenFrom(signer, this.collectionId, tokenId, fromAddressObj);3514  }35153516  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[]) {3517    return await this.helper.nft.setTokenProperties(signer, this.collectionId, tokenId, properties);3518  }35193520  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[]) {3521    return await this.helper.nft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys);3522  }35233524  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[]) {3525    return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions);3526  }35273528  async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken) {3529    return await this.helper.nft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj);3530  }35313532  async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3533    return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);3534  }35353536  scheduleAt<T extends UniqueHelper>(3537    executionBlockNumber: number,3538    options: ISchedulerOptions = {},3539  ) {3540    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3541    return new UniqueNFTCollection(this.collectionId, scheduledHelper);3542  }35433544  scheduleAfter<T extends UniqueHelper>(3545    blocksBeforeExecution: number,3546    options: ISchedulerOptions = {},3547  ) {3548    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3549    return new UniqueNFTCollection(this.collectionId, scheduledHelper);3550  }35513552  getSudo<T extends UniqueHelper>() {3553    return new UniqueNFTCollection(this.collectionId, this.helper.getSudo<T>());3554  }3555}355635573558export class UniqueRFTCollection extends UniqueBaseCollection {3559  getTokenObject(tokenId: number) {3560    return new UniqueRFToken(tokenId, this);3561  }35623563  async getToken(tokenId: number, blockHashAt?: string) {3564    return await this.helper.rft.getToken(this.collectionId, tokenId, [], blockHashAt);3565  }35663567  async getTokenOwner(tokenId: number, blockHashAt?: string) {3568    return await this.helper.rft.getTokenOwner(this.collectionId, tokenId, blockHashAt);3569  }35703571  async getTokensByAddress(addressObj: ICrossAccountId) {3572    return await this.helper.rft.getTokensByAddress(this.collectionId, addressObj);3573  }35743575  async getTop10TokenOwners(tokenId: number) {3576    return await this.helper.rft.getTokenTop10Owners(this.collectionId, tokenId);3577  }35783579  async getTokenTopmostOwner(tokenId: number, blockHashAt?: string) {3580    return await this.helper.rft.getTokenTopmostOwner(this.collectionId, tokenId, blockHashAt);3581  }35823583  async getTokenBalance(tokenId: number, addressObj: ICrossAccountId) {3584    return await this.helper.rft.getTokenBalance(this.collectionId, tokenId, addressObj);3585  }35863587  async getTokenTotalPieces(tokenId: number) {3588    return await this.helper.rft.getTokenTotalPieces(this.collectionId, tokenId);3589  }35903591  async getTokenApprovedPieces(tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3592    return await this.helper.rft.getTokenApprovedPieces(this.collectionId, tokenId, toAddressObj, fromAddressObj);3593  }35943595  async getPropertyPermissions(propertyKeys: string[] | null = null) {3596    return await this.helper.rft.getPropertyPermissions(this.collectionId, propertyKeys);3597  }35983599  async getTokenProperties(tokenId: number, propertyKeys?: string[] | null) {3600    return await this.helper.rft.getTokenProperties(this.collectionId, tokenId, propertyKeys);3601  }36023603  async getTokenPropertiesConsumedSpace(tokenId: number): Promise<number> {3604    const api = this.helper.getApi();3605    const props = (await api.query.refungible.tokenProperties(this.collectionId, tokenId)).toJSON();36063607    return (props! as any).consumedSpace;3608  }36093610  async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId, amount=1n) {3611    return await this.helper.rft.transferToken(signer, this.collectionId, tokenId, addressObj, amount);3612  }36133614  async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {3615    return await this.helper.rft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj, amount);3616  }36173618  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {3619    return await this.helper.rft.approveToken(signer, this.collectionId, tokenId, toAddressObj, amount);3620  }36213622  async repartitionToken(signer: TSigner, tokenId: number, amount: bigint) {3623    return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount);3624  }36253626  async mintToken(signer: TSigner, pieces = 1n, owner: ICrossAccountId = {Substrate: signer.address}, properties?: IProperty[]) {3627    return await this.helper.rft.mintToken(signer, {collectionId: this.collectionId, owner, pieces, properties});3628  }36293630  async mintMultipleTokens(signer: TSigner, tokens: {pieces: bigint, owner: ICrossAccountId, properties?: IProperty[]}[]) {3631    return await this.helper.rft.mintMultipleTokens(signer, this.collectionId, tokens);3632  }36333634  async burnToken(signer: TSigner, tokenId: number, amount=1n) {3635    return await this.helper.rft.burnToken(signer, this.collectionId, tokenId, amount);3636  }36373638  async burnTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId,  amount=1n) {3639    return await this.helper.rft.burnTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, amount);3640  }36413642  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[]) {3643    return await this.helper.rft.setTokenProperties(signer, this.collectionId, tokenId, properties);3644  }36453646  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[]) {3647    return await this.helper.rft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys);3648  }36493650  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[]) {3651    return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions);3652  }36533654  async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken) {3655    return await this.helper.rft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj);3656  }36573658  async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3659    return await this.helper.rft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);3660  }36613662  scheduleAt<T extends UniqueHelper>(3663    executionBlockNumber: number,3664    options: ISchedulerOptions = {},3665  ) {3666    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3667    return new UniqueRFTCollection(this.collectionId, scheduledHelper);3668  }36693670  scheduleAfter<T extends UniqueHelper>(3671    blocksBeforeExecution: number,3672    options: ISchedulerOptions = {},3673  ) {3674    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3675    return new UniqueRFTCollection(this.collectionId, scheduledHelper);3676  }36773678  getSudo<T extends UniqueHelper>() {3679    return new UniqueRFTCollection(this.collectionId, this.helper.getSudo<T>());3680  }3681}368236833684export class UniqueFTCollection extends UniqueBaseCollection {3685  async getBalance(addressObj: ICrossAccountId) {3686    return await this.helper.ft.getBalance(this.collectionId, addressObj);3687  }36883689  async getTotalPieces() {3690    return await this.helper.ft.getTotalPieces(this.collectionId);3691  }36923693  async getApprovedTokens(fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3694    return await this.helper.ft.getApprovedTokens(this.collectionId, fromAddressObj, toAddressObj);3695  }36963697  async getTop10Owners() {3698    return await this.helper.ft.getTop10Owners(this.collectionId);3699  }37003701  async mint(signer: TSigner, amount=1n, owner: ICrossAccountId = {Substrate: signer.address}) {3702    return await this.helper.ft.mintTokens(signer, this.collectionId, amount, owner);3703  }37043705  async mintWithOneOwner(signer: TSigner, tokens: {value: bigint}[], owner: ICrossAccountId = {Substrate: signer.address}) {3706    return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, tokens, owner);3707  }37083709  async transfer(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {3710    return await this.helper.ft.transfer(signer, this.collectionId, toAddressObj, amount);3711  }37123713  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {3714    return await this.helper.ft.transferFrom(signer, this.collectionId, fromAddressObj, toAddressObj, amount);3715  }37163717  async burnTokens(signer: TSigner, amount=1n) {3718    return await this.helper.ft.burnTokens(signer, this.collectionId, amount);3719  }37203721  async burnTokensFrom(signer: TSigner, fromAddressObj: ICrossAccountId, amount=1n) {3722    return await this.helper.ft.burnTokensFrom(signer, this.collectionId, fromAddressObj, amount);3723  }37243725  async approveTokens(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {3726    return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);3727  }37283729  scheduleAt<T extends UniqueHelper>(3730    executionBlockNumber: number,3731    options: ISchedulerOptions = {},3732  ) {3733    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3734    return new UniqueFTCollection(this.collectionId, scheduledHelper);3735  }37363737  scheduleAfter<T extends UniqueHelper>(3738    blocksBeforeExecution: number,3739    options: ISchedulerOptions = {},3740  ) {3741    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3742    return new UniqueFTCollection(this.collectionId, scheduledHelper);3743  }37443745  getSudo<T extends UniqueHelper>() {3746    return new UniqueFTCollection(this.collectionId, this.helper.getSudo<T>());3747  }3748}374937503751export class UniqueBaseToken {3752  collection: UniqueNFTCollection | UniqueRFTCollection;3753  collectionId: number;3754  tokenId: number;37553756  constructor(tokenId: number, collection: UniqueNFTCollection | UniqueRFTCollection) {3757    this.collection = collection;3758    this.collectionId = collection.collectionId;3759    this.tokenId = tokenId;3760  }37613762  async getNextSponsored(addressObj: ICrossAccountId) {3763    return await this.collection.getTokenNextSponsored(this.tokenId, addressObj);3764  }37653766  async getProperties(propertyKeys?: string[] | null) {3767    return await this.collection.getTokenProperties(this.tokenId, propertyKeys);3768  }37693770  async getTokenPropertiesConsumedSpace() {3771    return await this.collection.getTokenPropertiesConsumedSpace(this.tokenId);3772  }37733774  async setProperties(signer: TSigner, properties: IProperty[]) {3775    return await this.collection.setTokenProperties(signer, this.tokenId, properties);3776  }37773778  async deleteProperties(signer: TSigner, propertyKeys: string[]) {3779    return await this.collection.deleteTokenProperties(signer, this.tokenId, propertyKeys);3780  }37813782  async doesExist() {3783    return await this.collection.doesTokenExist(this.tokenId);3784  }37853786  nestingAccount() {3787    return this.collection.helper.util.getTokenAccount(this);3788  }37893790  scheduleAt<T extends UniqueHelper>(3791    executionBlockNumber: number,3792    options: ISchedulerOptions = {},3793  ) {3794    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);3795    return new UniqueBaseToken(this.tokenId, scheduledCollection);3796  }37973798  scheduleAfter<T extends UniqueHelper>(3799    blocksBeforeExecution: number,3800    options: ISchedulerOptions = {},3801  ) {3802    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);3803    return new UniqueBaseToken(this.tokenId, scheduledCollection);3804  }38053806  getSudo<T extends UniqueHelper>() {3807    return new UniqueBaseToken(this.tokenId, this.collection.getSudo<T>());3808  }3809}381038113812export class UniqueNFToken extends UniqueBaseToken {3813  collection: UniqueNFTCollection;38143815  constructor(tokenId: number, collection: UniqueNFTCollection) {3816    super(tokenId, collection);3817    this.collection = collection;3818  }38193820  async getData(blockHashAt?: string) {3821    return await this.collection.getToken(this.tokenId, blockHashAt);3822  }38233824  async getOwner(blockHashAt?: string) {3825    return await this.collection.getTokenOwner(this.tokenId, blockHashAt);3826  }38273828  async getTopmostOwner(blockHashAt?: string) {3829    return await this.collection.getTokenTopmostOwner(this.tokenId, blockHashAt);3830  }38313832  async getChildren(blockHashAt?: string) {3833    return await this.collection.getTokenChildren(this.tokenId, blockHashAt);3834  }38353836  async nest(signer: TSigner, toTokenObj: IToken) {3837    return await this.collection.nestToken(signer, this.tokenId, toTokenObj);3838  }38393840  async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3841    return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);3842  }38433844  async transfer(signer: TSigner, addressObj: ICrossAccountId) {3845    return await this.collection.transferToken(signer, this.tokenId, addressObj);3846  }38473848  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3849    return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj);3850  }38513852  async approve(signer: TSigner, toAddressObj: ICrossAccountId) {3853    return await this.collection.approveToken(signer, this.tokenId, toAddressObj);3854  }38553856  async isApproved(toAddressObj: ICrossAccountId) {3857    return await this.collection.isTokenApproved(this.tokenId, toAddressObj);3858  }38593860  async burn(signer: TSigner) {3861    return await this.collection.burnToken(signer, this.tokenId);3862  }38633864  async burnFrom(signer: TSigner, fromAddressObj: ICrossAccountId) {3865    return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj);3866  }38673868  scheduleAt<T extends UniqueHelper>(3869    executionBlockNumber: number,3870    options: ISchedulerOptions = {},3871  ) {3872    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);3873    return new UniqueNFToken(this.tokenId, scheduledCollection);3874  }38753876  scheduleAfter<T extends UniqueHelper>(3877    blocksBeforeExecution: number,3878    options: ISchedulerOptions = {},3879  ) {3880    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);3881    return new UniqueNFToken(this.tokenId, scheduledCollection);3882  }38833884  getSudo<T extends UniqueHelper>() {3885    return new UniqueNFToken(this.tokenId, this.collection.getSudo<T>());3886  }3887}38883889export class UniqueRFToken extends UniqueBaseToken {3890  collection: UniqueRFTCollection;38913892  constructor(tokenId: number, collection: UniqueRFTCollection) {3893    super(tokenId, collection);3894    this.collection = collection;3895  }38963897  async getData(blockHashAt?: string) {3898    return await this.collection.getToken(this.tokenId, blockHashAt);3899  }39003901  async getOwner(blockHashAt?: string) {3902    return await this.collection.getTokenOwner(this.tokenId, blockHashAt);3903  }39043905  async getTop10Owners() {3906    return await this.collection.getTop10TokenOwners(this.tokenId);3907  }39083909  async getTopmostOwner(blockHashAt?: string) {3910    return await this.collection.getTokenTopmostOwner(this.tokenId, blockHashAt);3911  }39123913  async nest(signer: TSigner, toTokenObj: IToken) {3914    return await this.collection.nestToken(signer, this.tokenId, toTokenObj);3915  }39163917  async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3918    return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);3919  }39203921  async getBalance(addressObj: ICrossAccountId) {3922    return await this.collection.getTokenBalance(this.tokenId, addressObj);3923  }39243925  async getTotalPieces() {3926    return await this.collection.getTokenTotalPieces(this.tokenId);3927  }39283929  async getApprovedPieces(fromAddressObj: ICrossAccountId, toAccountObj: ICrossAccountId) {3930    return await this.collection.getTokenApprovedPieces(this.tokenId, fromAddressObj, toAccountObj);3931  }39323933  async transfer(signer: TSigner, addressObj: ICrossAccountId, amount=1n) {3934    return await this.collection.transferToken(signer, this.tokenId, addressObj, amount);3935  }39363937  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {3938    return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj, amount);3939  }39403941  async approve(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {3942    return await this.collection.approveToken(signer, this.tokenId, toAddressObj, amount);3943  }39443945  async repartition(signer: TSigner, amount: bigint) {3946    return await this.collection.repartitionToken(signer, this.tokenId, amount);3947  }39483949  async burn(signer: TSigner, amount=1n) {3950    return await this.collection.burnToken(signer, this.tokenId, amount);3951  }39523953  async burnFrom(signer: TSigner, fromAddressObj: ICrossAccountId, amount=1n) {3954    return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj, amount);3955  }39563957  scheduleAt<T extends UniqueHelper>(3958    executionBlockNumber: number,3959    options: ISchedulerOptions = {},3960  ) {3961    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);3962    return new UniqueRFToken(this.tokenId, scheduledCollection);3963  }39643965  scheduleAfter<T extends UniqueHelper>(3966    blocksBeforeExecution: number,3967    options: ISchedulerOptions = {},3968  ) {3969    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);3970    return new UniqueRFToken(this.tokenId, scheduledCollection);3971  }39723973  getSudo<T extends UniqueHelper>() {3974    return new UniqueRFToken(this.tokenId, this.collection.getSudo<T>());3975  }3976}
after · tests/src/util/playgrounds/unique.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034/* eslint-disable @typescript-eslint/no-var-requires */5/* eslint-disable function-call-argument-newline */6/* eslint-disable no-prototype-builtins */78import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';9import {SignerOptions} from '@polkadot/api/types/submittable';10import {ApiInterfaceEvents} from '@polkadot/api/types';11import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';12import {IKeyringPair} from '@polkadot/types/types';13import {hexToU8a} from '@polkadot/util/hex';14import {u8aConcat} from '@polkadot/util/u8a';15import {16  IApiListeners,17  IBlock,18  IEvent,19  IChainProperties,20  ICollectionCreationOptions,21  ICollectionLimits,22  ICollectionPermissions,23  ICrossAccountId,24  ICrossAccountIdLower,25  ILogger,26  INestingPermissions,27  IProperty,28  IStakingInfo,29  ISchedulerOptions,30  ISubstrateBalance,31  IToken,32  ITokenPropertyPermission,33  ITransactionResult,34  IUniqueHelperLog,35  TApiAllowedListeners,36  TEthereumAccount,37  TSigner,38  TSubstrateAccount,39  TNetworks,40  IForeignAssetMetadata,41  AcalaAssetMetadata,42  MoonbeamAssetInfo,43  DemocracyStandardAccountVote,44  IEthCrossAccountId,45} from './types';46import {RuntimeDispatchInfo} from '@polkadot/types/interfaces';47import type {Vec} from '@polkadot/types-codec';48import {FrameSystemEventRecord} from '@polkadot/types/lookup';4950export class CrossAccountId implements ICrossAccountId {51  Substrate?: TSubstrateAccount;52  Ethereum?: TEthereumAccount;5354  constructor(account: ICrossAccountId) {55    if (account.Substrate) this.Substrate = account.Substrate;56    if (account.Ethereum) this.Ethereum = account.Ethereum;57  }5859  static fromKeyring(account: IKeyringPair, domain: 'Substrate' | 'Ethereum' = 'Substrate') {60    switch (domain) {61      case 'Substrate': return new CrossAccountId({Substrate: account.address});62      case 'Ethereum': return new CrossAccountId({Substrate: account.address}).toEthereum();63    }64  }6566  static fromLowerCaseKeys(address: ICrossAccountIdLower): CrossAccountId {67    return new CrossAccountId({Substrate: address.substrate, Ethereum: address.ethereum});68  }6970  static normalizeSubstrateAddress(address: TSubstrateAccount, ss58Format = 42): TSubstrateAccount {71    return encodeAddress(decodeAddress(address), ss58Format);72  }7374  static withNormalizedSubstrate(address: TSubstrateAccount, ss58Format = 42): CrossAccountId {75    return new CrossAccountId({Substrate: CrossAccountId.normalizeSubstrateAddress(address, ss58Format)});76  }7778  withNormalizedSubstrate(ss58Format = 42): CrossAccountId {79    if (this.Substrate) return CrossAccountId.withNormalizedSubstrate(this.Substrate, ss58Format);80    return this;81  }8283  static translateSubToEth(address: TSubstrateAccount): TEthereumAccount {84    return nesting.toChecksumAddress('0x' + Array.from(addressToEvm(address), i => i.toString(16).padStart(2, '0')).join(''));85  }8687  toEthereum(): CrossAccountId {88    if (this.Substrate) return new CrossAccountId({Ethereum: CrossAccountId.translateSubToEth(this.Substrate)});89    return this;90  }9192  static translateEthToSub(address: TEthereumAccount, ss58Format?: number): TSubstrateAccount {93    return evmToAddress(address, ss58Format);94  }9596  toSubstrate(ss58Format?: number): CrossAccountId {97    if (this.Ethereum) return new CrossAccountId({Substrate: CrossAccountId.translateEthToSub(this.Ethereum, ss58Format)});98    return this;99  }100101  toLowerCase(): CrossAccountId {102    if (this.Substrate) this.Substrate = this.Substrate.toLowerCase();103    if (this.Ethereum) this.Ethereum = this.Ethereum.toLowerCase();104    return this;105  }106}107108const nesting = {109  toChecksumAddress(address: string): string {110    if (typeof address === 'undefined') return '';111112    if(!/^(0x)?[0-9a-f]{40}$/i.test(address)) throw new Error(`Given address "${address}" is not a valid Ethereum address.`);113114    address = address.toLowerCase().replace(/^0x/i,'');115    const addressHash = keccakAsHex(address).replace(/^0x/i,'');116    const checksumAddress = ['0x'];117118    for (let i = 0; i < address.length; i++) {119      // If ith character is 8 to f then make it uppercase120      if (parseInt(addressHash[i], 16) > 7) {121        checksumAddress.push(address[i].toUpperCase());122      } else {123        checksumAddress.push(address[i]);124      }125    }126    return checksumAddress.join('');127  },128  tokenIdToAddress(collectionId: number, tokenId: number) {129    return this.toChecksumAddress(`0xf8238ccfff8ed887463fd5e0${collectionId.toString(16).padStart(8, '0')}${tokenId.toString(16).padStart(8, '0')}`);130  },131};132133class UniqueUtil {134  static transactionStatus = {135    NOT_READY: 'NotReady',136    FAIL: 'Fail',137    SUCCESS: 'Success',138  };139140  static chainLogType = {141    EXTRINSIC: 'extrinsic',142    RPC: 'rpc',143  };144145  static getTokenAccount(token: IToken): CrossAccountId {146    return new CrossAccountId({Ethereum: this.getTokenAddress(token)});147  }148149  static getTokenAddress(token: IToken): string {150    return nesting.tokenIdToAddress(token.collectionId, token.tokenId);151  }152153  static getDefaultLogger(): ILogger {154    return {155      log(msg: any, level = 'INFO') {156        console[level.toLocaleLowerCase() === 'error' ? 'error' : 'log'](...(Array.isArray(msg) ? msg : [msg]));157      },158      level: {159        ERROR: 'ERROR',160        WARNING: 'WARNING',161        INFO: 'INFO',162      },163    };164  }165166  static vec2str(arr: string[] | number[]) {167    return arr.map(x => String.fromCharCode(parseInt(x.toString()))).join('');168  }169170  static str2vec(string: string) {171    if (typeof string !== 'string') return string;172    return Array.from(string).map(x => x.charCodeAt(0));173  }174175  static fromSeed(seed: string, ss58Format = 42) {176    const keyring = new Keyring({type: 'sr25519', ss58Format});177    return keyring.addFromUri(seed);178  }179180  static extractCollectionIdFromCreationResult(creationResult: ITransactionResult): number {181    if (creationResult.status !== this.transactionStatus.SUCCESS) {182      throw Error('Unable to create collection!');183    }184185    let collectionId = null;186    creationResult.result.events.forEach(({event: {data, method, section}}) => {187      if ((section === 'common') && (method === 'CollectionCreated')) {188        collectionId = parseInt(data[0].toString(), 10);189      }190    });191192    if (collectionId === null) {193      throw Error('No CollectionCreated event was found!');194    }195196    return collectionId;197  }198199  static extractTokensFromCreationResult(creationResult: ITransactionResult): {200    success: boolean,201    tokens: {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[],202  } {203    if (creationResult.status !== this.transactionStatus.SUCCESS) {204      throw Error('Unable to create tokens!');205    }206    let success = false;207    const tokens = [] as {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[];208    creationResult.result.events.forEach(({event: {data, method, section}}) => {209      if (method === 'ExtrinsicSuccess') {210        success = true;211      } else if ((section === 'common') && (method === 'ItemCreated')) {212        tokens.push({213          collectionId: parseInt(data[0].toString(), 10),214          tokenId: parseInt(data[1].toString(), 10),215          owner: data[2].toHuman(),216          amount: data[3].toBigInt(),217        });218      }219    });220    return {success, tokens};221  }222223  static extractTokensFromBurnResult(burnResult: ITransactionResult): {224    success: boolean,225    tokens: {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[],226  } {227    if (burnResult.status !== this.transactionStatus.SUCCESS) {228      throw Error('Unable to burn tokens!');229    }230    let success = false;231    const tokens = [] as {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[];232    burnResult.result.events.forEach(({event: {data, method, section}}) => {233      if (method === 'ExtrinsicSuccess') {234        success = true;235      } else if ((section === 'common') && (method === 'ItemDestroyed')) {236        tokens.push({237          collectionId: parseInt(data[0].toString(), 10),238          tokenId: parseInt(data[1].toString(), 10),239          owner: data[2].toHuman(),240          amount: data[3].toBigInt(),241        });242      }243    });244    return {success, tokens};245  }246247  static findCollectionInEvents(events: {event: IEvent}[], collectionId: number, expectedSection: string, expectedMethod: string): boolean {248    let eventId = null;249    events.forEach(({event: {data, method, section}}) => {250      if ((section === expectedSection) && (method === expectedMethod)) {251        eventId = parseInt(data[0].toString(), 10);252      }253    });254255    if (eventId === null) {256      throw Error(`No ${expectedMethod} event was found!`);257    }258    return eventId === collectionId;259  }260261  static isTokenTransferSuccess(events: {event: IEvent}[], collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {262    const normalizeAddress = (address: string | ICrossAccountId) => {263      if(typeof address === 'string') return address;264      const obj = {} as any;265      Object.keys(address).forEach(k => {266        obj[k.toLocaleLowerCase()] = address[k as 'Substrate' | 'Ethereum'];267      });268      if(obj.substrate) return CrossAccountId.withNormalizedSubstrate(obj.substrate);269      if(obj.ethereum) return CrossAccountId.fromLowerCaseKeys(obj).toLowerCase();270      return address;271    };272    let transfer = {collectionId: null, tokenId: null, from: null, to: null, amount: 1} as any;273    events.forEach(({event: {data, method, section}}) => {274      if ((section === 'common') && (method === 'Transfer')) {275        const hData = (data as any).toJSON();276        transfer = {277          collectionId: hData[0],278          tokenId: hData[1],279          from: normalizeAddress(hData[2]),280          to: normalizeAddress(hData[3]),281          amount: BigInt(hData[4]),282        };283      }284    });285    let isSuccess = parseInt(collectionId.toString()) === transfer.collectionId && parseInt(tokenId.toString()) === transfer.tokenId;286    isSuccess = isSuccess && JSON.stringify(normalizeAddress(fromAddressObj)) === JSON.stringify(transfer.from);287    isSuccess = isSuccess && JSON.stringify(normalizeAddress(toAddressObj)) === JSON.stringify(transfer.to);288    isSuccess = isSuccess && amount === transfer.amount;289    return isSuccess;290  }291292  static bigIntToDecimals(number: bigint, decimals = 18) {293    const numberStr = number.toString();294    const dotPos = numberStr.length - decimals;295296    if (dotPos <= 0) {297      return '0.' + '0'.repeat(Math.abs(dotPos)) + numberStr;298    } else {299      const intPart = numberStr.substring(0, dotPos);300      const fractPart = numberStr.substring(dotPos);301      return intPart + '.' + fractPart;302    }303  }304}305306class UniqueEventHelper {307  private static extractIndex(index: any): [number, number] | string {308    if(index.toRawType() === '[u8;2]') return [index[0], index[1]];309    return index.toJSON();310  }311312  private static extractSub(data: any, subTypes: any): {[key: string]: any} {313    let obj: any = {};314    let index = 0;315316    if (data.entries) {317      for(const [key, value] of data.entries()) {318        obj[key] = this.extractData(value, subTypes[index]);319        index++;320      }321    } else obj = data.toJSON();322323    return obj;324  }325326  private static toHuman(data: any) {327    return data && data.toHuman ? data.toHuman() : `${data}`;328  }329330  private static extractData(data: any, type: any): any {331    if(!type) return this.toHuman(data);332    if (['u16', 'u32'].indexOf(type.type) > -1) return data.toNumber();333    if (['u64', 'u128', 'u256'].indexOf(type.type) > -1) return data.toBigInt();334    if(type.hasOwnProperty('sub')) return this.extractSub(data, type.sub);335    return this.toHuman(data);336  }337338  public static extractEvents(events: {event: any, phase: any}[]): IEvent[] {339    const parsedEvents: IEvent[] = [];340341    events.forEach((record) => {342      const {event, phase} = record;343      const types = event.typeDef;344345      const eventData: IEvent = {346        section: event.section.toString(),347        method: event.method.toString(),348        index: this.extractIndex(event.index),349        data: [],350        phase: phase.toJSON(),351      };352353      event.data.forEach((val: any, index: number) => {354        eventData.data.push(this.extractData(val, types[index]));355      });356357      parsedEvents.push(eventData);358    });359360    return parsedEvents;361  }362}363364export class ChainHelperBase {365  helperBase: any;366367  transactionStatus = UniqueUtil.transactionStatus;368  chainLogType = UniqueUtil.chainLogType;369  util: typeof UniqueUtil;370  eventHelper: typeof UniqueEventHelper;371  logger: ILogger;372  api: ApiPromise | null;373  forcedNetwork: TNetworks | null;374  network: TNetworks | null;375  wsEndpoint: string | null;376  chainLog: IUniqueHelperLog[];377  children: ChainHelperBase[];378  address: AddressGroup;379  chain: ChainGroup;380381  constructor(logger?: ILogger, helperBase?: any) {382    this.helperBase = helperBase;383384    this.util = UniqueUtil;385    this.eventHelper = UniqueEventHelper;386    if (typeof logger == 'undefined') logger = this.util.getDefaultLogger();387    this.logger = logger;388    this.api = null;389    this.forcedNetwork = null;390    this.network = null;391    this.wsEndpoint = null;392    this.chainLog = [];393    this.children = [];394    this.address = new AddressGroup(this);395    this.chain = new ChainGroup(this);396  }397398  clone(helperCls: ChainHelperBaseConstructor, options: {[key: string]: any} = {}) {399    Object.setPrototypeOf(helperCls.prototype, this);400    const newHelper = new helperCls(this.logger, options);401402    newHelper.api = this.api;403    newHelper.network = this.network;404    newHelper.forceNetwork = this.forceNetwork;405406    this.children.push(newHelper);407408    return newHelper;409  }410411  getEndpoint(): string {412    if (this.wsEndpoint === null) throw Error('No connection was established');413    return this.wsEndpoint;414  }415416  getApi(): ApiPromise {417    if(this.api === null) throw Error('API not initialized');418    return this.api;419  }420421  async subscribeEvents(expectedEvents: {section: string, names: string[]}[]) {422    const collectedEvents: IEvent[] = [];423    const unsubscribe = await this.getApi().query.system.events((events: Vec<FrameSystemEventRecord>) => {424      const ievents = this.eventHelper.extractEvents(events);425      ievents.forEach((event) => {426        expectedEvents.forEach((e => {427          if (event.section === e.section && e.names.includes(event.method)) {428            collectedEvents.push(event);429          }430        }));431      });432    });433    return {unsubscribe: unsubscribe as any, collectedEvents};434  }435436  clearChainLog(): void {437    this.chainLog = [];438  }439440  forceNetwork(value: TNetworks): void {441    this.forcedNetwork = value;442  }443444  async connect(wsEndpoint: string, listeners?: IApiListeners) {445    if (this.api !== null) throw Error('Already connected');446    const {api, network} = await ChainHelperBase.createConnection(wsEndpoint, listeners, this.forcedNetwork);447    this.wsEndpoint = wsEndpoint;448    this.api = api;449    this.network = network;450  }451452  async disconnect() {453    for (const child of this.children) {454      child.clearApi();455    }456457    if (this.api === null) return;458    await this.api.disconnect();459    this.clearApi();460  }461462  clearApi() {463    this.api = null;464    this.network = null;465  }466467  static async detectNetwork(api: ApiPromise): Promise<TNetworks> {468    const spec = (await api.query.system.lastRuntimeUpgrade()).toJSON() as any;469    const xcmChains = ['rococo', 'westend', 'westmint', 'acala', 'karura', 'moonbeam', 'moonriver'];470471    if(xcmChains.indexOf(spec.specName) > -1) return spec.specName;472473    if(['quartz', 'unique'].indexOf(spec.specName) > -1) return spec.specName;474    return 'opal';475  }476477  static async detectNetworkByWsEndpoint(wsEndpoint: string): Promise<TNetworks> {478    const api = new ApiPromise({provider: new WsProvider(wsEndpoint)});479    await api.isReady;480481    const network = await this.detectNetwork(api);482483    await api.disconnect();484485    return network;486  }487488  static async createConnection(wsEndpoint: string, listeners?: IApiListeners, network?: TNetworks | null): Promise<{489    api: ApiPromise;490    network: TNetworks;491  }> {492    if(typeof network === 'undefined' || network === null) network = 'opal';493    const supportedRPC = {494      opal: {495        unique: require('@unique-nft/opal-testnet-types/definitions').unique.rpc,496      },497      quartz: {498        unique: require('@unique-nft/quartz-mainnet-types/definitions').unique.rpc,499      },500      unique: {501        unique: require('@unique-nft/unique-mainnet-types/definitions').unique.rpc,502      },503      rococo: {},504      westend: {},505      moonbeam: {},506      moonriver: {},507      acala: {},508      karura: {},509      westmint: {},510    };511    if(!supportedRPC.hasOwnProperty(network)) network = await this.detectNetworkByWsEndpoint(wsEndpoint);512    const rpc = supportedRPC[network];513514    // TODO: investigate how to replace rpc in runtime515    // api._rpcCore.addUserInterfaces(rpc);516517    const api = new ApiPromise({provider: new WsProvider(wsEndpoint), rpc});518519    await api.isReadyOrError;520521    if (typeof listeners === 'undefined') listeners = {};522    for (const event of ['connected', 'disconnected', 'error', 'ready', 'decorated']) {523      if (!listeners.hasOwnProperty(event) || typeof listeners[event as TApiAllowedListeners] === 'undefined') continue;524      api.on(event as ApiInterfaceEvents, listeners[event as TApiAllowedListeners] as (...args: any[]) => any);525    }526527    return {api, network};528  }529530  getTransactionStatus(data: {events: {event: IEvent}[], status: any}) {531    const {events, status} = data;532    if (status.isReady) {533      return this.transactionStatus.NOT_READY;534    }535    if (status.isBroadcast) {536      return this.transactionStatus.NOT_READY;537    }538    if (status.isInBlock || status.isFinalized) {539      const errors = events.filter(e => e.event.method === 'ExtrinsicFailed');540      if (errors.length > 0) {541        return this.transactionStatus.FAIL;542      }543      if (events.filter(e => e.event.method === 'ExtrinsicSuccess').length > 0) {544        return this.transactionStatus.SUCCESS;545      }546    }547548    return this.transactionStatus.FAIL;549  }550551  signTransaction(sender: TSigner, transaction: any, options: Partial<SignerOptions> | null = null, label = 'transaction') {552    const sign = (callback: any) => {553      if(options !== null) return transaction.signAndSend(sender, options, callback);554      return transaction.signAndSend(sender, callback);555    };556    // eslint-disable-next-line no-async-promise-executor557    return new Promise(async (resolve, reject) => {558      try {559        const unsub = await sign((result: any) => {560          const status = this.getTransactionStatus(result);561562          if (status === this.transactionStatus.SUCCESS) {563            this.logger.log(`${label} successful`);564            unsub();565            resolve({result, status, blockHash: result.status.asInBlock.toHuman()});566          } else if (status === this.transactionStatus.FAIL) {567            let moduleError = null;568569            if (result.hasOwnProperty('dispatchError')) {570              const dispatchError = result['dispatchError'];571572              if (dispatchError) {573                if (dispatchError.isModule) {574                  const modErr = dispatchError.asModule;575                  const errorMeta = dispatchError.registry.findMetaError(modErr);576577                  moduleError = `${errorMeta.section}.${errorMeta.name}`;578                } else {579                  moduleError = dispatchError.toHuman();580                }581              } else {582                this.logger.log(result, this.logger.level.ERROR);583              }584            }585586            this.logger.log(`Something went wrong with ${label}. Status: ${status}`, this.logger.level.ERROR);587            unsub();588            reject({status, moduleError, result});589          }590        });591      } catch (e) {592        this.logger.log(e, this.logger.level.ERROR);593        reject(e);594      }595    });596  }597598  async signTransactionWithoutSending(signer: TSigner, tx: any) {599    const api = this.getApi();600    const signingInfo = await api.derive.tx.signingInfo(signer.address);601602    tx.sign(signer, {603      blockHash: api.genesisHash,604      genesisHash: api.genesisHash,605      runtimeVersion: api.runtimeVersion,606      nonce: signingInfo.nonce,607    });608609    return tx.toHex();610  }611612  async getPaymentInfo(signer: TSigner, tx: any, len: number | null) {613    const api = this.getApi();614    const signingInfo = await api.derive.tx.signingInfo(signer.address);615616    // We need to sign the tx because617    // unsigned transactions does not have an inclusion fee618    tx.sign(signer, {619      blockHash: api.genesisHash,620      genesisHash: api.genesisHash,621      runtimeVersion: api.runtimeVersion,622      nonce: signingInfo.nonce,623    });624625    if (len === null) {626      return (await this.callRpc('api.rpc.payment.queryInfo', [tx.toHex()])) as RuntimeDispatchInfo;627    } else {628      return (await api.call.transactionPaymentApi.queryInfo(tx, len)) as RuntimeDispatchInfo;629    }630  }631632  constructApiCall(apiCall: string, params: any[]) {633    if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);634    let call = this.getApi() as any;635    for(const part of apiCall.slice(4).split('.')) {636      call = call[part];637      if (!call) {638        const advice = part.includes('_') ? ' Looks like it needs to be converted to camel case.' : '';639        throw Error(`Function ${part} of api call ${apiCall} not found.${advice}`);640      }641    }642    return call(...params);643  }644645  async executeExtrinsic(sender: TSigner, extrinsic: string, params: any[], expectSuccess=true, options: Partial<SignerOptions>|null = null/*, failureMessage='expected success'*/) {646    if(this.api === null) throw Error('API not initialized');647    if(!extrinsic.startsWith('api.tx.')) throw Error(`${extrinsic} is not transaction`);648649    const startTime = (new Date()).getTime();650    let result: ITransactionResult;651    let events: IEvent[] = [];652    try {653      result = await this.signTransaction(sender, this.constructApiCall(extrinsic, params), options, extrinsic) as ITransactionResult;654      events = this.eventHelper.extractEvents(result.result.events);655      const errorEvent = events.find((event) => event.method == 'ExecutedFailed' || event.method == 'CreatedFailed');656      if (errorEvent)657        throw Error(errorEvent.method + ': ' + extrinsic);658    }659    catch(e) {660      if(!(e as object).hasOwnProperty('status')) throw e;661      result = e as ITransactionResult;662    }663664    const endTime = (new Date()).getTime();665666    const log = {667      executedAt: endTime,668      executionTime: endTime - startTime,669      type: this.chainLogType.EXTRINSIC,670      status: result.status,671      call: extrinsic,672      signer: this.getSignerAddress(sender),673      params,674    } as IUniqueHelperLog;675676    let errorMessage = '';677678    if(result.status !== this.transactionStatus.SUCCESS) {679      if (result.moduleError) {680        errorMessage = typeof result.moduleError === 'string'681          ? result.moduleError682          : `${Object.keys(result.moduleError)[0]}: ${Object.values(result.moduleError)[0]}`;683        log.moduleError = errorMessage;684      }685      else if (result.result.dispatchError) log.dispatchError = result.result.dispatchError;686    }687    if(events.length > 0) log.events = events;688689    this.chainLog.push(log);690691    if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) {692      if (result.moduleError) throw Error(`${errorMessage}`);693      else if (result.result.dispatchError) throw Error(JSON.stringify(result.result.dispatchError));694    }695    return result;696  }697698  async callRpc(rpc: string, params?: any[]) {699    if(typeof params === 'undefined') params = [];700    if(this.api === null) throw Error('API not initialized');701    if(!rpc.startsWith('api.rpc.') && !rpc.startsWith('api.query.')) throw Error(`${rpc} is not RPC call`);702703    const startTime = (new Date()).getTime();704    let result;705    let error = null;706    const log = {707      type: this.chainLogType.RPC,708      call: rpc,709      params,710    } as IUniqueHelperLog;711712    try {713      result = await this.constructApiCall(rpc, params);714    }715    catch(e) {716      error = e;717    }718719    const endTime = (new Date()).getTime();720721    log.executedAt = endTime;722    log.status = (error === null ? this.transactionStatus.SUCCESS : this.transactionStatus.FAIL) as 'Fail' | 'Success';723    log.executionTime = endTime - startTime;724725    this.chainLog.push(log);726727    if(error !== null) throw error;728729    return result;730  }731732  getSignerAddress(signer: IKeyringPair | string): string {733    if(typeof signer === 'string') return signer;734    return signer.address;735  }736737  fetchAllPalletNames(): string[] {738    if(this.api === null) throw Error('API not initialized');739    return this.api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());740  }741742  fetchMissingPalletNames(requiredPallets: string[]): string[] {743    const palletNames = this.fetchAllPalletNames();744    return requiredPallets.filter(p => !palletNames.includes(p));745  }746}747748749class HelperGroup<T extends ChainHelperBase> {750  helper: T;751752  constructor(uniqueHelper: T) {753    this.helper = uniqueHelper;754  }755}756757758class CollectionGroup extends HelperGroup<UniqueHelper> {759  /**760 * Get number of blocks when sponsored transaction is available.761 *762 * @param collectionId ID of collection763 * @param tokenId ID of token764 * @param addressObj address for which the sponsorship is checked765 * @example await getTokenNextSponsored(1, 2, {Substrate: '5DfhbVfww7ThF8q6f3...'});766 * @returns number of blocks or null if sponsorship hasn't been set767 */768  async getTokenNextSponsored(collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<number | null> {769    return (await this.helper.callRpc('api.rpc.unique.nextSponsored', [collectionId, addressObj, tokenId])).toJSON();770  }771772  /**773   * Get the number of created collections.774   *775   * @returns number of created collections776   */777  async getTotalCount(): Promise<number> {778    return (await this.helper.callRpc('api.rpc.unique.collectionStats')).created.toNumber();779  }780781  /**782   * Get information about the collection with additional data,783   * including the number of tokens it contains, its administrators,784   * the normalized address of the collection's owner, and decoded name and description.785   *786   * @param collectionId ID of collection787   * @example await getData(2)788   * @returns collection information object789   */790  async getData(collectionId: number): Promise<{791    id: number;792    name: string;793    description: string;794    tokensCount: number;795    admins: CrossAccountId[];796    normalizedOwner: TSubstrateAccount;797    raw: any798  } | null> {799    const collection = await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId]);800    const humanCollection = collection.toHuman(), collectionData = {801      id: collectionId, name: null, description: null, tokensCount: 0, admins: [],802      raw: humanCollection,803    } as any, jsonCollection = collection.toJSON();804    if (humanCollection === null) return null;805    collectionData.raw.limits = jsonCollection.limits;806    collectionData.raw.permissions = jsonCollection.permissions;807    collectionData.normalizedOwner = this.helper.address.normalizeSubstrate(collectionData.raw.owner);808    for (const key of ['name', 'description']) {809      collectionData[key] = this.helper.util.vec2str(humanCollection[key]);810    }811812    collectionData.tokensCount = (['RFT', 'NFT'].includes(humanCollection.mode))813      ? await this.helper[humanCollection.mode.toLocaleLowerCase() as 'nft' | 'rft'].getLastTokenId(collectionId)814      : 0;815    collectionData.admins = await this.getAdmins(collectionId);816817    return collectionData;818  }819820  /**821   * Get the addresses of the collection's administrators, optionally normalized.822   *823   * @param collectionId ID of collection824   * @param normalize whether to normalize the addresses to the default ss58 format825   * @example await getAdmins(1)826   * @returns array of administrators827   */828  async getAdmins(collectionId: number, normalize = false): Promise<CrossAccountId[]> {829    const admins = (await this.helper.callRpc('api.rpc.unique.adminlist', [collectionId])).toHuman();830831    return normalize832      ? admins.map((address: CrossAccountId) => address.withNormalizedSubstrate())833      : admins;834  }835836  /**837   * Get the addresses added to the collection allow-list, optionally normalized.838   * @param collectionId ID of collection839   * @param normalize whether to normalize the addresses to the default ss58 format840   * @example await getAllowList(1)841   * @returns array of allow-listed addresses842   */843  async getAllowList(collectionId: number, normalize = false): Promise<CrossAccountId[]> {844    const allowListed = (await this.helper.callRpc('api.rpc.unique.allowlist', [collectionId])).toHuman();845    return normalize846      ? allowListed.map((address: CrossAccountId) => address.withNormalizedSubstrate())847      : allowListed;848  }849850  /**851   * Get the effective limits of the collection instead of null for default values852   *853   * @param collectionId ID of collection854   * @example await getEffectiveLimits(2)855   * @returns object of collection limits856   */857  async getEffectiveLimits(collectionId: number): Promise<ICollectionLimits> {858    return (await this.helper.callRpc('api.rpc.unique.effectiveCollectionLimits', [collectionId])).toJSON();859  }860861  /**862   * Burns the collection if the signer has sufficient permissions and collection is empty.863   *864   * @param signer keyring of signer865   * @param collectionId ID of collection866   * @example await helper.collection.burn(aliceKeyring, 3);867   * @returns ```true``` if extrinsic success, otherwise ```false```868   */869  async burn(signer: TSigner, collectionId: number): Promise<boolean> {870    const result = await this.helper.executeExtrinsic(871      signer,872      'api.tx.unique.destroyCollection', [collectionId],873      true,874    );875876    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionDestroyed');877  }878879  /**880   * Sets the sponsor for the collection (Requires the Substrate address). Needs confirmation by the sponsor.881   *882   * @param signer keyring of signer883   * @param collectionId ID of collection884   * @param sponsorAddress Sponsor substrate address885   * @example setSponsor(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")886   * @returns ```true``` if extrinsic success, otherwise ```false```887   */888  async setSponsor(signer: TSigner, collectionId: number, sponsorAddress: TSubstrateAccount): Promise<boolean> {889    const result = await this.helper.executeExtrinsic(890      signer,891      'api.tx.unique.setCollectionSponsor', [collectionId, sponsorAddress],892      true,893    );894895    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionSponsorSet');896  }897898  /**899   * Confirms consent to sponsor the collection on behalf of the signer.900   *901   * @param signer keyring of signer902   * @param collectionId ID of collection903   * @example confirmSponsorship(aliceKeyring, 10)904   * @returns ```true``` if extrinsic success, otherwise ```false```905   */906  async confirmSponsorship(signer: TSigner, collectionId: number): Promise<boolean> {907    const result = await this.helper.executeExtrinsic(908      signer,909      'api.tx.unique.confirmSponsorship', [collectionId],910      true,911    );912913    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'SponsorshipConfirmed');914  }915916  /**917   * Removes the sponsor of a collection, regardless if it consented or not.918   *919   * @param signer keyring of signer920   * @param collectionId ID of collection921   * @example removeSponsor(aliceKeyring, 10)922   * @returns ```true``` if extrinsic success, otherwise ```false```923   */924  async removeSponsor(signer: TSigner, collectionId: number): Promise<boolean> {925    const result = await this.helper.executeExtrinsic(926      signer,927      'api.tx.unique.removeCollectionSponsor', [collectionId],928      true,929    );930931    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionSponsorRemoved');932  }933934  /**935   * Sets the limits of the collection. At least one limit must be specified for a correct call.936   *937   * @param signer keyring of signer938   * @param collectionId ID of collection939   * @param limits collection limits object940   * @example941   * await setLimits(942   *   aliceKeyring,943   *   10,944   *   {945   *     sponsorTransferTimeout: 0,946   *     ownerCanDestroy: false947   *   }948   * )949   * @returns ```true``` if extrinsic success, otherwise ```false```950   */951  async setLimits(signer: TSigner, collectionId: number, limits: ICollectionLimits): Promise<boolean> {952    const result = await this.helper.executeExtrinsic(953      signer,954      'api.tx.unique.setCollectionLimits', [collectionId, limits],955      true,956    );957958    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionLimitSet');959  }960961  /**962   * Changes the owner of the collection to the new Substrate address.963   *964   * @param signer keyring of signer965   * @param collectionId ID of collection966   * @param ownerAddress substrate address of new owner967   * @example changeOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")968   * @returns ```true``` if extrinsic success, otherwise ```false```969   */970  async changeOwner(signer: TSigner, collectionId: number, ownerAddress: TSubstrateAccount): Promise<boolean> {971    const result = await this.helper.executeExtrinsic(972      signer,973      'api.tx.unique.changeCollectionOwner', [collectionId, ownerAddress],974      true,975    );976977    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionOwnerChanged');978  }979980  /**981   * Adds a collection administrator.982   *983   * @param signer keyring of signer984   * @param collectionId ID of collection985   * @param adminAddressObj Administrator address (substrate or ethereum)986   * @example addAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})987   * @returns ```true``` if extrinsic success, otherwise ```false```988   */989  async addAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {990    const result = await this.helper.executeExtrinsic(991      signer,992      'api.tx.unique.addCollectionAdmin', [collectionId, adminAddressObj],993      true,994    );995996    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionAdminAdded');997  }998999  /**1000   * Removes a collection administrator.1001   *1002   * @param signer keyring of signer1003   * @param collectionId ID of collection1004   * @param adminAddressObj Administrator address (substrate or ethereum)1005   * @example removeAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})1006   * @returns ```true``` if extrinsic success, otherwise ```false```1007   */1008  async removeAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {1009    const result = await this.helper.executeExtrinsic(1010      signer,1011      'api.tx.unique.removeCollectionAdmin', [collectionId, adminAddressObj],1012      true,1013    );10141015    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionAdminRemoved');1016  }10171018  /**1019   * Check if user is in allow list.1020   *1021   * @param collectionId ID of collection1022   * @param user Account to check1023   * @example await getAdmins(1)1024   * @returns is user in allow list1025   */1026  async allowed(collectionId: number, user: ICrossAccountId): Promise<boolean> {1027    return (await this.helper.callRpc('api.rpc.unique.allowed', [collectionId, user])).toJSON();1028  }10291030  /**1031   * Adds an address to allow list1032   * @param signer keyring of signer1033   * @param collectionId ID of collection1034   * @param addressObj address to add to the allow list1035   * @returns ```true``` if extrinsic success, otherwise ```false```1036   */1037  async addToAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {1038    const result = await this.helper.executeExtrinsic(1039      signer,1040      'api.tx.unique.addToAllowList', [collectionId, addressObj],1041      true,1042    );10431044    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'AllowListAddressAdded');1045  }10461047  /**1048   * Removes an address from allow list1049   *1050   * @param signer keyring of signer1051   * @param collectionId ID of collection1052   * @param addressObj address to remove from the allow list1053   * @returns ```true``` if extrinsic success, otherwise ```false```1054   */1055  async removeFromAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {1056    const result = await this.helper.executeExtrinsic(1057      signer,1058      'api.tx.unique.removeFromAllowList', [collectionId, addressObj],1059      true,1060    );10611062    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'AllowListAddressRemoved');1063  }10641065  /**1066   * Sets onchain permissions for selected collection.1067   *1068   * @param signer keyring of signer1069   * @param collectionId ID of collection1070   * @param permissions collection permissions object1071   * @example setPermissions(aliceKeyring, 10, {access:'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true}});1072   * @returns ```true``` if extrinsic success, otherwise ```false```1073   */1074  async setPermissions(signer: TSigner, collectionId: number, permissions: ICollectionPermissions): Promise<boolean> {1075    const result = await this.helper.executeExtrinsic(1076      signer,1077      'api.tx.unique.setCollectionPermissions', [collectionId, permissions],1078      true,1079    );10801081    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPermissionSet');1082  }10831084  /**1085   * Enables nesting for selected collection. If `restricted` set, you can nest only tokens from specified collections.1086   *1087   * @param signer keyring of signer1088   * @param collectionId ID of collection1089   * @param permissions nesting permissions object1090   * @example enableNesting(aliceKeyring, 10, {collectionAdmin: true, tokenOwner: true});1091   * @returns ```true``` if extrinsic success, otherwise ```false```1092   */1093  async enableNesting(signer: TSigner, collectionId: number, permissions: INestingPermissions): Promise<boolean> {1094    return await this.setPermissions(signer, collectionId, {nesting: permissions});1095  }10961097  /**1098   * Disables nesting for selected collection.1099   *1100   * @param signer keyring of signer1101   * @param collectionId ID of collection1102   * @example disableNesting(aliceKeyring, 10);1103   * @returns ```true``` if extrinsic success, otherwise ```false```1104   */1105  async disableNesting(signer: TSigner, collectionId: number): Promise<boolean> {1106    return await this.setPermissions(signer, collectionId, {nesting: {tokenOwner: false, collectionAdmin: false}});1107  }11081109  /**1110   * Sets onchain properties to the collection.1111   *1112   * @param signer keyring of signer1113   * @param collectionId ID of collection1114   * @param properties array of property objects1115   * @example setProperties(aliceKeyring, 10, [{key: "gender", value: "male"}]);1116   * @returns ```true``` if extrinsic success, otherwise ```false```1117   */1118  async setProperties(signer: TSigner, collectionId: number, properties: IProperty[]): Promise<boolean> {1119    const result = await this.helper.executeExtrinsic(1120      signer,1121      'api.tx.unique.setCollectionProperties', [collectionId, properties],1122      true,1123    );11241125    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet');1126  }11271128  /**1129   * Get collection properties.1130   *1131   * @param collectionId ID of collection1132   * @param propertyKeys optionally filter the returned properties to only these keys1133   * @example getProperties(1219, ['location', 'date', 'time', 'isParadise']);1134   * @returns array of key-value pairs1135   */1136  async getProperties(collectionId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {1137    return (await this.helper.callRpc('api.rpc.unique.collectionProperties', [collectionId, propertyKeys])).toHuman();1138  }11391140  async getPropertiesConsumedSpace(collectionId: number): Promise<number> {1141    const api = this.helper.getApi();1142    const props = (await api.query.common.collectionProperties(collectionId)).toJSON();11431144    return (props! as any).consumedSpace;1145  }11461147  async getCollectionOptions(collectionId: number) {1148    return (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();1149  }11501151  /**1152   * Deletes onchain properties from the collection.1153   *1154   * @param signer keyring of signer1155   * @param collectionId ID of collection1156   * @param propertyKeys array of property keys to delete1157   * @example deleteProperties(aliceKeyring, 10, ["gender", "age"]);1158   * @returns ```true``` if extrinsic success, otherwise ```false```1159   */1160  async deleteProperties(signer: TSigner, collectionId: number, propertyKeys: string[]): Promise<boolean> {1161    const result = await this.helper.executeExtrinsic(1162      signer,1163      'api.tx.unique.deleteCollectionProperties', [collectionId, propertyKeys],1164      true,1165    );11661167    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertyDeleted');1168  }11691170  /**1171   * Changes the owner of the token.1172   *1173   * @param signer keyring of signer1174   * @param collectionId ID of collection1175   * @param tokenId ID of token1176   * @param addressObj address of a new owner1177   * @param amount amount of tokens to be transfered. For NFT must be set to 1n1178   * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1179   * @returns true if the token success, otherwise false1180   */1181  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {1182    const result = await this.helper.executeExtrinsic(1183      signer,1184      'api.tx.unique.transfer', [addressObj, collectionId, tokenId, amount],1185      true, // `Unable to transfer token #${tokenId} from collection #${collectionId}`,1186    );11871188    return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, {Substrate: typeof signer === 'string' ? signer : signer.address}, addressObj, amount);1189  }11901191  /**1192   *1193   * Change ownership of a token(s) on behalf of the owner.1194   *1195   * @param signer keyring of signer1196   * @param collectionId ID of collection1197   * @param tokenId ID of token1198   * @param fromAddressObj address on behalf of which the token will be sent1199   * @param toAddressObj new token owner1200   * @param amount amount of tokens to be transfered. For NFT must be set to 1n1201   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg"}, {Ethereum: "0x9F0583DbB85..."})1202   * @returns true if the token success, otherwise false1203   */1204  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1205    const result = await this.helper.executeExtrinsic(1206      signer,1207      'api.tx.unique.transferFrom', [fromAddressObj, toAddressObj, collectionId, tokenId, amount],1208      true, // `Unable to transfer token #${tokenId} from collection #${collectionId}`,1209    );1210    return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1211  }12121213  /**1214   *1215   * Destroys a concrete instance of NFT/RFT or burns a specified amount of fungible tokens.1216   *1217   * @param signer keyring of signer1218   * @param collectionId ID of collection1219   * @param tokenId ID of token1220   * @param amount amount of tokens to be burned. For NFT must be set to 1n1221   * @example burnToken(aliceKeyring, 10, 5);1222   * @returns ```true``` if the extrinsic is successful, otherwise ```false```1223   */1224  async burnToken(signer: TSigner, collectionId: number, tokenId: number, amount=1n): Promise<boolean> {1225    const burnResult = await this.helper.executeExtrinsic(1226      signer,1227      'api.tx.unique.burnItem', [collectionId, tokenId, amount],1228      true, // `Unable to burn token for ${label}`,1229    );1230    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);1231    if (burnedTokens.tokens.length > 1) throw Error('Burned multiple tokens');1232    return burnedTokens.success;1233  }12341235  /**1236   * Destroys a concrete instance of NFT on behalf of the owner1237   *1238   * @param signer keyring of signer1239   * @param collectionId ID of collection1240   * @param tokenId ID of token1241   * @param fromAddressObj address on behalf of which the token will be burnt1242   * @param amount amount of tokens to be burned. For NFT must be set to 1n1243   * @example burnTokenFrom(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."}, 5, {Ethereum: "0x9F0583DbB85..."})1244   * @returns ```true``` if extrinsic success, otherwise ```false```1245   */1246  async burnTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1247    const burnResult = await this.helper.executeExtrinsic(1248      signer,1249      'api.tx.unique.burnFrom', [collectionId, fromAddressObj, tokenId, amount],1250      true, // `Unable to burn token from for ${label}`,1251    );1252    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);1253    return burnedTokens.success && burnedTokens.tokens.length > 0;1254  }12551256  /**1257   * Set, change, or remove approved address to transfer the ownership of the NFT.1258   *1259   * @param signer keyring of signer1260   * @param collectionId ID of collection1261   * @param tokenId ID of token1262   * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens1263   * @param amount amount of token to be approved. For NFT must be set to 1n1264   * @returns ```true``` if extrinsic success, otherwise ```false```1265   */1266  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1267    const approveResult = await this.helper.executeExtrinsic(1268      signer,1269      'api.tx.unique.approve', [toAddressObj, collectionId, tokenId, amount],1270      true, // `Unable to approve token for ${label}`,1271    );12721273    return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');1274  }12751276  /**1277   * Set, change, or remove approved address to transfer the ownership of the NFT from eth mirror.1278   *1279   * @param signer keyring of signer1280   * @param collectionId ID of collection1281   * @param tokenId ID of token1282   * @param fromAddressObj Signer's Ethereum address containing her tokens1283   * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens1284   * @param amount amount of token to be approved. For NFT must be set to 1n1285   * @returns ```true``` if extrinsic success, otherwise ```false```1286   */1287  async approveTokenFrom(signer: IKeyringPair, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {1288    const approveResult = await this.helper.executeExtrinsic(1289      signer,1290      'api.tx.unique.approveFrom', [fromAddressObj, toAddressObj, collectionId, tokenId, amount],1291      true, // `Unable to approve token for ${label}`,1292    );12931294    return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');1295  }12961297  /**1298   * Set, change, or remove approved address to transfer the ownership of the NFT from eth mirror.1299   *1300   * @param signer keyring of signer1301   * @param collectionId ID of collection1302   * @param tokenId ID of token1303   * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens1304   * @param amount amount of token to be approved. For NFT must be set to 1n1305   * @returns ```true``` if extrinsic success, otherwise ```false```1306   */1307  async approveTokenFromEth(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1308    const ethMirror = CrossAccountId.fromKeyring(signer).toEthereum();1309    return await this.approveTokenFrom(signer, collectionId, tokenId, ethMirror, toAddressObj, amount);1310  }13111312  /**1313   * Get the amount of token pieces approved to transfer or burn. Normally 0.1314   *1315   * @param collectionId ID of collection1316   * @param tokenId ID of token1317   * @param toAccountObj address which is approved to use token pieces1318   * @param fromAccountObj address which may have allowed the use of its owned tokens1319   * @example getTokenApprovedPieces(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5ERZNF88Mm7UGfPP3mdG..."})1320   * @returns number of approved to transfer pieces1321   */1322  async getTokenApprovedPieces(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId, fromAccountObj: ICrossAccountId): Promise<bigint> {1323    return (await this.helper.callRpc('api.rpc.unique.allowance', [collectionId, fromAccountObj, toAccountObj, tokenId])).toBigInt();1324  }13251326  /**1327   * Get the last created token ID in a collection1328   *1329   * @param collectionId ID of collection1330   * @example getLastTokenId(10);1331   * @returns id of the last created token1332   */1333  async getLastTokenId(collectionId: number): Promise<number> {1334    return (await this.helper.callRpc('api.rpc.unique.lastTokenId', [collectionId])).toNumber();1335  }13361337  /**1338   * Check if token exists1339   *1340   * @param collectionId ID of collection1341   * @param tokenId ID of token1342   * @example doesTokenExist(10, 20);1343   * @returns true if the token exists, otherwise false1344   */1345  async doesTokenExist(collectionId: number, tokenId: number): Promise<boolean> {1346    return (await this.helper.callRpc('api.rpc.unique.tokenExists', [collectionId, tokenId])).toJSON();1347  }1348}13491350class NFTnRFT extends CollectionGroup {1351  /**1352   * Get tokens owned by account1353   *1354   * @param collectionId ID of collection1355   * @param addressObj tokens owner1356   * @example getTokensByAddress(10, {Substrate: "5DyN4Y92vZCjv38fg..."})1357   * @returns array of token ids owned by account1358   */1359  async getTokensByAddress(collectionId: number, addressObj: ICrossAccountId): Promise<number[]> {1360    return (await this.helper.callRpc('api.rpc.unique.accountTokens', [collectionId, addressObj])).toJSON();1361  }13621363  /**1364   * Get token data1365   *1366   * @param collectionId ID of collection1367   * @param tokenId ID of token1368   * @param propertyKeys optionally filter the token properties to only these keys1369   * @param blockHashAt optionally query the data at some block with this hash1370   * @example getToken(10, 5);1371   * @returns human readable token data1372   */1373  async getToken(collectionId: number, tokenId: number, propertyKeys: string[] = [], blockHashAt?: string): Promise<{1374    properties: IProperty[];1375    owner: CrossAccountId;1376    normalizedOwner: CrossAccountId;1377  }| null> {1378    let tokenData;1379    if(typeof blockHashAt === 'undefined') {1380      tokenData = await this.helper.callRpc('api.rpc.unique.tokenData', [collectionId, tokenId]);1381    }1382    else {1383      if(propertyKeys.length == 0) {1384        const collection = (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();1385        if(!collection) return null;1386        propertyKeys = collection.tokenPropertyPermissions.map((x: ITokenPropertyPermission) => x.key);1387      }1388      tokenData = await this.helper.callRpc('api.rpc.unique.tokenData', [collectionId, tokenId, propertyKeys, blockHashAt]);1389    }1390    tokenData = tokenData.toHuman();1391    if (tokenData === null || tokenData.owner === null) return null;1392    const owner = {} as any;1393    for (const key of Object.keys(tokenData.owner)) {1394      owner[key.toLocaleLowerCase()] = key.toLocaleLowerCase() == 'substrate'1395        ? CrossAccountId.normalizeSubstrateAddress(tokenData.owner[key])1396        : tokenData.owner[key];1397    }1398    tokenData.normalizedOwner = CrossAccountId.fromLowerCaseKeys(owner);1399    return tokenData;1400  }14011402  /**1403   * Get token's owner1404   * @param collectionId ID of collection1405   * @param tokenId ID of token1406   * @param blockHashAt optionally query the data at the block with this hash1407   * @example getTokenOwner(10, 5);1408   * @returns Address in CrossAccountId format, e.g. {Substrate: "5DnSF6RRjwteE3BrCj..."}1409   */1410  async getTokenOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<CrossAccountId> {1411    let owner;1412    if (typeof blockHashAt === 'undefined') {1413      owner = await this.helper.callRpc('api.rpc.unique.tokenOwner', [collectionId, tokenId]);1414    } else {1415      owner = await this.helper.callRpc('api.rpc.unique.tokenOwner', [collectionId, tokenId, blockHashAt]);1416    }1417    return CrossAccountId.fromLowerCaseKeys(owner.toJSON());1418  }14191420  /**1421   * Recursively find the address that owns the token1422   * @param collectionId ID of collection1423   * @param tokenId ID of token1424   * @param blockHashAt1425   * @example getTokenTopmostOwner(10, 5);1426   * @returns address in CrossAccountId format, e.g. {Substrate: "5DyN4Y92vZCjv38fg..."}1427   */1428  async getTokenTopmostOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<CrossAccountId | null> {1429    let owner;1430    if (typeof blockHashAt === 'undefined') {1431      owner = await this.helper.callRpc('api.rpc.unique.topmostTokenOwner', [collectionId, tokenId]);1432    } else {1433      owner = await this.helper.callRpc('api.rpc.unique.topmostTokenOwner', [collectionId, tokenId, blockHashAt]);1434    }14351436    if (owner === null) return null;14371438    return owner.toHuman();1439  }14401441  /**1442   * Nest one token into another1443   * @param signer keyring of signer1444   * @param tokenObj token to be nested1445   * @param rootTokenObj token to be parent1446   * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});1447   * @returns ```true``` if extrinsic success, otherwise ```false```1448   */1449  async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken): Promise<boolean> {1450    const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1451    const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);1452    if(!result) {1453      throw Error('Unable to nest token!');1454    }1455    return result;1456  }14571458  /**1459     * Remove token from nested state1460     * @param signer keyring of signer1461     * @param tokenObj token to unnest1462     * @param rootTokenObj parent of a token1463     * @param toAddressObj address of a new token owner1464     * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});1465     * @returns ```true``` if extrinsic success, otherwise ```false```1466     */1467  async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {1468    const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1469    const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);1470    if(!result) {1471      throw Error('Unable to unnest token!');1472    }1473    return result;1474  }14751476  /**1477   * Set permissions to change token properties1478   *1479   * @param signer keyring of signer1480   * @param collectionId ID of collection1481   * @param permissions permissions to change a property by the collection admin or token owner1482   * @example setTokenPropertyPermissions(1483   *   aliceKeyring, 10, [{key: "gender", permission: {tokenOwner: true, mutable: true, collectionAdmin: true}}]1484   * )1485   * @returns true if extrinsic success otherwise false1486   */1487  async setTokenPropertyPermissions(signer: TSigner, collectionId: number, permissions: ITokenPropertyPermission[]): Promise<boolean> {1488    const result = await this.helper.executeExtrinsic(1489      signer,1490      'api.tx.unique.setTokenPropertyPermissions', [collectionId, permissions],1491      true,1492    );14931494    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet');1495  }14961497  /**1498   * Get token property permissions.1499   *1500   * @param collectionId ID of collection1501   * @param propertyKeys optionally filter the returned property permissions to only these keys1502   * @example getPropertyPermissions(1219, ['location', 'date', 'time', 'isParadise']);1503   * @returns array of key-permission pairs1504   */1505  async getPropertyPermissions(collectionId: number, propertyKeys: string[] | null = null): Promise<ITokenPropertyPermission[]> {1506    return (await this.helper.callRpc('api.rpc.unique.propertyPermissions', [collectionId, ...(propertyKeys === null ? [] : [propertyKeys])])).toHuman();1507  }15081509  /**1510   * Set token properties1511   *1512   * @param signer keyring of signer1513   * @param collectionId ID of collection1514   * @param tokenId ID of token1515   * @param properties key-value pairs of metadata which to add to a token. Keys must be permitted in the collection1516   * @example setTokenProperties(aliceKeyring, 10, 5, [{key: "gender", value: "female"}, {key: "age", value: "23"}])1517   * @returns ```true``` if extrinsic success, otherwise ```false```1518   */1519  async setTokenProperties(signer: TSigner, collectionId: number, tokenId: number, properties: IProperty[]): Promise<boolean> {1520    const result = await this.helper.executeExtrinsic(1521      signer,1522      'api.tx.unique.setTokenProperties', [collectionId, tokenId, properties],1523      true,1524    );15251526    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet');1527  }15281529  /**1530   * Get properties, metadata assigned to a token.1531   *1532   * @param collectionId ID of collection1533   * @param tokenId ID of token1534   * @param propertyKeys optionally filter the returned properties to only these keys1535   * @example getTokenProperties(1219, ['location', 'date', 'time', 'isParadise']);1536   * @returns array of key-value pairs1537   */1538  async getTokenProperties(collectionId: number, tokenId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {1539    return (await this.helper.callRpc('api.rpc.unique.tokenProperties', [collectionId, tokenId, propertyKeys])).toHuman();1540  }15411542  /**1543   * Delete the provided properties of a token1544   * @param signer keyring of signer1545   * @param collectionId ID of collection1546   * @param tokenId ID of token1547   * @param propertyKeys property keys to be deleted1548   * @example deleteTokenProperties(aliceKeyring, 10, 5, ["gender", "age"])1549   * @returns ```true``` if extrinsic success, otherwise ```false```1550   */1551  async deleteTokenProperties(signer: TSigner, collectionId: number, tokenId: number, propertyKeys: string[]): Promise<boolean> {1552    const result = await this.helper.executeExtrinsic(1553      signer,1554      'api.tx.unique.deleteTokenProperties', [collectionId, tokenId, propertyKeys],1555      true,1556    );15571558    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertyDeleted');1559  }15601561  /**1562   * Mint new collection1563   *1564   * @param signer keyring of signer1565   * @param collectionOptions basic collection options and properties1566   * @param mode NFT or RFT type of a collection1567   * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")1568   * @returns object of the created collection1569   */1570  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueBaseCollection> {1571    collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1572    collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};1573    for (const key of ['name', 'description', 'tokenPrefix']) {1574      if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);1575    }1576    const creationResult = await this.helper.executeExtrinsic(1577      signer,1578      'api.tx.unique.createCollectionEx', [collectionOptions],1579      true, // errorLabel,1580    );1581    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));1582  }15831584  getCollectionObject(_collectionId: number): any {1585    return null;1586  }15871588  getTokenObject(_collectionId: number, _tokenId: number): any {1589    return null;1590  }15911592  /**1593   * Tells whether the given `owner` approves the `operator`.1594   * @param collectionId ID of collection1595   * @param owner owner address1596   * @param operator operator addrees1597   * @returns true if operator is enabled1598   */1599  async allowanceForAll(collectionId: number, owner: ICrossAccountId, operator: ICrossAccountId): Promise<boolean> {1600    return (await this.helper.callRpc('api.rpc.unique.allowanceForAll', [collectionId, owner, operator])).toJSON();1601  }16021603  /** Sets or unsets the approval of a given operator.1604   *  The `operator` is allowed to transfer all tokens of the `caller` on their behalf.1605   *  @param operator Operator1606   *  @param approved Should operator status be granted or revoked?1607   *  @returns ```true``` if extrinsic success, otherwise ```false```1608   */1609  async setAllowanceForAll(signer: TSigner, collectionId: number, operator: ICrossAccountId, approved: boolean): Promise<boolean> {1610    const result = await this.helper.executeExtrinsic(1611      signer,1612      'api.tx.unique.setAllowanceForAll', [collectionId, operator, approved],1613      true,1614    );1615    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'ApprovedForAll');1616  }1617}161816191620class NFTGroup extends NFTnRFT {1621  /**1622   * Get collection object1623   * @param collectionId ID of collection1624   * @example getCollectionObject(2);1625   * @returns instance of UniqueNFTCollection1626   */1627  getCollectionObject(collectionId: number): UniqueNFTCollection {1628    return new UniqueNFTCollection(collectionId, this.helper);1629  }16301631  /**1632   * Get token object1633   * @param collectionId ID of collection1634   * @param tokenId ID of token1635   * @example getTokenObject(10, 5);1636   * @returns instance of UniqueNFTToken1637   */1638  getTokenObject(collectionId: number, tokenId: number): UniqueNFToken {1639    return new UniqueNFToken(tokenId, this.getCollectionObject(collectionId));1640  }16411642  /**1643   * Is token approved to transfer1644   * @param collectionId ID of collection1645   * @param tokenId ID of token1646   * @param toAccountObj address to be approved1647   * @returns ```true``` if extrinsic success, otherwise ```false```1648   */1649  async isTokenApproved(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId): Promise<boolean> {1650    return (await this.getTokenApprovedPieces(collectionId, tokenId, toAccountObj, await this.getTokenOwner(collectionId, tokenId))) === 1n;1651  }16521653  /**1654   * Changes the owner of the token.1655   *1656   * @param signer keyring of signer1657   * @param collectionId ID of collection1658   * @param tokenId ID of token1659   * @param addressObj address of a new owner1660   * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1661   * @returns ```true``` if extrinsic success, otherwise ```false```1662   */1663  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<boolean> {1664    return await super.transferToken(signer, collectionId, tokenId, addressObj, 1n);1665  }16661667  /**1668   *1669   * Change ownership of a NFT on behalf of the owner.1670   *1671   * @param signer keyring of signer1672   * @param collectionId ID of collection1673   * @param tokenId ID of token1674   * @param fromAddressObj address on behalf of which the token will be sent1675   * @param toAddressObj new token owner1676   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Ethereum: "0x9F0583DbB85..."})1677   * @returns ```true``` if extrinsic success, otherwise ```false```1678   */1679  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId): Promise<boolean> {1680    return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, 1n);1681  }16821683  /**1684   * Get tokens nested in the provided token1685   * @param collectionId ID of collection1686   * @param tokenId ID of token1687   * @param blockHashAt optionally query the data at the block with this hash1688   * @example getTokenChildren(10, 5);1689   * @returns tokens whose depth of nesting is <= 51690   */1691  async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<IToken[]> {1692    let children;1693    if(typeof blockHashAt === 'undefined') {1694      children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId]);1695    } else {1696      children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId, blockHashAt]);1697    }16981699    return children.toJSON().map((x: any) => {1700      return {collectionId: x.collection, tokenId: x.token};1701    });1702  }17031704  /**1705   * Mint new collection1706   * @param signer keyring of signer1707   * @param collectionOptions Collection options1708   * @example1709   * mintCollection(aliceKeyring, {1710   *   name: 'New',1711   *   description: 'New collection',1712   *   tokenPrefix: 'NEW',1713   * })1714   * @returns object of the created collection1715   */1716  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions = {}): Promise<UniqueNFTCollection> {1717    return await super.mintCollection(signer, collectionOptions, 'NFT') as UniqueNFTCollection;1718  }17191720  /**1721   * Mint new token1722   * @param signer keyring of signer1723   * @param data token data1724   * @returns created token object1725   */1726  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; properties?: IProperty[]; }): Promise<UniqueNFToken> {1727    const creationResult = await this.helper.executeExtrinsic(1728      signer,1729      'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1730        nft: {1731          properties: data.properties,1732        },1733      }],1734      true,1735    );1736    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult);1737    if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');1738    if (createdTokens.tokens.length < 1) throw Error('No tokens minted');1739    return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);1740  }17411742  /**1743   * Mint multiple NFT tokens1744   * @param signer keyring of signer1745   * @param collectionId ID of collection1746   * @param tokens array of tokens with owner and properties1747   * @example1748   * mintMultipleTokens(aliceKeyring, 10, [{1749   *     owner: {Substrate: "5DyN4Y92vZCjv38fg..."},1750   *     properties: [{key: "gender", value: "male"},{key: "age", value: "45"}],1751   *   },{1752   *     owner: {Ethereum: "0x9F0583DbB855d..."},1753   *     properties: [{key: "gender", value: "female"},{key: "age", value: "22"}],1754   * }]);1755   * @returns ```true``` if extrinsic success, otherwise ```false```1756   */1757  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]): Promise<UniqueNFToken[]> {1758    const creationResult = await this.helper.executeExtrinsic(1759      signer,1760      'api.tx.unique.createMultipleItemsEx', [collectionId, {NFT: tokens}],1761      true,1762    );1763    const collection = this.getCollectionObject(collectionId);1764    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1765  }17661767  /**1768   * Mint multiple NFT tokens with one owner1769   * @param signer keyring of signer1770   * @param collectionId ID of collection1771   * @param owner tokens owner1772   * @param tokens array of tokens with owner and properties1773   * @example1774   * mintMultipleTokensWithOneOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...", [{1775   *   properties: [{1776   *   key: "gender",1777   *   value: "female",1778   *  },{1779   *   key: "age",1780   *   value: "33",1781   *  }],1782   * }]);1783   * @returns array of newly created tokens1784   */1785  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {properties?: IProperty[]}[]): Promise<UniqueNFToken[]> {1786    const rawTokens = [];1787    for (const token of tokens) {1788      const raw = {NFT: {properties: token.properties}};1789      rawTokens.push(raw);1790    }1791    const creationResult = await this.helper.executeExtrinsic(1792      signer,1793      'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],1794      true,1795    );1796    const collection = this.getCollectionObject(collectionId);1797    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1798  }17991800  /**1801   * Set, change, or remove approved address to transfer the ownership of the NFT.1802   *1803   * @param signer keyring of signer1804   * @param collectionId ID of collection1805   * @param tokenId ID of token1806   * @param toAddressObj address to approve1807   * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1808   * @returns ```true``` if extrinsic success, otherwise ```false```1809   */1810  approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1811    return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);1812  }1813}181418151816class RFTGroup extends NFTnRFT {1817  /**1818   * Get collection object1819   * @param collectionId ID of collection1820   * @example getCollectionObject(2);1821   * @returns instance of UniqueRFTCollection1822   */1823  getCollectionObject(collectionId: number): UniqueRFTCollection {1824    return new UniqueRFTCollection(collectionId, this.helper);1825  }18261827  /**1828   * Get token object1829   * @param collectionId ID of collection1830   * @param tokenId ID of token1831   * @example getTokenObject(10, 5);1832   * @returns instance of UniqueNFTToken1833   */1834  getTokenObject(collectionId: number, tokenId: number): UniqueRFToken {1835    return new UniqueRFToken(tokenId, this.getCollectionObject(collectionId));1836  }18371838  /**1839   * Get top 10 token owners with the largest number of pieces1840   * @param collectionId ID of collection1841   * @param tokenId ID of token1842   * @example getTokenTop10Owners(10, 5);1843   * @returns array of top 10 owners1844   */1845  async getTokenTop10Owners(collectionId: number, tokenId: number): Promise<CrossAccountId[]> {1846    return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, tokenId])).toJSON().map(CrossAccountId.fromLowerCaseKeys);1847  }18481849  /**1850   * Get number of pieces owned by address1851   * @param collectionId ID of collection1852   * @param tokenId ID of token1853   * @param addressObj address token owner1854   * @example getTokenBalance(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."});1855   * @returns number of pieces ownerd by address1856   */1857  async getTokenBalance(collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<bigint> {1858    return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, tokenId])).toBigInt();1859  }18601861  /**1862   * Transfer pieces of token to another address1863   * @param signer keyring of signer1864   * @param collectionId ID of collection1865   * @param tokenId ID of token1866   * @param addressObj address of a new owner1867   * @param amount number of pieces to be transfered1868   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, 2000n)1869   * @returns ```true``` if extrinsic success, otherwise ```false```1870   */1871  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {1872    return await super.transferToken(signer, collectionId, tokenId, addressObj, amount);1873  }18741875  /**1876   * Change ownership of some pieces of RFT on behalf of the owner.1877   * @param signer keyring of signer1878   * @param collectionId ID of collection1879   * @param tokenId ID of token1880   * @param fromAddressObj address on behalf of which the token will be sent1881   * @param toAddressObj new token owner1882   * @param amount number of pieces to be transfered1883   * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5DfhbVfww7ThF8q6f3i..."}, 2000n)1884   * @returns ```true``` if extrinsic success, otherwise ```false```1885   */1886  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1887    return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1888  }18891890  /**1891   * Mint new collection1892   * @param signer keyring of signer1893   * @param collectionOptions Collection options1894   * @example1895   * mintCollection(aliceKeyring, {1896   *   name: 'New',1897   *   description: 'New collection',1898   *   tokenPrefix: 'NEW',1899   * })1900   * @returns object of the created collection1901   */1902  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions = {}): Promise<UniqueRFTCollection> {1903    return await super.mintCollection(signer, collectionOptions, 'RFT') as UniqueRFTCollection;1904  }19051906  /**1907   * Mint new token1908   * @param signer keyring of signer1909   * @param data token data1910   * @example mintToken(aliceKeyring, {collectionId: 10, owner: {Substrate: '5GHoZe9c73RYbVzq...'}, pieces: 10000n});1911   * @returns created token object1912   */1913  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; pieces: bigint; properties?: IProperty[]; }): Promise<UniqueRFToken> {1914    const creationResult = await this.helper.executeExtrinsic(1915      signer,1916      'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1917        refungible: {1918          pieces: data.pieces,1919          properties: data.properties,1920        },1921      }],1922      true,1923    );1924    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult);1925    if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');1926    if (createdTokens.tokens.length < 1) throw Error('No tokens minted');1927    return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);1928  }19291930  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFToken[]> {1931    throw Error('Not implemented');1932    const creationResult = await this.helper.executeExtrinsic(1933      signer,1934      'api.tx.unique.createMultipleItemsEx', [collectionId, {RefungibleMultipleOwners: tokens}],1935      true, // `Unable to mint RFT tokens for ${label}`,1936    );1937    const collection = this.getCollectionObject(collectionId);1938    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1939  }19401941  /**1942   * Mint multiple RFT tokens with one owner1943   * @param signer keyring of signer1944   * @param collectionId ID of collection1945   * @param owner tokens owner1946   * @param tokens array of tokens with properties and pieces1947   * @example mintMultipleTokensWithOneOwner(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, [{pieces: 100000n, properties: [{key: "gender", value: "male"}]}]);1948   * @returns array of newly created RFT tokens1949   */1950  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFToken[]> {1951    const rawTokens = [];1952    for (const token of tokens) {1953      const raw = {ReFungible: {pieces: token.pieces, properties: token.properties}};1954      rawTokens.push(raw);1955    }1956    const creationResult = await this.helper.executeExtrinsic(1957      signer,1958      'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],1959      true,1960    );1961    const collection = this.getCollectionObject(collectionId);1962    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1963  }19641965  /**1966   * Destroys a concrete instance of RFT.1967   * @param signer keyring of signer1968   * @param collectionId ID of collection1969   * @param tokenId ID of token1970   * @param amount number of pieces to be burnt1971   * @example burnToken(aliceKeyring, 10, 5);1972   * @returns ```true``` if the extrinsic is successful, otherwise ```false```1973   */1974  async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, amount=1n): Promise<boolean> {1975    return await super.burnToken(signer, collectionId, tokenId, amount);1976  }19771978  /**1979   * Destroys a concrete instance of RFT on behalf of the owner.1980   * @param signer keyring of signer1981   * @param collectionId ID of collection1982   * @param tokenId ID of token1983   * @param fromAddressObj address on behalf of which the token will be burnt1984   * @param amount number of pieces to be burnt1985   * @example burnTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, 2n)1986   * @returns ```true``` if extrinsic success, otherwise ```false```1987   */1988  async burnTokenFrom(signer: IKeyringPair, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1989    return await super.burnTokenFrom(signer, collectionId, tokenId, fromAddressObj, amount);1990  }19911992  /**1993   * Set, change, or remove approved address to transfer the ownership of the RFT.1994   *1995   * @param signer keyring of signer1996   * @param collectionId ID of collection1997   * @param tokenId ID of token1998   * @param toAddressObj address to approve1999   * @param amount number of pieces to be approved2000   * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5GHoZe9c73RYbVzq..."}, "", 10000n);2001   * @returns true if the token success, otherwise false2002   */2003  approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {2004    return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);2005  }20062007  /**2008   * Get total number of pieces2009   * @param collectionId ID of collection2010   * @param tokenId ID of token2011   * @example getTokenTotalPieces(10, 5);2012   * @returns number of pieces2013   */2014  async getTokenTotalPieces(collectionId: number, tokenId: number): Promise<bigint> {2015    return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, tokenId])).unwrap().toBigInt();2016  }20172018  /**2019   * Change number of token pieces. Signer must be the owner of all token pieces.2020   * @param signer keyring of signer2021   * @param collectionId ID of collection2022   * @param tokenId ID of token2023   * @param amount new number of pieces2024   * @example repartitionToken(aliceKeyring, 10, 5, 12345n);2025   * @returns true if the repartion was success, otherwise false2026   */2027  async repartitionToken(signer: TSigner, collectionId: number, tokenId: number, amount: bigint): Promise<boolean> {2028    const currentAmount = await this.getTokenTotalPieces(collectionId, tokenId);2029    const repartitionResult = await this.helper.executeExtrinsic(2030      signer,2031      'api.tx.unique.repartition', [collectionId, tokenId, amount],2032      true,2033    );2034    if(currentAmount < amount) return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemCreated');2035    return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemDestroyed');2036  }2037}203820392040class FTGroup extends CollectionGroup {2041  /**2042   * Get collection object2043   * @param collectionId ID of collection2044   * @example getCollectionObject(2);2045   * @returns instance of UniqueFTCollection2046   */2047  getCollectionObject(collectionId: number): UniqueFTCollection {2048    return new UniqueFTCollection(collectionId, this.helper);2049  }20502051  /**2052   * Mint new fungible collection2053   * @param signer keyring of signer2054   * @param collectionOptions Collection options2055   * @param decimalPoints number of token decimals2056   * @example2057   * mintCollection(aliceKeyring, {2058   *   name: 'New',2059   *   description: 'New collection',2060   *   tokenPrefix: 'NEW',2061   * }, 18)2062   * @returns newly created fungible collection2063   */2064  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions = {}, decimalPoints = 0): Promise<UniqueFTCollection> {2065    collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object2066    if(collectionOptions.tokenPropertyPermissions) throw Error('Fungible collections has no tokenPropertyPermissions');2067    collectionOptions.mode = {fungible: decimalPoints};2068    for (const key of ['name', 'description', 'tokenPrefix']) {2069      if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);2070    }2071    const creationResult = await this.helper.executeExtrinsic(2072      signer,2073      'api.tx.unique.createCollectionEx', [collectionOptions],2074      true,2075    );2076    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));2077  }20782079  /**2080   * Mint tokens2081   * @param signer keyring of signer2082   * @param collectionId ID of collection2083   * @param owner address owner of new tokens2084   * @param amount amount of tokens to be meanted2085   * @example mintTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq"}, 1000n);2086   * @returns ```true``` if extrinsic success, otherwise ```false```2087   */2088  async mintTokens(signer: TSigner, collectionId: number, amount: bigint, owner: ICrossAccountId | string): Promise<boolean> {2089    const creationResult = await this.helper.executeExtrinsic(2090      signer,2091      'api.tx.unique.createItem', [collectionId, (typeof owner === 'string') ? {Substrate: owner} : owner, {2092        fungible: {2093          value: amount,2094        },2095      }],2096      true, // `Unable to mint fungible tokens for ${label}`,2097    );2098    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');2099  }21002101  /**2102   * Mint multiple Fungible tokens with one owner2103   * @param signer keyring of signer2104   * @param collectionId ID of collection2105   * @param owner tokens owner2106   * @param tokens array of tokens with properties and pieces2107   * @returns ```true``` if extrinsic success, otherwise ```false```2108   */2109  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, tokens: {value: bigint}[], owner: ICrossAccountId): Promise<boolean> {2110    const rawTokens = [];2111    for (const token of tokens) {2112      const raw = {Fungible: {Value: token.value}};2113      rawTokens.push(raw);2114    }2115    const creationResult = await this.helper.executeExtrinsic(2116      signer,2117      'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],2118      true,2119    );2120    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');2121  }21222123  /**2124   * Get the top 10 owners with the largest balance for the Fungible collection2125   * @param collectionId ID of collection2126   * @example getTop10Owners(10);2127   * @returns array of ```ICrossAccountId```2128   */2129  async getTop10Owners(collectionId: number): Promise<CrossAccountId[]> {2130    return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, 0])).toJSON().map(CrossAccountId.fromLowerCaseKeys);2131  }21322133  /**2134   * Get account balance2135   * @param collectionId ID of collection2136   * @param addressObj address of owner2137   * @example getBalance(10, {Substrate: "5GHoZe9c73RYbVzq..."})2138   * @returns amount of fungible tokens owned by address2139   */2140  async getBalance(collectionId: number, addressObj: ICrossAccountId): Promise<bigint> {2141    return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, 0])).toBigInt();2142  }21432144  /**2145   * Transfer tokens to address2146   * @param signer keyring of signer2147   * @param collectionId ID of collection2148   * @param toAddressObj address recipient2149   * @param amount amount of tokens to be sent2150   * @example transfer(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);2151   * @returns ```true``` if extrinsic success, otherwise ```false```2152   */2153  async transfer(signer: TSigner, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {2154    return await super.transferToken(signer, collectionId, 0, toAddressObj, amount);2155  }21562157  /**2158   * Transfer some tokens on behalf of the owner.2159   * @param signer keyring of signer2160   * @param collectionId ID of collection2161   * @param fromAddressObj address on behalf of which tokens will be sent2162   * @param toAddressObj address where token to be sent2163   * @param amount number of tokens to be sent2164   * @example transferFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, {Substrate: "5DfhbVfww7ThF8q6f3ij..."}, 10000n);2165   * @returns ```true``` if extrinsic success, otherwise ```false```2166   */2167  async transferFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {2168    return await super.transferTokenFrom(signer, collectionId, 0, fromAddressObj, toAddressObj, amount);2169  }21702171  /**2172   * Destroy some amount of tokens2173   * @param signer keyring of signer2174   * @param collectionId ID of collection2175   * @param amount amount of tokens to be destroyed2176   * @example burnTokens(aliceKeyring, 10, 1000n);2177   * @returns ```true``` if extrinsic success, otherwise ```false```2178   */2179  async burnTokens(signer: IKeyringPair, collectionId: number, amount=1n): Promise<boolean> {2180    return await super.burnToken(signer, collectionId, 0, amount);2181  }21822183  /**2184   * Burn some tokens on behalf of the owner.2185   * @param signer keyring of signer2186   * @param collectionId ID of collection2187   * @param fromAddressObj address on behalf of which tokens will be burnt2188   * @param amount amount of tokens to be burnt2189   * @example burnTokensFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);2190   * @returns ```true``` if extrinsic success, otherwise ```false```2191   */2192  async burnTokensFrom(signer: IKeyringPair, collectionId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {2193    return await super.burnTokenFrom(signer, collectionId, 0, fromAddressObj, amount);2194  }21952196  /**2197   * Get total collection supply2198   * @param collectionId2199   * @returns2200   */2201  async getTotalPieces(collectionId: number): Promise<bigint> {2202    return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, 0])).unwrap().toBigInt();2203  }22042205  /**2206   * Set, change, or remove approved address to transfer tokens.2207   *2208   * @param signer keyring of signer2209   * @param collectionId ID of collection2210   * @param toAddressObj address to be approved2211   * @param amount amount of tokens to be approved2212   * @example approveTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n)2213   * @returns ```true``` if extrinsic success, otherwise ```false```2214   */2215  approveTokens(signer: IKeyringPair, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {2216    return super.approveToken(signer, collectionId, 0, toAddressObj, amount);2217  }22182219  /**2220   * Get amount of fungible tokens approved to transfer2221   * @param collectionId ID of collection2222   * @param fromAddressObj owner of tokens2223   * @param toAddressObj the address approved for the transfer of tokens on behalf of the owner2224   * @returns number of tokens approved for the transfer2225   */2226  getApprovedTokens(collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {2227    return super.getTokenApprovedPieces(collectionId, 0, toAddressObj, fromAddressObj);2228  }2229}223022312232class ChainGroup extends HelperGroup<ChainHelperBase> {2233  /**2234   * Get system properties of a chain2235   * @example getChainProperties();2236   * @returns ss58Format, token decimals, and token symbol2237   */2238  getChainProperties(): IChainProperties {2239    const properties = (this.helper.getApi() as any).registry.getChainProperties().toJSON();2240    return {2241      ss58Format: properties.ss58Format.toJSON(),2242      tokenDecimals: properties.tokenDecimals.toJSON(),2243      tokenSymbol: properties.tokenSymbol.toJSON(),2244    };2245  }22462247  /**2248   * Get chain header2249   * @example getLatestBlockNumber();2250   * @returns the number of the last block2251   */2252  async getLatestBlockNumber(): Promise<number> {2253    return (await this.helper.callRpc('api.rpc.chain.getHeader')).number.toNumber();2254  }22552256  /**2257   * Get block hash by block number2258   * @param blockNumber number of block2259   * @example getBlockHashByNumber(12345);2260   * @returns hash of a block2261   */2262  async getBlockHashByNumber(blockNumber: number): Promise<string | null> {2263    const blockHash = (await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockNumber])).toJSON();2264    if(blockHash === '0x0000000000000000000000000000000000000000000000000000000000000000') return null;2265    return blockHash;2266  }22672268  // TODO add docs2269  async getBlock(blockHashOrNumber: string | number): Promise<IBlock | null> {2270    const blockHash = typeof blockHashOrNumber === 'string' ? blockHashOrNumber : await this.getBlockHashByNumber(blockHashOrNumber);2271    if (!blockHash) return null;2272    return (await this.helper.callRpc('api.rpc.chain.getBlock', [blockHash])).toHuman().block;2273  }22742275  /**2276   * Get latest relay block2277   * @returns {number} relay block2278   */2279  async getRelayBlockNumber(): Promise<bigint> {2280    const blockNumber = (await this.helper.callRpc('api.query.parachainSystem.validationData')).toJSON().relayParentNumber;2281    return BigInt(blockNumber);2282  }22832284  /**2285   * Get account nonce2286   * @param address substrate address2287   * @example getNonce("5GrwvaEF5zXb26Fz...");2288   * @returns number, account's nonce2289   */2290  async getNonce(address: TSubstrateAccount): Promise<number> {2291    return (await this.helper.callRpc('api.query.system.account', [address])).nonce.toNumber();2292  }2293}22942295class SubstrateBalanceGroup<T extends ChainHelperBase> extends HelperGroup<T> {2296  /**2297 * Get substrate address balance2298 * @param address substrate address2299 * @example getSubstrate("5GrwvaEF5zXb26Fz...")2300 * @returns amount of tokens on address2301 */2302  async getSubstrate(address: TSubstrateAccount): Promise<bigint> {2303    return (await this.helper.callRpc('api.query.system.account', [address])).data.free.toBigInt();2304  }23052306  /**2307   * Transfer tokens to substrate address2308   * @param signer keyring of signer2309   * @param address substrate address of a recipient2310   * @param amount amount of tokens to be transfered2311   * @example transferToSubstrate(aliceKeyring, "5GrwvaEF5zXb26Fz...", 100_000_000_000n);2312   * @returns ```true``` if extrinsic success, otherwise ```false```2313   */2314  async transferToSubstrate(signer: TSigner, address: TSubstrateAccount, amount: bigint | string): Promise<boolean> {2315    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.transfer', [address, amount], true/*, `Unable to transfer balance from ${this.helper.getSignerAddress(signer)} to ${address}`*/);23162317    let transfer = {from: null, to: null, amount: 0n} as any;2318    result.result.events.forEach(({event: {data, method, section}}) => {2319      if ((section === 'balances') && (method === 'Transfer')) {2320        transfer = {2321          from: this.helper.address.normalizeSubstrate(data[0]),2322          to: this.helper.address.normalizeSubstrate(data[1]),2323          amount: BigInt(data[2]),2324        };2325      }2326    });2327    const isSuccess = this.helper.address.normalizeSubstrate(typeof signer === 'string' ? signer : signer.address) === transfer.from2328      && this.helper.address.normalizeSubstrate(address) === transfer.to2329      && BigInt(amount) === transfer.amount;2330    return isSuccess;2331  }23322333  /**2334   * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved2335   * @param address substrate address2336   * @returns2337   */2338  async getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {2339    const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data;2340    return {free: accountInfo.free.toBigInt(), miscFrozen: accountInfo.miscFrozen.toBigInt(), feeFrozen: accountInfo.feeFrozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};2341  }23422343  async getLocked(address: TSubstrateAccount): Promise<[{id: string, amount: bigint, reason: string}]> {2344    const locks = (await this.helper.callRpc('api.query.balances.locks', [address])).toHuman();2345    return locks.map((lock: any) => {return {id: lock.id, amount: BigInt(lock.amount.replace(/,/g, '')), reasons: lock.reasons};});2346  }2347}23482349class EthereumBalanceGroup<T extends ChainHelperBase> extends HelperGroup<T> {2350  /**2351   * Get ethereum address balance2352   * @param address ethereum address2353   * @example getEthereum("0x9F0583DbB855d...")2354   * @returns amount of tokens on address2355   */2356  async getEthereum(address: TEthereumAccount): Promise<bigint> {2357    return (await this.helper.callRpc('api.rpc.eth.getBalance', [address])).toBigInt();2358  }23592360  /**2361   * Transfer tokens to address2362   * @param signer keyring of signer2363   * @param address Ethereum address of a recipient2364   * @param amount amount of tokens to be transfered2365   * @example transferToEthereum(alithKeyring, "0x9F0583DbB855d...", 100_000_000_000n);2366   * @returns ```true``` if extrinsic success, otherwise ```false```2367   */2368  async transferToEthereum(signer: TSigner, address: TEthereumAccount, amount: bigint | string): Promise<boolean> {2369    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.transfer', [address, amount], true);23702371    let transfer = {from: null, to: null, amount: 0n} as any;2372    result.result.events.forEach(({event: {data, method, section}}) => {2373      if ((section === 'balances') && (method === 'Transfer')) {2374        transfer = {2375          from: data[0].toString(),2376          to: data[1].toString(),2377          amount: BigInt(data[2]),2378        };2379      }2380    });2381    const isSuccess = (typeof signer === 'string' ? signer : signer.address) === transfer.from2382      && address === transfer.to2383      && BigInt(amount) === transfer.amount;2384    return isSuccess;2385  }2386}23872388class BalanceGroup<T extends ChainHelperBase> extends HelperGroup<T> {2389  subBalanceGroup: SubstrateBalanceGroup<T>;2390  ethBalanceGroup: EthereumBalanceGroup<T>;23912392  constructor(helper: T) {2393    super(helper);2394    this.subBalanceGroup = new SubstrateBalanceGroup(helper);2395    this.ethBalanceGroup = new EthereumBalanceGroup(helper);2396  }23972398  getCollectionCreationPrice(): bigint {2399    return 2n * this.getOneTokenNominal();2400  }2401  /**2402   * Representation of the native token in the smallest unit - one OPAL (OPL), QUARTZ (QTZ), or UNIQUE (UNQ).2403   * @example getOneTokenNominal()2404   * @returns ```BigInt``` representation of the native token in the smallest unit, e.g. ```1_000_000_000_000_000_000n``` for QTZ.2405   */2406  getOneTokenNominal(): bigint {2407    const chainProperties = this.helper.chain.getChainProperties();2408    return 10n ** BigInt((chainProperties.tokenDecimals || [18])[0]);2409  }24102411  /**2412   * Get substrate address balance2413   * @param address substrate address2414   * @example getSubstrate("5GrwvaEF5zXb26Fz...")2415   * @returns amount of tokens on address2416   */2417  getSubstrate(address: TSubstrateAccount): Promise<bigint> {2418    return this.subBalanceGroup.getSubstrate(address);2419  }24202421  /**2422   * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved2423   * @param address substrate address2424   * @returns2425   */2426  getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {2427    return this.subBalanceGroup.getSubstrateFull(address);2428  }24292430  /**2431   * Get locked balances2432   * @param address substrate address2433   * @returns locked balances with reason via api.query.balances.locks2434   */2435  getLocked(address: TSubstrateAccount) {2436    return this.subBalanceGroup.getLocked(address);2437  }24382439  /**2440   * Get ethereum address balance2441   * @param address ethereum address2442   * @example getEthereum("0x9F0583DbB855d...")2443   * @returns amount of tokens on address2444   */2445  getEthereum(address: TEthereumAccount): Promise<bigint> {2446    return this.ethBalanceGroup.getEthereum(address);2447  }24482449  /**2450   * Transfer tokens to substrate address2451   * @param signer keyring of signer2452   * @param address substrate address of a recipient2453   * @param amount amount of tokens to be transfered2454   * @example transferToSubstrate(aliceKeyring, "5GrwvaEF5zXb26Fz...", 100_000_000_000n);2455   * @returns ```true``` if extrinsic success, otherwise ```false```2456   */2457  transferToSubstrate(signer: TSigner, address: TSubstrateAccount, amount: bigint | string): Promise<boolean> {2458    return this.subBalanceGroup.transferToSubstrate(signer, address, amount);2459  }24602461  async forceTransferToSubstrate(signer: TSigner, from: TSubstrateAccount, to: TSubstrateAccount, amount: bigint | string): Promise<boolean> {2462    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.forceTransfer', [from, to, amount], true);24632464    let transfer = {from: null, to: null, amount: 0n} as any;2465    result.result.events.forEach(({event: {data, method, section}}) => {2466      if ((section === 'balances') && (method === 'Transfer')) {2467        transfer = {2468          from: this.helper.address.normalizeSubstrate(data[0]),2469          to: this.helper.address.normalizeSubstrate(data[1]),2470          amount: BigInt(data[2]),2471        };2472      }2473    });2474    let isSuccess = this.helper.address.normalizeSubstrate(from) === transfer.from;2475    isSuccess = isSuccess && this.helper.address.normalizeSubstrate(to) === transfer.to;2476    isSuccess = isSuccess && BigInt(amount) === transfer.amount;2477    return isSuccess;2478  }24792480  /**2481   * Transfer tokens with the unlock period2482   * @param signer signers Keyring2483   * @param address Substrate address of recipient2484   * @param schedule Schedule params2485   * @example vestedTransfer(signer, recepient.address, 20000, 100, 10, 50 * nominal); // total amount of vested tokens will be 100 * 50 = 50002486   */2487  async vestedTransfer(signer: TSigner, address: TSubstrateAccount, schedule: {start: bigint, period: bigint, periodCount: bigint, perPeriod: bigint}): Promise<void> {2488    const result = await this.helper.executeExtrinsic(signer, 'api.tx.vesting.vestedTransfer', [address, schedule]);2489    const event = result.result.events2490      .find(e => e.event.section === 'vesting' &&2491            e.event.method === 'VestingScheduleAdded' &&2492            e.event.data[0].toHuman() === signer.address);2493    if (!event) throw Error('Cannot find transfer in events');2494  }24952496  /**2497   * Get schedule for recepient of vested transfer2498   * @param address Substrate address of recipient2499   * @returns2500   */2501  async getVestingSchedules(address: TSubstrateAccount): Promise<{start: bigint, period: bigint, periodCount: bigint, perPeriod: bigint}[]> {2502    const schedule = (await this.helper.callRpc('api.query.vesting.vestingSchedules', [address])).toJSON();2503    return schedule.map((schedule: any) => {2504      return {2505        start: BigInt(schedule.start),2506        period: BigInt(schedule.period),2507        periodCount: BigInt(schedule.periodCount),2508        perPeriod: BigInt(schedule.perPeriod),2509      };2510    });2511  }25122513  /**2514   * Claim vested tokens2515   * @param signer signers Keyring2516   */2517  async claim(signer: TSigner) {2518    const result = await this.helper.executeExtrinsic(signer, 'api.tx.vesting.claim', []);2519    const event = result.result.events2520      .find(e => e.event.section === 'vesting' &&2521            e.event.method === 'Claimed' &&2522            e.event.data[0].toHuman() === signer.address);2523    if (!event) throw Error('Cannot find claim in events');2524  }2525}25262527class AddressGroup extends HelperGroup<ChainHelperBase> {2528  /**2529   * Normalizes the address to the specified ss58 format, by default ```42```.2530   * @param address substrate address2531   * @param ss58Format format for address conversion, by default ```42```2532   * @example normalizeSubstrate("unjKJQJrRd238pkUZZvzDQrfKuM39zBSnQ5zjAGAGcdRhaJTx") // returns 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY2533   * @returns substrate address converted to normalized (i.e., starting with 5) or specified explicitly representation2534   */2535  normalizeSubstrate(address: TSubstrateAccount, ss58Format = 42): TSubstrateAccount {2536    return CrossAccountId.normalizeSubstrateAddress(address, ss58Format);2537  }25382539  /**2540   * Get address in the connected chain format2541   * @param address substrate address2542   * @example normalizeSubstrateToChainFormat("5GrwvaEF5zXb26Fz...") // returns unjKJQJrRd238pkUZZ... for Unique Network2543   * @returns address in chain format2544   */2545  normalizeSubstrateToChainFormat(address: TSubstrateAccount): TSubstrateAccount {2546    return this.normalizeSubstrate(address, this.helper.chain.getChainProperties().ss58Format);2547  }25482549  /**2550   * Get substrate mirror of an ethereum address2551   * @param ethAddress ethereum address2552   * @param toChainFormat false for normalized account2553   * @example ethToSubstrate('0x9F0583DbB855d...')2554   * @returns substrate mirror of a provided ethereum address2555   */2556  ethToSubstrate(ethAddress: TEthereumAccount, toChainFormat=false): TSubstrateAccount {2557    return CrossAccountId.translateEthToSub(ethAddress, toChainFormat ? this.helper.chain.getChainProperties().ss58Format : undefined);2558  }25592560  /**2561   * Get ethereum mirror of a substrate address2562   * @param subAddress substrate account2563   * @example substrateToEth("5DnSF6RRjwteE3BrC...")2564   * @returns ethereum mirror of a provided substrate address2565   */2566  substrateToEth(subAddress: TSubstrateAccount): TEthereumAccount {2567    return CrossAccountId.translateSubToEth(subAddress);2568  }25692570  /**2571   * Encode key to substrate address2572   * @param key key for encoding address2573   * @param ss58Format prefix for encoding to the address of the corresponding network2574   * @returns encoded substrate address2575   */2576  encodeSubstrateAddress (key: Uint8Array | string | bigint, ss58Format = 42): string {2577    const u8a :Uint8Array = typeof key === 'string'2578      ? hexToU8a(key)2579      : typeof key === 'bigint'2580        ? hexToU8a(key.toString(16))2581        : key;25822583    if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) {2584      throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`);2585    }25862587    const allowedDecodedLengths = [1, 2, 4, 8, 32, 33];2588    if (!allowedDecodedLengths.includes(u8a.length)) {2589      throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(', ')}`);2590    }25912592    const u8aPrefix = ss58Format < 642593      ? new Uint8Array([ss58Format])2594      : new Uint8Array([2595        ((ss58Format & 0xfc) >> 2) | 0x40,2596        (ss58Format >> 8) | ((ss58Format & 0x03) << 6),2597      ]);25982599    const input = u8aConcat(u8aPrefix, u8a);26002601    return base58Encode(u8aConcat(2602      input,2603      blake2AsU8a(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1),2604    ));2605  }26062607  /**2608   * Restore substrate address from bigint representation2609   * @param number decimal representation of substrate address2610   * @returns substrate address2611   */2612  restoreCrossAccountFromBigInt(number: bigint): TSubstrateAccount {2613    if (this.helper.api === null) {2614      throw 'Not connected';2615    }2616    const res = this.helper.api.registry.createType('AccountId', '0x' + number.toString(16).padStart(64, '0')).toJSON();2617    if (res === undefined || res === null) {2618      throw 'Restore address error';2619    }2620    return res.toString();2621  }26222623  /**2624   * Convert etherium cross account id to substrate cross account id2625   * @param ethCrossAccount etherium cross account2626   * @returns substrate cross account id2627   */2628  convertCrossAccountFromEthCrossAccount(ethCrossAccount: IEthCrossAccountId): ICrossAccountId {2629    if (ethCrossAccount.sub === '0') {2630      return {Ethereum: ethCrossAccount.eth.toLocaleLowerCase()};2631    }26322633    const ss58 = this.restoreCrossAccountFromBigInt(BigInt(ethCrossAccount.sub));2634    return {Substrate: ss58};2635  }26362637  paraSiblingSovereignAccount(paraid: number) {2638    // We are getting a *sibling* parachain sovereign account,2639    // so we need a sibling prefix: encoded(b"sibl") == 0x7369626c2640    const siblingPrefix = '0x7369626c';26412642    const encodedParaId = this.helper.getApi().createType('u32', paraid).toHex(true).substring(2);2643    const suffix = '000000000000000000000000000000000000000000000000';26442645    return siblingPrefix + encodedParaId + suffix;2646  }2647}26482649class StakingGroup extends HelperGroup<UniqueHelper> {2650  /**2651   * Stake tokens for App Promotion2652   * @param signer keyring of signer2653   * @param amountToStake amount of tokens to stake2654   * @param label extra label for log2655   * @returns2656   */2657  async stake(signer: TSigner, amountToStake: bigint, label?: string): Promise<boolean> {2658    if(typeof label === 'undefined') label = `${signer.address} amount: ${amountToStake}`;2659    const _stakeResult = await this.helper.executeExtrinsic(2660      signer, 'api.tx.appPromotion.stake',2661      [amountToStake], true,2662    );2663    // TODO extract info from stakeResult2664    return true;2665  }26662667  /**2668   * Unstake all staked tokens2669   * @param signer keyring of signer2670   * @param amountToUnstake amount of tokens to unstake2671   * @param label extra label for log2672   * @returns block hash where unstake happened2673   */2674  async unstakeAll(signer: TSigner, label?: string): Promise<string> {2675    if(typeof label === 'undefined') label = `${signer.address}`;2676    const unstakeResult = await this.helper.executeExtrinsic(2677      signer, 'api.tx.appPromotion.unstakeAll',2678      [], true,2679    );2680    return unstakeResult.blockHash;2681  }26822683  /**2684   * Unstake the part of a staked tokens2685   * @param signer keyring of signer2686   * @param amount amount of tokens to unstake2687   * @param label extra label for log2688   * @returns block hash where unstake happened2689   */2690  async unstakePartial(signer: TSigner, amount: bigint, label?: string): Promise<string> {2691    if(typeof label === 'undefined') label = `${signer.address}`;2692    const unstakeResult = await this.helper.executeExtrinsic(2693      signer, 'api.tx.appPromotion.unstakePartial',2694      [amount], true,2695    );2696    return unstakeResult.blockHash;2697  }26982699  /**2700   * Get total number of active stakes2701   * @param address substrate address2702   * @returns {number}2703   */2704  async getStakesNumber(address: ICrossAccountId): Promise<number> {2705    if (address.Ethereum) throw Error('only substrate address');2706    return (await this.helper.callRpc('api.query.appPromotion.stakesPerAccount', [address.Substrate])).toNumber();2707  }27082709  /**2710   * Get total staked amount for address2711   * @param address substrate or ethereum address2712   * @returns total staked amount2713   */2714  async getTotalStaked(address?: ICrossAccountId): Promise<bigint> {2715    if (address) return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked', [address])).toBigInt();2716    return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked')).toBigInt();2717  }27182719  /**2720   * Get total staked per block2721   * @param address substrate or ethereum address2722   * @returns array of stakes. `block` – the number of the block in which the stake was made. `amount` - the number of tokens staked in the block2723   */2724  async getTotalStakedPerBlock(address: ICrossAccountId): Promise<IStakingInfo[]> {2725    const rawTotalStakerdPerBlock = await this.helper.callRpc('api.rpc.appPromotion.totalStakedPerBlock', [address]);2726    return rawTotalStakerdPerBlock.map(([block, amount]: any[]) => {2727      return {2728        block: block.toBigInt(),2729        amount: amount.toBigInt(),2730      };2731    });2732  }27332734  /**2735   * Get total pending unstake amount for address2736   * @param address substrate or ethereum address2737   * @returns total pending unstake amount2738   */2739  async getPendingUnstake(address: ICrossAccountId): Promise<bigint> {2740    return (await this.helper.callRpc('api.rpc.appPromotion.pendingUnstake', [address])).toBigInt();2741  }27422743  /**2744   * Get pending unstake amount per block for address2745   * @param address substrate or ethereum address2746   * @returns array of pending stakes. `block` – the number of the block in which the unstake was made. `amount` - the number of tokens unstaked in the block2747   */2748  async getPendingUnstakePerBlock(address: ICrossAccountId): Promise<IStakingInfo[]> {2749    const rawUnstakedPerBlock = await this.helper.callRpc('api.rpc.appPromotion.pendingUnstakePerBlock', [address]);2750    const result = rawUnstakedPerBlock.map(([block, amount]: any[]) => {2751      return {2752        block: block.toBigInt(),2753        amount: amount.toBigInt(),2754      };2755    });2756    return result;2757  }2758}27592760class SchedulerGroup extends HelperGroup<UniqueHelper> {2761  constructor(helper: UniqueHelper) {2762    super(helper);2763  }27642765  cancelScheduled(signer: TSigner, scheduledId: string) {2766    return this.helper.executeExtrinsic(2767      signer,2768      'api.tx.scheduler.cancelNamed',2769      [scheduledId],2770      true,2771    );2772  }27732774  changePriority(signer: TSigner, scheduledId: string, priority: number) {2775    return this.helper.executeExtrinsic(2776      signer,2777      'api.tx.scheduler.changeNamedPriority',2778      [scheduledId, priority],2779      true,2780    );2781  }27822783  scheduleAt<T extends UniqueHelper>(2784    executionBlockNumber: number,2785    options: ISchedulerOptions = {},2786  ) {2787    return this.schedule<T>('schedule', executionBlockNumber, options);2788  }27892790  scheduleAfter<T extends UniqueHelper>(2791    blocksBeforeExecution: number,2792    options: ISchedulerOptions = {},2793  ) {2794    return this.schedule<T>('scheduleAfter', blocksBeforeExecution, options);2795  }27962797  schedule<T extends UniqueHelper>(2798    scheduleFn: 'schedule' | 'scheduleAfter',2799    blocksNum: number,2800    options: ISchedulerOptions = {},2801  ) {2802    // eslint-disable-next-line @typescript-eslint/naming-convention2803    const ScheduledHelperType = ScheduledUniqueHelper(this.helper.helperBase);2804    return this.helper.clone(ScheduledHelperType, {2805      scheduleFn,2806      blocksNum,2807      options,2808    }) as T;2809  }2810}28112812class CollatorSelectionGroup extends HelperGroup<UniqueHelper> {2813  //todo:collator documentation2814  addInvulnerable(signer: TSigner, address: string) {2815    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.addInvulnerable', [address]);2816  }28172818  removeInvulnerable(signer: TSigner, address: string) {2819    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.removeInvulnerable', [address]);2820  }28212822  async getInvulnerables(): Promise<string[]> {2823    return (await this.helper.callRpc('api.query.collatorSelection.invulnerables')).map((x: any) => x.toHuman());2824  }28252826  /** and also total max invulnerables */2827  maxCollators(): number {2828    return (this.helper.getApi().consts.configuration.defaultCollatorSelectionMaxCollators.toJSON() as number);2829  }28302831  async getDesiredCollators(): Promise<number> {2832    return (await this.helper.callRpc('api.query.configuration.collatorSelectionDesiredCollatorsOverride')).toNumber();2833  }28342835  setLicenseBond(signer: TSigner, amount: bigint) {2836    return this.helper.executeExtrinsic(signer, 'api.tx.configuration.setCollatorSelectionLicenseBond', [amount]);2837  }28382839  async getLicenseBond(): Promise<bigint> {2840    return (await this.helper.callRpc('api.query.configuration.collatorSelectionLicenseBondOverride')).toBigInt();2841  }28422843  obtainLicense(signer: TSigner) {2844    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.getLicense', []);2845  }28462847  releaseLicense(signer: TSigner) {2848    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.releaseLicense', []);2849  }28502851  forceReleaseLicense(signer: TSigner, released: string) {2852    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.forceReleaseLicense', [released]);2853  }28542855  async hasLicense(address: string): Promise<bigint> {2856    return (await this.helper.callRpc('api.query.collatorSelection.licenseDepositOf', [address])).toBigInt();2857  }28582859  onboard(signer: TSigner) {2860    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.onboard', []);2861  }28622863  offboard(signer: TSigner) {2864    return this.helper.executeExtrinsic(signer, 'api.tx.collatorSelection.offboard', []);2865  }28662867  async getCandidates(): Promise<string[]> {2868    return (await this.helper.callRpc('api.query.collatorSelection.candidates')).map((x: any) => x.toHuman());2869  }2870}28712872class PreimageGroup extends HelperGroup<UniqueHelper> {2873  async getPreimageInfo(h256: string) {2874    return (await this.helper.callRpc('api.query.preimage.statusFor', [h256])).toJSON();2875  }28762877  /**2878   * Create a preimage with a hex or a byte array.2879   * @param signer keyring of the signer.2880   * @param bytes preimage encoded in hex or a byte array, e.g. an extrinsic call.2881   * @example await notePreimage(preimageMaker,2882   *   helper.constructApiCall('api.tx.identity.forceInsertIdentities', [identitiesToAdd]).method.toHex()2883   * );2884   * @returns promise of extrinsic execution.2885   */2886  notePreimage(signer: TSigner, bytes: string | Uint8Array) {2887    return this.helper.executeExtrinsic(signer, 'api.tx.preimage.notePreimage', [bytes]);2888  }28892890  /**2891   * Delete an existing preimage and return the deposit.2892   * @param signer keyring of the signer - either the owner or the preimage manager (sudo).2893   * @param h256 hash of the preimage.2894   * @returns promise of extrinsic execution.2895   */2896  unnotePreimage(signer: TSigner, h256: string) {2897    return this.helper.executeExtrinsic(signer, 'api.tx.preimage.unnotePreimage', [h256]);2898  }28992900  /**2901   * Request a preimage be uploaded to the chain without paying any fees or deposits.2902   * @param signer keyring of the signer - either the owner or the preimage manager (sudo).2903   * @param h256 hash of the preimage.2904   * @returns promise of extrinsic execution.2905   */2906  requestPreimage(signer: TSigner, h256: string) {2907    return this.helper.executeExtrinsic(signer, 'api.tx.preimage.requestPreimage', [h256]);2908  }29092910  /**2911   * Clear a previously made request for a preimage.2912   * @param signer keyring of the signer - either the owner or the preimage manager (sudo).2913   * @param h256 hash of the preimage.2914   * @returns promise of extrinsic execution.2915   */2916  unrequestPreimage(signer: TSigner, h256: string) {2917    return this.helper.executeExtrinsic(signer, 'api.tx.preimage.unrequestPreimage', [h256]);2918  }2919}29202921class ForeignAssetsGroup extends HelperGroup<UniqueHelper> {2922  async register(signer: TSigner, ownerAddress: TSubstrateAccount, location: any, metadata: IForeignAssetMetadata) {2923    await this.helper.executeExtrinsic(2924      signer,2925      'api.tx.foreignAssets.registerForeignAsset',2926      [ownerAddress, location, metadata],2927      true,2928    );2929  }29302931  async update(signer: TSigner, foreignAssetId: number, location: any, metadata: IForeignAssetMetadata) {2932    await this.helper.executeExtrinsic(2933      signer,2934      'api.tx.foreignAssets.updateForeignAsset',2935      [foreignAssetId, location, metadata],2936      true,2937    );2938  }2939}29402941class XcmGroup<T extends ChainHelperBase> extends HelperGroup<T> {2942  palletName: string;29432944  constructor(helper: T, palletName: string) {2945    super(helper);29462947    this.palletName = palletName;2948  }29492950  async limitedReserveTransferAssets(signer: TSigner, destination: any, beneficiary: any, assets: any, feeAssetItem: number, weightLimit: any) {2951    await this.helper.executeExtrinsic(signer, `api.tx.${this.palletName}.limitedReserveTransferAssets`, [destination, beneficiary, assets, feeAssetItem, weightLimit], true);2952  }29532954  async teleportAssets(signer: TSigner, destination: any, beneficiary: any, assets: any, feeAssetItem: number) {2955    await this.helper.executeExtrinsic(signer, `api.tx.${this.palletName}.teleportAssets`, [destination, beneficiary, assets, feeAssetItem], true);2956  }29572958  async teleportNativeAsset(signer: TSigner, destinationParaId: number, targetAccount: Uint8Array, amount: bigint) {2959    const destination = {2960      V1: {2961        parents: 0,2962        interior: {2963          X1: {2964            Parachain: destinationParaId,2965          },2966        },2967      },2968    };29692970    const beneficiary = {2971      V1: {2972        parents: 0,2973        interior: {2974          X1: {2975            AccountId32: {2976              network: 'Any',2977              id: targetAccount,2978            },2979          },2980        },2981      },2982    };29832984    const assets = {2985      V1: [2986        {2987          id: {2988            Concrete: {2989              parents: 0,2990              interior: 'Here',2991            },2992          },2993          fun: {2994            Fungible: amount,2995          },2996        },2997      ],2998    };29993000    const feeAssetItem = 0;30013002    await this.teleportAssets(signer, destination, beneficiary, assets, feeAssetItem);3003  }3004}30053006class XTokensGroup<T extends ChainHelperBase> extends HelperGroup<T> {3007  async transfer(signer: TSigner, currencyId: any, amount: bigint, destination: any, destWeight: any) {3008    await this.helper.executeExtrinsic(signer, 'api.tx.xTokens.transfer', [currencyId, amount, destination, destWeight], true);3009  }30103011  async transferMultiasset(signer: TSigner, asset: any, destination: any, destWeight: any) {3012    await this.helper.executeExtrinsic(signer, 'api.tx.xTokens.transferMultiasset', [asset, destination, destWeight], true);3013  }30143015  async transferMulticurrencies(signer: TSigner, currencies: any[], feeItem: number, destLocation: any, destWeight: any) {3016    await this.helper.executeExtrinsic(signer, 'api.tx.xTokens.transferMulticurrencies', [currencies, feeItem, destLocation, destWeight], true);3017  }3018}30193020class TokensGroup<T extends ChainHelperBase> extends HelperGroup<T> {3021  async accounts(address: string, currencyId: any) {3022    const {free} = (await this.helper.callRpc('api.query.tokens.accounts', [address, currencyId])).toJSON() as any;3023    return BigInt(free);3024  }3025}30263027class AssetsGroup<T extends ChainHelperBase> extends HelperGroup<T> {3028  async create(signer: TSigner, assetId: number, admin: string, minimalBalance: bigint) {3029    await this.helper.executeExtrinsic(signer, 'api.tx.assets.create', [assetId, admin, minimalBalance], true);3030  }30313032  async setMetadata(signer: TSigner, assetId: number, name: string, symbol: string, decimals: number) {3033    await this.helper.executeExtrinsic(signer, 'api.tx.assets.setMetadata', [assetId, name, symbol, decimals], true);3034  }30353036  async mint(signer: TSigner, assetId: number, beneficiary: string, amount: bigint) {3037    await this.helper.executeExtrinsic(signer, 'api.tx.assets.mint', [assetId, beneficiary, amount], true);3038  }30393040  async account(assetId: string | number, address: string) {3041    const accountAsset = (3042      await this.helper.callRpc('api.query.assets.account', [assetId, address])3043    ).toJSON()! as any;30443045    if (accountAsset !== null) {3046      return BigInt(accountAsset['balance']);3047    } else {3048      return null;3049    }3050  }3051}30523053class AcalaAssetRegistryGroup extends HelperGroup<AcalaHelper> {3054  async registerForeignAsset(signer: TSigner, destination: any, metadata: AcalaAssetMetadata) {3055    await this.helper.executeExtrinsic(signer, 'api.tx.assetRegistry.registerForeignAsset', [destination, metadata], true);3056  }3057}30583059class MoonbeamAssetManagerGroup extends HelperGroup<MoonbeamHelper> {3060  makeRegisterForeignAssetProposal(assetInfo: MoonbeamAssetInfo) {3061    const apiPrefix = 'api.tx.assetManager.';30623063    const registerTx = this.helper.constructApiCall(3064      apiPrefix + 'registerForeignAsset',3065      [assetInfo.location, assetInfo.metadata, assetInfo.existentialDeposit, assetInfo.isSufficient],3066    );30673068    const setUnitsTx = this.helper.constructApiCall(3069      apiPrefix + 'setAssetUnitsPerSecond',3070      [assetInfo.location, assetInfo.unitsPerSecond, assetInfo.numAssetsWeightHint],3071    );30723073    const batchCall = this.helper.getApi().tx.utility.batchAll([registerTx, setUnitsTx]);3074    const encodedProposal = batchCall?.method.toHex() || '';3075    return encodedProposal;3076  }30773078  async assetTypeId(location: any) {3079    return await this.helper.callRpc('api.query.assetManager.assetTypeId', [location]);3080  }3081}30823083class MoonbeamDemocracyGroup extends HelperGroup<MoonbeamHelper> {3084  notePreimagePallet: string;30853086  constructor(helper: MoonbeamHelper, options: {[key: string]: any} = {}) {3087    super(helper);3088    this.notePreimagePallet = options.notePreimagePallet;3089  }30903091  async notePreimage(signer: TSigner, encodedProposal: string) {3092    await this.helper.executeExtrinsic(signer, `api.tx.${this.notePreimagePallet}.notePreimage`, [encodedProposal], true);3093  }30943095  externalProposeMajority(proposal: any) {3096    return this.helper.constructApiCall('api.tx.democracy.externalProposeMajority', [proposal]);3097  }30983099  fastTrack(proposalHash: string, votingPeriod: number, delayPeriod: number) {3100    return this.helper.constructApiCall('api.tx.democracy.fastTrack', [proposalHash, votingPeriod, delayPeriod]);3101  }31023103  async referendumVote(signer: TSigner, referendumIndex: number, accountVote: DemocracyStandardAccountVote) {3104    await this.helper.executeExtrinsic(signer, 'api.tx.democracy.vote', [referendumIndex, {Standard: accountVote}], true);3105  }3106}31073108class MoonbeamCollectiveGroup extends HelperGroup<MoonbeamHelper> {3109  collective: string;31103111  constructor(helper: MoonbeamHelper, collective: string) {3112    super(helper);31133114    this.collective = collective;3115  }31163117  async propose(signer: TSigner, threshold: number, proposalHash: string, lengthBound: number) {3118    await this.helper.executeExtrinsic(signer, `api.tx.${this.collective}.propose`, [threshold, proposalHash, lengthBound], true);3119  }31203121  async vote(signer: TSigner, proposalHash: string, proposalIndex: number, approve: boolean) {3122    await this.helper.executeExtrinsic(signer, `api.tx.${this.collective}.vote`, [proposalHash, proposalIndex, approve], true);3123  }31243125  async close(signer: TSigner, proposalHash: string, proposalIndex: number, weightBound: any, lengthBound: number) {3126    await this.helper.executeExtrinsic(signer, `api.tx.${this.collective}.close`, [proposalHash, proposalIndex, weightBound, lengthBound], true);3127  }31283129  async proposalCount() {3130    return Number(await this.helper.callRpc(`api.query.${this.collective}.proposalCount`, []));3131  }3132}31333134export type ChainHelperBaseConstructor = new(...args: any[]) => ChainHelperBase;3135export type UniqueHelperConstructor = new(...args: any[]) => UniqueHelper;31363137export class UniqueHelper extends ChainHelperBase {3138  balance: BalanceGroup<UniqueHelper>;3139  collection: CollectionGroup;3140  nft: NFTGroup;3141  rft: RFTGroup;3142  ft: FTGroup;3143  staking: StakingGroup;3144  scheduler: SchedulerGroup;3145  collatorSelection: CollatorSelectionGroup;3146  preimage: PreimageGroup;3147  foreignAssets: ForeignAssetsGroup;3148  xcm: XcmGroup<UniqueHelper>;3149  xTokens: XTokensGroup<UniqueHelper>;3150  tokens: TokensGroup<UniqueHelper>;31513152  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3153    super(logger, options.helperBase ?? UniqueHelper);31543155    this.balance = new BalanceGroup(this);3156    this.collection = new CollectionGroup(this);3157    this.nft = new NFTGroup(this);3158    this.rft = new RFTGroup(this);3159    this.ft = new FTGroup(this);3160    this.staking = new StakingGroup(this);3161    this.scheduler = new SchedulerGroup(this);3162    this.collatorSelection = new CollatorSelectionGroup(this);3163    this.preimage = new PreimageGroup(this);3164    this.foreignAssets = new ForeignAssetsGroup(this);3165    this.xcm = new XcmGroup(this, 'polkadotXcm');3166    this.xTokens = new XTokensGroup(this);3167    this.tokens = new TokensGroup(this);3168  }31693170  getSudo<T extends UniqueHelper>() {3171    // eslint-disable-next-line @typescript-eslint/naming-convention3172    const SudoHelperType = SudoHelper(this.helperBase);3173    return this.clone(SudoHelperType) as T;3174  }3175}31763177export class XcmChainHelper extends ChainHelperBase {3178  async connect(wsEndpoint: string, _listeners?: any): Promise<void> {3179    const wsProvider = new WsProvider(wsEndpoint);3180    this.api = new ApiPromise({3181      provider: wsProvider,3182    });3183    await this.api.isReadyOrError;3184    this.network = await UniqueHelper.detectNetwork(this.api);3185  }3186}31873188export class RelayHelper extends XcmChainHelper {3189  balance: SubstrateBalanceGroup<RelayHelper>;3190  xcm: XcmGroup<RelayHelper>;31913192  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3193    super(logger, options.helperBase ?? RelayHelper);31943195    this.balance = new SubstrateBalanceGroup(this);3196    this.xcm = new XcmGroup(this, 'xcmPallet');3197  }3198}31993200export class WestmintHelper extends XcmChainHelper {3201  balance: SubstrateBalanceGroup<WestmintHelper>;3202  xcm: XcmGroup<WestmintHelper>;3203  assets: AssetsGroup<WestmintHelper>;3204  xTokens: XTokensGroup<WestmintHelper>;32053206  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3207    super(logger, options.helperBase ?? WestmintHelper);32083209    this.balance = new SubstrateBalanceGroup(this);3210    this.xcm = new XcmGroup(this, 'polkadotXcm');3211    this.assets = new AssetsGroup(this);3212    this.xTokens = new XTokensGroup(this);3213  }3214}32153216export class MoonbeamHelper extends XcmChainHelper {3217  balance: EthereumBalanceGroup<MoonbeamHelper>;3218  assetManager: MoonbeamAssetManagerGroup;3219  assets: AssetsGroup<MoonbeamHelper>;3220  xTokens: XTokensGroup<MoonbeamHelper>;3221  democracy: MoonbeamDemocracyGroup;3222  collective: {3223    council: MoonbeamCollectiveGroup,3224    techCommittee: MoonbeamCollectiveGroup,3225  };32263227  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3228    super(logger, options.helperBase ?? MoonbeamHelper);32293230    this.balance = new EthereumBalanceGroup(this);3231    this.assetManager = new MoonbeamAssetManagerGroup(this);3232    this.assets = new AssetsGroup(this);3233    this.xTokens = new XTokensGroup(this);3234    this.democracy = new MoonbeamDemocracyGroup(this, options);3235    this.collective = {3236      council: new MoonbeamCollectiveGroup(this, 'councilCollective'),3237      techCommittee: new MoonbeamCollectiveGroup(this, 'techCommitteeCollective'),3238    };3239  }3240}32413242export class AcalaHelper extends XcmChainHelper {3243  balance: SubstrateBalanceGroup<AcalaHelper>;3244  assetRegistry: AcalaAssetRegistryGroup;3245  xTokens: XTokensGroup<AcalaHelper>;3246  tokens: TokensGroup<AcalaHelper>;32473248  constructor(logger?: ILogger, options: {[key: string]: any} = {}) {3249    super(logger, options.helperBase ?? AcalaHelper);32503251    this.balance = new SubstrateBalanceGroup(this);3252    this.assetRegistry = new AcalaAssetRegistryGroup(this);3253    this.xTokens = new XTokensGroup(this);3254    this.tokens = new TokensGroup(this);3255  }32563257  getSudo<T extends AcalaHelper>() {3258    // eslint-disable-next-line @typescript-eslint/naming-convention3259    const SudoHelperType = SudoHelper(this.helperBase);3260    return this.clone(SudoHelperType) as T;3261  }3262}32633264// eslint-disable-next-line @typescript-eslint/naming-convention3265function ScheduledUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {3266  return class extends Base {3267    scheduleFn: 'schedule' | 'scheduleAfter';3268    blocksNum: number;3269    options: ISchedulerOptions;32703271    constructor(...args: any[]) {3272      const logger = args[0] as ILogger;3273      const options = args[1] as {3274        scheduleFn: 'schedule' | 'scheduleAfter',3275        blocksNum: number,3276        options: ISchedulerOptions3277      };32783279      super(logger);32803281      this.scheduleFn = options.scheduleFn;3282      this.blocksNum = options.blocksNum;3283      this.options = options.options;3284    }32853286    executeExtrinsic(sender: IKeyringPair, scheduledExtrinsic: string, scheduledParams: any[], expectSuccess?: boolean): Promise<ITransactionResult> {3287      const scheduledTx = this.constructApiCall(scheduledExtrinsic, scheduledParams);32883289      const mandatorySchedArgs = [3290        this.blocksNum,3291        this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,3292        this.options.priority ?? null,3293        scheduledTx,3294      ];32953296      let schedArgs;3297      let scheduleFn;32983299      if (this.options.scheduledId) {3300        schedArgs = [this.options.scheduledId!, ...mandatorySchedArgs];33013302        if (this.scheduleFn == 'schedule') {3303          scheduleFn = 'scheduleNamed';3304        } else if (this.scheduleFn == 'scheduleAfter') {3305          scheduleFn = 'scheduleNamedAfter';3306        }3307      } else {3308        schedArgs = mandatorySchedArgs;3309        scheduleFn = this.scheduleFn;3310      }33113312      const extrinsic = 'api.tx.scheduler.' +  scheduleFn;33133314      return super.executeExtrinsic(3315        sender,3316        extrinsic,3317        schedArgs,3318        expectSuccess,3319      );3320    }3321  };3322}33233324// eslint-disable-next-line @typescript-eslint/naming-convention3325function SudoHelper<T extends ChainHelperBaseConstructor>(Base: T) {3326  return class extends Base {3327    constructor(...args: any[]) {3328      super(...args);3329    }33303331    async executeExtrinsic(3332      sender: IKeyringPair,3333      extrinsic: string,3334      params: any[],3335      expectSuccess?: boolean,3336      options: Partial<SignerOptions>|null = null,3337    ): Promise<ITransactionResult> {3338      const call = this.constructApiCall(extrinsic, params);3339      const result = await super.executeExtrinsic(3340        sender,3341        'api.tx.sudo.sudo',3342        [call],3343        expectSuccess,3344        options,3345      );33463347      if (result.status === 'Fail') return result;33483349      const data = (result.result.events.find(x => x.event.section == 'sudo' && x.event.method == 'Sudid')?.event.data as any).sudoResult;3350      if (data.isErr) {3351        if (data.asErr.isModule) {3352          const error = (result.result.events[1].event.data as any).sudoResult.asErr.asModule;3353          const metaError = super.getApi()?.registry.findMetaError(error);3354          throw new Error(`${metaError.section}.${metaError.name}`);3355        } else {3356          throw new Error(data.asErr.toHuman());3357        }3358      }3359      return result;3360    }3361  };3362}33633364export class UniqueBaseCollection {3365  helper: UniqueHelper;3366  collectionId: number;33673368  constructor(collectionId: number, uniqueHelper: UniqueHelper) {3369    this.collectionId = collectionId;3370    this.helper = uniqueHelper;3371  }33723373  async getData() {3374    return await this.helper.collection.getData(this.collectionId);3375  }33763377  async getLastTokenId() {3378    return await this.helper.collection.getLastTokenId(this.collectionId);3379  }33803381  async doesTokenExist(tokenId: number) {3382    return await this.helper.collection.doesTokenExist(this.collectionId, tokenId);3383  }33843385  async getAdmins() {3386    return await this.helper.collection.getAdmins(this.collectionId);3387  }33883389  async getAllowList() {3390    return await this.helper.collection.getAllowList(this.collectionId);3391  }33923393  async getEffectiveLimits() {3394    return await this.helper.collection.getEffectiveLimits(this.collectionId);3395  }33963397  async getProperties(propertyKeys?: string[] | null) {3398    return await this.helper.collection.getProperties(this.collectionId, propertyKeys);3399  }34003401  async getPropertiesConsumedSpace() {3402    return await this.helper.collection.getPropertiesConsumedSpace(this.collectionId);3403  }34043405  async getTokenNextSponsored(tokenId: number, addressObj: ICrossAccountId) {3406    return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);3407  }34083409  async getOptions() {3410    return await this.helper.collection.getCollectionOptions(this.collectionId);3411  }34123413  async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {3414    return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);3415  }34163417  async confirmSponsorship(signer: TSigner) {3418    return await this.helper.collection.confirmSponsorship(signer, this.collectionId);3419  }34203421  async removeSponsor(signer: TSigner) {3422    return await this.helper.collection.removeSponsor(signer, this.collectionId);3423  }34243425  async setLimits(signer: TSigner, limits: ICollectionLimits) {3426    return await this.helper.collection.setLimits(signer, this.collectionId, limits);3427  }34283429  async changeOwner(signer: TSigner, ownerAddress: TSubstrateAccount) {3430    return await this.helper.collection.changeOwner(signer, this.collectionId, ownerAddress);3431  }34323433  async addAdmin(signer: TSigner, adminAddressObj: ICrossAccountId) {3434    return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj);3435  }34363437  async addToAllowList(signer: TSigner, addressObj: ICrossAccountId) {3438    return await this.helper.collection.addToAllowList(signer, this.collectionId, addressObj);3439  }34403441  async removeFromAllowList(signer: TSigner, addressObj: ICrossAccountId) {3442    return await this.helper.collection.removeFromAllowList(signer, this.collectionId, addressObj);3443  }34443445  async removeAdmin(signer: TSigner, adminAddressObj: ICrossAccountId) {3446    return await this.helper.collection.removeAdmin(signer, this.collectionId, adminAddressObj);3447  }34483449  async setProperties(signer: TSigner, properties: IProperty[]) {3450    return await this.helper.collection.setProperties(signer, this.collectionId, properties);3451  }34523453  async deleteProperties(signer: TSigner, propertyKeys: string[]) {3454    return await this.helper.collection.deleteProperties(signer, this.collectionId, propertyKeys);3455  }34563457  async setPermissions(signer: TSigner, permissions: ICollectionPermissions) {3458    return await this.helper.collection.setPermissions(signer, this.collectionId, permissions);3459  }34603461  async enableNesting(signer: TSigner, permissions: INestingPermissions) {3462    return await this.helper.collection.enableNesting(signer, this.collectionId, permissions);3463  }34643465  async disableNesting(signer: TSigner) {3466    return await this.helper.collection.disableNesting(signer, this.collectionId);3467  }34683469  async burn(signer: TSigner) {3470    return await this.helper.collection.burn(signer, this.collectionId);3471  }34723473  scheduleAt<T extends UniqueHelper>(3474    executionBlockNumber: number,3475    options: ISchedulerOptions = {},3476  ) {3477    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3478    return new UniqueBaseCollection(this.collectionId, scheduledHelper);3479  }34803481  scheduleAfter<T extends UniqueHelper>(3482    blocksBeforeExecution: number,3483    options: ISchedulerOptions = {},3484  ) {3485    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3486    return new UniqueBaseCollection(this.collectionId, scheduledHelper);3487  }34883489  getSudo<T extends UniqueHelper>() {3490    return new UniqueBaseCollection(this.collectionId, this.helper.getSudo<T>());3491  }3492}349334943495export class UniqueNFTCollection extends UniqueBaseCollection {3496  getTokenObject(tokenId: number) {3497    return new UniqueNFToken(tokenId, this);3498  }34993500  async getTokensByAddress(addressObj: ICrossAccountId) {3501    return await this.helper.nft.getTokensByAddress(this.collectionId, addressObj);3502  }35033504  async getToken(tokenId: number, blockHashAt?: string) {3505    return await this.helper.nft.getToken(this.collectionId, tokenId, [], blockHashAt);3506  }35073508  async getTokenOwner(tokenId: number, blockHashAt?: string) {3509    return await this.helper.nft.getTokenOwner(this.collectionId, tokenId, blockHashAt);3510  }35113512  async getTokenTopmostOwner(tokenId: number, blockHashAt?: string) {3513    return await this.helper.nft.getTokenTopmostOwner(this.collectionId, tokenId, blockHashAt);3514  }35153516  async getTokenChildren(tokenId: number, blockHashAt?: string) {3517    return await this.helper.nft.getTokenChildren(this.collectionId, tokenId, blockHashAt);3518  }35193520  async getPropertyPermissions(propertyKeys: string[] | null = null) {3521    return await this.helper.nft.getPropertyPermissions(this.collectionId, propertyKeys);3522  }35233524  async getTokenProperties(tokenId: number, propertyKeys?: string[] | null) {3525    return await this.helper.nft.getTokenProperties(this.collectionId, tokenId, propertyKeys);3526  }35273528  async getTokenPropertiesConsumedSpace(tokenId: number): Promise<number> {3529    const api = this.helper.getApi();3530    const props = (await api.query.nonfungible.tokenProperties(this.collectionId, tokenId)).toJSON();35313532    return (props! as any).consumedSpace;3533  }35343535  async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId) {3536    return await this.helper.nft.transferToken(signer, this.collectionId, tokenId, addressObj);3537  }35383539  async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3540    return await this.helper.nft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj);3541  }35423543  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId) {3544    return await this.helper.nft.approveToken(signer, this.collectionId, tokenId, toAddressObj);3545  }35463547  async isTokenApproved(tokenId: number, toAddressObj: ICrossAccountId) {3548    return await this.helper.nft.isTokenApproved(this.collectionId, tokenId, toAddressObj);3549  }35503551  async mintToken(signer: TSigner, owner: ICrossAccountId = {Substrate: signer.address}, properties?: IProperty[]) {3552    return await this.helper.nft.mintToken(signer, {collectionId: this.collectionId, owner, properties});3553  }35543555  async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]) {3556    return await this.helper.nft.mintMultipleTokens(signer, this.collectionId, tokens);3557  }35583559  async burnToken(signer: TSigner, tokenId: number) {3560    return await this.helper.nft.burnToken(signer, this.collectionId, tokenId);3561  }35623563  async burnTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId) {3564    return await this.helper.nft.burnTokenFrom(signer, this.collectionId, tokenId, fromAddressObj);3565  }35663567  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[]) {3568    return await this.helper.nft.setTokenProperties(signer, this.collectionId, tokenId, properties);3569  }35703571  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[]) {3572    return await this.helper.nft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys);3573  }35743575  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[]) {3576    return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions);3577  }35783579  async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken) {3580    return await this.helper.nft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj);3581  }35823583  async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3584    return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);3585  }35863587  scheduleAt<T extends UniqueHelper>(3588    executionBlockNumber: number,3589    options: ISchedulerOptions = {},3590  ) {3591    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3592    return new UniqueNFTCollection(this.collectionId, scheduledHelper);3593  }35943595  scheduleAfter<T extends UniqueHelper>(3596    blocksBeforeExecution: number,3597    options: ISchedulerOptions = {},3598  ) {3599    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3600    return new UniqueNFTCollection(this.collectionId, scheduledHelper);3601  }36023603  getSudo<T extends UniqueHelper>() {3604    return new UniqueNFTCollection(this.collectionId, this.helper.getSudo<T>());3605  }3606}360736083609export class UniqueRFTCollection extends UniqueBaseCollection {3610  getTokenObject(tokenId: number) {3611    return new UniqueRFToken(tokenId, this);3612  }36133614  async getToken(tokenId: number, blockHashAt?: string) {3615    return await this.helper.rft.getToken(this.collectionId, tokenId, [], blockHashAt);3616  }36173618  async getTokenOwner(tokenId: number, blockHashAt?: string) {3619    return await this.helper.rft.getTokenOwner(this.collectionId, tokenId, blockHashAt);3620  }36213622  async getTokensByAddress(addressObj: ICrossAccountId) {3623    return await this.helper.rft.getTokensByAddress(this.collectionId, addressObj);3624  }36253626  async getTop10TokenOwners(tokenId: number) {3627    return await this.helper.rft.getTokenTop10Owners(this.collectionId, tokenId);3628  }36293630  async getTokenTopmostOwner(tokenId: number, blockHashAt?: string) {3631    return await this.helper.rft.getTokenTopmostOwner(this.collectionId, tokenId, blockHashAt);3632  }36333634  async getTokenBalance(tokenId: number, addressObj: ICrossAccountId) {3635    return await this.helper.rft.getTokenBalance(this.collectionId, tokenId, addressObj);3636  }36373638  async getTokenTotalPieces(tokenId: number) {3639    return await this.helper.rft.getTokenTotalPieces(this.collectionId, tokenId);3640  }36413642  async getTokenApprovedPieces(tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3643    return await this.helper.rft.getTokenApprovedPieces(this.collectionId, tokenId, toAddressObj, fromAddressObj);3644  }36453646  async getPropertyPermissions(propertyKeys: string[] | null = null) {3647    return await this.helper.rft.getPropertyPermissions(this.collectionId, propertyKeys);3648  }36493650  async getTokenProperties(tokenId: number, propertyKeys?: string[] | null) {3651    return await this.helper.rft.getTokenProperties(this.collectionId, tokenId, propertyKeys);3652  }36533654  async getTokenPropertiesConsumedSpace(tokenId: number): Promise<number> {3655    const api = this.helper.getApi();3656    const props = (await api.query.refungible.tokenProperties(this.collectionId, tokenId)).toJSON();36573658    return (props! as any).consumedSpace;3659  }36603661  async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId, amount=1n) {3662    return await this.helper.rft.transferToken(signer, this.collectionId, tokenId, addressObj, amount);3663  }36643665  async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {3666    return await this.helper.rft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj, amount);3667  }36683669  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {3670    return await this.helper.rft.approveToken(signer, this.collectionId, tokenId, toAddressObj, amount);3671  }36723673  async repartitionToken(signer: TSigner, tokenId: number, amount: bigint) {3674    return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount);3675  }36763677  async mintToken(signer: TSigner, pieces = 1n, owner: ICrossAccountId = {Substrate: signer.address}, properties?: IProperty[]) {3678    return await this.helper.rft.mintToken(signer, {collectionId: this.collectionId, owner, pieces, properties});3679  }36803681  async mintMultipleTokens(signer: TSigner, tokens: {pieces: bigint, owner: ICrossAccountId, properties?: IProperty[]}[]) {3682    return await this.helper.rft.mintMultipleTokens(signer, this.collectionId, tokens);3683  }36843685  async burnToken(signer: TSigner, tokenId: number, amount=1n) {3686    return await this.helper.rft.burnToken(signer, this.collectionId, tokenId, amount);3687  }36883689  async burnTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId,  amount=1n) {3690    return await this.helper.rft.burnTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, amount);3691  }36923693  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[]) {3694    return await this.helper.rft.setTokenProperties(signer, this.collectionId, tokenId, properties);3695  }36963697  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[]) {3698    return await this.helper.rft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys);3699  }37003701  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[]) {3702    return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions);3703  }37043705  async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken) {3706    return await this.helper.rft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj);3707  }37083709  async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3710    return await this.helper.rft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);3711  }37123713  scheduleAt<T extends UniqueHelper>(3714    executionBlockNumber: number,3715    options: ISchedulerOptions = {},3716  ) {3717    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3718    return new UniqueRFTCollection(this.collectionId, scheduledHelper);3719  }37203721  scheduleAfter<T extends UniqueHelper>(3722    blocksBeforeExecution: number,3723    options: ISchedulerOptions = {},3724  ) {3725    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3726    return new UniqueRFTCollection(this.collectionId, scheduledHelper);3727  }37283729  getSudo<T extends UniqueHelper>() {3730    return new UniqueRFTCollection(this.collectionId, this.helper.getSudo<T>());3731  }3732}373337343735export class UniqueFTCollection extends UniqueBaseCollection {3736  async getBalance(addressObj: ICrossAccountId) {3737    return await this.helper.ft.getBalance(this.collectionId, addressObj);3738  }37393740  async getTotalPieces() {3741    return await this.helper.ft.getTotalPieces(this.collectionId);3742  }37433744  async getApprovedTokens(fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3745    return await this.helper.ft.getApprovedTokens(this.collectionId, fromAddressObj, toAddressObj);3746  }37473748  async getTop10Owners() {3749    return await this.helper.ft.getTop10Owners(this.collectionId);3750  }37513752  async mint(signer: TSigner, amount=1n, owner: ICrossAccountId = {Substrate: signer.address}) {3753    return await this.helper.ft.mintTokens(signer, this.collectionId, amount, owner);3754  }37553756  async mintWithOneOwner(signer: TSigner, tokens: {value: bigint}[], owner: ICrossAccountId = {Substrate: signer.address}) {3757    return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, tokens, owner);3758  }37593760  async transfer(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {3761    return await this.helper.ft.transfer(signer, this.collectionId, toAddressObj, amount);3762  }37633764  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {3765    return await this.helper.ft.transferFrom(signer, this.collectionId, fromAddressObj, toAddressObj, amount);3766  }37673768  async burnTokens(signer: TSigner, amount=1n) {3769    return await this.helper.ft.burnTokens(signer, this.collectionId, amount);3770  }37713772  async burnTokensFrom(signer: TSigner, fromAddressObj: ICrossAccountId, amount=1n) {3773    return await this.helper.ft.burnTokensFrom(signer, this.collectionId, fromAddressObj, amount);3774  }37753776  async approveTokens(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {3777    return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);3778  }37793780  scheduleAt<T extends UniqueHelper>(3781    executionBlockNumber: number,3782    options: ISchedulerOptions = {},3783  ) {3784    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);3785    return new UniqueFTCollection(this.collectionId, scheduledHelper);3786  }37873788  scheduleAfter<T extends UniqueHelper>(3789    blocksBeforeExecution: number,3790    options: ISchedulerOptions = {},3791  ) {3792    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);3793    return new UniqueFTCollection(this.collectionId, scheduledHelper);3794  }37953796  getSudo<T extends UniqueHelper>() {3797    return new UniqueFTCollection(this.collectionId, this.helper.getSudo<T>());3798  }3799}380038013802export class UniqueBaseToken {3803  collection: UniqueNFTCollection | UniqueRFTCollection;3804  collectionId: number;3805  tokenId: number;38063807  constructor(tokenId: number, collection: UniqueNFTCollection | UniqueRFTCollection) {3808    this.collection = collection;3809    this.collectionId = collection.collectionId;3810    this.tokenId = tokenId;3811  }38123813  async getNextSponsored(addressObj: ICrossAccountId) {3814    return await this.collection.getTokenNextSponsored(this.tokenId, addressObj);3815  }38163817  async getProperties(propertyKeys?: string[] | null) {3818    return await this.collection.getTokenProperties(this.tokenId, propertyKeys);3819  }38203821  async getTokenPropertiesConsumedSpace() {3822    return await this.collection.getTokenPropertiesConsumedSpace(this.tokenId);3823  }38243825  async setProperties(signer: TSigner, properties: IProperty[]) {3826    return await this.collection.setTokenProperties(signer, this.tokenId, properties);3827  }38283829  async deleteProperties(signer: TSigner, propertyKeys: string[]) {3830    return await this.collection.deleteTokenProperties(signer, this.tokenId, propertyKeys);3831  }38323833  async doesExist() {3834    return await this.collection.doesTokenExist(this.tokenId);3835  }38363837  nestingAccount() {3838    return this.collection.helper.util.getTokenAccount(this);3839  }38403841  scheduleAt<T extends UniqueHelper>(3842    executionBlockNumber: number,3843    options: ISchedulerOptions = {},3844  ) {3845    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);3846    return new UniqueBaseToken(this.tokenId, scheduledCollection);3847  }38483849  scheduleAfter<T extends UniqueHelper>(3850    blocksBeforeExecution: number,3851    options: ISchedulerOptions = {},3852  ) {3853    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);3854    return new UniqueBaseToken(this.tokenId, scheduledCollection);3855  }38563857  getSudo<T extends UniqueHelper>() {3858    return new UniqueBaseToken(this.tokenId, this.collection.getSudo<T>());3859  }3860}386138623863export class UniqueNFToken extends UniqueBaseToken {3864  collection: UniqueNFTCollection;38653866  constructor(tokenId: number, collection: UniqueNFTCollection) {3867    super(tokenId, collection);3868    this.collection = collection;3869  }38703871  async getData(blockHashAt?: string) {3872    return await this.collection.getToken(this.tokenId, blockHashAt);3873  }38743875  async getOwner(blockHashAt?: string) {3876    return await this.collection.getTokenOwner(this.tokenId, blockHashAt);3877  }38783879  async getTopmostOwner(blockHashAt?: string) {3880    return await this.collection.getTokenTopmostOwner(this.tokenId, blockHashAt);3881  }38823883  async getChildren(blockHashAt?: string) {3884    return await this.collection.getTokenChildren(this.tokenId, blockHashAt);3885  }38863887  async nest(signer: TSigner, toTokenObj: IToken) {3888    return await this.collection.nestToken(signer, this.tokenId, toTokenObj);3889  }38903891  async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3892    return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);3893  }38943895  async transfer(signer: TSigner, addressObj: ICrossAccountId) {3896    return await this.collection.transferToken(signer, this.tokenId, addressObj);3897  }38983899  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {3900    return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj);3901  }39023903  async approve(signer: TSigner, toAddressObj: ICrossAccountId) {3904    return await this.collection.approveToken(signer, this.tokenId, toAddressObj);3905  }39063907  async isApproved(toAddressObj: ICrossAccountId) {3908    return await this.collection.isTokenApproved(this.tokenId, toAddressObj);3909  }39103911  async burn(signer: TSigner) {3912    return await this.collection.burnToken(signer, this.tokenId);3913  }39143915  async burnFrom(signer: TSigner, fromAddressObj: ICrossAccountId) {3916    return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj);3917  }39183919  scheduleAt<T extends UniqueHelper>(3920    executionBlockNumber: number,3921    options: ISchedulerOptions = {},3922  ) {3923    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);3924    return new UniqueNFToken(this.tokenId, scheduledCollection);3925  }39263927  scheduleAfter<T extends UniqueHelper>(3928    blocksBeforeExecution: number,3929    options: ISchedulerOptions = {},3930  ) {3931    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);3932    return new UniqueNFToken(this.tokenId, scheduledCollection);3933  }39343935  getSudo<T extends UniqueHelper>() {3936    return new UniqueNFToken(this.tokenId, this.collection.getSudo<T>());3937  }3938}39393940export class UniqueRFToken extends UniqueBaseToken {3941  collection: UniqueRFTCollection;39423943  constructor(tokenId: number, collection: UniqueRFTCollection) {3944    super(tokenId, collection);3945    this.collection = collection;3946  }39473948  async getData(blockHashAt?: string) {3949    return await this.collection.getToken(this.tokenId, blockHashAt);3950  }39513952  async getOwner(blockHashAt?: string) {3953    return await this.collection.getTokenOwner(this.tokenId, blockHashAt);3954  }39553956  async getTop10Owners() {3957    return await this.collection.getTop10TokenOwners(this.tokenId);3958  }39593960  async getTopmostOwner(blockHashAt?: string) {3961    return await this.collection.getTokenTopmostOwner(this.tokenId, blockHashAt);3962  }39633964  async nest(signer: TSigner, toTokenObj: IToken) {3965    return await this.collection.nestToken(signer, this.tokenId, toTokenObj);3966  }39673968  async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {3969    return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);3970  }39713972  async getBalance(addressObj: ICrossAccountId) {3973    return await this.collection.getTokenBalance(this.tokenId, addressObj);3974  }39753976  async getTotalPieces() {3977    return await this.collection.getTokenTotalPieces(this.tokenId);3978  }39793980  async getApprovedPieces(fromAddressObj: ICrossAccountId, toAccountObj: ICrossAccountId) {3981    return await this.collection.getTokenApprovedPieces(this.tokenId, fromAddressObj, toAccountObj);3982  }39833984  async transfer(signer: TSigner, addressObj: ICrossAccountId, amount=1n) {3985    return await this.collection.transferToken(signer, this.tokenId, addressObj, amount);3986  }39873988  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {3989    return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj, amount);3990  }39913992  async approve(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {3993    return await this.collection.approveToken(signer, this.tokenId, toAddressObj, amount);3994  }39953996  async repartition(signer: TSigner, amount: bigint) {3997    return await this.collection.repartitionToken(signer, this.tokenId, amount);3998  }39994000  async burn(signer: TSigner, amount=1n) {4001    return await this.collection.burnToken(signer, this.tokenId, amount);4002  }40034004  async burnFrom(signer: TSigner, fromAddressObj: ICrossAccountId, amount=1n) {4005    return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj, amount);4006  }40074008  scheduleAt<T extends UniqueHelper>(4009    executionBlockNumber: number,4010    options: ISchedulerOptions = {},4011  ) {4012    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);4013    return new UniqueRFToken(this.tokenId, scheduledCollection);4014  }40154016  scheduleAfter<T extends UniqueHelper>(4017    blocksBeforeExecution: number,4018    options: ISchedulerOptions = {},4019  ) {4020    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);4021    return new UniqueRFToken(this.tokenId, scheduledCollection);4022  }40234024  getSudo<T extends UniqueHelper>() {4025    return new UniqueRFToken(this.tokenId, this.collection.getSudo<T>());4026  }4027}