git.delta.rocks / unique-network / refs/commits / ee40b79d7e69

difftreelog

Merge pull request #241 from UniqueNetwork/feature/unique-brand

str-mv2021-11-24parents: #bf917ac #05ae8ba.patch.diff
in: master
unique brand

129 files changed

modified.envdiffbeforeafterboth
--- a/.env
+++ b/.env
@@ -1,6 +1,6 @@
 RUST_TOOLCHAIN=nightly-2021-06-28
 RUST_C=1.55.0-nightly
 POLKA_VERSION=v0.9.12
-NFT_BRANCH=develop
+UNIQUE_BRANCH=develop
 USER=***
 PASS=***
modifiedDockerfile-parachaindiffbeforeafterboth
--- a/Dockerfile-parachain
+++ b/Dockerfile-parachain
@@ -5,7 +5,7 @@
 ARG RUST_TOOLCHAIN=nightly-2021-06-28
 #ARG RUST_C=1.55.0-nightly
 ARG POLKA_VERSION=v0.9.12
-ARG NFT_BRANCH=develop
+ARG UNIQUE_BRANCH=develop
 
 #ARG USER=***
 #ARG PASS=***
@@ -14,13 +14,13 @@
 ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
 #ENV RUST_C $RUST_C
 ENV POLKA_VERSION $POLKA_VERSION
-ENV NFT_BRANCH $NFT_BRANCH
+ENV UNIQUE_BRANCH $UNIQUE_BRANCH
 
 
 #RUN echo $RUST_TOOLCHAIN
 #RUN echo $RUST_C
 #RUN echo $POLKA_VERSION
-#RUN echo $NFT_BRANCH
+#RUN echo $UNIQUE_BRANCH
 
 ENV CARGO_HOME="/cargo-home"
 ENV PATH="/cargo-home/bin:$PATH"
@@ -40,8 +40,8 @@
 
 RUN cargo install cargo-chef
 
-RUN mkdir nft_parachain
-WORKDIR /nft_parachain
+RUN mkdir unique_parachain
+WORKDIR /unique_parachain
 
 # ===== Chef =====
 FROM rust-builder as chef
@@ -52,10 +52,10 @@
 # ===== BUILD ======
 FROM rust-builder as builder
 
-RUN mkdir nft_parachain
-WORKDIR /nft_parachain
+RUN mkdir unique_parachain
+WORKDIR /unique_parachain
 
-COPY --from=chef /nft_parachain/recipe.json recipe.json
+COPY --from=chef /unique_parachain/recipe.json recipe.json
 ARG PROFILE=release
 RUN cargo chef cook "--$PROFILE" --recipe-path recipe.json
 
@@ -67,8 +67,8 @@
 # ===== BUILD POLKADOT =====
 FROM rust-builder as builder-polkadot
 
-RUN mkdir nft_parachain
-WORKDIR /nft_parachain
+RUN mkdir unique_parachain
+WORKDIR /unique_parachain
 
 RUN git clone -b $POLKA_VERSION --depth 1 https://github.com/paritytech/polkadot.git && \
     cd polkadot && \
@@ -98,8 +98,8 @@
     npm install --global yarn && \
     yarn
 
-COPY --from=builder /nft_parachain/target/$PROFILE/nft /unique-chain/target/$PROFILE/
-COPY --from=builder-polkadot /nft_parachain/polkadot/target/$PROFILE/polkadot /polkadot/target/$PROFILE/
+COPY --from=builder /unique_parachain/target/$PROFILE/unique-collator /unique-chain/target/$PROFILE/
+COPY --from=builder-polkadot /unique_parachain/polkadot/target/$PROFILE/polkadot /polkadot/target/$PROFILE/
 
 CMD export NVM_DIR="$HOME/.nvm" && \
     [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
modifiedMakefilediffbeforeafterboth
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
 	@echo "evm_stubs - recompile contract stubs"
 	@echo "bench - run frame-benchmarking"
 	@echo "  bench-evm-migration"
-	@echo "  bench-nft"
+	@echo "  bench-unique"
 
 .PHONY: regenerate_solidity
 regenerate_solidity:
@@ -41,9 +41,9 @@
 bench-evm-migration:
 	make _bench PALLET=evm-migration
 
-.PHONY: bench-nft
-bench-nft:
-	make _bench PALLET=nft
+.PHONY: bench-unique
+bench-unique:
+	make _bench PALLET=unique
 
 .PHONY: bench-fungible
 bench-fungible:
@@ -58,4 +58,4 @@
 	make _bench PALLET=nonfungible
 
 .PHONY: bench
-bench: bench-evm-migration bench-nft bench-fungible bench-refungible bench-nonfungible
+bench: bench-evm-migration bench-unique bench-fungible bench-refungible bench-nonfungible
modifiedREADME.mddiffbeforeafterboth
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
 ![Docker build](https://github.com/usetech-llc/nft_parachain/workflows/Docker%20build/badge.svg)
 
-# NFT Parachain
+# Unique Parachain
 
 ## Project Description
 
-The NFT Pallet is the core of NFT functionality. Like ERC-721 standard in Ethereum ecosystem, this pallet provides the
+The Unique Pallet is the core of NFT functionality. Like ERC-721 standard in Ethereum ecosystem, this pallet provides the
 basement for creating collections of unique non-divisible things, also called Non Fungible Tokens (NFTs), minting NFT of
 a given Collection, and managing their ownership.
 
@@ -12,19 +12,19 @@
 concrete application that operates a Collection, so purposefully the NFT Tracking Module does not have any knowledge
 about properties except their byte size leaving application logic out to be controlled by Smart Contracts.
 
-The NFT Chain also provides:
+The Unique Chain also provides:
 
--   Smart Contracts Pallet and example smart contract that interacts with NFT Runtime
+-   Smart Contracts Pallet and example smart contract that interacts with Unique Runtime
 -   ERC-1155 Functionality (currently PoC as Re-Fungible tokens, i.e. items that are still unique, but that can be split
     between multiple users)
 -   Variety of economic options for dapp producers to choose from to create freemium games and other ways to attract
     users. As a step one, we implemented an economic model when a collection sponsor can be set to pay for collection
     Transfer transactions.
 
-Wider NFT Ecosystem (most of it was developed during Hackusama):
+Wider Unique Ecosystem (most of it was developed during Hackusama):
 
 -   [SubstraPunks Game hosted on IPFS](https://github.com/usetech-llc/substrapunks)
--   [NFT Wallet and UI](https://uniqueapps.usetech.com/#/nft)
+-   [Unique Wallet and UI](https://uniqueapps.usetech.com/#/nft)
 -   [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)
 
 Please see our [walk-thorugh instructions](doc/hackusama_walk_through.md) to try everything out!
@@ -34,15 +34,15 @@
 During the Kusama Hackaphon the following changes were made:
 
 -   Enabled Smart Contracts Pallet
--   Enabled integration between Smart Contracts and NFT Pallet (required special edition of RC4 Substrate version)
--   Fixed misc. bugs in NFT Pallet
--   Deployed NFT TestNet. Public node available at wss://unique.usetech.com, custom UI types - see below in this README.
+-   Enabled integration between Smart Contracts and Unique Pallet (required special edition of RC4 Substrate version)
+-   Fixed misc. bugs in Unique Pallet
+-   Deployed Unique TestNet. Public node available at wss://unique.usetech.com, custom UI types - see below in this README.
 -   New Features:
     -   Re-Fungible Token Mode
     -   Off-Chain Schema to store token image URLs
     -   Alternative economic model
     -   Allow Lists and Public Mint Permission
--   Use example: [SubstraPunks Game](https://github.com/usetech-llc/substrapunks), fully hosted on IPFS and NFT Testnet
+-   Use example: [SubstraPunks Game](https://github.com/usetech-llc/substrapunks), fully hosted on IPFS and Unique Testnet
     Blockchain.
 
 ## Application Development
@@ -51,7 +51,7 @@
 
 ## Building
 
-Building NFT chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything
+Building Unique chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything
 so that we can keep the builds stable.
 
 1. Install Rust:
@@ -168,12 +168,12 @@
 
 ```
 
-3. Export genesis state and runtime wasm from NFT parachain:
+3. Export genesis state and runtime wasm from Unique parachain:
 
 Run from this project root:
 ```
-./target/release/nft export-genesis-state --parachain-id 2000 > ./resources/para-2000-genesis
-./target/release/nft export-genesis-wasm > ./resources/para-2000-wasm
+./target/release/unique-collator export-genesis-state --parachain-id 2000 > ./resources/para-2000-genesis
+./target/release/unique-collator export-genesis-wasm > ./resources/para-2000-wasm
 ```
 
 4. Run two parachain nodes:
@@ -182,8 +182,8 @@
 
 Run from this project root:
 ```
-./target/release/nft --alice --collator --force-authoring --base-path ./tmp/parachain-alice --parachain-id 2000 --port 40333 --ws-port 9844  -- --execution wasm --chain ../polkadot/rococo-custom-4.json --port 30343 --ws-port 9977
-./target/release/nft --bob --collator --force-authoring --parachain-id 2000 --base-path ./tmp/parachain/bob --port 40334 --ws-port 9845 -- --execution wasm --chain ../polkadot/rococo-custom-4.json --port 30344 --ws-port 9978 --bootnodes /ip4/127.0.0.1/tcp/50556/p2p/12D3KooWN1ah2bFQSysEFnwZqcmcVpDDR8UedXyo6xfzV1zDNMNg
+./target/release/unique-collator --alice --collator --force-authoring --base-path ./tmp/parachain-alice --parachain-id 2000 --port 40333 --ws-port 9844  -- --execution wasm --chain ../polkadot/rococo-custom-4.json --port 30343 --ws-port 9977
+./target/release/unique-collator --bob --collator --force-authoring --parachain-id 2000 --base-path ./tmp/parachain/bob --port 40334 --ws-port 9845 -- --execution wasm --chain ../polkadot/rococo-custom-4.json --port 30344 --ws-port 9978 --bootnodes /ip4/127.0.0.1/tcp/50556/p2p/12D3KooWN1ah2bFQSysEFnwZqcmcVpDDR8UedXyo6xfzV1zDNMNg
 ```
 
 4. Reserve parachain ID as described here: https://substrate.dev/cumulus-workshop/#/en/2-relay-chain/2-reserve
@@ -218,7 +218,7 @@
 
 Run benchmark
 ```bash
-target/release/nft benchmark --chain dev --pallet "pallet_nft" --extrinsic "*" --repeat 1
+target/release/unique-collator benchmark --chain dev --pallet "pallet_unique" --extrinsic "*" --repeat 1
 ```
 
 ## UI custom types
modifiedclient/rpc/Cargo.tomldiffbeforeafterboth
--- a/client/rpc/Cargo.toml
+++ b/client/rpc/Cargo.toml
@@ -5,7 +5,7 @@
 
 [dependencies]
 pallet-common = { default-features = false, path = '../../pallets/common' }
-nft-data-structs = { default-features = false, path = '../../primitives/nft' }
+up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
 up-rpc = { path = "../../primitives/rpc" }
 codec = { package = "parity-scale-codec", version = "2.0.0" }
 jsonrpc-core = "18.0.0"
modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -3,21 +3,21 @@
 use codec::Decode;
 use jsonrpc_core::{Error as RpcError, ErrorCode, Result};
 use jsonrpc_derive::rpc;
-use nft_data_structs::{Collection, CollectionId, CollectionStats, TokenId};
+use up_data_structs::{Collection, CollectionId, CollectionStats, TokenId};
 use sp_api::{BlockId, BlockT, ProvideRuntimeApi};
 use sp_blockchain::HeaderBackend;
-use up_rpc::NftApi as NftRuntimeApi;
+use up_rpc::UniqueApi as UniqueRuntimeApi;
 
 #[rpc]
-pub trait NftApi<BlockHash, CrossAccountId, AccountId> {
-	#[rpc(name = "nft_accountTokens")]
+pub trait UniqueApi<BlockHash, CrossAccountId, AccountId> {
+	#[rpc(name = "unique_accountTokens")]
 	fn account_tokens(
 		&self,
 		collection: CollectionId,
 		account: CrossAccountId,
 		at: Option<BlockHash>,
 	) -> Result<Vec<TokenId>>;
-	#[rpc(name = "nft_tokenExists")]
+	#[rpc(name = "unique_tokenExists")]
 	fn token_exists(
 		&self,
 		collection: CollectionId,
@@ -25,21 +25,21 @@
 		at: Option<BlockHash>,
 	) -> Result<bool>;
 
-	#[rpc(name = "nft_tokenOwner")]
+	#[rpc(name = "unique_tokenOwner")]
 	fn token_owner(
 		&self,
 		collection: CollectionId,
 		token: TokenId,
 		at: Option<BlockHash>,
 	) -> Result<CrossAccountId>;
-	#[rpc(name = "nft_constMetadata")]
+	#[rpc(name = "unique_constMetadata")]
 	fn const_metadata(
 		&self,
 		collection: CollectionId,
 		token: TokenId,
 		at: Option<BlockHash>,
 	) -> Result<Vec<u8>>;
-	#[rpc(name = "nft_variableMetadata")]
+	#[rpc(name = "unique_variableMetadata")]
 	fn variable_metadata(
 		&self,
 		collection: CollectionId,
@@ -47,16 +47,16 @@
 		at: Option<BlockHash>,
 	) -> Result<Vec<u8>>;
 
-	#[rpc(name = "nft_collectionTokens")]
+	#[rpc(name = "unique_collectionTokens")]
 	fn collection_tokens(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<u32>;
-	#[rpc(name = "nft_accountBalance")]
+	#[rpc(name = "unique_accountBalance")]
 	fn account_balance(
 		&self,
 		collection: CollectionId,
 		account: CrossAccountId,
 		at: Option<BlockHash>,
 	) -> Result<u32>;
-	#[rpc(name = "nft_balance")]
+	#[rpc(name = "unique_balance")]
 	fn balance(
 		&self,
 		collection: CollectionId,
@@ -64,7 +64,7 @@
 		token: TokenId,
 		at: Option<BlockHash>,
 	) -> Result<String>;
-	#[rpc(name = "nft_allowance")]
+	#[rpc(name = "unique_allowance")]
 	fn allowance(
 		&self,
 		collection: CollectionId,
@@ -74,43 +74,43 @@
 		at: Option<BlockHash>,
 	) -> Result<String>;
 
-	#[rpc(name = "nft_adminlist")]
+	#[rpc(name = "unique_adminlist")]
 	fn adminlist(
 		&self,
 		collection: CollectionId,
 		at: Option<BlockHash>,
 	) -> Result<Vec<CrossAccountId>>;
-	#[rpc(name = "nft_allowlist")]
+	#[rpc(name = "unique_allowlist")]
 	fn allowlist(
 		&self,
 		collection: CollectionId,
 		at: Option<BlockHash>,
 	) -> Result<Vec<CrossAccountId>>;
-	#[rpc(name = "nft_allowed")]
+	#[rpc(name = "unique_allowed")]
 	fn allowed(
 		&self,
 		collection: CollectionId,
 		user: CrossAccountId,
 		at: Option<BlockHash>,
 	) -> Result<bool>;
-	#[rpc(name = "nft_lastTokenId")]
+	#[rpc(name = "unique_lastTokenId")]
 	fn last_token_id(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<TokenId>;
-	#[rpc(name = "nft_collectionById")]
+	#[rpc(name = "unique_collectionById")]
 	fn collection_by_id(
 		&self,
 		collection: CollectionId,
 		at: Option<BlockHash>,
 	) -> Result<Option<Collection<AccountId>>>;
-	#[rpc(name = "nft_collectionStats")]
+	#[rpc(name = "unique_collectionStats")]
 	fn collection_stats(&self, at: Option<BlockHash>) -> Result<CollectionStats>;
 }
 
-pub struct Nft<C, P> {
+pub struct Unique<C, P> {
 	client: Arc<C>,
 	_marker: std::marker::PhantomData<P>,
 }
 
-impl<C, P> Nft<C, P> {
+impl<C, P> Unique<C, P> {
 	pub fn new(client: Arc<C>) -> Self {
 		Self {
 			client,
@@ -154,13 +154,13 @@
 	};
 }
 
-impl<C, Block, CrossAccountId, AccountId> NftApi<<Block as BlockT>::Hash, CrossAccountId, AccountId>
-	for Nft<C, Block>
+impl<C, Block, CrossAccountId, AccountId>
+	UniqueApi<<Block as BlockT>::Hash, CrossAccountId, AccountId> for Unique<C, Block>
 where
 	Block: BlockT,
 	AccountId: Decode,
 	C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
-	C::Api: NftRuntimeApi<Block, CrossAccountId, AccountId>,
+	C::Api: UniqueRuntimeApi<Block, CrossAccountId, AccountId>,
 	CrossAccountId: pallet_common::account::CrossAccountId<AccountId>,
 {
 	pass_method!(account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId>);
modifieddocker-compose-tests-parachain.ymldiffbeforeafterboth
--- a/docker-compose-tests-parachain.yml
+++ b/docker-compose-tests-parachain.yml
@@ -9,7 +9,7 @@
         - RUST_TOOLCHAIN=${RUST_TOOLCHAIN:?err}
         - RUST_C=${RUST_C:?err}
         - POLKA_VERSION=${POLKA_VERSION:?err}
-        - NFT_BRANCH=${NFT_BRANCH:?err}
+        - UNIQUE_BRANCH=${UNIQUE_BRANCH:?err}
     volumes:
       - ./launch-config.json:/polkadot-launch/launch-config.json
     env_file:
@@ -22,7 +22,7 @@
     environment:
       RPC_URL: http://blockchain_nodes:9933/
     volumes:
-      - ./tests/src/config_docker.ts:/nft_parachain/src/config.ts
-      - /home/ubuntu/mochawesome-report:/nft_parachain/mochawesome-report
+      - ./tests/src/config_docker.ts:/unique_parachain/src/config.ts
+      - /home/ubuntu/mochawesome-report:/unique_parachain/mochawesome-report
     depends_on:
       - blockchain_nodes
modifiedlaunch-config.jsondiffbeforeafterboth
--- a/launch-config.json
+++ b/launch-config.json
@@ -55,7 +55,7 @@
     },
     "parachains": [
         {
-            "bin": "../unique-chain/target/release/nft",
+            "bin": "../unique-chain/target/release/unique-collator",
             "id": "2000",
             "balance": "1000000000000000000000",
             "nodes": [
modifiednode/cli/Cargo.tomldiffbeforeafterboth
--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -231,12 +231,11 @@
 ################################################################################
 # Local dependencies
 
-[dependencies.nft-runtime]
+[dependencies.unique-runtime]
 path = '../../runtime'
-version = '0.9.12'
 
-[dependencies.nft-data-structs]
-path = "../../primitives/nft"
+[dependencies.up-data-structs]
+path = "../../primitives/data-structs"
 default-features = false
 
 ################################################################################
@@ -245,16 +244,17 @@
 [package]
 authors = ['Unique Network <support@uniquenetwork.io>']
 build = 'build.rs'
-description = 'Substrate node nft'
+description = 'Unique Node'
 edition = '2018'
 homepage = 'https://unique.network'
 license = 'All Rights Reserved'
-name = 'nft'
-repository = 'https://github.com/usetech-llc/nft_private/'
+name = 'unique-node'
+repository = 'https://github.com/UniqueNetwork/unique-chain'
 version = '0.9.12'
 
 [[bin]]
-name = 'nft'
+name = 'unique-collator'
+path = "src/main.rs"
 
 [package.metadata.docs.rs]
 targets = ['x86_64-unknown-linux-gnu']
@@ -276,11 +276,11 @@
 fp-rpc = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
 pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
 
-nft-rpc = { path = "../rpc" }
+unique-rpc = { path = "../rpc" }
 
 [features]
 default = []
 runtime-benchmarks = [
-    'nft-runtime/runtime-benchmarks',
+    'unique-runtime/runtime-benchmarks',
     'polkadot-service/runtime-benchmarks',
 ]
modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -4,7 +4,7 @@
 //
 
 use cumulus_primitives_core::ParaId;
-use nft_runtime::*;
+use unique_runtime::*;
 use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
 use sc_service::ChainType;
 use sp_core::{sr25519, Pair, Public};
@@ -15,7 +15,7 @@
 use serde_json::map::Map;
 
 /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
-pub type ChainSpec = sc_service::GenericChainSpec<nft_runtime::GenesisConfig, Extensions>;
+pub type ChainSpec = sc_service::GenericChainSpec<unique_runtime::GenesisConfig, Extensions>;
 
 /// Helper function to generate a crypto pair from seed
 pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
@@ -151,8 +151,8 @@
 	id: ParaId,
 ) -> GenesisConfig {
 	GenesisConfig {
-		system: nft_runtime::SystemConfig {
-			code: nft_runtime::WASM_BINARY
+		system: unique_runtime::SystemConfig {
+			code: unique_runtime::WASM_BINARY
 				.expect("WASM binary was not build, please build it!")
 				.to_vec(),
 			changes_trie_config: Default::default(),
@@ -167,8 +167,8 @@
 		treasury: Default::default(),
 		sudo: SudoConfig { key: root_key },
 		vesting: VestingConfig { vesting: vec![] },
-		parachain_info: nft_runtime::ParachainInfoConfig { parachain_id: id },
-		aura: nft_runtime::AuraConfig {
+		parachain_info: unique_runtime::ParachainInfoConfig { parachain_id: id },
+		aura: unique_runtime::AuraConfig {
 			authorities: initial_authorities,
 		},
 		aura_ext: Default::default(),
modifiednode/cli/src/command.rsdiffbeforeafterboth
--- a/node/cli/src/command.rs
+++ b/node/cli/src/command.rs
@@ -24,7 +24,7 @@
 use cumulus_primitives_core::ParaId;
 use cumulus_client_service::genesis::generate_genesis_block;
 use log::info;
-use nft_runtime::Block;
+use unique_runtime::Block;
 use polkadot_parachain::primitives::AccountIdConversion;
 use sc_cli::{
 	ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
@@ -88,7 +88,7 @@
 	}
 
 	fn native_runtime_version(_: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
-		&nft_runtime::VERSION
+		&unique_runtime::VERSION
 	}
 }
 
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -13,7 +13,7 @@
 use futures::StreamExt;
 
 // Local Runtime Types
-use nft_runtime::RuntimeApi;
+use unique_runtime::RuntimeApi;
 
 // Cumulus Imports
 use cumulus_client_consensus_aura::{build_aura_consensus, BuildAuraConsensusParams, SlotProportion};
@@ -54,11 +54,11 @@
 	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
 
 	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-		nft_runtime::api::dispatch(method, data)
+		unique_runtime::api::dispatch(method, data)
 	}
 
 	fn native_version() -> sc_executor::NativeVersion {
-		nft_runtime::native_version()
+		unique_runtime::native_version()
 	}
 }
 
@@ -68,7 +68,7 @@
 		.as_ref()
 		.map(|base_path| base_path.config_dir(config.chain_spec.id()))
 		.unwrap_or_else(|| {
-			BasePath::from_project("", "", "nft").config_dir(config.chain_spec.id())
+			BasePath::from_project("", "", "unique").config_dir(config.chain_spec.id())
 		});
 	let database_dir = config_dir.join("frontier").join("db");
 
@@ -291,7 +291,7 @@
 
 	let rpc_frontier_backend = frontier_backend.clone();
 	let rpc_extensions_builder = Box::new(move |deny_unsafe, _| {
-		let full_deps = nft_rpc::FullDeps {
+		let full_deps = unique_rpc::FullDeps {
 			backend: rpc_frontier_backend.clone(),
 			deny_unsafe,
 			client: rpc_client.clone(),
@@ -307,7 +307,7 @@
 			max_past_logs: 10000,
 		};
 
-		Ok(nft_rpc::create_full::<_, _, _, _, RuntimeApi, _>(
+		Ok(unique_rpc::create_full::<_, _, _, _, RuntimeApi, _>(
 			full_deps,
 			subscription_executor.clone(),
 		))
modifiednode/rpc/Cargo.tomldiffbeforeafterboth
--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
-name = "nft-rpc"
-version = "3.3.1"
+name = "unique-rpc"
+version = "0.1.0"
 authors = ['Unique Network <support@uniquenetwork.io>']
 license = 'All Rights Reserved'
 edition = "2018"
@@ -48,10 +48,10 @@
 fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
 fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
 
-pallet-nft = { path = "../../pallets/nft" }
+pallet-unique = { path = "../../pallets/unique" }
 uc-rpc = { path = "../../client/rpc" }
 up-rpc = { path = "../../primitives/rpc" }
-nft-runtime = { path = "../../runtime" }
+unique-runtime = { path = "../../runtime" }
 
 [features]
 std = []
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -1,4 +1,4 @@
-use nft_runtime::{Hash, AccountId, CrossAccountId, Index, opaque::Block, BlockNumber, Balance};
+use unique_runtime::{Hash, AccountId, CrossAccountId, Index, opaque::Block, BlockNumber, Balance};
 use fc_rpc::{
 	EthBlockDataCache, OverrideHandle, RuntimeApiStorageOverride, SchemaV1Override, StorageOverride,
 };
@@ -100,10 +100,10 @@
 where
 	Block: sp_api::BlockT,
 	C: ProvideRuntimeApi<Block>,
-	C::Api: up_rpc::NftApi<Block, CrossAccountId, AccountId>,
+	C::Api: up_rpc::UniqueApi<Block, CrossAccountId, AccountId>,
 {
 	fn code(&self, block: &sp_api::BlockId<Block>, account: sp_core::H160) -> Option<Vec<u8>> {
-		use up_rpc::NftApi;
+		use up_rpc::UniqueApi;
 		self.client
 			.runtime_api()
 			.eth_contract_code(block, account)
@@ -127,7 +127,7 @@
 	// C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,
 	C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
 	C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
-	C::Api: up_rpc::NftApi<Block, CrossAccountId, AccountId>,
+	C::Api: up_rpc::UniqueApi<Block, CrossAccountId, AccountId>,
 	B: sc_client_api::Backend<Block> + Send + Sync + 'static,
 	B::State: sc_client_api::backend::StateBackend<sp_runtime::traits::HashFor<Block>>,
 	SC: SelectChain<Block> + 'static,
@@ -139,7 +139,7 @@
 		EthPubSubApiServer, EthSigner, HexEncodedIdProvider, NetApi, NetApiServer, Web3Api,
 		Web3ApiServer,
 	};
-	use uc_rpc::{NftApi, Nft};
+	use uc_rpc::{UniqueApi, Unique};
 	// use pallet_contracts_rpc::{Contracts, ContractsApi};
 	use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
 	use substrate_frame_rpc_system::{FullSystem, SystemApi};
@@ -195,7 +195,7 @@
 		client.clone(),
 		pool.clone(),
 		graph,
-		nft_runtime::TransactionConverter,
+		unique_runtime::TransactionConverter,
 		network.clone(),
 		signers,
 		overrides.clone(),
@@ -204,7 +204,7 @@
 		max_past_logs,
 		block_data_cache.clone(),
 	)));
-	io.extend_with(NftApi::to_delegate(Nft::new(client.clone())));
+	io.extend_with(UniqueApi::to_delegate(Unique::new(client.clone())));
 
 	if let Some(filter_pool) = filter_pool {
 		io.extend_with(EthFilterApiServer::to_delegate(EthFilterApi::new(
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
--- a/pallets/common/Cargo.toml
+++ b/pallets/common/Cargo.toml
@@ -16,7 +16,7 @@
 sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 up-evm-mapping = { default-features = false, path = '../../primitives/evm-mapping' }
-nft-data-structs = { default-features = false, path = '../../primitives/nft' }
+up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
 pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
@@ -33,7 +33,7 @@
     "sp-runtime/std",
     "sp-std/std",
     "up-evm-mapping/std",
-    "nft-data-structs/std",
+    "up-data-structs/std",
     "pallet-evm/std",
 ]
 runtime-benchmarks = []
modifiedpallets/common/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/common/src/benchmarking.rs
+++ b/pallets/common/src/benchmarking.rs
@@ -1,6 +1,6 @@
 use sp_std::vec::Vec;
 use crate::{Config, CollectionHandle};
-use nft_data_structs::{
+use up_data_structs::{
 	CollectionMode, Collection, CollectionId, MAX_COLLECTION_NAME_LENGTH,
 	MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, OFFCHAIN_SCHEMA_LIMIT,
 	VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT,
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -1,4 +1,4 @@
-use nft_data_structs::{CollectionId, TokenId};
+use up_data_structs::{CollectionId, TokenId};
 use sp_core::H160;
 
 // 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 1
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -8,7 +8,7 @@
 	ensure, fail,
 	traits::{Imbalance, Get, Currency},
 };
-use nft_data_structs::{
+use up_data_structs::{
 	COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,
 	MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_COLLECTION_NAME_LENGTH, MAX_TOKEN_PREFIX_LENGTH,
 	COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo, TokenId, Weight,
@@ -143,7 +143,7 @@
 	use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key};
 	use account::CrossAccountId;
 	use frame_support::traits::Currency;
-	use nft_data_structs::TokenId;
+	use up_data_structs::TokenId;
 	use scale_info::TypeInfo;
 
 	#[pallet::config]
modifiedpallets/evm-migration/src/weights.rsdiffbeforeafterboth
--- a/pallets/evm-migration/src/weights.rs
+++ b/pallets/evm-migration/src/weights.rs
@@ -7,7 +7,7 @@
 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
 
 // Executed Command:
-// target/release/nft
+// target/release/unique-collator
 // benchmark
 // --pallet
 // pallet-evm-migration
modifiedpallets/fungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/fungible/Cargo.toml
+++ b/pallets/fungible/Cargo.toml
@@ -16,7 +16,7 @@
 sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 pallet-common = { default-features = false, path = '../common' }
-nft-data-structs = { default-features = false, path = '../../primitives/nft' }
+up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
 ethereum = { git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
@@ -32,7 +32,7 @@
     "frame-system/std",
     "sp-runtime/std",
     "sp-std/std",
-    "nft-data-structs/std",
+    "up-data-structs/std",
     "pallet-common/std",
     "evm-coder/std",
     "ethereum/std",
modifiedpallets/fungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/fungible/src/benchmarking.rs
+++ b/pallets/fungible/src/benchmarking.rs
@@ -4,7 +4,7 @@
 use sp_std::prelude::*;
 use pallet_common::benchmarking::create_collection_raw;
 use frame_benchmarking::{benchmarks, account};
-use nft_data_structs::{CollectionMode};
+use up_data_structs::{CollectionMode};
 use pallet_common::bench_init;
 
 const SEED: u32 = 1;
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -1,7 +1,7 @@
 use core::marker::PhantomData;
 
 use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
-use nft_data_structs::TokenId;
+use up_data_structs::TokenId;
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
 use sp_runtime::ArithmeticError;
 use sp_std::{vec::Vec, vec};
@@ -51,10 +51,10 @@
 		&self,
 		sender: T::CrossAccountId,
 		to: T::CrossAccountId,
-		data: nft_data_structs::CreateItemData,
+		data: up_data_structs::CreateItemData,
 	) -> DispatchResultWithPostInfo {
 		match data {
-			nft_data_structs::CreateItemData::Fungible(data) => with_weight(
+			up_data_structs::CreateItemData::Fungible(data) => with_weight(
 				<Pallet<T>>::create_item(self, &sender, (to, data.value)),
 				<CommonWeights<T>>::create_item(),
 			),
@@ -66,12 +66,12 @@
 		&self,
 		sender: T::CrossAccountId,
 		to: T::CrossAccountId,
-		data: Vec<nft_data_structs::CreateItemData>,
+		data: Vec<up_data_structs::CreateItemData>,
 	) -> DispatchResultWithPostInfo {
 		let mut sum: u128 = 0;
 		for data in data {
 			match data {
-				nft_data_structs::CreateItemData::Fungible(data) => {
+				up_data_structs::CreateItemData::Fungible(data) => {
 					sum = sum
 						.checked_add(data.value)
 						.ok_or(ArithmeticError::Overflow)?;
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -1,7 +1,7 @@
 use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
 use core::convert::TryInto;
 use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*};
-use nft_data_structs::CollectionMode;
+use up_data_structs::CollectionMode;
 use pallet_common::erc::CommonEvmHandler;
 use sp_core::{H160, U256};
 use sp_std::vec::Vec;
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -2,7 +2,7 @@
 
 use core::ops::Deref;
 use frame_support::{ensure};
-use nft_data_structs::{AccessMode, Collection, CollectionId, TokenId};
+use up_data_structs::{AccessMode, Collection, CollectionId, TokenId};
 use pallet_common::{
 	Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,
 };
@@ -25,7 +25,7 @@
 #[frame_support::pallet]
 pub mod pallet {
 	use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
-	use nft_data_structs::CollectionId;
+	use up_data_structs::CollectionId;
 	use super::weights::WeightInfo;
 
 	#[pallet::error]
modifiedpallets/fungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/fungible/src/weights.rs
+++ b/pallets/fungible/src/weights.rs
@@ -7,7 +7,7 @@
 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
 
 // Executed Command:
-// target/release/nft
+// target/release/unique-collator
 // benchmark
 // --pallet
 // pallet-fungible
modifiedpallets/inflation/Cargo.tomldiffbeforeafterboth
--- a/pallets/inflation/Cargo.toml
+++ b/pallets/inflation/Cargo.toml
@@ -3,13 +3,13 @@
 
 [package]
 authors = ['Unique Network <support@uniquenetwork.io>']
-description = 'Substrate node nft'
+description = 'Unique Inflation Pallet'
 edition = '2018'
 homepage = 'https://unique.network'
 license = 'All Rights Reserved'
 name = 'pallet-inflation'
-repository = 'https://github.com/usetech-llc/nft_private/'
-version = '3.0.0'
+repository = 'https://github.com/UniqueNetwork/unique-chain'
+version = '0.1.0'
 
 [package.metadata.docs.rs]
 targets = ['x86_64-unknown-linux-gnu']
deletedpallets/nft/Cargo.tomldiffbeforeafterboth
--- a/pallets/nft/Cargo.toml
+++ /dev/null
@@ -1,154 +0,0 @@
-################################################################################
-# Package
-
-[package]
-authors = ['Unique Network <support@uniquenetwork.io>']
-description = 'Substrate node nft'
-edition = '2018'
-homepage = 'https://unique.network'
-license = 'All Rights Reserved'
-name = 'pallet-nft'
-repository = 'https://github.com/usetech-llc/nft_private/'
-version = '3.0.0'
-
-[package.metadata.docs.rs]
-targets = ['x86_64-unknown-linux-gnu']
-
-[features]
-default = ['std']
-runtime-benchmarks = ['frame-benchmarking', 'pallet-common/runtime-benchmarks']
-std = [
-    'codec/std',
-    'serde/std',
-    'frame-support/std',
-    'frame-system/std',
-    'pallet-balances/std',
-    'pallet-evm/std',
-    'pallet-timestamp/std',
-    'pallet-randomness-collective-flip/std',
-    'pallet-transaction-payment/std',
-    'pallet-common/std',
-    'pallet-fungible/std',
-    'pallet-nonfungible/std',
-    'pallet-refungible/std',
-    'fp-evm/std',
-    'nft-data-structs/std',
-    'up-sponsorship/std',
-    'up-evm-mapping/std',
-    'sp-std/std',
-    'sp-api/std',
-    'sp-runtime/std',
-    'frame-benchmarking/std',
-    'ethereum/std',
-    'rlp/std',
-
-    'primitive-types/std',
-    'evm-coder/std',
-    'pallet-evm-coder-substrate/std',
-]
-limit-testing = ["nft-data-structs/limit-testing"]
-
-################################################################################
-# Substrate Dependencies
-
-[dependencies.codec]
-default-features = false
-features = ['derive']
-package = 'parity-scale-codec'
-version = '2.3.0'
-
-[dependencies.frame-benchmarking]
-default-features = false
-optional = true
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.frame-support]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.frame-system]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.pallet-balances]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.pallet-timestamp]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.pallet-randomness-collective-flip]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.sp-std]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.pallet-transaction-payment]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.serde]
-default-features = false
-features = ['derive']
-version = '1.0.130'
-
-[dependencies.sp-runtime]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.sp-core]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-[dependencies.sp-io]
-default-features = false
-git = 'https://github.com/paritytech/substrate.git'
-branch = 'polkadot-v0.9.12'
-
-
-################################################################################
-# Local Dependencies
-
-[dependencies.nft-data-structs]
-default-features = false
-path = '../../primitives/nft'
-version = '0.9.0'
-
-[dependencies]
-scale-info = { version = "1.0.0", default-features = false, features = [
-    "derive",
-] }
-ethereum = { version = "0.9", git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
-rlp = { default-features = false, version = "0.5.0" }
-sp-api = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.12" }
-
-up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/UniqueNetwork/pallet-sponsoring" } 
-up-evm-mapping = { default-features = false, path = "../../primitives/evm-mapping" }
-evm-coder = { default-features = false, path = "../../crates/evm-coder" }
-pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
-primitive-types = { version = "0.10.1", default-features = false, features = [
-    "serde_no_std",
-] }
-
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
-hex-literal = "0.3.3"
-
-pallet-common = { default-features = false, path = "../common" }
-pallet-fungible = { default-features = false, path = "../fungible" }
-pallet-nonfungible = { default-features = false, path = "../nonfungible" }
-pallet-refungible = { default-features = false, path = "../refungible" }
deletedpallets/nft/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nft/src/benchmarking.rs
+++ /dev/null
@@ -1,171 +0,0 @@
-#![cfg(feature = "runtime-benchmarks")]
-
-use super::*;
-use crate::Pallet;
-use frame_system::RawOrigin;
-use frame_benchmarking::{benchmarks, account};
-use nft_data_structs::*;
-use core::convert::TryInto;
-use sp_runtime::DispatchError;
-use pallet_common::benchmarking::{create_data, create_u16_data};
-
-const SEED: u32 = 1;
-
-fn create_collection_helper<T: Config>(
-	owner: T::AccountId,
-	mode: CollectionMode,
-) -> Result<CollectionId, DispatchError> {
-	T::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get());
-	let col_name = create_u16_data(MAX_COLLECTION_NAME_LENGTH)
-		.try_into()
-		.unwrap();
-	let col_desc = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH)
-		.try_into()
-		.unwrap();
-	let token_prefix = create_data(MAX_TOKEN_PREFIX_LENGTH).try_into().unwrap();
-	<Pallet<T>>::create_collection(
-		RawOrigin::Signed(owner).into(),
-		col_name,
-		col_desc,
-		token_prefix,
-		mode,
-	)?;
-	Ok(<pallet_common::CreatedCollectionCount<T>>::get())
-}
-fn create_nft_collection<T: Config>(owner: T::AccountId) -> Result<CollectionId, DispatchError> {
-	create_collection_helper::<T>(owner, CollectionMode::NFT)
-}
-
-benchmarks! {
-
-	create_collection {
-		let col_name: Vec<u16> = create_u16_data(MAX_COLLECTION_NAME_LENGTH);
-		let col_desc: Vec<u16> = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH);
-		let token_prefix: Vec<u8> = create_data(MAX_TOKEN_PREFIX_LENGTH);
-		let mode: CollectionMode = CollectionMode::NFT;
-		let caller: T::AccountId = account("caller", 0, SEED);
-		T::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
-	}: _(RawOrigin::Signed(caller.clone()), col_name.clone(), col_desc.clone(), token_prefix.clone(), mode)
-	verify {
-		assert_eq!(<pallet_common::CollectionById<T>>::get(CollectionId(1)).unwrap().owner, caller);
-	}
-
-	destroy_collection {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection)
-
-	add_to_allow_list {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let allowlist_account: T::AccountId = account("admin", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(allowlist_account))
-
-	remove_from_allow_list {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let allowlist_account: T::AccountId = account("admin", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		<Pallet<T>>::add_to_allow_list(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(allowlist_account.clone()))?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(allowlist_account))
-
-	set_public_access_mode {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, AccessMode::AllowList)
-
-	set_mint_permission {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, true)
-
-	change_collection_owner {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let new_owner: T::AccountId = account("admin", 0, SEED);
-	}: _(RawOrigin::Signed(caller.clone()), collection, new_owner)
-
-	add_collection_admin {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let new_admin: T::AccountId = account("admin", 0, SEED);
-	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(new_admin))
-
-	remove_collection_admin {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let new_admin: T::AccountId = account("admin", 0, SEED);
-		<Pallet<T>>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(new_admin.clone()))?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(new_admin))
-
-	set_collection_sponsor {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, caller.clone())
-
-	confirm_sponsorship {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), collection, caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection)
-
-	remove_collection_sponsor {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), collection, caller.clone())?;
-		<Pallet<T>>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), collection)?;
-	}: _(RawOrigin::Signed(caller.clone()), collection)
-
-	set_transfers_enabled_flag {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, false)
-
-	set_offchain_schema {
-		let b in 0..OFFCHAIN_SCHEMA_LIMIT;
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let data = create_data(b as usize);
-	}: set_offchain_schema(RawOrigin::Signed(caller.clone()), collection, data)
-
-	set_const_on_chain_schema {
-		let b in 0..CONST_ON_CHAIN_SCHEMA_LIMIT;
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let data = create_data(b as usize);
-	}: set_const_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data)
-
-	set_variable_on_chain_schema {
-		let b in 0..VARIABLE_ON_CHAIN_SCHEMA_LIMIT;
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let data = create_data(b as usize);
-	}: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data)
-
-	set_schema_version {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: set_schema_version(RawOrigin::Signed(caller.clone()), collection, SchemaVersion::Unique)
-
-	set_collection_limits{
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-
-		let cl = CollectionLimits {
-			account_token_ownership_limit: Some(0),
-			sponsored_data_size: 0,
-			token_limit: 1,
-			sponsor_transfer_timeout: 0,
-			owner_can_destroy: true,
-			owner_can_transfer: true,
-			sponsored_data_rate_limit: None,
-		};
-	}: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)
-
-	set_meta_update_permission_flag {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, MetaUpdatePermission::Admin)
-}
deletedpallets/nft/src/common.rsdiffbeforeafterboth
--- a/pallets/nft/src/common.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use core::marker::PhantomData;
-use frame_support::{weights::Weight};
-use pallet_common::{CommonWeightInfo};
-
-use pallet_fungible::{common::CommonWeights as FungibleWeights};
-use pallet_nonfungible::{common::CommonWeights as NonfungibleWeights};
-use pallet_refungible::{common::CommonWeights as RefungibleWeights};
-
-use crate::{Config, dispatch::dispatch_weight};
-
-macro_rules! max_weight_of {
-	($method:ident ( $($args:tt)* )) => {
-		<FungibleWeights<T>>::$method($($args)*)
-		.max(<NonfungibleWeights<T>>::$method($($args)*))
-		.max(<RefungibleWeights<T>>::$method($($args)*))
-	};
-}
-
-pub struct CommonWeights<T: Config>(PhantomData<T>);
-impl<T: Config> CommonWeightInfo for CommonWeights<T> {
-	fn create_item() -> nft_data_structs::Weight {
-		dispatch_weight::<T>() + max_weight_of!(create_item())
-	}
-
-	fn create_multiple_items(amount: u32) -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(create_multiple_items(amount))
-	}
-
-	fn burn_item() -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(burn_item())
-	}
-
-	fn transfer() -> nft_data_structs::Weight {
-		dispatch_weight::<T>() + max_weight_of!(transfer())
-	}
-
-	fn approve() -> nft_data_structs::Weight {
-		dispatch_weight::<T>() + max_weight_of!(approve())
-	}
-
-	fn transfer_from() -> nft_data_structs::Weight {
-		dispatch_weight::<T>() + max_weight_of!(transfer_from())
-	}
-
-	fn set_variable_metadata(bytes: u32) -> nft_data_structs::Weight {
-		dispatch_weight::<T>() + max_weight_of!(set_variable_metadata(bytes))
-	}
-
-	fn burn_from() -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(burn_from())
-	}
-}
deletedpallets/nft/src/dispatch.rsdiffbeforeafterboth
--- a/pallets/nft/src/dispatch.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-use frame_support::{
-	dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo},
-	traits::Get,
-	weights::Weight,
-};
-use nft_data_structs::{CollectionId, CollectionMode, Pays, PostDispatchInfo};
-use pallet_common::{CollectionHandle, CommonCollectionOperations};
-use pallet_fungible::FungibleHandle;
-use pallet_nonfungible::NonfungibleHandle;
-use pallet_refungible::RefungibleHandle;
-
-use crate::Config;
-
-// TODO: move to benchmarking
-/// Price of [`dispatch_call`] call with noop `call` argument
-pub fn dispatch_weight<T: Config>() -> Weight {
-	// Read collection
-	<T as frame_system::Config>::DbWeight::get().reads(1)
-	// Dynamic dispatch?
-	+ 6_000_000
-	// submit_logs is measured as part of collection pallets
-}
-
-pub enum Dispatched<T: Config> {
-	Fungible(FungibleHandle<T>),
-	Nonfungible(NonfungibleHandle<T>),
-	Refungible(RefungibleHandle<T>),
-}
-impl<T: Config> Dispatched<T> {
-	pub fn dispatch(handle: CollectionHandle<T>) -> Self {
-		match handle.mode {
-			CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),
-			CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),
-			CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),
-		}
-	}
-	fn into_inner(self) -> CollectionHandle<T> {
-		match self {
-			Dispatched::Fungible(f) => f.into_inner(),
-			Dispatched::Nonfungible(f) => f.into_inner(),
-			Dispatched::Refungible(f) => f.into_inner(),
-		}
-	}
-	pub fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {
-		match self {
-			Dispatched::Fungible(h) => h,
-			Dispatched::Nonfungible(h) => h,
-			Dispatched::Refungible(h) => h,
-		}
-	}
-}
-
-/// Helper function to implement substrate calls for common collection methods
-pub fn dispatch_call<
-	T: Config,
-	C: FnOnce(&dyn pallet_common::CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,
->(
-	collection: CollectionId,
-	call: C,
-) -> DispatchResultWithPostInfo {
-	let handle =
-		CollectionHandle::try_get(collection).map_err(|error| DispatchErrorWithPostInfo {
-			post_info: PostDispatchInfo {
-				actual_weight: Some(dispatch_weight::<T>()),
-				pays_fee: Pays::Yes,
-			},
-			error,
-		})?;
-	let dispatched = Dispatched::dispatch(handle);
-	let mut result = call(dispatched.as_dyn());
-	match &mut result {
-		Ok(PostDispatchInfo {
-			actual_weight: Some(weight),
-			..
-		})
-		| Err(DispatchErrorWithPostInfo {
-			post_info: PostDispatchInfo {
-				actual_weight: Some(weight),
-				..
-			},
-			..
-		}) => *weight += dispatch_weight::<T>(),
-		_ => {}
-	}
-
-	// TODO: Make submit_logs infallible, but it shouldn't fail here anyway
-	dispatched
-		.into_inner()
-		.submit_logs()
-		.expect("should succeed");
-	result
-}
deletedpallets/nft/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/mod.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-pub mod sponsoring;
-
-use pallet_common::{
-	CollectionById,
-	erc::CommonEvmHandler,
-	eth::{map_eth_to_id, map_eth_to_token_id},
-};
-use pallet_fungible::FungibleHandle;
-use pallet_nonfungible::NonfungibleHandle;
-use pallet_refungible::{RefungibleHandle, erc::RefungibleTokenHandle};
-use sp_std::borrow::ToOwned;
-use sp_std::vec::Vec;
-use pallet_evm::{PrecompileOutput};
-use sp_core::{H160, U256};
-use crate::{CollectionMode, Config, dispatch::Dispatched};
-use pallet_common::CollectionHandle;
-
-pub struct NftErcSupport<T: Config>(core::marker::PhantomData<T>);
-
-impl<T: Config> pallet_evm::OnMethodCall<T> for NftErcSupport<T> {
-	fn is_reserved(target: &H160) -> bool {
-		map_eth_to_id(target).is_some()
-	}
-	fn is_used(target: &H160) -> bool {
-		map_eth_to_id(target)
-			.map(<CollectionById<T>>::contains_key)
-			.unwrap_or(false)
-	}
-	fn get_code(target: &H160) -> Option<Vec<u8>> {
-		if let Some(collection_id) = map_eth_to_id(target) {
-			let collection = <CollectionById<T>>::get(collection_id)?;
-			Some(
-				match collection.mode {
-					CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,
-					CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,
-					CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,
-				}
-				.to_owned(),
-			)
-		} else if let Some((collection_id, _token_id)) = map_eth_to_token_id(target) {
-			let collection = <CollectionById<T>>::get(collection_id)?;
-			if collection.mode != CollectionMode::ReFungible {
-				return None;
-			}
-			// TODO: check token existence
-			Some(<RefungibleTokenHandle<T>>::CODE.to_owned())
-		} else {
-			None
-		}
-	}
-	fn call(
-		source: &H160,
-		target: &H160,
-		gas_limit: u64,
-		input: &[u8],
-		value: U256,
-	) -> Option<PrecompileOutput> {
-		if let Some(collection_id) = map_eth_to_id(target) {
-			let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;
-			let dispatched = Dispatched::dispatch(collection);
-
-			match dispatched {
-				Dispatched::Fungible(h) => h.call(source, input, value),
-				Dispatched::Nonfungible(h) => h.call(source, input, value),
-				Dispatched::Refungible(h) => h.call(source, input, value),
-			}
-		} else if let Some((collection_id, token_id)) = map_eth_to_token_id(target) {
-			let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;
-			if collection.mode != CollectionMode::ReFungible {
-				return None;
-			}
-
-			let handle = RefungibleHandle::cast(collection);
-			// TODO: check token existence
-			RefungibleTokenHandle(handle, token_id).call(source, input, value)
-		} else {
-			None
-		}
-	}
-}
deletedpallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/sponsoring.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-//! Implements EVM sponsoring logic via OnChargeEVMTransaction
-
-use crate::{Config, sponsorship::*};
-use evm_coder::{Call, abi::AbiReader};
-use pallet_common::{CollectionHandle, eth::map_eth_to_id};
-use sp_core::H160;
-use sp_std::prelude::*;
-use up_sponsorship::SponsorshipHandler;
-use core::marker::PhantomData;
-use core::convert::TryInto;
-use nft_data_structs::TokenId;
-use up_evm_mapping::EvmBackwardsAddressMapping;
-use pallet_common::account::CrossAccountId;
-
-use pallet_nonfungible::erc::{UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721Call};
-use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};
-
-pub struct NftEthSponsorshipHandler<T: Config>(PhantomData<*const T>);
-impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for NftEthSponsorshipHandler<T> {
-	fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {
-		let collection_id = map_eth_to_id(&call.0)?;
-		let collection = <CollectionHandle<T>>::new(collection_id)?;
-		let sponsor = collection.sponsorship.sponsor()?.clone();
-		let sponsor =
-			<T as pallet_common::Config>::EvmBackwardsAddressMapping::from_account_id(sponsor);
-		let who = T::CrossAccountId::from_eth(*who);
-		let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
-		match &collection.mode {
-			crate::CollectionMode::NFT => {
-				let call = UniqueNFTCall::parse(method_id, &mut reader).ok()??;
-				match call {
-					UniqueNFTCall::ERC721UniqueExtensions(
-						ERC721UniqueExtensionsCall::Transfer { token_id, .. },
-					) => {
-						let token_id: TokenId = token_id.try_into().ok()?;
-						withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
-					}
-					UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
-						let token_id: TokenId = token_id.try_into().ok()?;
-						let from = T::CrossAccountId::from_eth(from);
-						withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
-					}
-					UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
-						let token_id: TokenId = token_id.try_into().ok()?;
-						withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
-							.map(|()| sponsor)
-					}
-					_ => None,
-				}
-			}
-			crate::CollectionMode::Fungible(_) => {
-				let call = UniqueFungibleCall::parse(method_id, &mut reader).ok()??;
-				#[allow(clippy::single_match)]
-				match call {
-					UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
-						withdraw_transfer::<T>(&collection, &who, &TokenId::default())
-							.map(|()| sponsor)
-					}
-					UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
-						let from = T::CrossAccountId::from_eth(from);
-						withdraw_transfer::<T>(&collection, &from, &TokenId::default())
-							.map(|()| sponsor)
-					}
-					UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
-						withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
-							.map(|()| sponsor)
-					}
-					_ => None,
-				}
-			}
-			_ => None,
-		}
-	}
-}
deletedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ /dev/null
@@ -1,955 +0,0 @@
-//
-// This file is subject to the terms and conditions defined in
-// file 'LICENSE', which is part of this source code package.
-//
-
-#![recursion_limit = "1024"]
-#![cfg_attr(not(feature = "std"), no_std)]
-#![allow(
-	clippy::too_many_arguments,
-	clippy::unnecessary_mut_passed,
-	clippy::unused_unit
-)]
-
-extern crate alloc;
-
-pub use serde::{Serialize, Deserialize};
-
-pub use frame_support::{
-	construct_runtime, decl_module, decl_storage, decl_error,
-	dispatch::DispatchResult,
-	ensure, fail, parameter_types,
-	traits::{
-		ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness,
-		IsSubType, WithdrawReasons,
-	},
-	weights::{
-		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
-		DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
-		WeightToFeePolynomial, DispatchClass,
-	},
-	StorageValue, transactional,
-	pallet_prelude::DispatchResultWithPostInfo,
-};
-use scale_info::TypeInfo;
-use frame_system::{self as system, ensure_signed};
-use sp_runtime::{sp_std::prelude::Vec};
-use nft_data_structs::{
-	MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,
-	VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,
-	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-	NFT_SPONSOR_TRANSFER_TIMEOUT, AccessMode, Collection, CreateItemData, CollectionLimits,
-	CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,
-};
-use pallet_common::{
-	account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,
-	CommonWeightInfo,
-};
-use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle};
-use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};
-use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};
-
-#[cfg(test)]
-mod mock;
-
-#[cfg(test)]
-mod tests;
-
-mod eth;
-mod sponsorship;
-pub use sponsorship::NftSponsorshipHandler;
-pub use eth::sponsoring::NftEthSponsorshipHandler;
-
-pub use eth::NftErcSupport;
-
-pub mod common;
-use common::CommonWeights;
-pub mod dispatch;
-use dispatch::dispatch_call;
-
-#[cfg(feature = "runtime-benchmarks")]
-mod benchmarking;
-pub mod weights;
-use weights::WeightInfo;
-
-decl_error! {
-	/// Error for non-fungible-token module.
-	pub enum Error for Module<T: Config> {
-		/// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.
-		CollectionDecimalPointLimitExceeded,
-		/// This address is not set as sponsor, use setCollectionSponsor first.
-		ConfirmUnsetSponsorFail,
-		/// Length of items properties must be greater than 0.
-		EmptyArgument,
-		/// Collection limit bounds per collection exceeded
-		CollectionLimitBoundsExceeded,
-		/// Tried to enable permissions which are only permitted to be disabled
-		OwnerPermissionsCantBeReverted,
-	}
-}
-pub trait Config:
-	system::Config
-	+ pallet_evm_coder_substrate::Config
-	+ pallet_common::Config
-	+ pallet_nonfungible::Config
-	+ pallet_refungible::Config
-	+ pallet_fungible::Config
-	+ Sized
-	+ TypeInfo
-{
-	/// Weight information for extrinsics in this pallet.
-	type WeightInfo: WeightInfo;
-}
-
-type SelfWeightOf<T> = <T as Config>::WeightInfo;
-
-// # Used definitions
-//
-// ## User control levels
-//
-// chain-controlled - key is uncontrolled by user
-//                    i.e autoincrementing index
-//                    can use non-cryptographic hash
-// real - key is controlled by user
-//        but it is hard to generate enough colliding values, i.e owner of signed txs
-//        can use non-cryptographic hash
-// controlled - key is completly controlled by users
-//              i.e maps with mutable keys
-//              should use cryptographic hash
-//
-// ## User control level downgrade reasons
-//
-// ?1 - chain-controlled -> controlled
-//      collections/tokens can be destroyed, resulting in massive holes
-// ?2 - chain-controlled -> controlled
-//      same as ?1, but can be only added, resulting in easier exploitation
-// ?3 - real -> controlled
-//      no confirmation required, so addresses can be easily generated
-decl_storage! {
-	trait Store for Module<T: Config> as Nft {
-
-		//#region Private members
-		/// Used for migrations
-		ChainVersion: u64;
-		//#endregion
-
-		//#region Tokens transfer rate limit baskets
-		/// (Collection id (controlled?2), who created (real))
-		/// TODO: Off chain worker should remove from this map when collection gets removed
-		pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;
-		/// Collection id (controlled?2), token id (controlled?2)
-		pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
-		/// Collection id (controlled?2), owning user (real)
-		pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
-		/// Collection id (controlled?2), token id (controlled?2)
-		pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
-		//#endregion
-
-		/// Variable metadata sponsoring
-		/// Collection id (controlled?2), token id (controlled?2)
-		pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
-		/// Approval sponsoring
-		pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
-		pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
-		pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
-	}
-}
-
-decl_module! {
-	pub struct Module<T: Config> for enum Call
-	where
-		origin: T::Origin
-	{
-		type Error = Error<T>;
-
-		fn on_initialize(_now: T::BlockNumber) -> Weight {
-			0
-		}
-
-		/// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.
-		///
-		/// # Permissions
-		///
-		/// * Anyone.
-		///
-		/// # Arguments
-		///
-		/// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.
-		///
-		/// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.
-		///
-		/// * token_prefix: UTF-8 string with token prefix.
-		///
-		/// * mode: [CollectionMode] collection type and type dependent data.
-		// returns collection ID
-		#[weight = <SelfWeightOf<T>>::create_collection()]
-		#[transactional]
-		pub fn create_collection(origin,
-								 collection_name: Vec<u16>,
-								 collection_description: Vec<u16>,
-								 token_prefix: Vec<u8>,
-								 mode: CollectionMode) -> DispatchResult {
-
-			// Anyone can create a collection
-			let who = ensure_signed(origin)?;
-
-			// Create new collection
-			let new_collection = Collection {
-				owner: who.clone(),
-				name: collection_name,
-				mode: mode.clone(),
-				mint_mode: false,
-				access: AccessMode::Normal,
-				description: collection_description,
-				token_prefix,
-				offchain_schema: Vec::new(),
-				schema_version: SchemaVersion::ImageURL,
-				sponsorship: SponsorshipState::Disabled,
-				variable_on_chain_schema: Vec::new(),
-				const_on_chain_schema: Vec::new(),
-				limits: Default::default(),
-				meta_update_permission: Default::default(),
-			};
-
-			let _id = match mode {
-				CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(new_collection)?},
-				CollectionMode::Fungible(decimal_points) => {
-					// check params
-					ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);
-					<PalletFungible<T>>::init_collection(new_collection)?
-				}
-				CollectionMode::ReFungible => {
-					<PalletRefungible<T>>::init_collection(new_collection)?
-				}
-			};
-
-			Ok(())
-		}
-
-		/// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: collection to destroy.
-		#[weight = <SelfWeightOf<T>>::destroy_collection()]
-		#[transactional]
-		pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			collection.check_is_owner(&sender)?;
-
-			// =========
-
-			match collection.mode {
-				CollectionMode::ReFungible => PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?,
-				CollectionMode::Fungible(_) => PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?,
-				CollectionMode::NFT => PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?,
-			}
-
-			<NftTransferBasket<T>>::remove_prefix(collection_id, None);
-			<FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
-			<ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);
-
-			<VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
-			<NftApproveBasket<T>>::remove_prefix(collection_id, None);
-			<FungibleApproveBasket<T>>::remove_prefix(collection_id, None);
-			<RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);
-
-			Ok(())
-		}
-
-		/// Add an address to allow list.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * address.
-		#[weight = <SelfWeightOf<T>>::add_to_allow_list()]
-		#[transactional]
-		pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{
-
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
-
-			<PalletCommon<T>>::toggle_allowlist(
-				&collection,
-				&sender,
-				&address,
-				true,
-			)?;
-
-			Ok(())
-		}
-
-		/// Remove an address from allow list.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * address.
-		#[weight = <SelfWeightOf<T>>::remove_from_allow_list()]
-		#[transactional]
-		pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{
-
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
-
-			<PalletCommon<T>>::toggle_allowlist(
-				&collection,
-				&sender,
-				&address,
-				false,
-			)?;
-
-			Ok(())
-		}
-
-		/// Toggle between normal and allow list access for the methods with access for `Anyone`.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * mode: [AccessMode]
-		#[weight = <SelfWeightOf<T>>::set_public_access_mode()]
-		#[transactional]
-		pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult
-		{
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner(&sender)?;
-
-			target_collection.access = mode;
-			target_collection.save()
-		}
-
-		/// Allows Anyone to create tokens if:
-		/// * Allow List is enabled, and
-		/// * Address is added to allow list, and
-		/// * This method was called with True parameter
-		///
-		/// # Permissions
-		/// * Collection Owner
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.
-		#[weight = <SelfWeightOf<T>>::set_mint_permission()]
-		#[transactional]
-		pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult
-		{
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner(&sender)?;
-
-			target_collection.mint_mode = mint_permission;
-			target_collection.save()
-		}
-
-		/// Change the owner of the collection.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * new_owner.
-		#[weight = <SelfWeightOf<T>>::change_collection_owner()]
-		#[transactional]
-		pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {
-
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner(&sender)?;
-
-			target_collection.owner = new_owner;
-			target_collection.save()
-		}
-
-		/// Adds an admin of the Collection.
-		/// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		/// * Collection Admin.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the Collection to add admin for.
-		///
-		/// * new_admin_id: Address of new admin to add.
-		#[weight = <SelfWeightOf<T>>::add_collection_admin()]
-		#[transactional]
-		pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
-
-			<PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)
-		}
-
-		/// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		/// * Collection Admin.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the Collection to remove admin for.
-		///
-		/// * account_id: Address of admin to remove.
-		#[weight = <SelfWeightOf<T>>::remove_collection_admin()]
-		#[transactional]
-		pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
-
-			<PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)
-		}
-
-		/// # Permissions
-		///
-		/// * Collection Owner
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * new_sponsor.
-		#[weight = <SelfWeightOf<T>>::set_collection_sponsor()]
-		#[transactional]
-		pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner(&sender)?;
-
-			target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);
-			target_collection.save()
-		}
-
-		/// # Permissions
-		///
-		/// * Sponsor.
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		#[weight = <SelfWeightOf<T>>::confirm_sponsorship()]
-		#[transactional]
-		pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {
-			let sender = ensure_signed(origin)?;
-
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			ensure!(
-				target_collection.sponsorship.pending_sponsor() == Some(&sender),
-				Error::<T>::ConfirmUnsetSponsorFail
-			);
-
-			target_collection.sponsorship = SponsorshipState::Confirmed(sender);
-			target_collection.save()
-		}
-
-		/// Switch back to pay-per-own-transaction model.
-		///
-		/// # Permissions
-		///
-		/// * Collection owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		#[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]
-		#[transactional]
-		pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner(&sender)?;
-
-			target_collection.sponsorship = SponsorshipState::Disabled;
-			target_collection.save()
-		}
-
-		/// This method creates a concrete instance of NFT Collection created with CreateCollection method.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		/// * Collection Admin.
-		/// * Anyone if
-		///     * Allow List is enabled, and
-		///     * Address is added to allow list, and
-		///     * MintPermission is enabled (see SetMintPermission method)
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the collection.
-		///
-		/// * owner: Address, initial owner of the NFT.
-		///
-		/// * data: Token data to store on chain.
-		#[weight = <CommonWeights<T>>::create_item()]
-		#[transactional]
-		pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data))
-		}
-
-		/// This method creates multiple items in a collection created with CreateCollection method.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		/// * Collection Admin.
-		/// * Anyone if
-		///     * Allow List is enabled, and
-		///     * Address is added to allow list, and
-		///     * MintPermission is enabled (see SetMintPermission method)
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the collection.
-		///
-		/// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].
-		///
-		/// * owner: Address, initial owner of the NFT.
-		#[weight = <CommonWeights<T>>::create_multiple_items(items_data.len() as u32)]
-		#[transactional]
-		pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {
-			ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data))
-		}
-
-		// TODO! transaction weight
-
-		/// Set transfers_enabled value for particular collection
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the collection.
-		///
-		/// * value: New flag value.
-		#[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]
-		#[transactional]
-		pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner(&sender)?;
-
-			// =========
-
-			target_collection.limits.transfers_enabled = Some(value);
-			target_collection.save()
-		}
-
-		/// Destroys a concrete instance of NFT.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		/// * Collection Admin.
-		/// * Current NFT Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the collection.
-		///
-		/// * item_id: ID of NFT to burn.
-		#[weight = <CommonWeights<T>>::burn_item()]
-		#[transactional]
-		pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;
-			if value == 1 {
-				<NftTransferBasket<T>>::remove(collection_id, item_id);
-				<NftApproveBasket<T>>::remove(collection_id, item_id);
-			}
-			// Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?
-			// <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());
-			// <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));
-			Ok(post_info)
-		}
-
-		/// Destroys a concrete instance of NFT on behalf of the owner
-		/// See also: [`approve`]
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		/// * Collection Admin.
-		/// * Current NFT Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the collection.
-		///
-		/// * item_id: ID of NFT to burn.
-		///
-		/// * from: owner of item
-		#[weight = <CommonWeights<T>>::burn_from()]
-		#[transactional]
-		pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value))
-		}
-
-		/// Change ownership of the token.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		/// * Current NFT owner
-		///
-		/// # Arguments
-		///
-		/// * recipient: Address of token recipient.
-		///
-		/// * collection_id.
-		///
-		/// * item_id: ID of the item
-		///     * Non-Fungible Mode: Required.
-		///     * Fungible Mode: Ignored.
-		///     * Re-Fungible Mode: Required.
-		///
-		/// * value: Amount to transfer.
-		///     * Non-Fungible Mode: Ignored
-		///     * Fungible Mode: Must specify transferred amount
-		///     * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)
-		#[weight = <CommonWeights<T>>::transfer()]
-		#[transactional]
-		pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value))
-		}
-
-		/// Set, change, or remove approved address to transfer the ownership of the NFT.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		/// * Current NFT owner
-		///
-		/// # Arguments
-		///
-		/// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).
-		///
-		/// * collection_id.
-		///
-		/// * item_id: ID of the item.
-		#[weight = <CommonWeights<T>>::approve()]
-		#[transactional]
-		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
-		}
-
-		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
-		///
-		/// # Permissions
-		/// * Collection Owner
-		/// * Collection Admin
-		/// * Current NFT owner
-		/// * Address approved by current NFT owner
-		///
-		/// # Arguments
-		///
-		/// * from: Address that owns token.
-		///
-		/// * recipient: Address of token recipient.
-		///
-		/// * collection_id.
-		///
-		/// * item_id: ID of the item.
-		///
-		/// * value: Amount to transfer.
-		#[weight = <CommonWeights<T>>::transfer_from()]
-		#[transactional]
-		pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value))
-		}
-
-		/// Set off-chain data schema.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * schema: String representing the offchain data schema.
-		#[weight = <CommonWeights<T>>::set_variable_metadata(data.len() as u32)]
-		#[transactional]
-		pub fn set_variable_meta_data (
-			origin,
-			collection_id: CollectionId,
-			item_id: TokenId,
-			data: Vec<u8>
-		) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))
-		}
-
-		/// Set meta_update_permission value for particular collection
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the collection.
-		///
-		/// * value: New flag value.
-		#[weight = <SelfWeightOf<T>>::set_meta_update_permission_flag()]
-		#[transactional]
-		pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-
-			ensure!(
-				target_collection.meta_update_permission != MetaUpdatePermission::None,
-				<CommonError<T>>::MetadataFlagFrozen,
-			);
-			target_collection.check_is_owner(&sender)?;
-
-			target_collection.meta_update_permission = value;
-
-			target_collection.save()
-		}
-
-		/// Set schema standard
-		/// ImageURL
-		/// Unique
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * schema: SchemaVersion: enum
-		#[weight = <SelfWeightOf<T>>::set_schema_version()]
-		#[transactional]
-		pub fn set_schema_version(
-			origin,
-			collection_id: CollectionId,
-			version: SchemaVersion
-		) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner_or_admin(&sender)?;
-			target_collection.schema_version = version;
-			target_collection.save()
-		}
-
-		/// Set off-chain data schema.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * schema: String representing the offchain data schema.
-		#[weight = <SelfWeightOf<T>>::set_offchain_schema(schema.len() as u32)]
-		#[transactional]
-		pub fn set_offchain_schema(
-			origin,
-			collection_id: CollectionId,
-			schema: Vec<u8>
-		) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner_or_admin(&sender)?;
-
-			// check schema limit
-			ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, "");
-
-			target_collection.offchain_schema = schema;
-			target_collection.save()
-		}
-
-		/// Set const on-chain data schema.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * schema: String representing the const on-chain data schema.
-		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]
-		#[transactional]
-		pub fn set_const_on_chain_schema (
-			origin,
-			collection_id: CollectionId,
-			schema: Vec<u8>
-		) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner_or_admin(&sender)?;
-
-			// check schema limit
-			ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, "");
-
-			target_collection.const_on_chain_schema = schema;
-			target_collection.save()
-		}
-
-		/// Set variable on-chain data schema.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * schema: String representing the variable on-chain data schema.
-		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]
-		#[transactional]
-		pub fn set_variable_on_chain_schema (
-			origin,
-			collection_id: CollectionId,
-			schema: Vec<u8>
-		) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner_or_admin(&sender)?;
-
-			// check schema limit
-			ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, "");
-
-			target_collection.variable_on_chain_schema = schema;
-			target_collection.save()
-		}
-
-		#[weight = <SelfWeightOf<T>>::set_collection_limits()]
-		#[transactional]
-		pub fn set_collection_limits(
-			origin,
-			collection_id: CollectionId,
-			new_limit: CollectionLimits,
-		) -> DispatchResult {
-			let mut new_limit = new_limit;
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-			target_collection.check_is_owner(&sender)?;
-			let old_limit = &target_collection.limits;
-
-			macro_rules! limit_default {
-				($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{
-					$(
-						if let Some($new) = $new.$field {
-							let $old = $old.$field($($arg)?);
-							let _ = $new;
-							let _ = $old;
-							$check
-						} else {
-							$new.$field = $old.$field
-						}
-					)*
-				}};
-			}
-
-			limit_default!(old_limit, new_limit,
-				account_token_ownership_limit => ensure!(
-					new_limit <= MAX_TOKEN_OWNERSHIP,
-					<Error<T>>::CollectionLimitBoundsExceeded,
-				),
-				sponsor_transfer_timeout(match target_collection.mode {
-					CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
-					CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-					CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-				}) => ensure!(
-					new_limit <= MAX_SPONSOR_TIMEOUT,
-					<Error<T>>::CollectionLimitBoundsExceeded,
-				),
-				sponsored_data_size => ensure!(
-					new_limit <= CUSTOM_DATA_LIMIT,
-					<Error<T>>::CollectionLimitBoundsExceeded,
-				),
-				token_limit => ensure!(
-					old_limit >= new_limit && new_limit > 0,
-					<CommonError<T>>::CollectionTokenLimitExceeded
-				),
-				owner_can_transfer => ensure!(
-					old_limit || !new_limit,
-					<Error<T>>::OwnerPermissionsCantBeReverted,
-				),
-				owner_can_destroy => ensure!(
-					old_limit || !new_limit,
-					<Error<T>>::OwnerPermissionsCantBeReverted,
-				),
-				sponsored_data_rate_limit => {},
-				transfers_enabled => {},
-			);
-
-			target_collection.limits = new_limit;
-
-			target_collection.save()
-		}
-	}
-}
deletedpallets/nft/src/mock.rsdiffbeforeafterboth
--- a/pallets/nft/src/mock.rs
+++ /dev/null
@@ -1,177 +0,0 @@
-#![allow(clippy::from_over_into)]
-
-use crate as pallet_template;
-use sp_core::H256;
-use frame_support::{parameter_types, traits::Everything, weights::IdentityFee};
-use sp_runtime::{
-	traits::{BlakeTwo256, IdentityLookup},
-	testing::Header,
-};
-use pallet_transaction_payment::{CurrencyAdapter};
-use frame_system as system;
-use pallet_evm::AddressMapping;
-use crate::{EvmBackwardsAddressMapping, CrossAccountId};
-use codec::{Encode, Decode};
-use scale_info::TypeInfo;
-
-type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
-type Block = frame_system::mocking::MockBlock<Test>;
-
-// Configure a mock runtime to test the pallet.
-frame_support::construct_runtime!(
-	pub enum Test where
-		Block = Block,
-		NodeBlock = Block,
-		UncheckedExtrinsic = UncheckedExtrinsic,
-	{
-		System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
-		TemplateModule: pallet_template::{Pallet, Call, Storage},
-		Balances: pallet_balances::{Pallet, Call, Storage},
-	}
-);
-
-parameter_types! {
-	pub const BlockHashCount: u64 = 250;
-	pub const SS58Prefix: u8 = 42;
-}
-
-impl system::Config for Test {
-	type BaseCallFilter = Everything;
-	type BlockWeights = ();
-	type BlockLength = ();
-	type DbWeight = ();
-	type Origin = Origin;
-	type Call = Call;
-	type Index = u64;
-	type BlockNumber = u64;
-	type Hash = H256;
-	type Hashing = BlakeTwo256;
-	type AccountId = u64;
-	type Lookup = IdentityLookup<Self::AccountId>;
-	type Header = Header;
-	type Event = ();
-	type BlockHashCount = BlockHashCount;
-	type Version = ();
-	type PalletInfo = PalletInfo;
-	type AccountData = pallet_balances::AccountData<u64>;
-	type OnNewAccount = ();
-	type OnKilledAccount = ();
-	type SystemWeightInfo = ();
-	type SS58Prefix = SS58Prefix;
-	type OnSetCode = ();
-}
-
-parameter_types! {
-	pub const ExistentialDeposit: u64 = 1;
-	pub const MaxLocks: u32 = 50;
-}
-//frame_system::Module<Test>;
-impl pallet_balances::Config for Test {
-	type AccountStore = System;
-	type Balance = u64;
-	type DustRemoval = ();
-	type Event = ();
-	type ExistentialDeposit = ExistentialDeposit;
-	type WeightInfo = ();
-	type MaxLocks = MaxLocks;
-	type MaxReserves = ();
-	type ReserveIdentifier = [u8; 8];
-}
-
-parameter_types! {
-	pub const TransactionByteFee: u64 = 1;
-	pub const OperationalFeeMultiplier: u8 = 5;
-}
-
-impl pallet_transaction_payment::Config for Test {
-	type OnChargeTransaction = CurrencyAdapter<pallet_balances::Pallet<Test>, ()>;
-	type TransactionByteFee = TransactionByteFee;
-	type WeightToFee = IdentityFee<u64>;
-	type FeeMultiplierUpdate = ();
-	type OperationalFeeMultiplier = OperationalFeeMultiplier;
-}
-
-parameter_types! {
-	pub const MinimumPeriod: u64 = 1;
-}
-impl pallet_timestamp::Config for Test {
-	type Moment = u64;
-	type OnTimestampSet = ();
-	type MinimumPeriod = MinimumPeriod;
-	type WeightInfo = ();
-}
-
-parameter_types! {
-	pub const CollectionCreationPrice: u32 = 0;
-	pub TreasuryAccountId: u64 = 1234;
-	pub EthereumChainId: u32 = 1111;
-}
-
-pub struct TestEvmAddressMapping;
-impl AddressMapping<u64> for TestEvmAddressMapping {
-	fn into_account_id(_addr: sp_core::H160) -> u64 {
-		unimplemented!()
-	}
-}
-
-pub struct TestEvmBackwardsAddressMapping;
-impl EvmBackwardsAddressMapping<u64> for TestEvmBackwardsAddressMapping {
-	fn from_account_id(_account_id: u64) -> sp_core::H160 {
-		unimplemented!()
-	}
-}
-
-#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, TypeInfo)]
-pub struct TestCrossAccountId(u64, sp_core::H160);
-impl CrossAccountId<u64> for TestCrossAccountId {
-	fn from_sub(sub: u64) -> Self {
-		let mut eth = [0; 20];
-		eth[12..20].copy_from_slice(&sub.to_be_bytes());
-		Self(sub, sp_core::H160(eth))
-	}
-	fn as_sub(&self) -> &u64 {
-		&self.0
-	}
-	fn from_eth(eth: sp_core::H160) -> Self {
-		let mut sub_raw = [0; 8];
-		sub_raw.copy_from_slice(&eth.0[0..8]);
-		let sub = u64::from_be_bytes(sub_raw);
-		Self(sub, eth)
-	}
-	fn as_eth(&self) -> &sp_core::H160 {
-		&self.1
-	}
-}
-
-pub struct TestEtheremTransactionSender;
-impl pallet_ethereum::EthereumTransactionSender for TestEtheremTransactionSender {
-	fn submit_logs_transaction(
-		_tx: pallet_ethereum::Transaction,
-		_logs: Vec<pallet_ethereum::Log>,
-	) -> Result<(), sp_runtime::DispatchError> {
-		Ok(())
-	}
-}
-
-impl pallet_evm_coder_substrate::Config for Test {
-	type EthereumTransactionSender = TestEtheremTransactionSender;
-}
-
-impl pallet_template::Config for Test {
-	type Event = ();
-	type WeightInfo = ();
-	type CollectionCreationPrice = CollectionCreationPrice;
-	type Currency = pallet_balances::Pallet<Test>;
-	type TreasuryAccountId = TreasuryAccountId;
-	type EvmAddressMapping = TestEvmAddressMapping;
-	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
-	type CrossAccountId = TestCrossAccountId;
-}
-
-// Build genesis storage according to the mock runtime.
-pub fn new_test_ext() -> sp_io::TestExternalities {
-	system::GenesisConfig::default()
-		.build_storage::<Test>()
-		.unwrap()
-		.into()
-}
deletedpallets/nft/src/sponsorship.rsdiffbeforeafterboth
--- a/pallets/nft/src/sponsorship.rs
+++ /dev/null
@@ -1,282 +0,0 @@
-use crate::{
-	Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,
-	FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode, NftApproveBasket,
-	FungibleApproveBasket, RefungibleApproveBasket,
-};
-use core::marker::PhantomData;
-use up_sponsorship::SponsorshipHandler;
-use frame_support::{
-	traits::{IsSubType},
-	storage::{StorageMap, StorageDoubleMap, StorageNMap},
-};
-use nft_data_structs::{
-	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
-	NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId,
-};
-use pallet_common::{CollectionHandle};
-use pallet_common::account::CrossAccountId;
-
-pub fn withdraw_transfer<T: Config>(
-	collection: &CollectionHandle<T>,
-	who: &T::CrossAccountId,
-	item_id: &TokenId,
-) -> Option<()> {
-	// preliminary sponsoring correctness check
-	match collection.mode {
-		CollectionMode::NFT => {
-			let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
-			if !owner.conv_eq(who) {
-				return None;
-			}
-		}
-		CollectionMode::Fungible(_) => {
-			if item_id != &TokenId::default() {
-				return None;
-			}
-			if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
-				return None;
-			}
-		}
-		CollectionMode::ReFungible => {
-			if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
-				return None;
-			}
-		}
-	}
-
-	// sponsor timeout
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection
-		.limits
-		.sponsor_transfer_timeout(match collection.mode {
-			CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
-			CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-			CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-		});
-
-	let last_tx_block = match collection.mode {
-		CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),
-		CollectionMode::Fungible(_) => {
-			<FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
-		}
-		CollectionMode::ReFungible => {
-			<ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))
-		}
-	};
-
-	if let Some(last_tx_block) = last_tx_block {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	match collection.mode {
-		CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),
-		CollectionMode::Fungible(_) => {
-			<FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)
-		}
-		CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(
-			(collection.id, item_id, who.as_sub()),
-			block_number,
-		),
-	};
-
-	Some(())
-}
-
-pub fn withdraw_create_item<T: Config>(
-	collection: &CollectionHandle<T>,
-	who: &T::AccountId,
-	_properties: &CreateItemData,
-) -> Option<()> {
-	if _properties.data_size() as u32 > collection.limits.sponsored_data_size() {
-		return None;
-	}
-
-	// sponsor timeout
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection
-		.limits
-		.sponsor_transfer_timeout(match _properties {
-			CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,
-			CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-			CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-		});
-
-	if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, &who)) {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	CreateItemBasket::<T>::insert((collection.id, who.clone()), block_number);
-
-	Some(())
-}
-
-pub fn withdraw_set_variable_meta_data<T: Config>(
-	who: &T::CrossAccountId,
-	collection: &CollectionHandle<T>,
-	item_id: &TokenId,
-	data: &[u8],
-) -> Option<()> {
-	// TODO: make it work for admins
-	if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {
-		return None;
-	}
-	// preliminary sponsoring correctness check
-	match collection.mode {
-		CollectionMode::NFT => {
-			let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
-			if !owner.conv_eq(who) {
-				return None;
-			}
-		}
-		CollectionMode::Fungible(_) => {
-			if item_id != &TokenId::default() {
-				return None;
-			}
-			if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
-				return None;
-			}
-		}
-		CollectionMode::ReFungible => {
-			if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
-				return None;
-			}
-		}
-	}
-
-	// Can't sponsor fungible collection, this tx will be rejected
-	// as invalid
-	if matches!(collection.mode, CollectionMode::Fungible(_)) {
-		return None;
-	}
-	if data.len() > collection.limits.sponsored_data_size() as usize {
-		return None;
-	}
-
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection.limits.sponsored_data_rate_limit()?;
-
-	if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	<VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);
-
-	Some(())
-}
-
-pub fn withdraw_approve<T: Config>(
-	collection: &CollectionHandle<T>,
-	who: &T::AccountId,
-	item_id: &TokenId,
-) -> Option<()> {
-	// sponsor timeout
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection.limits.sponsor_approve_timeout();
-
-	let last_tx_block = match collection.mode {
-		CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),
-		CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),
-		CollectionMode::ReFungible => {
-			<RefungibleApproveBasket<T>>::get((collection.id, item_id, who))
-		}
-	};
-
-	if let Some(last_tx_block) = last_tx_block {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	match collection.mode {
-		CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),
-		CollectionMode::Fungible(_) => {
-			<FungibleApproveBasket<T>>::insert(collection.id, who, block_number)
-		}
-		CollectionMode::ReFungible => {
-			<RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)
-		}
-	};
-
-	Some(())
-}
-
-fn load<T: Config>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {
-	let collection = CollectionHandle::new(id)?;
-	let sponsor = collection.sponsorship.sponsor().cloned()?;
-	Some((sponsor, collection))
-}
-
-pub struct NftSponsorshipHandler<T>(PhantomData<T>);
-impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>
-where
-	T: Config,
-	C: IsSubType<Call<T>>,
-{
-	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
-		match IsSubType::<Call<T>>::is_sub_type(call)? {
-			Call::create_item {
-				collection_id,
-				data,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_create_item::<T>(&collection, who, data).map(|()| sponsor)
-			}
-			Call::transfer {
-				collection_id,
-				item_id,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_transfer::<T>(
-					&collection,
-					&T::CrossAccountId::from_sub(who.clone()),
-					item_id,
-				)
-				.map(|()| sponsor)
-			}
-			Call::transfer_from {
-				collection_id,
-				item_id,
-				from,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)
-			}
-			Call::approve {
-				collection_id,
-				item_id,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
-			}
-			Call::set_variable_meta_data {
-				collection_id,
-				item_id,
-				data,
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_set_variable_meta_data::<T>(
-					&T::CrossAccountId::from_sub(who.clone()),
-					&collection,
-					item_id,
-					data,
-				)
-				.map(|()| sponsor)
-			}
-			_ => None,
-		}
-	}
-}
deletedpallets/nft/src/tests.rsdiffbeforeafterboth
--- a/pallets/nft/src/tests.rs
+++ /dev/null
@@ -1,2291 +0,0 @@
-// Tests to be written here
-use super::*;
-use crate::mock::*;
-use crate::{AccessMode, CollectionMode, Ownership, CreateItemData};
-use nft_data_structs::{
-	CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId,
-	MAX_DECIMAL_POINTS,
-};
-use frame_support::{assert_noop, assert_ok};
-use sp_std::convert::TryInto;
-
-fn default_nft_data() -> CreateNftData {
-	CreateNftData {
-		const_data: vec![1, 2, 3].try_into().unwrap(),
-		variable_data: vec![3, 2, 1].try_into().unwrap(),
-	}
-}
-
-fn default_fungible_data() -> CreateFungibleData {
-	CreateFungibleData { value: 5 }
-}
-
-fn default_re_fungible_data() -> CreateReFungibleData {
-	CreateReFungibleData {
-		const_data: vec![1, 2, 3].try_into().unwrap(),
-		variable_data: vec![3, 2, 1].try_into().unwrap(),
-		pieces: 1023,
-	}
-}
-
-fn create_test_collection_for_owner(
-	mode: &CollectionMode,
-	owner: u64,
-	id: CollectionId,
-) -> CollectionId {
-	let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-	let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-	let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-
-	let origin1 = Origin::signed(owner);
-	assert_ok!(TemplateModule::create_collection(
-		origin1,
-		col_name1,
-		col_desc1,
-		token_prefix1,
-		mode.clone()
-	));
-
-	let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-	let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-	let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();
-	assert_eq!(TemplateModule::collection_id(id).unwrap().owner, owner);
-	assert_eq!(
-		TemplateModule::collection_id(id).unwrap().name,
-		saved_col_name
-	);
-	assert_eq!(TemplateModule::collection_id(id).unwrap().mode, *mode);
-	assert_eq!(
-		TemplateModule::collection_id(id).unwrap().description,
-		saved_description
-	);
-	assert_eq!(
-		TemplateModule::collection_id(id).unwrap().token_prefix,
-		saved_prefix
-	);
-	id
-}
-
-fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {
-	create_test_collection_for_owner(&mode, 1, id)
-}
-
-fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {
-	let origin1 = Origin::signed(1);
-	assert_ok!(TemplateModule::create_item(
-		origin1,
-		collection_id,
-		account(1),
-		data.clone()
-	));
-}
-
-fn account(sub: u64) -> TestCrossAccountId {
-	TestCrossAccountId::from_sub(sub)
-}
-
-// Use cases tests region
-// #region
-
-#[test]
-fn set_version_schema() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		assert_ok!(TemplateModule::set_schema_version(
-			origin1,
-			collection_id,
-			SchemaVersion::Unique
-		));
-		assert_eq!(
-			TemplateModule::collection_id(collection_id)
-				.unwrap()
-				.schema_version,
-			SchemaVersion::Unique
-		);
-	});
-}
-
-#[test]
-fn create_fungible_collection_fails_with_large_decimal_numbers() {
-	new_test_ext().execute_with(|| {
-		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-
-		let origin1 = Origin::signed(1);
-		assert_noop!(
-			TemplateModule::create_collection(
-				origin1,
-				col_name1,
-				col_desc1,
-				token_prefix1,
-				CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)
-			),
-			Error::<Test>::CollectionDecimalPointLimitExceeded
-		);
-	});
-}
-
-#[test]
-fn create_nft_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.clone().into());
-		let item = TemplateModule::nft_item_id(collection_id, 1).unwrap();
-		assert_eq!(item.const_data, data.const_data.into_inner());
-		assert_eq!(item.variable_data, data.variable_data.into_inner());
-	});
-}
-
-// Use cases tests region
-// #region
-#[test]
-fn create_nft_multiple_items() {
-	new_test_ext().execute_with(|| {
-		create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];
-
-		assert_ok!(TemplateModule::create_multiple_items(
-			origin1,
-			1,
-			account(1),
-			items_data
-				.clone()
-				.into_iter()
-				.map(|d| { d.into() })
-				.collect()
-		));
-		for (index, data) in items_data.into_iter().enumerate() {
-			let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap();
-			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
-			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
-		}
-	});
-}
-
-#[test]
-fn create_refungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
-
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.clone().into());
-		let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();
-		assert_eq!(item.const_data, data.const_data.into_inner());
-		assert_eq!(item.variable_data, data.variable_data.into_inner());
-		assert_eq!(
-			item.owner[0],
-			Ownership {
-				owner: account(1),
-				fraction: 1023
-			}
-		);
-	});
-}
-
-#[test]
-fn create_multiple_refungible_items() {
-	new_test_ext().execute_with(|| {
-		create_test_collection(&CollectionMode::ReFungible, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let items_data = vec![
-			default_re_fungible_data(),
-			default_re_fungible_data(),
-			default_re_fungible_data(),
-		];
-
-		assert_ok!(TemplateModule::create_multiple_items(
-			origin1,
-			1,
-			account(1),
-			items_data
-				.clone()
-				.into_iter()
-				.map(|d| { d.into() })
-				.collect()
-		));
-		for (index, data) in items_data.into_iter().enumerate() {
-			let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap();
-			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
-			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
-			assert_eq!(
-				item.owner[0],
-				Ownership {
-					owner: account(1),
-					fraction: 1023
-				}
-			);
-		}
-	});
-}
-
-#[test]
-fn create_fungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).value, 5);
-	});
-}
-
-//#[test]
-// fn create_multiple_fungible_items() {
-//     new_test_ext().execute_with(|| {
-//         default_limits();
-
-//         create_test_collection(&CollectionMode::Fungible(3), 1);
-
-//         let origin1 = Origin::signed(1);
-
-//         let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];
-
-//         assert_ok!(TemplateModule::create_multiple_items(
-//             origin1.clone(),
-//             1,
-//             1,
-//             items_data.clone().into_iter().map(|d| { d.into() }).collect()
-//         ));
-
-//         for (index, _) in items_data.iter().enumerate() {
-//             assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);
-//         }
-//         assert_eq!(TemplateModule::balance_count(1, 1), 3000);
-//         assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);
-//     });
-// }
-
-#[test]
-fn transfer_fungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 5);
-		assert_eq!(TemplateModule::balance_count(1, 1), 5);
-
-		// change owner scenario
-		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 5));
-		assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 0);
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-		assert_eq!(TemplateModule::balance_count(1, 2), 5);
-
-		// split item scenario
-		assert_ok!(TemplateModule::transfer(
-			origin2.clone(),
-			account(3),
-			1,
-			1,
-			3
-		));
-		assert_eq!(TemplateModule::balance_count(1, 2), 2);
-		assert_eq!(TemplateModule::balance_count(1, 3), 3);
-
-		// split item and new owner has account scenario
-		assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 1));
-		assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 1);
-		assert_eq!(TemplateModule::fungible_item_id(1, 3).value, 4);
-		assert_eq!(TemplateModule::balance_count(1, 2), 1);
-		assert_eq!(TemplateModule::balance_count(1, 3), 4);
-	});
-}
-
-#[test]
-fn transfer_refungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
-
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.clone().into());
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-		{
-			let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();
-			assert_eq!(item.const_data, data.const_data.into_inner());
-			assert_eq!(item.variable_data, data.variable_data.into_inner());
-			assert_eq!(
-				item.owner[0],
-				Ownership {
-					owner: account(1),
-					fraction: 1023
-				}
-			);
-		}
-		assert_eq!(TemplateModule::balance_count(1, 1), 1023);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-
-		// change owner scenario
-		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1023));
-		assert_eq!(
-			TemplateModule::refungible_item_id(1, 1).unwrap().owner[0],
-			Ownership {
-				owner: account(2),
-				fraction: 1023
-			}
-		);
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-		assert_eq!(TemplateModule::balance_count(1, 2), 1023);
-		// assert_eq!(TemplateModule::address_tokens(1, 1), []);
-		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
-
-		// split item scenario
-		assert_ok!(TemplateModule::transfer(
-			origin2.clone(),
-			account(3),
-			1,
-			1,
-			500
-		));
-		{
-			let item = TemplateModule::refungible_item_id(1, 1).unwrap();
-			assert_eq!(
-				item.owner[0],
-				Ownership {
-					owner: account(2),
-					fraction: 523
-				}
-			);
-			assert_eq!(
-				item.owner[1],
-				Ownership {
-					owner: account(3),
-					fraction: 500
-				}
-			);
-		}
-		assert_eq!(TemplateModule::balance_count(1, 2), 523);
-		assert_eq!(TemplateModule::balance_count(1, 3), 500);
-		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
-		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
-
-		// split item and new owner has account scenario
-		assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 200));
-		{
-			let item = TemplateModule::refungible_item_id(1, 1).unwrap();
-			assert_eq!(
-				item.owner[0],
-				Ownership {
-					owner: account(2),
-					fraction: 323
-				}
-			);
-			assert_eq!(
-				item.owner[1],
-				Ownership {
-					owner: account(3),
-					fraction: 700
-				}
-			);
-		}
-		assert_eq!(TemplateModule::balance_count(1, 2), 323);
-		assert_eq!(TemplateModule::balance_count(1, 3), 700);
-		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
-		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
-	});
-}
-
-#[test]
-fn transfer_nft_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-
-		let origin1 = Origin::signed(1);
-		// default scenario
-		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));
-		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-		assert_eq!(TemplateModule::balance_count(1, 2), 1);
-		// assert_eq!(TemplateModule::address_tokens(1, 1), []);
-		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
-	});
-}
-
-#[test]
-fn nft_approve_and_transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-
-		// neg transfer
-		assert_noop!(
-			TemplateModule::transfer_from(origin2.clone(), account(1), account(2), 1, 1, 1),
-			Error::<Test>::NoPermission
-		);
-
-		// do approve
-		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 5));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(3),
-			1,
-			1,
-			1
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);
-	});
-}
-
-#[test]
-fn nft_approve_and_transfer_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.clone().into());
-
-		assert_eq!(
-			&TemplateModule::nft_item_id(1, 1).unwrap().const_data,
-			&data.const_data.into_inner()
-		);
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			1,
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			1,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(3)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(2),
-			1,
-			1,
-			5
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
-		assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(3),
-			1,
-			1,
-			1
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);
-	});
-}
-
-#[test]
-fn refungible_approve_and_transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_eq!(TemplateModule::balance_count(1, 1), 1023);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			1,
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			1,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(3)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1023));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023);
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(3),
-			1,
-			1,
-			100
-		));
-		assert_eq!(TemplateModule::balance_count(1, 1), 923);
-		assert_eq!(TemplateModule::balance_count(1, 3), 100);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
-
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 923);
-	});
-}
-
-#[test]
-fn fungible_approve_and_transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_eq!(TemplateModule::balance_count(1, 1), 5);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			1,
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			1,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(3)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(2),
-			1,
-			1,
-			5
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
-		assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2.clone(),
-			account(1),
-			account(3),
-			1,
-			1,
-			4
-		));
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-		assert_eq!(TemplateModule::balance_count(1, 3), 4);
-
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);
-
-		assert_noop!(
-			TemplateModule::transfer_from(origin2, account(1), account(3), 1, 1, 4),
-			Error::<Test>::NoPermission
-		);
-	});
-}
-
-#[test]
-fn change_collection_owner() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::change_collection_owner(
-			origin1,
-			collection_id,
-			2
-		));
-		assert_eq!(
-			TemplateModule::collection_id(collection_id).unwrap().owner,
-			2
-		);
-	});
-}
-
-#[test]
-fn destroy_collection() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));
-	});
-}
-
-#[test]
-fn burn_nft_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-
-		// burn item
-		assert_ok!(TemplateModule::burn_item(
-			origin1.clone(),
-			collection_id,
-			1,
-			1
-		));
-		assert_noop!(
-			TemplateModule::burn_item(origin1, collection_id, 1, 1),
-			Error::<Test>::TokenNotFound
-		);
-
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-	});
-}
-
-#[test]
-fn burn_fungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(TemplateModule::balance_count(1, 1), 5);
-
-		// burn item
-		assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));
-		assert_noop!(
-			TemplateModule::burn_item(origin1, 1, 1, 5),
-			Error::<Test>::TokenValueNotEnough
-		);
-
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-	});
-}
-
-#[test]
-fn burn_refungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			1,
-			account(2)
-		));
-
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 2)
-		assert_eq!(TemplateModule::balance_count(1, 1), 1023);
-
-		// burn item
-		assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023));
-		assert_noop!(
-			TemplateModule::burn_item(origin1, 1, 1, 1023),
-			Error::<Test>::TokenNotFound
-		);
-
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-	});
-}
-
-#[test]
-fn add_collection_admin() {
-	new_test_ext().execute_with(|| {
-		let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
-		create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);
-		create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);
-
-		let origin1 = Origin::signed(1);
-
-		// collection admin
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection1_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection1_id,
-			account(3)
-		));
-
-		assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(2)),);
-		assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(3)),);
-	});
-}
-
-#[test]
-fn remove_collection_admin() {
-	new_test_ext().execute_with(|| {
-		let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
-		create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);
-		create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		// collection admin
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection1_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection1_id,
-			account(3)
-		));
-
-		assert!(TemplateModule::admin_list_collection(1).contains(&account(2)),);
-		assert!(TemplateModule::admin_list_collection(1).contains(&account(3)),);
-
-		// remove admin
-		assert_ok!(TemplateModule::remove_collection_admin(
-			origin2,
-			1,
-			account(3)
-		));
-		assert!(!TemplateModule::admin_list_collection(1).contains(&account(3)),);
-	});
-}
-
-#[test]
-fn balance_of() {
-	new_test_ext().execute_with(|| {
-		let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);
-		let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);
-
-		// check balance before
-		assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);
-		assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);
-		assert_eq!(
-			TemplateModule::balance_count(re_fungible_collection_id, 1),
-			0
-		);
-
-		let nft_data = default_nft_data();
-		create_test_item(nft_collection_id, &nft_data.into());
-
-		let fungible_data = default_fungible_data();
-		create_test_item(fungible_collection_id, &fungible_data.into());
-
-		let re_fungible_data = default_re_fungible_data();
-		create_test_item(re_fungible_collection_id, &re_fungible_data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);
-		assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);
-		assert_eq!(
-			TemplateModule::balance_count(re_fungible_collection_id, 1),
-			1023
-		);
-		assert_eq!(
-			TemplateModule::nft_item_id(nft_collection_id, 1)
-				.unwrap()
-				.owner,
-			account(1)
-		);
-		assert_eq!(
-			TemplateModule::fungible_item_id(fungible_collection_id, 1).value,
-			5
-		);
-		assert_eq!(
-			TemplateModule::refungible_item_id(re_fungible_collection_id, 1)
-				.unwrap()
-				.owner[0]
-				.owner,
-			account(1)
-		);
-	});
-}
-
-#[test]
-fn approve() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-
-		// approve
-		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);
-	});
-}
-
-#[test]
-fn transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		// approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(2),
-			1,
-			1,
-			1
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			1,
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			1,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(origin1, 1, account(3)));
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(2),
-			1,
-			1,
-			1
-		));
-
-		// after transfer
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-		assert_eq!(TemplateModule::balance_count(1, 2), 1);
-	});
-}
-
-// #endregion
-
-// Coverage tests region
-// #region
-
-#[test]
-fn owner_can_add_address_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert!(TemplateModule::allow_list(collection_id, 2));
-	});
-}
-
-#[test]
-fn admin_can_add_address_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin2,
-			collection_id,
-			account(3)
-		));
-		assert!(TemplateModule::allow_list(collection_id, 3));
-	});
-}
-
-#[test]
-fn nonprivileged_user_cannot_add_address_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin2 = Origin::signed(2);
-		assert_noop!(
-			TemplateModule::add_to_allow_list(origin2, collection_id, account(3)),
-			Error::<Test>::NoPermission
-		);
-	});
-}
-
-#[test]
-fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		assert_noop!(
-			TemplateModule::add_to_allow_list(origin1, 1, account(2)),
-			Error::<Test>::CollectionNotFound
-		);
-	});
-}
-
-#[test]
-fn nobody_can_add_address_to_allow_list_of_deleted_collection() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::destroy_collection(
-			origin1.clone(),
-			collection_id
-		));
-		assert_noop!(
-			TemplateModule::add_to_allow_list(origin1, collection_id, account(2)),
-			Error::<Test>::CollectionNotFound
-		);
-	});
-}
-
-// If address is already added to allow list, nothing happens
-#[test]
-fn address_is_already_added_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert!(TemplateModule::allow_list(collection_id, 2));
-	});
-}
-
-#[test]
-fn owner_can_remove_address_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert!(!TemplateModule::allow_list(collection_id, 2));
-	});
-}
-
-#[test]
-fn admin_can_remove_address_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(3)
-		));
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin2,
-			collection_id,
-			account(3)
-		));
-		assert!(!TemplateModule::allow_list(collection_id, 3));
-	});
-}
-
-#[test]
-fn nonprivileged_user_cannot_remove_address_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert_noop!(
-			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),
-			Error::<Test>::NoPermission
-		);
-		assert!(TemplateModule::allow_list(collection_id, 2));
-	});
-}
-
-#[test]
-fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		assert_noop!(
-			TemplateModule::remove_from_allow_list(origin1, 1, account(2)),
-			Error::<Test>::CollectionNotFound
-		);
-	});
-}
-
-#[test]
-fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));
-		assert_noop!(
-			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),
-			Error::<Test>::CollectionNotFound
-		);
-		assert!(!TemplateModule::allow_list(collection_id, 2));
-	});
-}
-
-// If address is already removed from allow list, nothing happens
-#[test]
-fn address_is_already_removed_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert!(!TemplateModule::allow_list(collection_id, 2));
-	});
-}
-
-// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)
-#[test]
-fn allow_list_test_1() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer(origin1, account(3), 1, 1, 1),
-			Error::<Test>::AddresNotInAllowList
-		);
-	});
-}
-
-#[test]
-fn allow_list_test_2() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(2)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(1),
-			1,
-			1,
-			1
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);
-
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),
-			Error::<Test>::AddresNotInAllowList
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)
-#[test]
-fn allow_list_test_3() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			1,
-			account(1)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer(origin1, account(3), 1, 1, 1),
-			Error::<Test>::AddresNotInAllowList
-		);
-	});
-}
-
-#[test]
-fn allow_list_test_4() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(1),
-			1,
-			1,
-			1
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);
-
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),
-			Error::<Test>::AddresNotInAllowList
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)
-#[test]
-fn allow_list_test_5() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_noop!(
-			TemplateModule::burn_item(origin1.clone(), 1, 1, 5),
-			Error::<Test>::AddresNotInAllowList
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).
-#[test]
-fn allow_list_test_6() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-
-		// do approve
-		assert_noop!(
-			TemplateModule::approve(origin1, account(1), 1, 1, 5),
-			Error::<Test>::AddresNotInAllowList
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and
-//          tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)
-#[test]
-fn allow_list_test_7() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1));
-	});
-}
-
-#[test]
-fn allow_list_test_8() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(1),
-			1,
-			1,
-			5
-		));
-		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 5);
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin1,
-			account(1),
-			account(2),
-			1,
-			1,
-			1
-		));
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.
-#[test]
-fn allow_list_test_9() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			false
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.
-#[test]
-fn allow_list_test_10() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			false
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::create_item(
-			origin2,
-			collection_id,
-			account(2),
-			default_nft_data().into()
-		));
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow listed address.
-#[test]
-fn allow_list_test_11() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			false
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_noop!(
-			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),
-			Error::<Test>::PublicMintingNotAllowed
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address.
-#[test]
-fn allow_list_test_12() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			false
-		));
-
-		assert_noop!(
-			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),
-			Error::<Test>::PublicMintingNotAllowed
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.
-#[test]
-fn allow_list_test_13() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			true
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.
-#[test]
-fn allow_list_test_14() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::create_item(
-			origin2,
-			1,
-			account(2),
-			default_nft_data().into()
-		));
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address.
-#[test]
-fn allow_list_test_15() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			true
-		));
-
-		assert_noop!(
-			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),
-			Error::<Test>::AddresNotInAllowList
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address.
-#[test]
-fn allow_list_test_16() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::create_item(
-			origin2,
-			1,
-			account(2),
-			default_nft_data().into()
-		));
-	});
-}
-
-// Total number of collections. Positive test
-#[test]
-fn total_number_collections_bound() {
-	new_test_ext().execute_with(|| {
-		create_test_collection(&CollectionMode::NFT, 1);
-	});
-}
-
-// Total number of collections. Negotive test
-#[test]
-fn total_number_collections_bound_neg() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		for i in 0..COLLECTION_NUMBER_LIMIT {
-			create_test_collection(&CollectionMode::NFT, i + 1);
-		}
-
-		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-
-		// 11-th collection in chain. Expects error
-		assert_noop!(
-			TemplateModule::create_collection(
-				origin1,
-				col_name1,
-				col_desc1,
-				token_prefix1,
-				CollectionMode::NFT
-			),
-			Error::<Test>::TotalCollectionsLimitExceeded
-		);
-	});
-}
-
-// Owned tokens by a single address. Positive test
-#[test]
-fn owned_tokens_bound() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.clone().into());
-		create_test_item(collection_id, &data.into());
-	});
-}
-
-// Owned tokens by a single address. Negotive test
-#[test]
-fn owned_tokens_bound_neg() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		for _ in 0..ACCOUNT_TOKEN_OWNERSHIP_LIMIT {
-			let data = default_nft_data();
-			create_test_item(collection_id, &data.clone().into());
-		}
-
-		let data = default_nft_data();
-		assert_noop!(
-			TemplateModule::create_item(origin1, 1, account(1), data.into()),
-			Error::<Test>::AccountTokenLimitExceeded
-		);
-	});
-}
-
-// Number of collection admins. Positive test
-#[test]
-fn collection_admins_bound() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(3)
-		));
-	});
-}
-
-// Number of collection admins. Negotive test
-#[test]
-fn collection_admins_bound_neg() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		for i in 0..COLLECTION_ADMINS_LIMIT {
-			assert_ok!(TemplateModule::add_collection_admin(
-				origin1.clone(),
-				collection_id,
-				account(2 + i)
-			));
-		}
-		assert_noop!(
-			TemplateModule::add_collection_admin(
-				origin1,
-				collection_id,
-				account(3 + COLLECTION_ADMINS_LIMIT)
-			),
-			Error::<Test>::CollectionAdminsLimitExceeded
-		);
-	});
-}
-// #endregion
-
-#[test]
-fn set_const_on_chain_schema() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::set_const_on_chain_schema(
-			origin1,
-			collection_id,
-			b"test const on chain schema".to_vec()
-		));
-
-		assert_eq!(
-			TemplateModule::collection_id(collection_id)
-				.unwrap()
-				.const_on_chain_schema,
-			b"test const on chain schema".to_vec()
-		);
-		assert_eq!(
-			TemplateModule::collection_id(collection_id)
-				.unwrap()
-				.variable_on_chain_schema,
-			b"".to_vec()
-		);
-	});
-}
-
-#[test]
-fn set_variable_on_chain_schema() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::set_variable_on_chain_schema(
-			origin1,
-			collection_id,
-			b"test variable on chain schema".to_vec()
-		));
-
-		assert_eq!(
-			TemplateModule::collection_id(collection_id)
-				.unwrap()
-				.const_on_chain_schema,
-			b"".to_vec()
-		);
-		assert_eq!(
-			TemplateModule::collection_id(collection_id)
-				.unwrap()
-				.variable_on_chain_schema,
-			b"test variable on chain schema".to_vec()
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(1, &data.into());
-
-		let variable_data = b"test data".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			1,
-			variable_data.clone()
-		));
-
-		assert_eq!(
-			TemplateModule::nft_item_id(collection_id, 1)
-				.unwrap()
-				.variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_re_fungible_data();
-		create_test_item(1, &data.into());
-
-		let variable_data = b"test data".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			1,
-			variable_data.clone()
-		));
-
-		assert_eq!(
-			TemplateModule::refungible_item_id(collection_id, 1)
-				.unwrap()
-				.variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_fungible_token_fails() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_fungible_data();
-		create_test_item(1, &data.into());
-
-		let variable_data = b"test data".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),
-			Error::<Test>::CantStoreMetadataInFungibleTokens
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_token_fails_for_big_data() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(1, &data.into());
-
-		let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),
-			Error::<Test>::TokenVariableDataLimitExceeded
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_re_fungible_data();
-		create_test_item(1, &data.into());
-
-		let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),
-			Error::<Test>::TokenVariableDataLimitExceeded
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {
-	new_test_ext().execute_with(|| {
-		//default_limits();
-
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(1, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin1.clone(),
-			collection_id,
-			MetaUpdatePermission::ItemOwner,
-		));
-
-		let variable_data = b"ten chars.".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			1,
-			variable_data.clone()
-		));
-
-		assert_eq!(
-			TemplateModule::nft_item_id(collection_id, 1)
-				.unwrap()
-				.variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-
-		let data = default_nft_data();
-		create_test_item(1, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin1.clone(),
-			collection_id,
-			MetaUpdatePermission::ItemOwner,
-		));
-
-		let variable_data = b"1234567890123".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(
-				origin1,
-				collection_id,
-				1,
-				variable_data.clone()
-			),
-			Error::<Test>::TokenVariableDataLimitExceeded
-		);
-	})
-}
-
-#[test]
-fn collection_transfer_flag_works() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		assert_ok!(TemplateModule::set_transfers_enabled_flag(origin1, 1, true));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-
-		let origin1 = Origin::signed(1);
-
-		// default scenario
-		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));
-		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));
-		assert_eq!(TemplateModule::balance_count(1, 1), 0);
-		assert_eq!(TemplateModule::balance_count(1, 2), 1);
-
-		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_admin_flag() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin2.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin2.clone(),
-			collection_id,
-			account(1)
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin2.clone(),
-			collection_id,
-			account(1)
-		));
-
-		let data = default_nft_data();
-		create_test_item(1, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin2.clone(),
-			collection_id,
-			MetaUpdatePermission::Admin,
-		));
-
-		let variable_data = b"test.".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			1,
-			variable_data.clone()
-		));
-
-		assert_eq!(
-			TemplateModule::nft_item_id(collection_id, 1)
-				.unwrap()
-				.variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_admin_flag_neg() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin2.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin2.clone(),
-			collection_id,
-			account(1)
-		));
-
-		let data = default_nft_data();
-		create_test_item(1, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin2.clone(),
-			collection_id,
-			MetaUpdatePermission::Admin,
-		));
-
-		let variable_data = b"test.".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(
-				origin1,
-				collection_id,
-				1,
-				variable_data.clone()
-			),
-			Error::<Test>::NoPermission
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_flag_after_freeze() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
-
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin2.clone(),
-			collection_id,
-			MetaUpdatePermission::None,
-		));
-		assert_noop!(
-			TemplateModule::set_meta_update_permission_flag(
-				origin2.clone(),
-				collection_id,
-				MetaUpdatePermission::Admin
-			),
-			Error::<Test>::MetadataFlagFrozen
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_none_flag_neg() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(1, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin1.clone(),
-			collection_id,
-			MetaUpdatePermission::None,
-		));
-
-		let variable_data = b"test.".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(
-				origin1.clone(),
-				collection_id,
-				1,
-				variable_data.clone()
-			),
-			Error::<Test>::MetadataUpdateDenied
-		);
-	});
-}
-
-#[test]
-fn collection_transfer_flag_works_neg() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
-		assert_ok!(TemplateModule::set_transfers_enabled_flag(
-			origin1, 1, false
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-
-		let origin1 = Origin::signed(1);
-
-		// default scenario
-		assert_noop!(
-			TemplateModule::transfer(origin1, account(2), 1, 1, 1000),
-			Error::<Test>::TransferNotAllowed
-		);
-		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(1));
-		assert_eq!(TemplateModule::balance_count(1, 1), 1);
-		assert_eq!(TemplateModule::balance_count(1, 2), 0);
-
-		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
-	});
-}
deletedpallets/nft/src/weights.rsdiffbeforeafterboth
--- a/pallets/nft/src/weights.rs
+++ /dev/null
@@ -1,314 +0,0 @@
-// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
-
-//! Autogenerated weights for pallet_nft
-//!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2021-10-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
-//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
-
-// Executed Command:
-// target/release/nft
-// benchmark
-// --pallet
-// pallet-nft
-// --wasm-execution
-// compiled
-// --extrinsic
-// *
-// --template
-// .maintain/frame-weight-template.hbs
-// --steps=50
-// --repeat=20
-// --output=./pallets/nft/src/weights.rs
-
-
-#![cfg_attr(rustfmt, rustfmt_skip)]
-#![allow(unused_parens)]
-#![allow(unused_imports)]
-
-use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
-use sp_std::marker::PhantomData;
-
-/// Weight functions needed for pallet_nft.
-pub trait WeightInfo {
-	fn create_collection() -> Weight;
-	fn destroy_collection() -> Weight;
-	fn add_to_allow_list() -> Weight;
-	fn remove_from_allow_list() -> Weight;
-	fn set_public_access_mode() -> Weight;
-	fn set_mint_permission() -> Weight;
-	fn change_collection_owner() -> Weight;
-	fn add_collection_admin() -> Weight;
-	fn remove_collection_admin() -> Weight;
-	fn set_collection_sponsor() -> Weight;
-	fn confirm_sponsorship() -> Weight;
-	fn remove_collection_sponsor() -> Weight;
-	fn set_transfers_enabled_flag() -> Weight;
-	fn set_offchain_schema(b: u32, ) -> Weight;
-	fn set_const_on_chain_schema(b: u32, ) -> Weight;
-	fn set_variable_on_chain_schema(b: u32, ) -> Weight;
-	fn set_schema_version() -> Weight;
-	fn set_collection_limits() -> Weight;
-	fn set_meta_update_permission_flag() -> Weight;
-}
-
-/// Weights for pallet_nft using the Substrate node and recommended hardware.
-pub struct SubstrateWeight<T>(PhantomData<T>);
-impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
-	// Storage: Common CreatedCollectionCount (r:1 w:1)
-	// Storage: Common DestroyedCollectionCount (r:1 w:0)
-	// Storage: System Account (r:2 w:2)
-	// Storage: Common CollectionById (r:0 w:1)
-	fn create_collection() -> Weight {
-		(23_803_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(4 as Weight))
-			.saturating_add(T::DbWeight::get().writes(4 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	// Storage: Common DestroyedCollectionCount (r:1 w:1)
-	// Storage: Nonfungible TokensMinted (r:0 w:1)
-	// Storage: Nonfungible TokensBurnt (r:0 w:1)
-	fn destroy_collection() -> Weight {
-		(27_831_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(2 as Weight))
-			.saturating_add(T::DbWeight::get().writes(4 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common Allowlist (r:0 w:1)
-	fn add_to_allow_list() -> Weight {
-		(6_629_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common Allowlist (r:0 w:1)
-	fn remove_from_allow_list() -> Weight {
-		(6_596_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_public_access_mode() -> Weight {
-		(6_338_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_mint_permission() -> Weight {
-		(6_383_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn change_collection_owner() -> Weight {
-		(6_493_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common IsAdmin (r:0 w:1)
-	fn add_collection_admin() -> Weight {
-		(6_850_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common IsAdmin (r:0 w:1)
-	fn remove_collection_admin() -> Weight {
-		(6_615_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_collection_sponsor() -> Weight {
-		(6_430_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn confirm_sponsorship() -> Weight {
-		(6_125_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn remove_collection_sponsor() -> Weight {
-		(6_236_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_transfers_enabled_flag() -> Weight {
-		(6_500_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_offchain_schema(_b: u32, ) -> Weight {
-		(6_538_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
-		(6_542_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_variable_on_chain_schema(b: u32, ) -> Weight {
-		(6_092_000 as Weight)
-			// Standard Error: 0
-			.saturating_add((2_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_schema_version() -> Weight {
-		(6_470_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_collection_limits() -> Weight {
-		(6_841_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_meta_update_permission_flag() -> Weight {
-		(6_278_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-}
-
-// For backwards compatibility and tests
-impl WeightInfo for () {
-	// Storage: Common CreatedCollectionCount (r:1 w:1)
-	// Storage: Common DestroyedCollectionCount (r:1 w:0)
-	// Storage: System Account (r:2 w:2)
-	// Storage: Common CollectionById (r:0 w:1)
-	fn create_collection() -> Weight {
-		(23_803_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	// Storage: Common DestroyedCollectionCount (r:1 w:1)
-	// Storage: Nonfungible TokensMinted (r:0 w:1)
-	// Storage: Nonfungible TokensBurnt (r:0 w:1)
-	fn destroy_collection() -> Weight {
-		(27_831_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common Allowlist (r:0 w:1)
-	fn add_to_allow_list() -> Weight {
-		(6_629_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common Allowlist (r:0 w:1)
-	fn remove_from_allow_list() -> Weight {
-		(6_596_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_public_access_mode() -> Weight {
-		(6_338_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_mint_permission() -> Weight {
-		(6_383_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn change_collection_owner() -> Weight {
-		(6_493_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common IsAdmin (r:0 w:1)
-	fn add_collection_admin() -> Weight {
-		(6_850_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:0)
-	// Storage: Common IsAdmin (r:0 w:1)
-	fn remove_collection_admin() -> Weight {
-		(6_615_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_collection_sponsor() -> Weight {
-		(6_430_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn confirm_sponsorship() -> Weight {
-		(6_125_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn remove_collection_sponsor() -> Weight {
-		(6_236_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_transfers_enabled_flag() -> Weight {
-		(6_500_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_offchain_schema(_b: u32, ) -> Weight {
-		(6_538_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
-		(6_542_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_variable_on_chain_schema(b: u32, ) -> Weight {
-		(6_092_000 as Weight)
-			// Standard Error: 0
-			.saturating_add((2_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_schema_version() -> Weight {
-		(6_470_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_collection_limits() -> Weight {
-		(6_841_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_meta_update_permission_flag() -> Weight {
-		(6_278_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-}
\ No newline at end of file
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -16,7 +16,7 @@
 sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 pallet-common = { default-features = false, path = '../common' }
-nft-data-structs = { default-features = false, path = '../../primitives/nft' }
+up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
 evm-coder = { default-features = false, path = '../../crates/evm-coder' }
 pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
 ethereum = { git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
@@ -32,7 +32,7 @@
     "frame-system/std",
     "sp-runtime/std",
     "sp-std/std",
-    "nft-data-structs/std",
+    "up-data-structs/std",
     "pallet-common/std",
     "evm-coder/std",
     "ethereum/std",
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -4,7 +4,7 @@
 use sp_std::prelude::*;
 use pallet_common::benchmarking::{create_collection_raw, create_data};
 use frame_benchmarking::{benchmarks, account};
-use nft_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH};
+use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH};
 use pallet_common::bench_init;
 use core::convert::TryInto;
 
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -1,7 +1,7 @@
 use core::marker::PhantomData;
 
 use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
-use nft_data_structs::TokenId;
+use up_data_structs::TokenId;
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
 use sp_runtime::DispatchError;
 use sp_std::vec::Vec;
@@ -47,11 +47,11 @@
 }
 
 fn map_create_data<T: Config>(
-	data: nft_data_structs::CreateItemData,
+	data: up_data_structs::CreateItemData,
 	to: &T::CrossAccountId,
 ) -> Result<CreateItemData<T>, DispatchError> {
 	match data {
-		nft_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData {
+		up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData {
 			const_data: data.const_data,
 			variable_data: data.variable_data,
 			owner: to.clone(),
@@ -65,7 +65,7 @@
 		&self,
 		sender: T::CrossAccountId,
 		to: T::CrossAccountId,
-		data: nft_data_structs::CreateItemData,
+		data: up_data_structs::CreateItemData,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
 			<Pallet<T>>::create_item(self, &sender, map_create_data(data, &to)?),
@@ -77,7 +77,7 @@
 		&self,
 		sender: T::CrossAccountId,
 		to: T::CrossAccountId,
-		data: Vec<nft_data_structs::CreateItemData>,
+		data: Vec<up_data_structs::CreateItemData>,
 	) -> DispatchResultWithPostInfo {
 		let data = data
 			.into_iter()
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -4,7 +4,7 @@
 };
 use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*};
 use frame_support::BoundedVec;
-use nft_data_structs::TokenId;
+use up_data_structs::TokenId;
 use pallet_evm_coder_substrate::dispatch_to_evm;
 use sp_core::{H160, U256};
 use sp_std::{vec::Vec, vec};
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -2,7 +2,7 @@
 
 use erc::ERC721Events;
 use frame_support::{BoundedVec, ensure};
-use nft_data_structs::{
+use up_data_structs::{
 	AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit, TokenId,
 };
 use pallet_common::{
@@ -41,7 +41,7 @@
 pub mod pallet {
 	use super::*;
 	use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
-	use nft_data_structs::{CollectionId, TokenId};
+	use up_data_structs::{CollectionId, TokenId};
 	use super::weights::WeightInfo;
 
 	#[pallet::error]
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -7,7 +7,7 @@
 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
 
 // Executed Command:
-// target/release/nft
+// target/release/unique-collator
 // benchmark
 // --pallet
 // pallet-nonfungible
modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -16,7 +16,7 @@
 sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 pallet-common = { default-features = false, path = '../common' }
-nft-data-structs = { default-features = false, path = '../../primitives/nft' }
+up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
 frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
 scale-info = { version = "1.0.0", default-features = false, features = [
     "derive",
@@ -29,7 +29,7 @@
     "frame-system/std",
     "sp-runtime/std",
     "sp-std/std",
-    "nft-data-structs/std",
+    "up-data-structs/std",
     "pallet-common/std",
     'frame-benchmarking/std',
 ]
modifiedpallets/refungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -4,7 +4,7 @@
 use sp_std::prelude::*;
 use pallet_common::benchmarking::{create_collection_raw, create_data};
 use frame_benchmarking::{benchmarks, account};
-use nft_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH};
+use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH};
 use pallet_common::bench_init;
 use core::convert::TryInto;
 use core::iter::IntoIterator;
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -2,7 +2,7 @@
 
 use sp_std::collections::btree_map::BTreeMap;
 use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};
-use nft_data_structs::TokenId;
+use up_data_structs::TokenId;
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
 use sp_runtime::DispatchError;
 use sp_std::vec::Vec;
@@ -67,11 +67,11 @@
 }
 
 fn map_create_data<T: Config>(
-	data: nft_data_structs::CreateItemData,
+	data: up_data_structs::CreateItemData,
 	to: &T::CrossAccountId,
 ) -> Result<CreateItemData<T>, DispatchError> {
 	match data {
-		nft_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData {
+		up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData {
 			const_data: data.const_data,
 			variable_data: data.variable_data,
 			users: {
@@ -89,7 +89,7 @@
 		&self,
 		sender: T::CrossAccountId,
 		to: T::CrossAccountId,
-		data: nft_data_structs::CreateItemData,
+		data: up_data_structs::CreateItemData,
 	) -> DispatchResultWithPostInfo {
 		with_weight(
 			<Pallet<T>>::create_item(self, &sender, map_create_data(data, &to)?),
@@ -101,7 +101,7 @@
 		&self,
 		sender: T::CrossAccountId,
 		to: T::CrossAccountId,
-		data: Vec<nft_data_structs::CreateItemData>,
+		data: Vec<up_data_structs::CreateItemData>,
 	) -> DispatchResultWithPostInfo {
 		let data = data
 			.into_iter()
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -1,4 +1,4 @@
-use nft_data_structs::TokenId;
+use up_data_structs::TokenId;
 use pallet_common::erc::CommonEvmHandler;
 
 use crate::{Config, RefungibleHandle};
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -1,7 +1,7 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use frame_support::{ensure, BoundedVec};
-use nft_data_structs::{
+use up_data_structs::{
 	AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit,
 	MAX_REFUNGIBLE_PIECES, TokenId,
 };
@@ -37,7 +37,7 @@
 pub mod pallet {
 	use super::*;
 	use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
-	use nft_data_structs::{CollectionId, TokenId};
+	use up_data_structs::{CollectionId, TokenId};
 	use super::weights::WeightInfo;
 
 	#[pallet::error]
modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -7,7 +7,7 @@
 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
 
 // Executed Command:
-// target/release/nft
+// target/release/unique-collator
 // benchmark
 // --pallet
 // pallet-refungible
modifiedpallets/scheduler/Cargo.tomldiffbeforeafterboth
--- a/pallets/scheduler/Cargo.toml
+++ b/pallets/scheduler/Cargo.toml
@@ -1,12 +1,12 @@
 [package]
 name = "pallet-unq-scheduler"
-version = "3.0.0"
-authors = ["Parity Technologies <admin@parity.io>"]
+version = "0.1.0"
+authors = ["Unique Network <support@uniquenetwork.io>"]
 edition = "2018"
-license = "Unlicense"
-homepage = "https://substrate.dev"
-repository = "https://github.com/paritytech/substrate/"
-description = "FRAME example pallet"
+license = "All Rights Reserved"
+homepage = "https://unique.network"
+repository = "https://github.com/UniqueNetwork/unique-chain"
+description = "Unique Scheduler pallet"
 readme = "README.md"
 
 [dependencies]
addedpallets/unique/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/Cargo.toml
@@ -0,0 +1,150 @@
+################################################################################
+# Package
+
+[package]
+authors = ['Unique Network <support@uniquenetwork.io>']
+description = 'Unique Pallet'
+edition = '2018'
+homepage = 'https://unique.network'
+license = 'All Rights Reserved'
+name = 'pallet-unique'
+repository = 'https://github.com/UniqueNetwork/unique-chain'
+version = '0.1.0'
+
+[package.metadata.docs.rs]
+targets = ['x86_64-unknown-linux-gnu']
+
+[features]
+default = ['std']
+runtime-benchmarks = ['frame-benchmarking', 'pallet-common/runtime-benchmarks']
+std = [
+    'codec/std',
+    'serde/std',
+    'frame-support/std',
+    'frame-system/std',
+    'pallet-balances/std',
+    'pallet-evm/std',
+    'pallet-timestamp/std',
+    'pallet-randomness-collective-flip/std',
+    'pallet-transaction-payment/std',
+    'pallet-common/std',
+    'pallet-fungible/std',
+    'pallet-nonfungible/std',
+    'pallet-refungible/std',
+    'fp-evm/std',
+    'up-data-structs/std',
+    'up-sponsorship/std',
+    'up-evm-mapping/std',
+    'sp-std/std',
+    'sp-api/std',
+    'sp-runtime/std',
+    'frame-benchmarking/std',
+    'ethereum/std',
+    'rlp/std',
+
+    'primitive-types/std',
+    'evm-coder/std',
+    'pallet-evm-coder-substrate/std',
+]
+limit-testing = ["up-data-structs/limit-testing"]
+
+################################################################################
+# Substrate Dependencies
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '2.3.0'
+
+[dependencies.frame-benchmarking]
+default-features = false
+optional = true
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.frame-support]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.frame-system]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.pallet-balances]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.pallet-timestamp]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.pallet-randomness-collective-flip]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.sp-std]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.pallet-transaction-payment]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.serde]
+default-features = false
+features = ['derive']
+version = '1.0.130'
+
+[dependencies.sp-runtime]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.sp-core]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+[dependencies.sp-io]
+default-features = false
+git = 'https://github.com/paritytech/substrate.git'
+branch = 'polkadot-v0.9.12'
+
+
+################################################################################
+# Local Dependencies
+[dependencies]
+up-data-structs = { default-features = false, path = "../../primitives/data-structs" }
+
+scale-info = { version = "1.0.0", default-features = false, features = [
+    "derive",
+] }
+ethereum = { version = "0.9", git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
+rlp = { default-features = false, version = "0.5.0" }
+sp-api = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.12" }
+
+up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/UniqueNetwork/pallet-sponsoring" } 
+up-evm-mapping = { default-features = false, path = "../../primitives/evm-mapping" }
+evm-coder = { default-features = false, path = "../../crates/evm-coder" }
+pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
+primitive-types = { version = "0.10.1", default-features = false, features = [
+    "serde_no_std",
+] }
+
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }
+hex-literal = "0.3.3"
+
+pallet-common = { default-features = false, path = "../common" }
+pallet-fungible = { default-features = false, path = "../fungible" }
+pallet-nonfungible = { default-features = false, path = "../nonfungible" }
+pallet-refungible = { default-features = false, path = "../refungible" }
addedpallets/unique/src/benchmarking.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/benchmarking.rs
@@ -0,0 +1,171 @@
+#![cfg(feature = "runtime-benchmarks")]
+
+use super::*;
+use crate::Pallet;
+use frame_system::RawOrigin;
+use frame_benchmarking::{benchmarks, account};
+use up_data_structs::*;
+use core::convert::TryInto;
+use sp_runtime::DispatchError;
+use pallet_common::benchmarking::{create_data, create_u16_data};
+
+const SEED: u32 = 1;
+
+fn create_collection_helper<T: Config>(
+	owner: T::AccountId,
+	mode: CollectionMode,
+) -> Result<CollectionId, DispatchError> {
+	T::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get());
+	let col_name = create_u16_data(MAX_COLLECTION_NAME_LENGTH)
+		.try_into()
+		.unwrap();
+	let col_desc = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH)
+		.try_into()
+		.unwrap();
+	let token_prefix = create_data(MAX_TOKEN_PREFIX_LENGTH).try_into().unwrap();
+	<Pallet<T>>::create_collection(
+		RawOrigin::Signed(owner).into(),
+		col_name,
+		col_desc,
+		token_prefix,
+		mode,
+	)?;
+	Ok(<pallet_common::CreatedCollectionCount<T>>::get())
+}
+fn create_nft_collection<T: Config>(owner: T::AccountId) -> Result<CollectionId, DispatchError> {
+	create_collection_helper::<T>(owner, CollectionMode::NFT)
+}
+
+benchmarks! {
+
+	create_collection {
+		let col_name: Vec<u16> = create_u16_data(MAX_COLLECTION_NAME_LENGTH);
+		let col_desc: Vec<u16> = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH);
+		let token_prefix: Vec<u8> = create_data(MAX_TOKEN_PREFIX_LENGTH);
+		let mode: CollectionMode = CollectionMode::NFT;
+		let caller: T::AccountId = account("caller", 0, SEED);
+		T::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
+	}: _(RawOrigin::Signed(caller.clone()), col_name.clone(), col_desc.clone(), token_prefix.clone(), mode)
+	verify {
+		assert_eq!(<pallet_common::CollectionById<T>>::get(CollectionId(1)).unwrap().owner, caller);
+	}
+
+	destroy_collection {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection)
+
+	add_to_allow_list {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let allowlist_account: T::AccountId = account("admin", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(allowlist_account))
+
+	remove_from_allow_list {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let allowlist_account: T::AccountId = account("admin", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		<Pallet<T>>::add_to_allow_list(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(allowlist_account.clone()))?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(allowlist_account))
+
+	set_public_access_mode {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, AccessMode::AllowList)
+
+	set_mint_permission {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, true)
+
+	change_collection_owner {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let new_owner: T::AccountId = account("admin", 0, SEED);
+	}: _(RawOrigin::Signed(caller.clone()), collection, new_owner)
+
+	add_collection_admin {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let new_admin: T::AccountId = account("admin", 0, SEED);
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(new_admin))
+
+	remove_collection_admin {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let new_admin: T::AccountId = account("admin", 0, SEED);
+		<Pallet<T>>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(new_admin.clone()))?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(new_admin))
+
+	set_collection_sponsor {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, caller.clone())
+
+	confirm_sponsorship {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), collection, caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection)
+
+	remove_collection_sponsor {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), collection, caller.clone())?;
+		<Pallet<T>>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), collection)?;
+	}: _(RawOrigin::Signed(caller.clone()), collection)
+
+	set_transfers_enabled_flag {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, false)
+
+	set_offchain_schema {
+		let b in 0..OFFCHAIN_SCHEMA_LIMIT;
+
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = create_data(b as usize);
+	}: set_offchain_schema(RawOrigin::Signed(caller.clone()), collection, data)
+
+	set_const_on_chain_schema {
+		let b in 0..CONST_ON_CHAIN_SCHEMA_LIMIT;
+
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = create_data(b as usize);
+	}: set_const_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data)
+
+	set_variable_on_chain_schema {
+		let b in 0..VARIABLE_ON_CHAIN_SCHEMA_LIMIT;
+
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		let data = create_data(b as usize);
+	}: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data)
+
+	set_schema_version {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: set_schema_version(RawOrigin::Signed(caller.clone()), collection, SchemaVersion::Unique)
+
+	set_collection_limits{
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+
+		let cl = CollectionLimits {
+			account_token_ownership_limit: Some(0),
+			sponsored_data_size: 0,
+			token_limit: 1,
+			sponsor_transfer_timeout: 0,
+			owner_can_destroy: true,
+			owner_can_transfer: true,
+			sponsored_data_rate_limit: None,
+		};
+	}: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)
+
+	set_meta_update_permission_flag {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, MetaUpdatePermission::Admin)
+}
addedpallets/unique/src/common.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/common.rs
@@ -0,0 +1,52 @@
+use core::marker::PhantomData;
+use frame_support::{weights::Weight};
+use pallet_common::{CommonWeightInfo};
+
+use pallet_fungible::{common::CommonWeights as FungibleWeights};
+use pallet_nonfungible::{common::CommonWeights as NonfungibleWeights};
+use pallet_refungible::{common::CommonWeights as RefungibleWeights};
+
+use crate::{Config, dispatch::dispatch_weight};
+
+macro_rules! max_weight_of {
+	($method:ident ( $($args:tt)* )) => {
+		<FungibleWeights<T>>::$method($($args)*)
+		.max(<NonfungibleWeights<T>>::$method($($args)*))
+		.max(<RefungibleWeights<T>>::$method($($args)*))
+	};
+}
+
+pub struct CommonWeights<T: Config>(PhantomData<T>);
+impl<T: Config> CommonWeightInfo for CommonWeights<T> {
+	fn create_item() -> up_data_structs::Weight {
+		dispatch_weight::<T>() + max_weight_of!(create_item())
+	}
+
+	fn create_multiple_items(amount: u32) -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(create_multiple_items(amount))
+	}
+
+	fn burn_item() -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(burn_item())
+	}
+
+	fn transfer() -> up_data_structs::Weight {
+		dispatch_weight::<T>() + max_weight_of!(transfer())
+	}
+
+	fn approve() -> up_data_structs::Weight {
+		dispatch_weight::<T>() + max_weight_of!(approve())
+	}
+
+	fn transfer_from() -> up_data_structs::Weight {
+		dispatch_weight::<T>() + max_weight_of!(transfer_from())
+	}
+
+	fn set_variable_metadata(bytes: u32) -> up_data_structs::Weight {
+		dispatch_weight::<T>() + max_weight_of!(set_variable_metadata(bytes))
+	}
+
+	fn burn_from() -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(burn_from())
+	}
+}
addedpallets/unique/src/dispatch.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/dispatch.rs
@@ -0,0 +1,92 @@
+use frame_support::{
+	dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo},
+	traits::Get,
+	weights::Weight,
+};
+use up_data_structs::{CollectionId, CollectionMode, Pays, PostDispatchInfo};
+use pallet_common::{CollectionHandle, CommonCollectionOperations};
+use pallet_fungible::FungibleHandle;
+use pallet_nonfungible::NonfungibleHandle;
+use pallet_refungible::RefungibleHandle;
+
+use crate::Config;
+
+// TODO: move to benchmarking
+/// Price of [`dispatch_call`] call with noop `call` argument
+pub fn dispatch_weight<T: Config>() -> Weight {
+	// Read collection
+	<T as frame_system::Config>::DbWeight::get().reads(1)
+	// Dynamic dispatch?
+	+ 6_000_000
+	// submit_logs is measured as part of collection pallets
+}
+
+pub enum Dispatched<T: Config> {
+	Fungible(FungibleHandle<T>),
+	Nonfungible(NonfungibleHandle<T>),
+	Refungible(RefungibleHandle<T>),
+}
+impl<T: Config> Dispatched<T> {
+	pub fn dispatch(handle: CollectionHandle<T>) -> Self {
+		match handle.mode {
+			CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),
+			CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),
+			CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),
+		}
+	}
+	fn into_inner(self) -> CollectionHandle<T> {
+		match self {
+			Dispatched::Fungible(f) => f.into_inner(),
+			Dispatched::Nonfungible(f) => f.into_inner(),
+			Dispatched::Refungible(f) => f.into_inner(),
+		}
+	}
+	pub fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {
+		match self {
+			Dispatched::Fungible(h) => h,
+			Dispatched::Nonfungible(h) => h,
+			Dispatched::Refungible(h) => h,
+		}
+	}
+}
+
+/// Helper function to implement substrate calls for common collection methods
+pub fn dispatch_call<
+	T: Config,
+	C: FnOnce(&dyn pallet_common::CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,
+>(
+	collection: CollectionId,
+	call: C,
+) -> DispatchResultWithPostInfo {
+	let handle =
+		CollectionHandle::try_get(collection).map_err(|error| DispatchErrorWithPostInfo {
+			post_info: PostDispatchInfo {
+				actual_weight: Some(dispatch_weight::<T>()),
+				pays_fee: Pays::Yes,
+			},
+			error,
+		})?;
+	let dispatched = Dispatched::dispatch(handle);
+	let mut result = call(dispatched.as_dyn());
+	match &mut result {
+		Ok(PostDispatchInfo {
+			actual_weight: Some(weight),
+			..
+		})
+		| Err(DispatchErrorWithPostInfo {
+			post_info: PostDispatchInfo {
+				actual_weight: Some(weight),
+				..
+			},
+			..
+		}) => *weight += dispatch_weight::<T>(),
+		_ => {}
+	}
+
+	// TODO: Make submit_logs infallible, but it shouldn't fail here anyway
+	dispatched
+		.into_inner()
+		.submit_logs()
+		.expect("should succeed");
+	result
+}
addedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/eth/mod.rs
@@ -0,0 +1,80 @@
+pub mod sponsoring;
+
+use pallet_common::{
+	CollectionById,
+	erc::CommonEvmHandler,
+	eth::{map_eth_to_id, map_eth_to_token_id},
+};
+use pallet_fungible::FungibleHandle;
+use pallet_nonfungible::NonfungibleHandle;
+use pallet_refungible::{RefungibleHandle, erc::RefungibleTokenHandle};
+use sp_std::borrow::ToOwned;
+use sp_std::vec::Vec;
+use pallet_evm::{PrecompileOutput};
+use sp_core::{H160, U256};
+use crate::{CollectionMode, Config, dispatch::Dispatched};
+use pallet_common::CollectionHandle;
+
+pub struct UniqueErcSupport<T: Config>(core::marker::PhantomData<T>);
+
+impl<T: Config> pallet_evm::OnMethodCall<T> for UniqueErcSupport<T> {
+	fn is_reserved(target: &H160) -> bool {
+		map_eth_to_id(target).is_some()
+	}
+	fn is_used(target: &H160) -> bool {
+		map_eth_to_id(target)
+			.map(<CollectionById<T>>::contains_key)
+			.unwrap_or(false)
+	}
+	fn get_code(target: &H160) -> Option<Vec<u8>> {
+		if let Some(collection_id) = map_eth_to_id(target) {
+			let collection = <CollectionById<T>>::get(collection_id)?;
+			Some(
+				match collection.mode {
+					CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,
+					CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,
+					CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,
+				}
+				.to_owned(),
+			)
+		} else if let Some((collection_id, _token_id)) = map_eth_to_token_id(target) {
+			let collection = <CollectionById<T>>::get(collection_id)?;
+			if collection.mode != CollectionMode::ReFungible {
+				return None;
+			}
+			// TODO: check token existence
+			Some(<RefungibleTokenHandle<T>>::CODE.to_owned())
+		} else {
+			None
+		}
+	}
+	fn call(
+		source: &H160,
+		target: &H160,
+		gas_limit: u64,
+		input: &[u8],
+		value: U256,
+	) -> Option<PrecompileOutput> {
+		if let Some(collection_id) = map_eth_to_id(target) {
+			let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;
+			let dispatched = Dispatched::dispatch(collection);
+
+			match dispatched {
+				Dispatched::Fungible(h) => h.call(source, input, value),
+				Dispatched::Nonfungible(h) => h.call(source, input, value),
+				Dispatched::Refungible(h) => h.call(source, input, value),
+			}
+		} else if let Some((collection_id, token_id)) = map_eth_to_token_id(target) {
+			let collection = <CollectionHandle<T>>::new_with_gas_limit(collection_id, gas_limit)?;
+			if collection.mode != CollectionMode::ReFungible {
+				return None;
+			}
+
+			let handle = RefungibleHandle::cast(collection);
+			// TODO: check token existence
+			RefungibleTokenHandle(handle, token_id).call(source, input, value)
+		} else {
+			None
+		}
+	}
+}
addedpallets/unique/src/eth/sponsoring.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/eth/sponsoring.rs
@@ -0,0 +1,74 @@
+//! Implements EVM sponsoring logic via OnChargeEVMTransaction
+
+use crate::{Config, sponsorship::*};
+use evm_coder::{Call, abi::AbiReader};
+use pallet_common::{CollectionHandle, eth::map_eth_to_id};
+use sp_core::H160;
+use sp_std::prelude::*;
+use up_sponsorship::SponsorshipHandler;
+use core::marker::PhantomData;
+use core::convert::TryInto;
+use up_data_structs::TokenId;
+use up_evm_mapping::EvmBackwardsAddressMapping;
+use pallet_common::account::CrossAccountId;
+
+use pallet_nonfungible::erc::{UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721Call};
+use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};
+
+pub struct UniqueEthSponsorshipHandler<T: Config>(PhantomData<*const T>);
+impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for UniqueEthSponsorshipHandler<T> {
+	fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {
+		let collection_id = map_eth_to_id(&call.0)?;
+		let collection = <CollectionHandle<T>>::new(collection_id)?;
+		let sponsor = collection.sponsorship.sponsor()?.clone();
+		let sponsor =
+			<T as pallet_common::Config>::EvmBackwardsAddressMapping::from_account_id(sponsor);
+		let who = T::CrossAccountId::from_eth(*who);
+		let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
+		match &collection.mode {
+			crate::CollectionMode::NFT => {
+				let call = UniqueNFTCall::parse(method_id, &mut reader).ok()??;
+				match call {
+					UniqueNFTCall::ERC721UniqueExtensions(
+						ERC721UniqueExtensionsCall::Transfer { token_id, .. },
+					) => {
+						let token_id: TokenId = token_id.try_into().ok()?;
+						withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
+					}
+					UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
+						let token_id: TokenId = token_id.try_into().ok()?;
+						let from = T::CrossAccountId::from_eth(from);
+						withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
+					}
+					UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
+						let token_id: TokenId = token_id.try_into().ok()?;
+						withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
+							.map(|()| sponsor)
+					}
+					_ => None,
+				}
+			}
+			crate::CollectionMode::Fungible(_) => {
+				let call = UniqueFungibleCall::parse(method_id, &mut reader).ok()??;
+				#[allow(clippy::single_match)]
+				match call {
+					UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
+						withdraw_transfer::<T>(&collection, &who, &TokenId::default())
+							.map(|()| sponsor)
+					}
+					UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
+						let from = T::CrossAccountId::from_eth(from);
+						withdraw_transfer::<T>(&collection, &from, &TokenId::default())
+							.map(|()| sponsor)
+					}
+					UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
+						withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
+							.map(|()| sponsor)
+					}
+					_ => None,
+				}
+			}
+			_ => None,
+		}
+	}
+}
addedpallets/unique/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/lib.rs
@@ -0,0 +1,955 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+#![recursion_limit = "1024"]
+#![cfg_attr(not(feature = "std"), no_std)]
+#![allow(
+	clippy::too_many_arguments,
+	clippy::unnecessary_mut_passed,
+	clippy::unused_unit
+)]
+
+extern crate alloc;
+
+pub use serde::{Serialize, Deserialize};
+
+pub use frame_support::{
+	construct_runtime, decl_module, decl_storage, decl_error,
+	dispatch::DispatchResult,
+	ensure, fail, parameter_types,
+	traits::{
+		ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness,
+		IsSubType, WithdrawReasons,
+	},
+	weights::{
+		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
+		DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
+		WeightToFeePolynomial, DispatchClass,
+	},
+	StorageValue, transactional,
+	pallet_prelude::DispatchResultWithPostInfo,
+};
+use scale_info::TypeInfo;
+use frame_system::{self as system, ensure_signed};
+use sp_runtime::{sp_std::prelude::Vec};
+use up_data_structs::{
+	MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,
+	VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,
+	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+	NFT_SPONSOR_TRANSFER_TIMEOUT, AccessMode, Collection, CreateItemData, CollectionLimits,
+	CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,
+};
+use pallet_common::{
+	account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,
+	CommonWeightInfo,
+};
+use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle};
+use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};
+use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};
+
+#[cfg(test)]
+mod mock;
+
+#[cfg(test)]
+mod tests;
+
+mod eth;
+mod sponsorship;
+pub use sponsorship::UniqueSponsorshipHandler;
+pub use eth::sponsoring::UniqueEthSponsorshipHandler;
+
+pub use eth::UniqueErcSupport;
+
+pub mod common;
+use common::CommonWeights;
+pub mod dispatch;
+use dispatch::dispatch_call;
+
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+pub mod weights;
+use weights::WeightInfo;
+
+decl_error! {
+	/// Error for non-fungible-token module.
+	pub enum Error for Module<T: Config> {
+		/// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.
+		CollectionDecimalPointLimitExceeded,
+		/// This address is not set as sponsor, use setCollectionSponsor first.
+		ConfirmUnsetSponsorFail,
+		/// Length of items properties must be greater than 0.
+		EmptyArgument,
+		/// Collection limit bounds per collection exceeded
+		CollectionLimitBoundsExceeded,
+		/// Tried to enable permissions which are only permitted to be disabled
+		OwnerPermissionsCantBeReverted,
+	}
+}
+pub trait Config:
+	system::Config
+	+ pallet_evm_coder_substrate::Config
+	+ pallet_common::Config
+	+ pallet_nonfungible::Config
+	+ pallet_refungible::Config
+	+ pallet_fungible::Config
+	+ Sized
+	+ TypeInfo
+{
+	/// Weight information for extrinsics in this pallet.
+	type WeightInfo: WeightInfo;
+}
+
+type SelfWeightOf<T> = <T as Config>::WeightInfo;
+
+// # Used definitions
+//
+// ## User control levels
+//
+// chain-controlled - key is uncontrolled by user
+//                    i.e autoincrementing index
+//                    can use non-cryptographic hash
+// real - key is controlled by user
+//        but it is hard to generate enough colliding values, i.e owner of signed txs
+//        can use non-cryptographic hash
+// controlled - key is completly controlled by users
+//              i.e maps with mutable keys
+//              should use cryptographic hash
+//
+// ## User control level downgrade reasons
+//
+// ?1 - chain-controlled -> controlled
+//      collections/tokens can be destroyed, resulting in massive holes
+// ?2 - chain-controlled -> controlled
+//      same as ?1, but can be only added, resulting in easier exploitation
+// ?3 - real -> controlled
+//      no confirmation required, so addresses can be easily generated
+decl_storage! {
+	trait Store for Module<T: Config> as Unique {
+
+		//#region Private members
+		/// Used for migrations
+		ChainVersion: u64;
+		//#endregion
+
+		//#region Tokens transfer rate limit baskets
+		/// (Collection id (controlled?2), who created (real))
+		/// TODO: Off chain worker should remove from this map when collection gets removed
+		pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;
+		/// Collection id (controlled?2), token id (controlled?2)
+		pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
+		/// Collection id (controlled?2), owning user (real)
+		pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
+		/// Collection id (controlled?2), token id (controlled?2)
+		pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
+		//#endregion
+
+		/// Variable metadata sponsoring
+		/// Collection id (controlled?2), token id (controlled?2)
+		pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
+		/// Approval sponsoring
+		pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
+		pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
+		pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
+	}
+}
+
+decl_module! {
+	pub struct Module<T: Config> for enum Call
+	where
+		origin: T::Origin
+	{
+		type Error = Error<T>;
+
+		fn on_initialize(_now: T::BlockNumber) -> Weight {
+			0
+		}
+
+		/// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.
+		///
+		/// # Permissions
+		///
+		/// * Anyone.
+		///
+		/// # Arguments
+		///
+		/// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.
+		///
+		/// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.
+		///
+		/// * token_prefix: UTF-8 string with token prefix.
+		///
+		/// * mode: [CollectionMode] collection type and type dependent data.
+		// returns collection ID
+		#[weight = <SelfWeightOf<T>>::create_collection()]
+		#[transactional]
+		pub fn create_collection(origin,
+								 collection_name: Vec<u16>,
+								 collection_description: Vec<u16>,
+								 token_prefix: Vec<u8>,
+								 mode: CollectionMode) -> DispatchResult {
+
+			// Anyone can create a collection
+			let who = ensure_signed(origin)?;
+
+			// Create new collection
+			let new_collection = Collection {
+				owner: who.clone(),
+				name: collection_name,
+				mode: mode.clone(),
+				mint_mode: false,
+				access: AccessMode::Normal,
+				description: collection_description,
+				token_prefix,
+				offchain_schema: Vec::new(),
+				schema_version: SchemaVersion::ImageURL,
+				sponsorship: SponsorshipState::Disabled,
+				variable_on_chain_schema: Vec::new(),
+				const_on_chain_schema: Vec::new(),
+				limits: Default::default(),
+				meta_update_permission: Default::default(),
+			};
+
+			let _id = match mode {
+				CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(new_collection)?},
+				CollectionMode::Fungible(decimal_points) => {
+					// check params
+					ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);
+					<PalletFungible<T>>::init_collection(new_collection)?
+				}
+				CollectionMode::ReFungible => {
+					<PalletRefungible<T>>::init_collection(new_collection)?
+				}
+			};
+
+			Ok(())
+		}
+
+		/// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: collection to destroy.
+		#[weight = <SelfWeightOf<T>>::destroy_collection()]
+		#[transactional]
+		pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			collection.check_is_owner(&sender)?;
+
+			// =========
+
+			match collection.mode {
+				CollectionMode::ReFungible => PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?,
+				CollectionMode::Fungible(_) => PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?,
+				CollectionMode::NFT => PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?,
+			}
+
+			<NftTransferBasket<T>>::remove_prefix(collection_id, None);
+			<FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
+			<ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);
+
+			<VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
+			<NftApproveBasket<T>>::remove_prefix(collection_id, None);
+			<FungibleApproveBasket<T>>::remove_prefix(collection_id, None);
+			<RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);
+
+			Ok(())
+		}
+
+		/// Add an address to allow list.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * address.
+		#[weight = <SelfWeightOf<T>>::add_to_allow_list()]
+		#[transactional]
+		pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{
+
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
+
+			<PalletCommon<T>>::toggle_allowlist(
+				&collection,
+				&sender,
+				&address,
+				true,
+			)?;
+
+			Ok(())
+		}
+
+		/// Remove an address from allow list.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * address.
+		#[weight = <SelfWeightOf<T>>::remove_from_allow_list()]
+		#[transactional]
+		pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{
+
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
+
+			<PalletCommon<T>>::toggle_allowlist(
+				&collection,
+				&sender,
+				&address,
+				false,
+			)?;
+
+			Ok(())
+		}
+
+		/// Toggle between normal and allow list access for the methods with access for `Anyone`.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * mode: [AccessMode]
+		#[weight = <SelfWeightOf<T>>::set_public_access_mode()]
+		#[transactional]
+		pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult
+		{
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner(&sender)?;
+
+			target_collection.access = mode;
+			target_collection.save()
+		}
+
+		/// Allows Anyone to create tokens if:
+		/// * Allow List is enabled, and
+		/// * Address is added to allow list, and
+		/// * This method was called with True parameter
+		///
+		/// # Permissions
+		/// * Collection Owner
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.
+		#[weight = <SelfWeightOf<T>>::set_mint_permission()]
+		#[transactional]
+		pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult
+		{
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner(&sender)?;
+
+			target_collection.mint_mode = mint_permission;
+			target_collection.save()
+		}
+
+		/// Change the owner of the collection.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * new_owner.
+		#[weight = <SelfWeightOf<T>>::change_collection_owner()]
+		#[transactional]
+		pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {
+
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner(&sender)?;
+
+			target_collection.owner = new_owner;
+			target_collection.save()
+		}
+
+		/// Adds an admin of the Collection.
+		/// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		/// * Collection Admin.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the Collection to add admin for.
+		///
+		/// * new_admin_id: Address of new admin to add.
+		#[weight = <SelfWeightOf<T>>::add_collection_admin()]
+		#[transactional]
+		pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
+
+			<PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)
+		}
+
+		/// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		/// * Collection Admin.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the Collection to remove admin for.
+		///
+		/// * account_id: Address of admin to remove.
+		#[weight = <SelfWeightOf<T>>::remove_collection_admin()]
+		#[transactional]
+		pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let collection = <CollectionHandle<T>>::try_get(collection_id)?;
+
+			<PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)
+		}
+
+		/// # Permissions
+		///
+		/// * Collection Owner
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * new_sponsor.
+		#[weight = <SelfWeightOf<T>>::set_collection_sponsor()]
+		#[transactional]
+		pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner(&sender)?;
+
+			target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);
+			target_collection.save()
+		}
+
+		/// # Permissions
+		///
+		/// * Sponsor.
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		#[weight = <SelfWeightOf<T>>::confirm_sponsorship()]
+		#[transactional]
+		pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {
+			let sender = ensure_signed(origin)?;
+
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			ensure!(
+				target_collection.sponsorship.pending_sponsor() == Some(&sender),
+				Error::<T>::ConfirmUnsetSponsorFail
+			);
+
+			target_collection.sponsorship = SponsorshipState::Confirmed(sender);
+			target_collection.save()
+		}
+
+		/// Switch back to pay-per-own-transaction model.
+		///
+		/// # Permissions
+		///
+		/// * Collection owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		#[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]
+		#[transactional]
+		pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner(&sender)?;
+
+			target_collection.sponsorship = SponsorshipState::Disabled;
+			target_collection.save()
+		}
+
+		/// This method creates a concrete instance of NFT Collection created with CreateCollection method.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		/// * Collection Admin.
+		/// * Anyone if
+		///     * Allow List is enabled, and
+		///     * Address is added to allow list, and
+		///     * MintPermission is enabled (see SetMintPermission method)
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the collection.
+		///
+		/// * owner: Address, initial owner of the NFT.
+		///
+		/// * data: Token data to store on chain.
+		#[weight = <CommonWeights<T>>::create_item()]
+		#[transactional]
+		pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data))
+		}
+
+		/// This method creates multiple items in a collection created with CreateCollection method.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		/// * Collection Admin.
+		/// * Anyone if
+		///     * Allow List is enabled, and
+		///     * Address is added to allow list, and
+		///     * MintPermission is enabled (see SetMintPermission method)
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the collection.
+		///
+		/// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].
+		///
+		/// * owner: Address, initial owner of the NFT.
+		#[weight = <CommonWeights<T>>::create_multiple_items(items_data.len() as u32)]
+		#[transactional]
+		pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {
+			ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data))
+		}
+
+		// TODO! transaction weight
+
+		/// Set transfers_enabled value for particular collection
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the collection.
+		///
+		/// * value: New flag value.
+		#[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]
+		#[transactional]
+		pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner(&sender)?;
+
+			// =========
+
+			target_collection.limits.transfers_enabled = Some(value);
+			target_collection.save()
+		}
+
+		/// Destroys a concrete instance of NFT.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		/// * Collection Admin.
+		/// * Current NFT Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the collection.
+		///
+		/// * item_id: ID of NFT to burn.
+		#[weight = <CommonWeights<T>>::burn_item()]
+		#[transactional]
+		pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;
+			if value == 1 {
+				<NftTransferBasket<T>>::remove(collection_id, item_id);
+				<NftApproveBasket<T>>::remove(collection_id, item_id);
+			}
+			// Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?
+			// <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());
+			// <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));
+			Ok(post_info)
+		}
+
+		/// Destroys a concrete instance of NFT on behalf of the owner
+		/// See also: [`approve`]
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		/// * Collection Admin.
+		/// * Current NFT Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the collection.
+		///
+		/// * item_id: ID of NFT to burn.
+		///
+		/// * from: owner of item
+		#[weight = <CommonWeights<T>>::burn_from()]
+		#[transactional]
+		pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value))
+		}
+
+		/// Change ownership of the token.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		/// * Current NFT owner
+		///
+		/// # Arguments
+		///
+		/// * recipient: Address of token recipient.
+		///
+		/// * collection_id.
+		///
+		/// * item_id: ID of the item
+		///     * Non-Fungible Mode: Required.
+		///     * Fungible Mode: Ignored.
+		///     * Re-Fungible Mode: Required.
+		///
+		/// * value: Amount to transfer.
+		///     * Non-Fungible Mode: Ignored
+		///     * Fungible Mode: Must specify transferred amount
+		///     * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)
+		#[weight = <CommonWeights<T>>::transfer()]
+		#[transactional]
+		pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value))
+		}
+
+		/// Set, change, or remove approved address to transfer the ownership of the NFT.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		/// * Current NFT owner
+		///
+		/// # Arguments
+		///
+		/// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).
+		///
+		/// * collection_id.
+		///
+		/// * item_id: ID of the item.
+		#[weight = <CommonWeights<T>>::approve()]
+		#[transactional]
+		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
+		}
+
+		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
+		///
+		/// # Permissions
+		/// * Collection Owner
+		/// * Collection Admin
+		/// * Current NFT owner
+		/// * Address approved by current NFT owner
+		///
+		/// # Arguments
+		///
+		/// * from: Address that owns token.
+		///
+		/// * recipient: Address of token recipient.
+		///
+		/// * collection_id.
+		///
+		/// * item_id: ID of the item.
+		///
+		/// * value: Amount to transfer.
+		#[weight = <CommonWeights<T>>::transfer_from()]
+		#[transactional]
+		pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value))
+		}
+
+		/// Set off-chain data schema.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * schema: String representing the offchain data schema.
+		#[weight = <CommonWeights<T>>::set_variable_metadata(data.len() as u32)]
+		#[transactional]
+		pub fn set_variable_meta_data (
+			origin,
+			collection_id: CollectionId,
+			item_id: TokenId,
+			data: Vec<u8>
+		) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))
+		}
+
+		/// Set meta_update_permission value for particular collection
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner.
+		///
+		/// # Arguments
+		///
+		/// * collection_id: ID of the collection.
+		///
+		/// * value: New flag value.
+		#[weight = <SelfWeightOf<T>>::set_meta_update_permission_flag()]
+		#[transactional]
+		pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+
+			ensure!(
+				target_collection.meta_update_permission != MetaUpdatePermission::None,
+				<CommonError<T>>::MetadataFlagFrozen,
+			);
+			target_collection.check_is_owner(&sender)?;
+
+			target_collection.meta_update_permission = value;
+
+			target_collection.save()
+		}
+
+		/// Set schema standard
+		/// ImageURL
+		/// Unique
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * schema: SchemaVersion: enum
+		#[weight = <SelfWeightOf<T>>::set_schema_version()]
+		#[transactional]
+		pub fn set_schema_version(
+			origin,
+			collection_id: CollectionId,
+			version: SchemaVersion
+		) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner_or_admin(&sender)?;
+			target_collection.schema_version = version;
+			target_collection.save()
+		}
+
+		/// Set off-chain data schema.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * schema: String representing the offchain data schema.
+		#[weight = <SelfWeightOf<T>>::set_offchain_schema(schema.len() as u32)]
+		#[transactional]
+		pub fn set_offchain_schema(
+			origin,
+			collection_id: CollectionId,
+			schema: Vec<u8>
+		) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner_or_admin(&sender)?;
+
+			// check schema limit
+			ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, "");
+
+			target_collection.offchain_schema = schema;
+			target_collection.save()
+		}
+
+		/// Set const on-chain data schema.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * schema: String representing the const on-chain data schema.
+		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]
+		#[transactional]
+		pub fn set_const_on_chain_schema (
+			origin,
+			collection_id: CollectionId,
+			schema: Vec<u8>
+		) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner_or_admin(&sender)?;
+
+			// check schema limit
+			ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, "");
+
+			target_collection.const_on_chain_schema = schema;
+			target_collection.save()
+		}
+
+		/// Set variable on-chain data schema.
+		///
+		/// # Permissions
+		///
+		/// * Collection Owner
+		/// * Collection Admin
+		///
+		/// # Arguments
+		///
+		/// * collection_id.
+		///
+		/// * schema: String representing the variable on-chain data schema.
+		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]
+		#[transactional]
+		pub fn set_variable_on_chain_schema (
+			origin,
+			collection_id: CollectionId,
+			schema: Vec<u8>
+		) -> DispatchResult {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner_or_admin(&sender)?;
+
+			// check schema limit
+			ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, "");
+
+			target_collection.variable_on_chain_schema = schema;
+			target_collection.save()
+		}
+
+		#[weight = <SelfWeightOf<T>>::set_collection_limits()]
+		#[transactional]
+		pub fn set_collection_limits(
+			origin,
+			collection_id: CollectionId,
+			new_limit: CollectionLimits,
+		) -> DispatchResult {
+			let mut new_limit = new_limit;
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+			target_collection.check_is_owner(&sender)?;
+			let old_limit = &target_collection.limits;
+
+			macro_rules! limit_default {
+				($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{
+					$(
+						if let Some($new) = $new.$field {
+							let $old = $old.$field($($arg)?);
+							let _ = $new;
+							let _ = $old;
+							$check
+						} else {
+							$new.$field = $old.$field
+						}
+					)*
+				}};
+			}
+
+			limit_default!(old_limit, new_limit,
+				account_token_ownership_limit => ensure!(
+					new_limit <= MAX_TOKEN_OWNERSHIP,
+					<Error<T>>::CollectionLimitBoundsExceeded,
+				),
+				sponsor_transfer_timeout(match target_collection.mode {
+					CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
+					CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+					CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+				}) => ensure!(
+					new_limit <= MAX_SPONSOR_TIMEOUT,
+					<Error<T>>::CollectionLimitBoundsExceeded,
+				),
+				sponsored_data_size => ensure!(
+					new_limit <= CUSTOM_DATA_LIMIT,
+					<Error<T>>::CollectionLimitBoundsExceeded,
+				),
+				token_limit => ensure!(
+					old_limit >= new_limit && new_limit > 0,
+					<CommonError<T>>::CollectionTokenLimitExceeded
+				),
+				owner_can_transfer => ensure!(
+					old_limit || !new_limit,
+					<Error<T>>::OwnerPermissionsCantBeReverted,
+				),
+				owner_can_destroy => ensure!(
+					old_limit || !new_limit,
+					<Error<T>>::OwnerPermissionsCantBeReverted,
+				),
+				sponsored_data_rate_limit => {},
+				transfers_enabled => {},
+			);
+
+			target_collection.limits = new_limit;
+
+			target_collection.save()
+		}
+	}
+}
addedpallets/unique/src/mock.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/mock.rs
@@ -0,0 +1,177 @@
+#![allow(clippy::from_over_into)]
+
+use crate as pallet_template;
+use sp_core::H256;
+use frame_support::{parameter_types, traits::Everything, weights::IdentityFee};
+use sp_runtime::{
+	traits::{BlakeTwo256, IdentityLookup},
+	testing::Header,
+};
+use pallet_transaction_payment::{CurrencyAdapter};
+use frame_system as system;
+use pallet_evm::AddressMapping;
+use crate::{EvmBackwardsAddressMapping, CrossAccountId};
+use codec::{Encode, Decode};
+use scale_info::TypeInfo;
+
+type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
+type Block = frame_system::mocking::MockBlock<Test>;
+
+// Configure a mock runtime to test the pallet.
+frame_support::construct_runtime!(
+	pub enum Test where
+		Block = Block,
+		NodeBlock = Block,
+		UncheckedExtrinsic = UncheckedExtrinsic,
+	{
+		System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
+		TemplateModule: pallet_template::{Pallet, Call, Storage},
+		Balances: pallet_balances::{Pallet, Call, Storage},
+	}
+);
+
+parameter_types! {
+	pub const BlockHashCount: u64 = 250;
+	pub const SS58Prefix: u8 = 42;
+}
+
+impl system::Config for Test {
+	type BaseCallFilter = Everything;
+	type BlockWeights = ();
+	type BlockLength = ();
+	type DbWeight = ();
+	type Origin = Origin;
+	type Call = Call;
+	type Index = u64;
+	type BlockNumber = u64;
+	type Hash = H256;
+	type Hashing = BlakeTwo256;
+	type AccountId = u64;
+	type Lookup = IdentityLookup<Self::AccountId>;
+	type Header = Header;
+	type Event = ();
+	type BlockHashCount = BlockHashCount;
+	type Version = ();
+	type PalletInfo = PalletInfo;
+	type AccountData = pallet_balances::AccountData<u64>;
+	type OnNewAccount = ();
+	type OnKilledAccount = ();
+	type SystemWeightInfo = ();
+	type SS58Prefix = SS58Prefix;
+	type OnSetCode = ();
+}
+
+parameter_types! {
+	pub const ExistentialDeposit: u64 = 1;
+	pub const MaxLocks: u32 = 50;
+}
+//frame_system::Module<Test>;
+impl pallet_balances::Config for Test {
+	type AccountStore = System;
+	type Balance = u64;
+	type DustRemoval = ();
+	type Event = ();
+	type ExistentialDeposit = ExistentialDeposit;
+	type WeightInfo = ();
+	type MaxLocks = MaxLocks;
+	type MaxReserves = ();
+	type ReserveIdentifier = [u8; 8];
+}
+
+parameter_types! {
+	pub const TransactionByteFee: u64 = 1;
+	pub const OperationalFeeMultiplier: u8 = 5;
+}
+
+impl pallet_transaction_payment::Config for Test {
+	type OnChargeTransaction = CurrencyAdapter<pallet_balances::Pallet<Test>, ()>;
+	type TransactionByteFee = TransactionByteFee;
+	type WeightToFee = IdentityFee<u64>;
+	type FeeMultiplierUpdate = ();
+	type OperationalFeeMultiplier = OperationalFeeMultiplier;
+}
+
+parameter_types! {
+	pub const MinimumPeriod: u64 = 1;
+}
+impl pallet_timestamp::Config for Test {
+	type Moment = u64;
+	type OnTimestampSet = ();
+	type MinimumPeriod = MinimumPeriod;
+	type WeightInfo = ();
+}
+
+parameter_types! {
+	pub const CollectionCreationPrice: u32 = 0;
+	pub TreasuryAccountId: u64 = 1234;
+	pub EthereumChainId: u32 = 1111;
+}
+
+pub struct TestEvmAddressMapping;
+impl AddressMapping<u64> for TestEvmAddressMapping {
+	fn into_account_id(_addr: sp_core::H160) -> u64 {
+		unimplemented!()
+	}
+}
+
+pub struct TestEvmBackwardsAddressMapping;
+impl EvmBackwardsAddressMapping<u64> for TestEvmBackwardsAddressMapping {
+	fn from_account_id(_account_id: u64) -> sp_core::H160 {
+		unimplemented!()
+	}
+}
+
+#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, TypeInfo)]
+pub struct TestCrossAccountId(u64, sp_core::H160);
+impl CrossAccountId<u64> for TestCrossAccountId {
+	fn from_sub(sub: u64) -> Self {
+		let mut eth = [0; 20];
+		eth[12..20].copy_from_slice(&sub.to_be_bytes());
+		Self(sub, sp_core::H160(eth))
+	}
+	fn as_sub(&self) -> &u64 {
+		&self.0
+	}
+	fn from_eth(eth: sp_core::H160) -> Self {
+		let mut sub_raw = [0; 8];
+		sub_raw.copy_from_slice(&eth.0[0..8]);
+		let sub = u64::from_be_bytes(sub_raw);
+		Self(sub, eth)
+	}
+	fn as_eth(&self) -> &sp_core::H160 {
+		&self.1
+	}
+}
+
+pub struct TestEtheremTransactionSender;
+impl pallet_ethereum::EthereumTransactionSender for TestEtheremTransactionSender {
+	fn submit_logs_transaction(
+		_tx: pallet_ethereum::Transaction,
+		_logs: Vec<pallet_ethereum::Log>,
+	) -> Result<(), sp_runtime::DispatchError> {
+		Ok(())
+	}
+}
+
+impl pallet_evm_coder_substrate::Config for Test {
+	type EthereumTransactionSender = TestEtheremTransactionSender;
+}
+
+impl pallet_template::Config for Test {
+	type Event = ();
+	type WeightInfo = ();
+	type CollectionCreationPrice = CollectionCreationPrice;
+	type Currency = pallet_balances::Pallet<Test>;
+	type TreasuryAccountId = TreasuryAccountId;
+	type EvmAddressMapping = TestEvmAddressMapping;
+	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
+	type CrossAccountId = TestCrossAccountId;
+}
+
+// Build genesis storage according to the mock runtime.
+pub fn new_test_ext() -> sp_io::TestExternalities {
+	system::GenesisConfig::default()
+		.build_storage::<Test>()
+		.unwrap()
+		.into()
+}
addedpallets/unique/src/sponsorship.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/sponsorship.rs
@@ -0,0 +1,282 @@
+use crate::{
+	Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,
+	FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode, NftApproveBasket,
+	FungibleApproveBasket, RefungibleApproveBasket,
+};
+use core::marker::PhantomData;
+use up_sponsorship::SponsorshipHandler;
+use frame_support::{
+	traits::{IsSubType},
+	storage::{StorageMap, StorageDoubleMap, StorageNMap},
+};
+use up_data_structs::{
+	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
+	NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId,
+};
+use pallet_common::{CollectionHandle};
+use pallet_common::account::CrossAccountId;
+
+pub fn withdraw_transfer<T: Config>(
+	collection: &CollectionHandle<T>,
+	who: &T::CrossAccountId,
+	item_id: &TokenId,
+) -> Option<()> {
+	// preliminary sponsoring correctness check
+	match collection.mode {
+		CollectionMode::NFT => {
+			let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
+			if !owner.conv_eq(who) {
+				return None;
+			}
+		}
+		CollectionMode::Fungible(_) => {
+			if item_id != &TokenId::default() {
+				return None;
+			}
+			if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
+				return None;
+			}
+		}
+		CollectionMode::ReFungible => {
+			if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
+				return None;
+			}
+		}
+	}
+
+	// sponsor timeout
+	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+	let limit = collection
+		.limits
+		.sponsor_transfer_timeout(match collection.mode {
+			CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
+			CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+			CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+		});
+
+	let last_tx_block = match collection.mode {
+		CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),
+		CollectionMode::Fungible(_) => {
+			<FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
+		}
+		CollectionMode::ReFungible => {
+			<ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))
+		}
+	};
+
+	if let Some(last_tx_block) = last_tx_block {
+		let timeout = last_tx_block + limit.into();
+		if block_number < timeout {
+			return None;
+		}
+	}
+
+	match collection.mode {
+		CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),
+		CollectionMode::Fungible(_) => {
+			<FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)
+		}
+		CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(
+			(collection.id, item_id, who.as_sub()),
+			block_number,
+		),
+	};
+
+	Some(())
+}
+
+pub fn withdraw_create_item<T: Config>(
+	collection: &CollectionHandle<T>,
+	who: &T::AccountId,
+	_properties: &CreateItemData,
+) -> Option<()> {
+	if _properties.data_size() as u32 > collection.limits.sponsored_data_size() {
+		return None;
+	}
+
+	// sponsor timeout
+	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+	let limit = collection
+		.limits
+		.sponsor_transfer_timeout(match _properties {
+			CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,
+			CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+			CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+		});
+
+	if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, &who)) {
+		let timeout = last_tx_block + limit.into();
+		if block_number < timeout {
+			return None;
+		}
+	}
+
+	CreateItemBasket::<T>::insert((collection.id, who.clone()), block_number);
+
+	Some(())
+}
+
+pub fn withdraw_set_variable_meta_data<T: Config>(
+	who: &T::CrossAccountId,
+	collection: &CollectionHandle<T>,
+	item_id: &TokenId,
+	data: &[u8],
+) -> Option<()> {
+	// TODO: make it work for admins
+	if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {
+		return None;
+	}
+	// preliminary sponsoring correctness check
+	match collection.mode {
+		CollectionMode::NFT => {
+			let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
+			if !owner.conv_eq(who) {
+				return None;
+			}
+		}
+		CollectionMode::Fungible(_) => {
+			if item_id != &TokenId::default() {
+				return None;
+			}
+			if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
+				return None;
+			}
+		}
+		CollectionMode::ReFungible => {
+			if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
+				return None;
+			}
+		}
+	}
+
+	// Can't sponsor fungible collection, this tx will be rejected
+	// as invalid
+	if matches!(collection.mode, CollectionMode::Fungible(_)) {
+		return None;
+	}
+	if data.len() > collection.limits.sponsored_data_size() as usize {
+		return None;
+	}
+
+	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+	let limit = collection.limits.sponsored_data_rate_limit()?;
+
+	if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {
+		let timeout = last_tx_block + limit.into();
+		if block_number < timeout {
+			return None;
+		}
+	}
+
+	<VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);
+
+	Some(())
+}
+
+pub fn withdraw_approve<T: Config>(
+	collection: &CollectionHandle<T>,
+	who: &T::AccountId,
+	item_id: &TokenId,
+) -> Option<()> {
+	// sponsor timeout
+	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+	let limit = collection.limits.sponsor_approve_timeout();
+
+	let last_tx_block = match collection.mode {
+		CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),
+		CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),
+		CollectionMode::ReFungible => {
+			<RefungibleApproveBasket<T>>::get((collection.id, item_id, who))
+		}
+	};
+
+	if let Some(last_tx_block) = last_tx_block {
+		let timeout = last_tx_block + limit.into();
+		if block_number < timeout {
+			return None;
+		}
+	}
+
+	match collection.mode {
+		CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),
+		CollectionMode::Fungible(_) => {
+			<FungibleApproveBasket<T>>::insert(collection.id, who, block_number)
+		}
+		CollectionMode::ReFungible => {
+			<RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)
+		}
+	};
+
+	Some(())
+}
+
+fn load<T: Config>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {
+	let collection = CollectionHandle::new(id)?;
+	let sponsor = collection.sponsorship.sponsor().cloned()?;
+	Some((sponsor, collection))
+}
+
+pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);
+impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>
+where
+	T: Config,
+	C: IsSubType<Call<T>>,
+{
+	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
+		match IsSubType::<Call<T>>::is_sub_type(call)? {
+			Call::create_item {
+				collection_id,
+				data,
+				..
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_create_item::<T>(&collection, who, data).map(|()| sponsor)
+			}
+			Call::transfer {
+				collection_id,
+				item_id,
+				..
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_transfer::<T>(
+					&collection,
+					&T::CrossAccountId::from_sub(who.clone()),
+					item_id,
+				)
+				.map(|()| sponsor)
+			}
+			Call::transfer_from {
+				collection_id,
+				item_id,
+				from,
+				..
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)
+			}
+			Call::approve {
+				collection_id,
+				item_id,
+				..
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
+			}
+			Call::set_variable_meta_data {
+				collection_id,
+				item_id,
+				data,
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_set_variable_meta_data::<T>(
+					&T::CrossAccountId::from_sub(who.clone()),
+					&collection,
+					item_id,
+					data,
+				)
+				.map(|()| sponsor)
+			}
+			_ => None,
+		}
+	}
+}
addedpallets/unique/src/tests.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/tests.rs
@@ -0,0 +1,2291 @@
+// Tests to be written here
+use super::*;
+use crate::mock::*;
+use crate::{AccessMode, CollectionMode, Ownership, CreateItemData};
+use up_data_structs::{
+	CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId,
+	MAX_DECIMAL_POINTS,
+};
+use frame_support::{assert_noop, assert_ok};
+use sp_std::convert::TryInto;
+
+fn default_nft_data() -> CreateNftData {
+	CreateNftData {
+		const_data: vec![1, 2, 3].try_into().unwrap(),
+		variable_data: vec![3, 2, 1].try_into().unwrap(),
+	}
+}
+
+fn default_fungible_data() -> CreateFungibleData {
+	CreateFungibleData { value: 5 }
+}
+
+fn default_re_fungible_data() -> CreateReFungibleData {
+	CreateReFungibleData {
+		const_data: vec![1, 2, 3].try_into().unwrap(),
+		variable_data: vec![3, 2, 1].try_into().unwrap(),
+		pieces: 1023,
+	}
+}
+
+fn create_test_collection_for_owner(
+	mode: &CollectionMode,
+	owner: u64,
+	id: CollectionId,
+) -> CollectionId {
+	let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+	let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+	let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+
+	let origin1 = Origin::signed(owner);
+	assert_ok!(TemplateModule::create_collection(
+		origin1,
+		col_name1,
+		col_desc1,
+		token_prefix1,
+		mode.clone()
+	));
+
+	let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+	let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+	let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();
+	assert_eq!(TemplateModule::collection_id(id).unwrap().owner, owner);
+	assert_eq!(
+		TemplateModule::collection_id(id).unwrap().name,
+		saved_col_name
+	);
+	assert_eq!(TemplateModule::collection_id(id).unwrap().mode, *mode);
+	assert_eq!(
+		TemplateModule::collection_id(id).unwrap().description,
+		saved_description
+	);
+	assert_eq!(
+		TemplateModule::collection_id(id).unwrap().token_prefix,
+		saved_prefix
+	);
+	id
+}
+
+fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {
+	create_test_collection_for_owner(&mode, 1, id)
+}
+
+fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {
+	let origin1 = Origin::signed(1);
+	assert_ok!(TemplateModule::create_item(
+		origin1,
+		collection_id,
+		account(1),
+		data.clone()
+	));
+}
+
+fn account(sub: u64) -> TestCrossAccountId {
+	TestCrossAccountId::from_sub(sub)
+}
+
+// Use cases tests region
+// #region
+
+#[test]
+fn set_version_schema() {
+	new_test_ext().execute_with(|| {
+		let origin1 = Origin::signed(1);
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		assert_ok!(TemplateModule::set_schema_version(
+			origin1,
+			collection_id,
+			SchemaVersion::Unique
+		));
+		assert_eq!(
+			TemplateModule::collection_id(collection_id)
+				.unwrap()
+				.schema_version,
+			SchemaVersion::Unique
+		);
+	});
+}
+
+#[test]
+fn create_fungible_collection_fails_with_large_decimal_numbers() {
+	new_test_ext().execute_with(|| {
+		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+
+		let origin1 = Origin::signed(1);
+		assert_noop!(
+			TemplateModule::create_collection(
+				origin1,
+				col_name1,
+				col_desc1,
+				token_prefix1,
+				CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)
+			),
+			Error::<Test>::CollectionDecimalPointLimitExceeded
+		);
+	});
+}
+
+#[test]
+fn create_nft_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.clone().into());
+		let item = TemplateModule::nft_item_id(collection_id, 1).unwrap();
+		assert_eq!(item.const_data, data.const_data.into_inner());
+		assert_eq!(item.variable_data, data.variable_data.into_inner());
+	});
+}
+
+// Use cases tests region
+// #region
+#[test]
+fn create_nft_multiple_items() {
+	new_test_ext().execute_with(|| {
+		create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];
+
+		assert_ok!(TemplateModule::create_multiple_items(
+			origin1,
+			1,
+			account(1),
+			items_data
+				.clone()
+				.into_iter()
+				.map(|d| { d.into() })
+				.collect()
+		));
+		for (index, data) in items_data.into_iter().enumerate() {
+			let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap();
+			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
+			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
+		}
+	});
+}
+
+#[test]
+fn create_refungible_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
+
+		let data = default_re_fungible_data();
+		create_test_item(collection_id, &data.clone().into());
+		let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();
+		assert_eq!(item.const_data, data.const_data.into_inner());
+		assert_eq!(item.variable_data, data.variable_data.into_inner());
+		assert_eq!(
+			item.owner[0],
+			Ownership {
+				owner: account(1),
+				fraction: 1023
+			}
+		);
+	});
+}
+
+#[test]
+fn create_multiple_refungible_items() {
+	new_test_ext().execute_with(|| {
+		create_test_collection(&CollectionMode::ReFungible, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let items_data = vec![
+			default_re_fungible_data(),
+			default_re_fungible_data(),
+			default_re_fungible_data(),
+		];
+
+		assert_ok!(TemplateModule::create_multiple_items(
+			origin1,
+			1,
+			account(1),
+			items_data
+				.clone()
+				.into_iter()
+				.map(|d| { d.into() })
+				.collect()
+		));
+		for (index, data) in items_data.into_iter().enumerate() {
+			let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap();
+			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
+			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
+			assert_eq!(
+				item.owner[0],
+				Ownership {
+					owner: account(1),
+					fraction: 1023
+				}
+			);
+		}
+	});
+}
+
+#[test]
+fn create_fungible_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
+
+		let data = default_fungible_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).value, 5);
+	});
+}
+
+//#[test]
+// fn create_multiple_fungible_items() {
+//     new_test_ext().execute_with(|| {
+//         default_limits();
+
+//         create_test_collection(&CollectionMode::Fungible(3), 1);
+
+//         let origin1 = Origin::signed(1);
+
+//         let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];
+
+//         assert_ok!(TemplateModule::create_multiple_items(
+//             origin1.clone(),
+//             1,
+//             1,
+//             items_data.clone().into_iter().map(|d| { d.into() }).collect()
+//         ));
+
+//         for (index, _) in items_data.iter().enumerate() {
+//             assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);
+//         }
+//         assert_eq!(TemplateModule::balance_count(1, 1), 3000);
+//         assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);
+//     });
+// }
+
+#[test]
+fn transfer_fungible_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		let data = default_fungible_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 5);
+		assert_eq!(TemplateModule::balance_count(1, 1), 5);
+
+		// change owner scenario
+		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 5));
+		assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 0);
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+		assert_eq!(TemplateModule::balance_count(1, 2), 5);
+
+		// split item scenario
+		assert_ok!(TemplateModule::transfer(
+			origin2.clone(),
+			account(3),
+			1,
+			1,
+			3
+		));
+		assert_eq!(TemplateModule::balance_count(1, 2), 2);
+		assert_eq!(TemplateModule::balance_count(1, 3), 3);
+
+		// split item and new owner has account scenario
+		assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 1));
+		assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 1);
+		assert_eq!(TemplateModule::fungible_item_id(1, 3).value, 4);
+		assert_eq!(TemplateModule::balance_count(1, 2), 1);
+		assert_eq!(TemplateModule::balance_count(1, 3), 4);
+	});
+}
+
+#[test]
+fn transfer_refungible_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
+
+		let data = default_re_fungible_data();
+		create_test_item(collection_id, &data.clone().into());
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+		{
+			let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();
+			assert_eq!(item.const_data, data.const_data.into_inner());
+			assert_eq!(item.variable_data, data.variable_data.into_inner());
+			assert_eq!(
+				item.owner[0],
+				Ownership {
+					owner: account(1),
+					fraction: 1023
+				}
+			);
+		}
+		assert_eq!(TemplateModule::balance_count(1, 1), 1023);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
+		// change owner scenario
+		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1023));
+		assert_eq!(
+			TemplateModule::refungible_item_id(1, 1).unwrap().owner[0],
+			Ownership {
+				owner: account(2),
+				fraction: 1023
+			}
+		);
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+		assert_eq!(TemplateModule::balance_count(1, 2), 1023);
+		// assert_eq!(TemplateModule::address_tokens(1, 1), []);
+		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
+
+		// split item scenario
+		assert_ok!(TemplateModule::transfer(
+			origin2.clone(),
+			account(3),
+			1,
+			1,
+			500
+		));
+		{
+			let item = TemplateModule::refungible_item_id(1, 1).unwrap();
+			assert_eq!(
+				item.owner[0],
+				Ownership {
+					owner: account(2),
+					fraction: 523
+				}
+			);
+			assert_eq!(
+				item.owner[1],
+				Ownership {
+					owner: account(3),
+					fraction: 500
+				}
+			);
+		}
+		assert_eq!(TemplateModule::balance_count(1, 2), 523);
+		assert_eq!(TemplateModule::balance_count(1, 3), 500);
+		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
+		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
+
+		// split item and new owner has account scenario
+		assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 200));
+		{
+			let item = TemplateModule::refungible_item_id(1, 1).unwrap();
+			assert_eq!(
+				item.owner[0],
+				Ownership {
+					owner: account(2),
+					fraction: 323
+				}
+			);
+			assert_eq!(
+				item.owner[1],
+				Ownership {
+					owner: account(3),
+					fraction: 700
+				}
+			);
+		}
+		assert_eq!(TemplateModule::balance_count(1, 2), 323);
+		assert_eq!(TemplateModule::balance_count(1, 3), 700);
+		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
+		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
+	});
+}
+
+#[test]
+fn transfer_nft_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
+		let origin1 = Origin::signed(1);
+		// default scenario
+		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));
+		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+		assert_eq!(TemplateModule::balance_count(1, 2), 1);
+		// assert_eq!(TemplateModule::address_tokens(1, 1), []);
+		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
+	});
+}
+
+#[test]
+fn nft_approve_and_transfer_from() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
+		// neg transfer
+		assert_noop!(
+			TemplateModule::transfer_from(origin2.clone(), account(1), account(2), 1, 1, 1),
+			Error::<Test>::NoPermission
+		);
+
+		// do approve
+		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 5));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
+
+		assert_ok!(TemplateModule::transfer_from(
+			origin2,
+			account(1),
+			account(3),
+			1,
+			1,
+			1
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);
+	});
+}
+
+#[test]
+fn nft_approve_and_transfer_from_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.clone().into());
+
+		assert_eq!(
+			&TemplateModule::nft_item_id(1, 1).unwrap().const_data,
+			&data.const_data.into_inner()
+		);
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			1,
+			true
+		));
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			1,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(3)
+		));
+
+		// do approve
+		assert_ok!(TemplateModule::approve(
+			origin1.clone(),
+			account(2),
+			1,
+			1,
+			5
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
+		assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);
+
+		assert_ok!(TemplateModule::transfer_from(
+			origin2,
+			account(1),
+			account(3),
+			1,
+			1,
+			1
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);
+	});
+}
+
+#[test]
+fn refungible_approve_and_transfer_from() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		let data = default_re_fungible_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_eq!(TemplateModule::balance_count(1, 1), 1023);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			1,
+			true
+		));
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			1,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(3)
+		));
+
+		// do approve
+		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1023));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023);
+
+		assert_ok!(TemplateModule::transfer_from(
+			origin2,
+			account(1),
+			account(3),
+			1,
+			1,
+			100
+		));
+		assert_eq!(TemplateModule::balance_count(1, 1), 923);
+		assert_eq!(TemplateModule::balance_count(1, 3), 100);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
+
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 923);
+	});
+}
+
+#[test]
+fn fungible_approve_and_transfer_from() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
+
+		let data = default_fungible_data();
+		create_test_item(collection_id, &data.into());
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_eq!(TemplateModule::balance_count(1, 1), 5);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			1,
+			true
+		));
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			1,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(3)
+		));
+
+		// do approve
+		assert_ok!(TemplateModule::approve(
+			origin1.clone(),
+			account(2),
+			1,
+			1,
+			5
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
+		assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);
+
+		assert_ok!(TemplateModule::transfer_from(
+			origin2.clone(),
+			account(1),
+			account(3),
+			1,
+			1,
+			4
+		));
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+		assert_eq!(TemplateModule::balance_count(1, 3), 4);
+
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);
+
+		assert_noop!(
+			TemplateModule::transfer_from(origin2, account(1), account(3), 1, 1, 4),
+			Error::<Test>::NoPermission
+		);
+	});
+}
+
+#[test]
+fn change_collection_owner() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::change_collection_owner(
+			origin1,
+			collection_id,
+			2
+		));
+		assert_eq!(
+			TemplateModule::collection_id(collection_id).unwrap().owner,
+			2
+		);
+	});
+}
+
+#[test]
+fn destroy_collection() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));
+	});
+}
+
+#[test]
+fn burn_nft_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		// check balance (collection with id = 1, user id = 1)
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+
+		// burn item
+		assert_ok!(TemplateModule::burn_item(
+			origin1.clone(),
+			collection_id,
+			1,
+			1
+		));
+		assert_noop!(
+			TemplateModule::burn_item(origin1, collection_id, 1, 1),
+			Error::<Test>::TokenNotFound
+		);
+
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+	});
+}
+
+#[test]
+fn burn_fungible_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		let data = default_fungible_data();
+		create_test_item(collection_id, &data.into());
+
+		// check balance (collection with id = 1, user id = 1)
+		assert_eq!(TemplateModule::balance_count(1, 1), 5);
+
+		// burn item
+		assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));
+		assert_noop!(
+			TemplateModule::burn_item(origin1, 1, 1, 5),
+			Error::<Test>::TokenValueNotEnough
+		);
+
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+	});
+}
+
+#[test]
+fn burn_refungible_item() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			collection_id,
+			true
+		));
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1.clone(),
+			1,
+			account(2)
+		));
+
+		let data = default_re_fungible_data();
+		create_test_item(collection_id, &data.into());
+
+		// check balance (collection with id = 1, user id = 2)
+		assert_eq!(TemplateModule::balance_count(1, 1), 1023);
+
+		// burn item
+		assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023));
+		assert_noop!(
+			TemplateModule::burn_item(origin1, 1, 1, 1023),
+			Error::<Test>::TokenNotFound
+		);
+
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+	});
+}
+
+#[test]
+fn add_collection_admin() {
+	new_test_ext().execute_with(|| {
+		let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
+		create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);
+		create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);
+
+		let origin1 = Origin::signed(1);
+
+		// collection admin
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1.clone(),
+			collection1_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1,
+			collection1_id,
+			account(3)
+		));
+
+		assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(2)),);
+		assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(3)),);
+	});
+}
+
+#[test]
+fn remove_collection_admin() {
+	new_test_ext().execute_with(|| {
+		let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
+		create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);
+		create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		// collection admin
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1.clone(),
+			collection1_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1,
+			collection1_id,
+			account(3)
+		));
+
+		assert!(TemplateModule::admin_list_collection(1).contains(&account(2)),);
+		assert!(TemplateModule::admin_list_collection(1).contains(&account(3)),);
+
+		// remove admin
+		assert_ok!(TemplateModule::remove_collection_admin(
+			origin2,
+			1,
+			account(3)
+		));
+		assert!(!TemplateModule::admin_list_collection(1).contains(&account(3)),);
+	});
+}
+
+#[test]
+fn balance_of() {
+	new_test_ext().execute_with(|| {
+		let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);
+		let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);
+
+		// check balance before
+		assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);
+		assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);
+		assert_eq!(
+			TemplateModule::balance_count(re_fungible_collection_id, 1),
+			0
+		);
+
+		let nft_data = default_nft_data();
+		create_test_item(nft_collection_id, &nft_data.into());
+
+		let fungible_data = default_fungible_data();
+		create_test_item(fungible_collection_id, &fungible_data.into());
+
+		let re_fungible_data = default_re_fungible_data();
+		create_test_item(re_fungible_collection_id, &re_fungible_data.into());
+
+		// check balance (collection with id = 1, user id = 1)
+		assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);
+		assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);
+		assert_eq!(
+			TemplateModule::balance_count(re_fungible_collection_id, 1),
+			1023
+		);
+		assert_eq!(
+			TemplateModule::nft_item_id(nft_collection_id, 1)
+				.unwrap()
+				.owner,
+			account(1)
+		);
+		assert_eq!(
+			TemplateModule::fungible_item_id(fungible_collection_id, 1).value,
+			5
+		);
+		assert_eq!(
+			TemplateModule::refungible_item_id(re_fungible_collection_id, 1)
+				.unwrap()
+				.owner[0]
+				.owner,
+			account(1)
+		);
+	});
+}
+
+#[test]
+fn approve() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		let origin1 = Origin::signed(1);
+
+		// approve
+		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);
+	});
+}
+
+#[test]
+fn transfer_from() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		// approve
+		assert_ok!(TemplateModule::approve(
+			origin1.clone(),
+			account(2),
+			1,
+			1,
+			1
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			1,
+			true
+		));
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			1,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(origin1, 1, account(3)));
+
+		assert_ok!(TemplateModule::transfer_from(
+			origin2,
+			account(1),
+			account(2),
+			1,
+			1,
+			1
+		));
+
+		// after transfer
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+		assert_eq!(TemplateModule::balance_count(1, 2), 1);
+	});
+}
+
+// #endregion
+
+// Coverage tests region
+// #region
+
+#[test]
+fn owner_can_add_address_to_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1,
+			collection_id,
+			account(2)
+		));
+		assert!(TemplateModule::allow_list(collection_id, 2));
+	});
+}
+
+#[test]
+fn admin_can_add_address_to_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1,
+			collection_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin2,
+			collection_id,
+			account(3)
+		));
+		assert!(TemplateModule::allow_list(collection_id, 3));
+	});
+}
+
+#[test]
+fn nonprivileged_user_cannot_add_address_to_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin2 = Origin::signed(2);
+		assert_noop!(
+			TemplateModule::add_to_allow_list(origin2, collection_id, account(3)),
+			Error::<Test>::NoPermission
+		);
+	});
+}
+
+#[test]
+fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {
+	new_test_ext().execute_with(|| {
+		let origin1 = Origin::signed(1);
+
+		assert_noop!(
+			TemplateModule::add_to_allow_list(origin1, 1, account(2)),
+			Error::<Test>::CollectionNotFound
+		);
+	});
+}
+
+#[test]
+fn nobody_can_add_address_to_allow_list_of_deleted_collection() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::destroy_collection(
+			origin1.clone(),
+			collection_id
+		));
+		assert_noop!(
+			TemplateModule::add_to_allow_list(origin1, collection_id, account(2)),
+			Error::<Test>::CollectionNotFound
+		);
+	});
+}
+
+// If address is already added to allow list, nothing happens
+#[test]
+fn address_is_already_added_to_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1,
+			collection_id,
+			account(2)
+		));
+		assert!(TemplateModule::allow_list(collection_id, 2));
+	});
+}
+
+#[test]
+fn owner_can_remove_address_from_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::remove_from_allow_list(
+			origin1,
+			collection_id,
+			account(2)
+		));
+		assert!(!TemplateModule::allow_list(collection_id, 2));
+	});
+}
+
+#[test]
+fn admin_can_remove_address_from_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1,
+			collection_id,
+			account(3)
+		));
+		assert_ok!(TemplateModule::remove_from_allow_list(
+			origin2,
+			collection_id,
+			account(3)
+		));
+		assert!(!TemplateModule::allow_list(collection_id, 3));
+	});
+}
+
+#[test]
+fn nonprivileged_user_cannot_remove_address_from_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1,
+			collection_id,
+			account(2)
+		));
+		assert_noop!(
+			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),
+			Error::<Test>::NoPermission
+		);
+		assert!(TemplateModule::allow_list(collection_id, 2));
+	});
+}
+
+#[test]
+fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {
+	new_test_ext().execute_with(|| {
+		let origin1 = Origin::signed(1);
+
+		assert_noop!(
+			TemplateModule::remove_from_allow_list(origin1, 1, account(2)),
+			Error::<Test>::CollectionNotFound
+		);
+	});
+}
+
+#[test]
+fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));
+		assert_noop!(
+			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),
+			Error::<Test>::CollectionNotFound
+		);
+		assert!(!TemplateModule::allow_list(collection_id, 2));
+	});
+}
+
+// If address is already removed from allow list, nothing happens
+#[test]
+fn address_is_already_removed_from_allow_list() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::remove_from_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::remove_from_allow_list(
+			origin1,
+			collection_id,
+			account(2)
+		));
+		assert!(!TemplateModule::allow_list(collection_id, 2));
+	});
+}
+
+// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)
+#[test]
+fn allow_list_test_1() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		assert_noop!(
+			TemplateModule::transfer(origin1, account(3), 1, 1, 1),
+			Error::<Test>::AddresNotInAllowList
+		);
+	});
+}
+
+#[test]
+fn allow_list_test_2() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(2)
+		));
+
+		// do approve
+		assert_ok!(TemplateModule::approve(
+			origin1.clone(),
+			account(1),
+			1,
+			1,
+			1
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);
+
+		assert_ok!(TemplateModule::remove_from_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+
+		assert_noop!(
+			TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),
+			Error::<Test>::AddresNotInAllowList
+		);
+	});
+}
+
+// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)
+#[test]
+fn allow_list_test_3() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			1,
+			account(1)
+		));
+
+		assert_noop!(
+			TemplateModule::transfer(origin1, account(3), 1, 1, 1),
+			Error::<Test>::AddresNotInAllowList
+		);
+	});
+}
+
+#[test]
+fn allow_list_test_4() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		// do approve
+		assert_ok!(TemplateModule::approve(
+			origin1.clone(),
+			account(1),
+			1,
+			1,
+			1
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);
+
+		assert_ok!(TemplateModule::remove_from_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		assert_noop!(
+			TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),
+			Error::<Test>::AddresNotInAllowList
+		);
+	});
+}
+
+// If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)
+#[test]
+fn allow_list_test_5() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_noop!(
+			TemplateModule::burn_item(origin1.clone(), 1, 1, 5),
+			Error::<Test>::AddresNotInAllowList
+		);
+	});
+}
+
+// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).
+#[test]
+fn allow_list_test_6() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+
+		// do approve
+		assert_noop!(
+			TemplateModule::approve(origin1, account(1), 1, 1, 5),
+			Error::<Test>::AddresNotInAllowList
+		);
+	});
+}
+
+// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and
+//          tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)
+#[test]
+fn allow_list_test_7() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1));
+	});
+}
+
+#[test]
+fn allow_list_test_8() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(1)
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+
+		// do approve
+		assert_ok!(TemplateModule::approve(
+			origin1.clone(),
+			account(1),
+			1,
+			1,
+			5
+		));
+		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 5);
+
+		assert_ok!(TemplateModule::transfer_from(
+			origin1,
+			account(1),
+			account(2),
+			1,
+			1,
+			1
+		));
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.
+#[test]
+fn allow_list_test_9() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1,
+			collection_id,
+			false
+		));
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.
+#[test]
+fn allow_list_test_10() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			collection_id,
+			false
+		));
+
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1,
+			collection_id,
+			account(2)
+		));
+
+		assert_ok!(TemplateModule::create_item(
+			origin2,
+			collection_id,
+			account(2),
+			default_nft_data().into()
+		));
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow listed address.
+#[test]
+fn allow_list_test_11() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			collection_id,
+			false
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1,
+			collection_id,
+			account(2)
+		));
+
+		assert_noop!(
+			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),
+			Error::<Test>::PublicMintingNotAllowed
+		);
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address.
+#[test]
+fn allow_list_test_12() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1,
+			collection_id,
+			false
+		));
+
+		assert_noop!(
+			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),
+			Error::<Test>::PublicMintingNotAllowed
+		);
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.
+#[test]
+fn allow_list_test_13() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1,
+			collection_id,
+			true
+		));
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.
+#[test]
+fn allow_list_test_14() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			collection_id,
+			true
+		));
+
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1,
+			collection_id,
+			account(2)
+		));
+
+		assert_ok!(TemplateModule::create_item(
+			origin2,
+			1,
+			account(2),
+			default_nft_data().into()
+		));
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address.
+#[test]
+fn allow_list_test_15() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1,
+			collection_id,
+			true
+		));
+
+		assert_noop!(
+			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),
+			Error::<Test>::AddresNotInAllowList
+		);
+	});
+}
+
+// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address.
+#[test]
+fn allow_list_test_16() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_public_access_mode(
+			origin1.clone(),
+			collection_id,
+			AccessMode::AllowList
+		));
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			collection_id,
+			true
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1,
+			collection_id,
+			account(2)
+		));
+
+		assert_ok!(TemplateModule::create_item(
+			origin2,
+			1,
+			account(2),
+			default_nft_data().into()
+		));
+	});
+}
+
+// Total number of collections. Positive test
+#[test]
+fn total_number_collections_bound() {
+	new_test_ext().execute_with(|| {
+		create_test_collection(&CollectionMode::NFT, 1);
+	});
+}
+
+// Total number of collections. Negotive test
+#[test]
+fn total_number_collections_bound_neg() {
+	new_test_ext().execute_with(|| {
+		let origin1 = Origin::signed(1);
+
+		for i in 0..COLLECTION_NUMBER_LIMIT {
+			create_test_collection(&CollectionMode::NFT, i + 1);
+		}
+
+		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+
+		// 11-th collection in chain. Expects error
+		assert_noop!(
+			TemplateModule::create_collection(
+				origin1,
+				col_name1,
+				col_desc1,
+				token_prefix1,
+				CollectionMode::NFT
+			),
+			Error::<Test>::TotalCollectionsLimitExceeded
+		);
+	});
+}
+
+// Owned tokens by a single address. Positive test
+#[test]
+fn owned_tokens_bound() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.clone().into());
+		create_test_item(collection_id, &data.into());
+	});
+}
+
+// Owned tokens by a single address. Negotive test
+#[test]
+fn owned_tokens_bound_neg() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		for _ in 0..ACCOUNT_TOKEN_OWNERSHIP_LIMIT {
+			let data = default_nft_data();
+			create_test_item(collection_id, &data.clone().into());
+		}
+
+		let data = default_nft_data();
+		assert_noop!(
+			TemplateModule::create_item(origin1, 1, account(1), data.into()),
+			Error::<Test>::AccountTokenLimitExceeded
+		);
+	});
+}
+
+// Number of collection admins. Positive test
+#[test]
+fn collection_admins_bound() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1.clone(),
+			collection_id,
+			account(2)
+		));
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin1,
+			collection_id,
+			account(3)
+		));
+	});
+}
+
+// Number of collection admins. Negotive test
+#[test]
+fn collection_admins_bound_neg() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		for i in 0..COLLECTION_ADMINS_LIMIT {
+			assert_ok!(TemplateModule::add_collection_admin(
+				origin1.clone(),
+				collection_id,
+				account(2 + i)
+			));
+		}
+		assert_noop!(
+			TemplateModule::add_collection_admin(
+				origin1,
+				collection_id,
+				account(3 + COLLECTION_ADMINS_LIMIT)
+			),
+			Error::<Test>::CollectionAdminsLimitExceeded
+		);
+	});
+}
+// #endregion
+
+#[test]
+fn set_const_on_chain_schema() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::set_const_on_chain_schema(
+			origin1,
+			collection_id,
+			b"test const on chain schema".to_vec()
+		));
+
+		assert_eq!(
+			TemplateModule::collection_id(collection_id)
+				.unwrap()
+				.const_on_chain_schema,
+			b"test const on chain schema".to_vec()
+		);
+		assert_eq!(
+			TemplateModule::collection_id(collection_id)
+				.unwrap()
+				.variable_on_chain_schema,
+			b"".to_vec()
+		);
+	});
+}
+
+#[test]
+fn set_variable_on_chain_schema() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+		assert_ok!(TemplateModule::set_variable_on_chain_schema(
+			origin1,
+			collection_id,
+			b"test variable on chain schema".to_vec()
+		));
+
+		assert_eq!(
+			TemplateModule::collection_id(collection_id)
+				.unwrap()
+				.const_on_chain_schema,
+			b"".to_vec()
+		);
+		assert_eq!(
+			TemplateModule::collection_id(collection_id)
+				.unwrap()
+				.variable_on_chain_schema,
+			b"test variable on chain schema".to_vec()
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(1, &data.into());
+
+		let variable_data = b"test data".to_vec();
+		assert_ok!(TemplateModule::set_variable_meta_data(
+			origin1,
+			collection_id,
+			1,
+			variable_data.clone()
+		));
+
+		assert_eq!(
+			TemplateModule::nft_item_id(collection_id, 1)
+				.unwrap()
+				.variable_data,
+			variable_data
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_re_fungible_data();
+		create_test_item(1, &data.into());
+
+		let variable_data = b"test data".to_vec();
+		assert_ok!(TemplateModule::set_variable_meta_data(
+			origin1,
+			collection_id,
+			1,
+			variable_data.clone()
+		));
+
+		assert_eq!(
+			TemplateModule::refungible_item_id(collection_id, 1)
+				.unwrap()
+				.variable_data,
+			variable_data
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_fungible_token_fails() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_fungible_data();
+		create_test_item(1, &data.into());
+
+		let variable_data = b"test data".to_vec();
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),
+			Error::<Test>::CantStoreMetadataInFungibleTokens
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_token_fails_for_big_data() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(1, &data.into());
+
+		let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),
+			Error::<Test>::TokenVariableDataLimitExceeded
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_re_fungible_data();
+		create_test_item(1, &data.into());
+
+		let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),
+			Error::<Test>::TokenVariableDataLimitExceeded
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {
+	new_test_ext().execute_with(|| {
+		//default_limits();
+
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(1, &data.into());
+
+		assert_ok!(TemplateModule::set_meta_update_permission_flag(
+			origin1.clone(),
+			collection_id,
+			MetaUpdatePermission::ItemOwner,
+		));
+
+		let variable_data = b"ten chars.".to_vec();
+		assert_ok!(TemplateModule::set_variable_meta_data(
+			origin1,
+			collection_id,
+			1,
+			variable_data.clone()
+		));
+
+		assert_eq!(
+			TemplateModule::nft_item_id(collection_id, 1)
+				.unwrap()
+				.variable_data,
+			variable_data
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {
+	new_test_ext().execute_with(|| {
+		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
+
+		let origin1 = Origin::signed(1);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin1.clone(),
+			collection_id,
+			true
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin1.clone(),
+			collection_id,
+			account(1)
+		));
+
+		let data = default_nft_data();
+		create_test_item(1, &data.into());
+
+		assert_ok!(TemplateModule::set_meta_update_permission_flag(
+			origin1.clone(),
+			collection_id,
+			MetaUpdatePermission::ItemOwner,
+		));
+
+		let variable_data = b"1234567890123".to_vec();
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(
+				origin1,
+				collection_id,
+				1,
+				variable_data.clone()
+			),
+			Error::<Test>::TokenVariableDataLimitExceeded
+		);
+	})
+}
+
+#[test]
+fn collection_transfer_flag_works() {
+	new_test_ext().execute_with(|| {
+		let origin1 = Origin::signed(1);
+
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		assert_ok!(TemplateModule::set_transfers_enabled_flag(origin1, 1, true));
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
+		let origin1 = Origin::signed(1);
+
+		// default scenario
+		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));
+		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));
+		assert_eq!(TemplateModule::balance_count(1, 1), 0);
+		assert_eq!(TemplateModule::balance_count(1, 2), 1);
+
+		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_admin_flag() {
+	new_test_ext().execute_with(|| {
+		// default_limits();
+
+		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin2.clone(),
+			collection_id,
+			true
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin2.clone(),
+			collection_id,
+			account(1)
+		));
+
+		assert_ok!(TemplateModule::add_collection_admin(
+			origin2.clone(),
+			collection_id,
+			account(1)
+		));
+
+		let data = default_nft_data();
+		create_test_item(1, &data.into());
+
+		assert_ok!(TemplateModule::set_meta_update_permission_flag(
+			origin2.clone(),
+			collection_id,
+			MetaUpdatePermission::Admin,
+		));
+
+		let variable_data = b"test.".to_vec();
+		assert_ok!(TemplateModule::set_variable_meta_data(
+			origin1,
+			collection_id,
+			1,
+			variable_data.clone()
+		));
+
+		assert_eq!(
+			TemplateModule::nft_item_id(collection_id, 1)
+				.unwrap()
+				.variable_data,
+			variable_data
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_admin_flag_neg() {
+	new_test_ext().execute_with(|| {
+		// default_limits();
+
+		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
+
+		let origin1 = Origin::signed(1);
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_mint_permission(
+			origin2.clone(),
+			collection_id,
+			true
+		));
+		assert_ok!(TemplateModule::add_to_allow_list(
+			origin2.clone(),
+			collection_id,
+			account(1)
+		));
+
+		let data = default_nft_data();
+		create_test_item(1, &data.into());
+
+		assert_ok!(TemplateModule::set_meta_update_permission_flag(
+			origin2.clone(),
+			collection_id,
+			MetaUpdatePermission::Admin,
+		));
+
+		let variable_data = b"test.".to_vec();
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(
+				origin1,
+				collection_id,
+				1,
+				variable_data.clone()
+			),
+			Error::<Test>::NoPermission
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_flag_after_freeze() {
+	new_test_ext().execute_with(|| {
+		// default_limits();
+
+		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);
+
+		let origin2 = Origin::signed(2);
+
+		assert_ok!(TemplateModule::set_meta_update_permission_flag(
+			origin2.clone(),
+			collection_id,
+			MetaUpdatePermission::None,
+		));
+		assert_noop!(
+			TemplateModule::set_meta_update_permission_flag(
+				origin2.clone(),
+				collection_id,
+				MetaUpdatePermission::Admin
+			),
+			Error::<Test>::MetadataFlagFrozen
+		);
+	});
+}
+
+#[test]
+fn set_variable_meta_data_on_nft_with_none_flag_neg() {
+	new_test_ext().execute_with(|| {
+		// default_limits();
+
+		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
+		let origin1 = Origin::signed(1);
+
+		let data = default_nft_data();
+		create_test_item(1, &data.into());
+
+		assert_ok!(TemplateModule::set_meta_update_permission_flag(
+			origin1.clone(),
+			collection_id,
+			MetaUpdatePermission::None,
+		));
+
+		let variable_data = b"test.".to_vec();
+		assert_noop!(
+			TemplateModule::set_variable_meta_data(
+				origin1.clone(),
+				collection_id,
+				1,
+				variable_data.clone()
+			),
+			Error::<Test>::MetadataUpdateDenied
+		);
+	});
+}
+
+#[test]
+fn collection_transfer_flag_works_neg() {
+	new_test_ext().execute_with(|| {
+		let origin1 = Origin::signed(1);
+
+		let collection_id = create_test_collection(&CollectionMode::NFT, 1);
+		assert_ok!(TemplateModule::set_transfers_enabled_flag(
+			origin1, 1, false
+		));
+
+		let data = default_nft_data();
+		create_test_item(collection_id, &data.into());
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
+		let origin1 = Origin::signed(1);
+
+		// default scenario
+		assert_noop!(
+			TemplateModule::transfer(origin1, account(2), 1, 1, 1000),
+			Error::<Test>::TransferNotAllowed
+		);
+		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(1));
+		assert_eq!(TemplateModule::balance_count(1, 1), 1);
+		assert_eq!(TemplateModule::balance_count(1, 2), 0);
+
+		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+	});
+}
addedpallets/unique/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/unique/src/weights.rs
@@ -0,0 +1,314 @@
+// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
+
+//! Autogenerated weights for pallet_unique
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2021-10-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
+
+// Executed Command:
+// target/release/unique-collator
+// benchmark
+// --pallet
+// pallet-unique
+// --wasm-execution
+// compiled
+// --extrinsic
+// *
+// --template
+// .maintain/frame-weight-template.hbs
+// --steps=50
+// --repeat=20
+// --output=./pallets/unique/src/weights.rs
+
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_unique.
+pub trait WeightInfo {
+	fn create_collection() -> Weight;
+	fn destroy_collection() -> Weight;
+	fn add_to_allow_list() -> Weight;
+	fn remove_from_allow_list() -> Weight;
+	fn set_public_access_mode() -> Weight;
+	fn set_mint_permission() -> Weight;
+	fn change_collection_owner() -> Weight;
+	fn add_collection_admin() -> Weight;
+	fn remove_collection_admin() -> Weight;
+	fn set_collection_sponsor() -> Weight;
+	fn confirm_sponsorship() -> Weight;
+	fn remove_collection_sponsor() -> Weight;
+	fn set_transfers_enabled_flag() -> Weight;
+	fn set_offchain_schema(b: u32, ) -> Weight;
+	fn set_const_on_chain_schema(b: u32, ) -> Weight;
+	fn set_variable_on_chain_schema(b: u32, ) -> Weight;
+	fn set_schema_version() -> Weight;
+	fn set_collection_limits() -> Weight;
+	fn set_meta_update_permission_flag() -> Weight;
+}
+
+/// Weights for pallet_unique using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	// Storage: Common CreatedCollectionCount (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:0)
+	// Storage: System Account (r:2 w:2)
+	// Storage: Common CollectionById (r:0 w:1)
+	fn create_collection() -> Weight {
+		(23_803_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(4 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:1)
+	// Storage: Nonfungible TokensMinted (r:0 w:1)
+	// Storage: Nonfungible TokensBurnt (r:0 w:1)
+	fn destroy_collection() -> Weight {
+		(27_831_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
+	fn add_to_allow_list() -> Weight {
+		(6_629_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
+	fn remove_from_allow_list() -> Weight {
+		(6_596_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_public_access_mode() -> Weight {
+		(6_338_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_mint_permission() -> Weight {
+		(6_383_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn change_collection_owner() -> Weight {
+		(6_493_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
+	fn add_collection_admin() -> Weight {
+		(6_850_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
+	fn remove_collection_admin() -> Weight {
+		(6_615_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_collection_sponsor() -> Weight {
+		(6_430_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn confirm_sponsorship() -> Weight {
+		(6_125_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn remove_collection_sponsor() -> Weight {
+		(6_236_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_transfers_enabled_flag() -> Weight {
+		(6_500_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_offchain_schema(_b: u32, ) -> Weight {
+		(6_538_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
+		(6_542_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_variable_on_chain_schema(b: u32, ) -> Weight {
+		(6_092_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((2_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_schema_version() -> Weight {
+		(6_470_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_collection_limits() -> Weight {
+		(6_841_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_meta_update_permission_flag() -> Weight {
+		(6_278_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	// Storage: Common CreatedCollectionCount (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:0)
+	// Storage: System Account (r:2 w:2)
+	// Storage: Common CollectionById (r:0 w:1)
+	fn create_collection() -> Weight {
+		(23_803_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:1)
+	// Storage: Nonfungible TokensMinted (r:0 w:1)
+	// Storage: Nonfungible TokensBurnt (r:0 w:1)
+	fn destroy_collection() -> Weight {
+		(27_831_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
+	fn add_to_allow_list() -> Weight {
+		(6_629_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
+	fn remove_from_allow_list() -> Weight {
+		(6_596_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_public_access_mode() -> Weight {
+		(6_338_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_mint_permission() -> Weight {
+		(6_383_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn change_collection_owner() -> Weight {
+		(6_493_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
+	fn add_collection_admin() -> Weight {
+		(6_850_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
+	fn remove_collection_admin() -> Weight {
+		(6_615_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_collection_sponsor() -> Weight {
+		(6_430_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn confirm_sponsorship() -> Weight {
+		(6_125_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn remove_collection_sponsor() -> Weight {
+		(6_236_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_transfers_enabled_flag() -> Weight {
+		(6_500_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_offchain_schema(_b: u32, ) -> Weight {
+		(6_538_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
+		(6_542_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_variable_on_chain_schema(b: u32, ) -> Weight {
+		(6_092_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((2_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_schema_version() -> Weight {
+		(6_470_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_collection_limits() -> Weight {
+		(6_841_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_meta_update_permission_flag() -> Weight {
+		(6_278_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+}
\ No newline at end of file
addedprimitives/data-structs/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/primitives/data-structs/Cargo.toml
@@ -0,0 +1,39 @@
+[package]
+name = "up-data-structs"
+authors = ["Unique Network <support@uniquenetwork.io>"]
+description = "Unique data structs definitions"
+edition = "2018"
+license = 'All Rights Reserved'
+homepage = "https://unique.network"
+repository = 'https://github.com/UniqueNetwork/unique-chain'
+version = '0.1.0'
+
+[dependencies]
+scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
+codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = [
+  'derive',
+] }
+serde = { version = "1.0.130", features = [
+  'derive',
+], default-features = false, optional = true }
+frame-support = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
+frame-system = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
+sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
+sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
+sp-runtime = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
+derivative = "2.2.0"
+
+[features]
+default = ["std"]
+std = [
+  "serde1",
+  "serde/std",
+  "codec/std",
+  "frame-system/std",
+  "frame-support/std",
+  "sp-runtime/std",
+  "sp-core/std",
+  "sp-std/std",
+]
+serde1 = ["serde"]
+limit-testing = []
addedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/primitives/data-structs/src/lib.rs
@@ -0,0 +1,434 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use core::convert::{TryFrom, TryInto};
+
+#[cfg(feature = "serde")]
+pub use serde::{Serialize, Deserialize};
+
+use sp_core::U256;
+use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};
+use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
+pub use frame_support::{
+	BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,
+	dispatch::DispatchResult,
+	ensure, fail, parameter_types,
+	traits::{
+		Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,
+		Randomness, IsSubType, WithdrawReasons,
+	},
+	weights::{
+		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
+		DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
+		WeightToFeePolynomial, DispatchClass,
+	},
+	StorageValue, transactional,
+};
+use derivative::Derivative;
+use scale_info::TypeInfo;
+
+pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;
+pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;
+pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;
+pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;
+
+pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
+	100000
+} else {
+	10
+};
+pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
+	2048
+} else {
+	10
+};
+pub const COLLECTION_ADMINS_LIMIT: u32 = 5;
+pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;
+pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
+	1000000
+} else {
+	10
+};
+
+// Timeouts for item types in passed blocks
+pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
+pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
+pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
+
+pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;
+
+// Schema limits
+pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 1024;
+pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;
+pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;
+
+pub const MAX_COLLECTION_NAME_LENGTH: usize = 64;
+pub const MAX_COLLECTION_DESCRIPTION_LENGTH: usize = 256;
+pub const MAX_TOKEN_PREFIX_LENGTH: usize = 16;
+
+/// How much items can be created per single
+/// create_many call
+pub const MAX_ITEMS_PER_BATCH: u32 = 200;
+
+parameter_types! {
+	pub const CustomDataLimit: u32 = CUSTOM_DATA_LIMIT;
+}
+
+#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct CollectionId(pub u32);
+impl EncodeLike<u32> for CollectionId {}
+impl EncodeLike<CollectionId> for u32 {}
+
+#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct TokenId(pub u32);
+impl EncodeLike<u32> for TokenId {}
+impl EncodeLike<TokenId> for u32 {}
+
+impl TokenId {
+	pub fn try_next(self) -> Result<TokenId, ArithmeticError> {
+		self.0
+			.checked_add(1)
+			.ok_or(ArithmeticError::Overflow)
+			.map(Self)
+	}
+}
+
+impl From<TokenId> for U256 {
+	fn from(t: TokenId) -> Self {
+		t.0.into()
+	}
+}
+
+impl TryFrom<U256> for TokenId {
+	type Error = &'static str;
+
+	fn try_from(value: U256) -> Result<Self, Self::Error> {
+		Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))
+	}
+}
+
+pub struct OverflowError;
+impl From<OverflowError> for &'static str {
+	fn from(_: OverflowError) -> Self {
+		"overflow occured"
+	}
+}
+
+pub type DecimalPoints = u8;
+
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub enum CollectionMode {
+	NFT,
+	// decimal points
+	Fungible(DecimalPoints),
+	ReFungible,
+}
+
+impl CollectionMode {
+	pub fn id(&self) -> u8 {
+		match self {
+			CollectionMode::NFT => 1,
+			CollectionMode::Fungible(_) => 2,
+			CollectionMode::ReFungible => 3,
+		}
+	}
+}
+
+pub trait SponsoringResolve<AccountId, Call> {
+	fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;
+}
+
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub enum AccessMode {
+	Normal,
+	AllowList,
+}
+impl Default for AccessMode {
+	fn default() -> Self {
+		Self::Normal
+	}
+}
+
+#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub enum SchemaVersion {
+	ImageURL,
+	Unique,
+}
+impl Default for SchemaVersion {
+	fn default() -> Self {
+		Self::ImageURL
+	}
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct Ownership<AccountId> {
+	pub owner: AccountId,
+	pub fraction: u128,
+}
+
+#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub enum SponsorshipState<AccountId> {
+	/// The fees are applied to the transaction sender
+	Disabled,
+	Unconfirmed(AccountId),
+	/// Transactions are sponsored by specified account
+	Confirmed(AccountId),
+}
+
+impl<AccountId> SponsorshipState<AccountId> {
+	pub fn sponsor(&self) -> Option<&AccountId> {
+		match self {
+			Self::Confirmed(sponsor) => Some(sponsor),
+			_ => None,
+		}
+	}
+
+	pub fn pending_sponsor(&self) -> Option<&AccountId> {
+		match self {
+			Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),
+			_ => None,
+		}
+	}
+
+	pub fn confirmed(&self) -> bool {
+		matches!(self, Self::Confirmed(_))
+	}
+}
+
+impl<T> Default for SponsorshipState<T> {
+	fn default() -> Self {
+		Self::Disabled
+	}
+}
+
+#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct Collection<AccountId> {
+	pub owner: AccountId,
+	pub mode: CollectionMode,
+	pub access: AccessMode,
+	pub name: Vec<u16>,        // 64 include null escape char
+	pub description: Vec<u16>, // 256 include null escape char
+	pub token_prefix: Vec<u8>, // 16 include null escape char
+	pub mint_mode: bool,
+	pub offchain_schema: Vec<u8>,
+	pub schema_version: SchemaVersion,
+	pub sponsorship: SponsorshipState<AccountId>,
+	pub limits: CollectionLimits,          // Collection private restrictions
+	pub variable_on_chain_schema: Vec<u8>, //
+	pub const_on_chain_schema: Vec<u8>,    //
+	pub meta_update_permission: MetaUpdatePermission,
+}
+
+#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct NftItemType<AccountId> {
+	pub owner: AccountId,
+	pub const_data: Vec<u8>,
+	pub variable_data: Vec<u8>,
+}
+
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct FungibleItemType {
+	pub value: u128,
+}
+
+#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct ReFungibleItemType<AccountId> {
+	pub owner: Vec<Ownership<AccountId>>,
+	pub const_data: Vec<u8>,
+	pub variable_data: Vec<u8>,
+}
+
+/// All fields are wrapped in `Option`s, where None means chain default
+#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct CollectionLimits {
+	pub account_token_ownership_limit: Option<u32>,
+	pub sponsored_data_size: Option<u32>,
+	/// None - setVariableMetadata is not sponsored
+	/// Some(v) - setVariableMetadata is sponsored
+	///           if there is v block between txs
+	pub sponsored_data_rate_limit: Option<(Option<u32>,)>,
+	pub token_limit: Option<u32>,
+
+	// Timeouts for item types in passed blocks
+	pub sponsor_transfer_timeout: Option<u32>,
+	pub sponsor_approve_timeout: Option<u32>,
+	pub owner_can_transfer: Option<bool>,
+	pub owner_can_destroy: Option<bool>,
+	pub transfers_enabled: Option<bool>,
+}
+
+impl CollectionLimits {
+	pub fn account_token_ownership_limit(&self) -> u32 {
+		self.account_token_ownership_limit
+			.unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)
+			.min(MAX_TOKEN_OWNERSHIP)
+	}
+	pub fn sponsored_data_size(&self) -> u32 {
+		self.sponsored_data_size
+			.unwrap_or(CUSTOM_DATA_LIMIT)
+			.min(CUSTOM_DATA_LIMIT)
+	}
+	pub fn token_limit(&self) -> u32 {
+		self.token_limit
+			.unwrap_or(COLLECTION_TOKEN_LIMIT)
+			.min(COLLECTION_TOKEN_LIMIT)
+	}
+	pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {
+		self.sponsor_transfer_timeout
+			.unwrap_or(default)
+			.min(MAX_SPONSOR_TIMEOUT)
+	}
+	pub fn sponsor_approve_timeout(&self) -> u32 {
+		self.sponsor_approve_timeout
+			.unwrap_or(SPONSOR_APPROVE_TIMEOUT)
+			.min(MAX_SPONSOR_TIMEOUT)
+	}
+	pub fn owner_can_transfer(&self) -> bool {
+		self.owner_can_transfer.unwrap_or(true)
+	}
+	pub fn owner_can_destroy(&self) -> bool {
+		self.owner_can_destroy.unwrap_or(true)
+	}
+	pub fn transfers_enabled(&self) -> bool {
+		self.transfers_enabled.unwrap_or(true)
+	}
+	pub fn sponsored_data_rate_limit(&self) -> Option<u32> {
+		self.sponsored_data_rate_limit
+			.unwrap_or((None,))
+			.0
+			.map(|v| v.min(MAX_SPONSOR_TIMEOUT))
+	}
+}
+
+/// BoundedVec doesn't supports serde
+#[cfg(feature = "serde1")]
+mod bounded_serde {
+	use core::convert::TryFrom;
+	use frame_support::{BoundedVec, traits::Get};
+	use serde::{
+		ser::{self, Serialize},
+		de::{self, Deserialize, Error},
+	};
+	use sp_std::vec::Vec;
+
+	pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>
+	where
+		D: ser::Serializer,
+		V: Serialize,
+	{
+		let vec: &Vec<_> = &value;
+		vec.serialize(serializer)
+	}
+
+	pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>
+	where
+		D: de::Deserializer<'de>,
+		V: de::Deserialize<'de>,
+		S: Get<u32>,
+	{
+		// TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec?
+		let vec = <Vec<V>>::deserialize(deserializer)?;
+		let len = vec.len();
+		TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
+	}
+}
+
+#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+#[derivative(Debug)]
+pub struct CreateNftData {
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub const_data: BoundedVec<u8, CustomDataLimit>,
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub variable_data: BoundedVec<u8, CustomDataLimit>,
+}
+
+#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct CreateFungibleData {
+	pub value: u128,
+}
+
+#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+#[derivative(Debug)]
+pub struct CreateReFungibleData {
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub const_data: BoundedVec<u8, CustomDataLimit>,
+	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+	#[derivative(Debug = "ignore")]
+	pub variable_data: BoundedVec<u8, CustomDataLimit>,
+	pub pieces: u128,
+}
+
+#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub enum MetaUpdatePermission {
+	ItemOwner,
+	Admin,
+	None,
+}
+
+impl Default for MetaUpdatePermission {
+	fn default() -> Self {
+		Self::ItemOwner
+	}
+}
+
+#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub enum CreateItemData {
+	NFT(CreateNftData),
+	Fungible(CreateFungibleData),
+	ReFungible(CreateReFungibleData),
+}
+
+impl CreateItemData {
+	pub fn data_size(&self) -> usize {
+		match self {
+			CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),
+			CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),
+			_ => 0,
+		}
+	}
+}
+
+impl From<CreateNftData> for CreateItemData {
+	fn from(item: CreateNftData) -> Self {
+		CreateItemData::NFT(item)
+	}
+}
+
+impl From<CreateReFungibleData> for CreateItemData {
+	fn from(item: CreateReFungibleData) -> Self {
+		CreateItemData::ReFungible(item)
+	}
+}
+
+impl From<CreateFungibleData> for CreateItemData {
+	fn from(item: CreateFungibleData) -> Self {
+		CreateItemData::Fungible(item)
+	}
+}
+
+#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+pub struct CollectionStats {
+	pub created: u32,
+	pub destroyed: u32,
+	pub alive: u32,
+}
deletedprimitives/nft/Cargo.tomldiffbeforeafterboth
--- a/primitives/nft/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-[package]
-name = "nft-data-structs"
-authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
-description = "Nft data structs definitions"
-edition = "2018"
-license = 'GPL-3.0'
-homepage = "https://substrate.dev"
-repository = 'https://github.com/clover-network/clover'
-version = '0.9.0'
-
-[dependencies]
-scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
-codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = [
-  'derive',
-] }
-serde = { version = "1.0.130", features = [
-  'derive',
-], default-features = false, optional = true }
-frame-support = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
-frame-system = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
-sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
-sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
-sp-runtime = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
-derivative = "2.2.0"
-
-[features]
-default = ["std"]
-std = [
-  "serde1",
-  "serde/std",
-  "codec/std",
-  "frame-system/std",
-  "frame-support/std",
-  "sp-runtime/std",
-  "sp-core/std",
-  "sp-std/std",
-]
-serde1 = ["serde"]
-limit-testing = []
deletedprimitives/nft/src/lib.rsdiffbeforeafterboth
--- a/primitives/nft/src/lib.rs
+++ /dev/null
@@ -1,434 +0,0 @@
-#![cfg_attr(not(feature = "std"), no_std)]
-
-use core::convert::{TryFrom, TryInto};
-
-#[cfg(feature = "serde")]
-pub use serde::{Serialize, Deserialize};
-
-use sp_core::U256;
-use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};
-use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
-pub use frame_support::{
-	BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,
-	dispatch::DispatchResult,
-	ensure, fail, parameter_types,
-	traits::{
-		Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,
-		Randomness, IsSubType, WithdrawReasons,
-	},
-	weights::{
-		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
-		DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
-		WeightToFeePolynomial, DispatchClass,
-	},
-	StorageValue, transactional,
-};
-use derivative::Derivative;
-use scale_info::TypeInfo;
-
-pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;
-pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;
-pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;
-pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;
-
-pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
-	100000
-} else {
-	10
-};
-pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
-	2048
-} else {
-	10
-};
-pub const COLLECTION_ADMINS_LIMIT: u32 = 5;
-pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;
-pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
-	1000000
-} else {
-	10
-};
-
-// Timeouts for item types in passed blocks
-pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
-pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
-pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;
-
-pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;
-
-// Schema limits
-pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 1024;
-pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;
-pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 1024;
-
-pub const MAX_COLLECTION_NAME_LENGTH: usize = 64;
-pub const MAX_COLLECTION_DESCRIPTION_LENGTH: usize = 256;
-pub const MAX_TOKEN_PREFIX_LENGTH: usize = 16;
-
-/// How much items can be created per single
-/// create_many call
-pub const MAX_ITEMS_PER_BATCH: u32 = 200;
-
-parameter_types! {
-	pub const CustomDataLimit: u32 = CUSTOM_DATA_LIMIT;
-}
-
-#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct CollectionId(pub u32);
-impl EncodeLike<u32> for CollectionId {}
-impl EncodeLike<CollectionId> for u32 {}
-
-#[derive(Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct TokenId(pub u32);
-impl EncodeLike<u32> for TokenId {}
-impl EncodeLike<TokenId> for u32 {}
-
-impl TokenId {
-	pub fn try_next(self) -> Result<TokenId, ArithmeticError> {
-		self.0
-			.checked_add(1)
-			.ok_or(ArithmeticError::Overflow)
-			.map(Self)
-	}
-}
-
-impl From<TokenId> for U256 {
-	fn from(t: TokenId) -> Self {
-		t.0.into()
-	}
-}
-
-impl TryFrom<U256> for TokenId {
-	type Error = &'static str;
-
-	fn try_from(value: U256) -> Result<Self, Self::Error> {
-		Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))
-	}
-}
-
-pub struct OverflowError;
-impl From<OverflowError> for &'static str {
-	fn from(_: OverflowError) -> Self {
-		"overflow occured"
-	}
-}
-
-pub type DecimalPoints = u8;
-
-#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub enum CollectionMode {
-	NFT,
-	// decimal points
-	Fungible(DecimalPoints),
-	ReFungible,
-}
-
-impl CollectionMode {
-	pub fn id(&self) -> u8 {
-		match self {
-			CollectionMode::NFT => 1,
-			CollectionMode::Fungible(_) => 2,
-			CollectionMode::ReFungible => 3,
-		}
-	}
-}
-
-pub trait SponsoringResolve<AccountId, Call> {
-	fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;
-}
-
-#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub enum AccessMode {
-	Normal,
-	AllowList,
-}
-impl Default for AccessMode {
-	fn default() -> Self {
-		Self::Normal
-	}
-}
-
-#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub enum SchemaVersion {
-	ImageURL,
-	Unique,
-}
-impl Default for SchemaVersion {
-	fn default() -> Self {
-		Self::ImageURL
-	}
-}
-
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct Ownership<AccountId> {
-	pub owner: AccountId,
-	pub fraction: u128,
-}
-
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub enum SponsorshipState<AccountId> {
-	/// The fees are applied to the transaction sender
-	Disabled,
-	Unconfirmed(AccountId),
-	/// Transactions are sponsored by specified account
-	Confirmed(AccountId),
-}
-
-impl<AccountId> SponsorshipState<AccountId> {
-	pub fn sponsor(&self) -> Option<&AccountId> {
-		match self {
-			Self::Confirmed(sponsor) => Some(sponsor),
-			_ => None,
-		}
-	}
-
-	pub fn pending_sponsor(&self) -> Option<&AccountId> {
-		match self {
-			Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),
-			_ => None,
-		}
-	}
-
-	pub fn confirmed(&self) -> bool {
-		matches!(self, Self::Confirmed(_))
-	}
-}
-
-impl<T> Default for SponsorshipState<T> {
-	fn default() -> Self {
-		Self::Disabled
-	}
-}
-
-#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct Collection<AccountId> {
-	pub owner: AccountId,
-	pub mode: CollectionMode,
-	pub access: AccessMode,
-	pub name: Vec<u16>,        // 64 include null escape char
-	pub description: Vec<u16>, // 256 include null escape char
-	pub token_prefix: Vec<u8>, // 16 include null escape char
-	pub mint_mode: bool,
-	pub offchain_schema: Vec<u8>,
-	pub schema_version: SchemaVersion,
-	pub sponsorship: SponsorshipState<AccountId>,
-	pub limits: CollectionLimits,          // Collection private restrictions
-	pub variable_on_chain_schema: Vec<u8>, //
-	pub const_on_chain_schema: Vec<u8>,    //
-	pub meta_update_permission: MetaUpdatePermission,
-}
-
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct NftItemType<AccountId> {
-	pub owner: AccountId,
-	pub const_data: Vec<u8>,
-	pub variable_data: Vec<u8>,
-}
-
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct FungibleItemType {
-	pub value: u128,
-}
-
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct ReFungibleItemType<AccountId> {
-	pub owner: Vec<Ownership<AccountId>>,
-	pub const_data: Vec<u8>,
-	pub variable_data: Vec<u8>,
-}
-
-/// All fields are wrapped in `Option`s, where None means chain default
-#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct CollectionLimits {
-	pub account_token_ownership_limit: Option<u32>,
-	pub sponsored_data_size: Option<u32>,
-	/// None - setVariableMetadata is not sponsored
-	/// Some(v) - setVariableMetadata is sponsored
-	///           if there is v block between txs
-	pub sponsored_data_rate_limit: Option<(Option<u32>,)>,
-	pub token_limit: Option<u32>,
-
-	// Timeouts for item types in passed blocks
-	pub sponsor_transfer_timeout: Option<u32>,
-	pub sponsor_approve_timeout: Option<u32>,
-	pub owner_can_transfer: Option<bool>,
-	pub owner_can_destroy: Option<bool>,
-	pub transfers_enabled: Option<bool>,
-}
-
-impl CollectionLimits {
-	pub fn account_token_ownership_limit(&self) -> u32 {
-		self.account_token_ownership_limit
-			.unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)
-			.min(MAX_TOKEN_OWNERSHIP)
-	}
-	pub fn sponsored_data_size(&self) -> u32 {
-		self.sponsored_data_size
-			.unwrap_or(CUSTOM_DATA_LIMIT)
-			.min(CUSTOM_DATA_LIMIT)
-	}
-	pub fn token_limit(&self) -> u32 {
-		self.token_limit
-			.unwrap_or(COLLECTION_TOKEN_LIMIT)
-			.min(COLLECTION_TOKEN_LIMIT)
-	}
-	pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {
-		self.sponsor_transfer_timeout
-			.unwrap_or(default)
-			.min(MAX_SPONSOR_TIMEOUT)
-	}
-	pub fn sponsor_approve_timeout(&self) -> u32 {
-		self.sponsor_approve_timeout
-			.unwrap_or(SPONSOR_APPROVE_TIMEOUT)
-			.min(MAX_SPONSOR_TIMEOUT)
-	}
-	pub fn owner_can_transfer(&self) -> bool {
-		self.owner_can_transfer.unwrap_or(true)
-	}
-	pub fn owner_can_destroy(&self) -> bool {
-		self.owner_can_destroy.unwrap_or(true)
-	}
-	pub fn transfers_enabled(&self) -> bool {
-		self.transfers_enabled.unwrap_or(true)
-	}
-	pub fn sponsored_data_rate_limit(&self) -> Option<u32> {
-		self.sponsored_data_rate_limit
-			.unwrap_or((None,))
-			.0
-			.map(|v| v.min(MAX_SPONSOR_TIMEOUT))
-	}
-}
-
-/// BoundedVec doesn't supports serde
-#[cfg(feature = "serde1")]
-mod bounded_serde {
-	use core::convert::TryFrom;
-	use frame_support::{BoundedVec, traits::Get};
-	use serde::{
-		ser::{self, Serialize},
-		de::{self, Deserialize, Error},
-	};
-	use sp_std::vec::Vec;
-
-	pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>
-	where
-		D: ser::Serializer,
-		V: Serialize,
-	{
-		let vec: &Vec<_> = &value;
-		vec.serialize(serializer)
-	}
-
-	pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>
-	where
-		D: de::Deserializer<'de>,
-		V: de::Deserialize<'de>,
-		S: Get<u32>,
-	{
-		// TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec?
-		let vec = <Vec<V>>::deserialize(deserializer)?;
-		let len = vec.len();
-		TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
-	}
-}
-
-#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-#[derivative(Debug)]
-pub struct CreateNftData {
-	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
-	#[derivative(Debug = "ignore")]
-	pub const_data: BoundedVec<u8, CustomDataLimit>,
-	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
-	#[derivative(Debug = "ignore")]
-	pub variable_data: BoundedVec<u8, CustomDataLimit>,
-}
-
-#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct CreateFungibleData {
-	pub value: u128,
-}
-
-#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-#[derivative(Debug)]
-pub struct CreateReFungibleData {
-	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
-	#[derivative(Debug = "ignore")]
-	pub const_data: BoundedVec<u8, CustomDataLimit>,
-	#[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
-	#[derivative(Debug = "ignore")]
-	pub variable_data: BoundedVec<u8, CustomDataLimit>,
-	pub pieces: u128,
-}
-
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub enum MetaUpdatePermission {
-	ItemOwner,
-	Admin,
-	None,
-}
-
-impl Default for MetaUpdatePermission {
-	fn default() -> Self {
-		Self::ItemOwner
-	}
-}
-
-#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub enum CreateItemData {
-	NFT(CreateNftData),
-	Fungible(CreateFungibleData),
-	ReFungible(CreateReFungibleData),
-}
-
-impl CreateItemData {
-	pub fn data_size(&self) -> usize {
-		match self {
-			CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),
-			CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),
-			_ => 0,
-		}
-	}
-}
-
-impl From<CreateNftData> for CreateItemData {
-	fn from(item: CreateNftData) -> Self {
-		CreateItemData::NFT(item)
-	}
-}
-
-impl From<CreateReFungibleData> for CreateItemData {
-	fn from(item: CreateReFungibleData) -> Self {
-		CreateItemData::ReFungible(item)
-	}
-}
-
-impl From<CreateFungibleData> for CreateItemData {
-	fn from(item: CreateFungibleData) -> Self {
-		CreateItemData::Fungible(item)
-	}
-}
-
-#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct CollectionStats {
-	pub created: u32,
-	pub destroyed: u32,
-	pub alive: u32,
-}
modifiedprimitives/rpc/Cargo.tomldiffbeforeafterboth
--- a/primitives/rpc/Cargo.toml
+++ b/primitives/rpc/Cargo.toml
@@ -5,7 +5,7 @@
 
 [dependencies]
 pallet-common = { default-features = false, path = '../../pallets/common' }
-nft-data-structs = { default-features = false, path = '../nft' }
+up-data-structs = { default-features = false, path = '../data-structs' }
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
 	"derive",
 ] }
@@ -23,5 +23,5 @@
 	"sp-api/std",
 	"sp-runtime/std",
 	"pallet-common/std",
-	"nft-data-structs/std",
+	"up-data-structs/std",
 ]
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -1,12 +1,12 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
-use nft_data_structs::{CollectionId, TokenId, Collection, CollectionStats};
+use up_data_structs::{CollectionId, TokenId, Collection, CollectionStats};
 use sp_std::vec::Vec;
 use sp_core::H160;
 use codec::Decode;
 
 sp_api::decl_runtime_apis! {
-	pub trait NftApi<CrossAccountId, AccountId> where
+	pub trait UniqueApi<CrossAccountId, AccountId> where
 		AccountId: Decode,
 		CrossAccountId: pallet_common::account::CrossAccountId<AccountId>,
 	{
modifiedruntime/Cargo.tomldiffbeforeafterboth
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -4,12 +4,12 @@
 [package]
 authors = ['Unique Network <support@uniquenetwork.io>']
 build = 'build.rs'
-description = 'Substrate node nft'
+description = 'Unique Runtime'
 edition = '2018'
 homepage = 'https://unique.network'
 license = 'All Rights Reserved'
-name = 'nft-runtime'
-repository = 'https://github.com/usetech-llc/nft_private/'
+name = 'unique-runtime'
+repository = 'https://github.com/UniqueNetwork/unique-chain'
 version = '0.9.12'
 
 [package.metadata.docs.rs]
@@ -30,7 +30,7 @@
     'pallet-fungible/runtime-benchmarks',
     'pallet-refungible/runtime-benchmarks',
     'pallet-nonfungible/runtime-benchmarks',
-    'pallet-nft/runtime-benchmarks',
+    'pallet-unique/runtime-benchmarks',
     'pallet-inflation/runtime-benchmarks',
     'pallet-xcm/runtime-benchmarks',
     'sp-runtime/runtime-benchmarks',
@@ -78,10 +78,10 @@
     'pallet-fungible/std',
     'pallet-refungible/std',
     'pallet-nonfungible/std',
-    'pallet-nft/std',
+    'pallet-unique/std',
     'pallet-unq-scheduler/std',
-    'pallet-nft-charge-transaction/std',
-    'nft-data-structs/std',
+    'pallet-charge-transaction/std',
+    'up-data-structs/std',
     'sp-api/std',
     'sp-block-builder/std',
     "sp-consensus-aura/std",
@@ -100,7 +100,7 @@
 
     "orml-vesting/std",
 ]
-limit-testing = ['pallet-nft/limit-testing', 'nft-data-structs/limit-testing']
+limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
 
 ################################################################################
 # Substrate Dependencies
@@ -374,18 +374,18 @@
     "derive",
 ] }
 derivative = "2.2.0"
-pallet-nft = { path = '../pallets/nft', default-features = false, version = '3.0.0' }
+pallet-unique = { path = '../pallets/unique', default-features = false }
 up-rpc = { path = "../primitives/rpc", default-features = false }
 up-evm-mapping = { path = "../primitives/evm-mapping", default-features = false }
-pallet-inflation = { path = '../pallets/inflation', default-features = false, version = '3.0.0' }
-nft-data-structs = { path = '../primitives/nft', default-features = false, version = '0.9.0' }
+pallet-inflation = { path = '../pallets/inflation', default-features = false }
+up-data-structs = { path = '../primitives/data-structs', default-features = false }
 pallet-common = { default-features = false, path = "../pallets/common" }
 pallet-fungible = { default-features = false, path = "../pallets/fungible" }
 pallet-refungible = { default-features = false, path = "../pallets/refungible" }
 pallet-nonfungible = { default-features = false, path = "../pallets/nonfungible" }
-pallet-unq-scheduler = { path = '../pallets/scheduler', default-features = false, version = '3.0.0' }
+pallet-unq-scheduler = { path = '../pallets/scheduler', default-features = false }
 # pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }
-pallet-nft-charge-transaction = { git = "https://github.com/UniqueNetwork/pallet-sponsoring", package = "pallet-template-transaction-payment", default-features = false, version = '3.0.0' }
+pallet-charge-transaction = { git = "https://github.com/UniqueNetwork/pallet-sponsoring", package = "pallet-template-transaction-payment", default-features = false, version = '3.0.0' }
 pallet-evm-migration = { path = '../pallets/evm-migration', default-features = false }
 pallet-evm-contract-helpers = { path = '../pallets/evm-contract-helpers', default-features = false }
 pallet-evm-transaction-payment = { path = '../pallets/evm-transaction-payment', default-features = false }
modifiedruntime/src/lib.rsdiffbeforeafterboth
before · runtime/src/lib.rs
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.78#![cfg_attr(not(feature = "std"), no_std)]9// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.10#![recursion_limit = "1024"]11#![allow(clippy::from_over_into, clippy::identity_op)]12#![allow(clippy::fn_to_numeric_cast_with_truncation)]13// Make the WASM binary available.14#[cfg(feature = "std")]15include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));1617use sp_api::impl_runtime_apis;18use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};19// #[cfg(any(feature = "std", test))]20// pub use sp_runtime::BuildStorage;2122use sp_runtime::{23	Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,24	traits::{25		AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, AccountIdConversion,26	},27	transaction_validity::{TransactionSource, TransactionValidity},28	ApplyExtrinsicResult, MultiSignature,29};3031use sp_std::prelude::*;3233#[cfg(feature = "std")]34use sp_version::NativeVersion;35use sp_version::RuntimeVersion;36pub use pallet_transaction_payment::{37	Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,38};39// A few exports that help ease life for downstream crates.40pub use pallet_balances::Call as BalancesCall;41pub use pallet_evm::{EnsureAddressTruncated, HashedAddressMapping, Runner};42pub use frame_support::{43	construct_runtime, match_type,44	dispatch::DispatchResult,45	PalletId, parameter_types, StorageValue, ConsensusEngineId,46	traits::{47		Everything, Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem,48		LockIdentifier, OnUnbalanced, Randomness, FindAuthor,49	},50	weights::{51		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},52		DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,53		WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients,54	},55};56use nft_data_structs::*;57// use pallet_contracts::weights::WeightInfo;58// #[cfg(any(feature = "std", test))]59use frame_system::{60	self as system, EnsureRoot, EnsureSigned,61	limits::{BlockWeights, BlockLength},62};63use sp_arithmetic::{64	traits::{BaseArithmetic, Unsigned},65};66use smallvec::smallvec;67use codec::{Encode, Decode};68use pallet_evm::{Account as EVMAccount, FeeCalculator, OnMethodCall};69use fp_rpc::TransactionStatus;70use sp_core::crypto::Public;71use sp_runtime::{72	traits::{BlockNumberProvider, Dispatchable, PostDispatchInfoOf},73	transaction_validity::TransactionValidityError,74};7576// pub use pallet_timestamp::Call as TimestampCall;77pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;7879// Polkadot imports80use pallet_xcm::XcmPassthrough;81use polkadot_parachain::primitives::Sibling;82use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};83use xcm_builder::{84	AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,85	EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset,86	ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,87	SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,88	SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,89};90use xcm_executor::{Config, XcmExecutor};9192// mod chain_extension;93// use crate::chain_extension::{NFTExtension, Imbalance};9495/// An index to a block.96pub type BlockNumber = u32;9798/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.99pub type Signature = MultiSignature;100101/// Some way of identifying an account on the chain. We intentionally make it equivalent102/// to the public key of our transaction signing scheme.103pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;104105pub type CrossAccountId = pallet_common::account::BasicCrossAccountId<Runtime>;106107/// The type for looking up accounts. We don't expect more than 4 billion of them, but you108/// never know...109pub type AccountIndex = u32;110111/// Balance of an account.112pub type Balance = u128;113114/// Index of a transaction in the chain.115pub type Index = u32;116117/// A hash of some data used by the chain.118pub type Hash = sp_core::H256;119120/// Digest item type.121pub type DigestItem = generic::DigestItem<Hash>;122123/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know124/// the specifics of the runtime. They can then be made to be agnostic over specific formats125/// of data like extrinsics, allowing for them to continue syncing the network through upgrades126/// to even the core data structures.127pub mod opaque {128	use super::*;129130	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;131132	/// Opaque block type.133	pub type Block = generic::Block<Header, UncheckedExtrinsic>;134135	pub type SessionHandlers = ();136137	impl_opaque_keys! {138		pub struct SessionKeys {139			pub aura: Aura,140		}141	}142}143144/// This runtime version.145pub const VERSION: RuntimeVersion = RuntimeVersion {146	spec_name: create_runtime_str!("opal"),147	impl_name: create_runtime_str!("opal"),148	authoring_version: 1,149	spec_version: 912202,150	impl_version: 1,151	apis: RUNTIME_API_VERSIONS,152	transaction_version: 1,153};154155pub const MILLISECS_PER_BLOCK: u64 = 12000;156157pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;158159// These time units are defined in number of blocks.160pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);161pub const HOURS: BlockNumber = MINUTES * 60;162pub const DAYS: BlockNumber = HOURS * 24;163164parameter_types! {165	pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;166}167168#[derive(codec::Encode, codec::Decode)]169pub enum XCMPMessage<XAccountId, XBalance> {170	/// Transfer tokens to the given account from the Parachain account.171	TransferToken(XAccountId, XBalance),172}173174/// The version information used to identify this runtime when compiled natively.175#[cfg(feature = "std")]176pub fn native_version() -> NativeVersion {177	NativeVersion {178		runtime_version: VERSION,179		can_author_with: Default::default(),180	}181}182183type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;184185pub struct DealWithFees;186impl OnUnbalanced<NegativeImbalance> for DealWithFees {187	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {188		if let Some(fees) = fees_then_tips.next() {189			// for fees, 100% to treasury190			let mut split = fees.ration(100, 0);191			if let Some(tips) = fees_then_tips.next() {192				// for tips, if any, 100% to treasury193				tips.ration_merge_into(100, 0, &mut split);194			}195			Treasury::on_unbalanced(split.0);196			// Author::on_unbalanced(split.1);197		}198	}199}200201/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.202/// This is used to limit the maximal weight of a single extrinsic.203const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);204/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used205/// by  Operational  extrinsics.206const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);207/// We allow for 2 seconds of compute with a 6 second average block time.208const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2;209210parameter_types! {211	pub const BlockHashCount: BlockNumber = 2400;212	pub RuntimeBlockLength: BlockLength =213		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);214	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);215	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;216	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()217		.base_block(BlockExecutionWeight::get())218		.for_class(DispatchClass::all(), |weights| {219			weights.base_extrinsic = ExtrinsicBaseWeight::get();220		})221		.for_class(DispatchClass::Normal, |weights| {222			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);223		})224		.for_class(DispatchClass::Operational, |weights| {225			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);226			// Operational transactions have some extra reserved space, so that they227			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.228			weights.reserved = Some(229				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT230			);231		})232		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)233		.build_or_panic();234	pub const Version: RuntimeVersion = VERSION;235	pub const SS58Prefix: u8 = 42;236}237238parameter_types! {239	pub const ChainId: u64 = 8888;240}241242pub struct FixedFee;243impl FeeCalculator for FixedFee {244	fn min_gas_price() -> U256 {245		1.into()246	}247}248249impl pallet_evm::Config for Runtime {250	type BlockGasLimit = BlockGasLimit;251	type FeeCalculator = FixedFee;252	type GasWeightMapping = ();253	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;254	type CallOrigin = EnsureAddressTruncated;255	type WithdrawOrigin = EnsureAddressTruncated;256	type AddressMapping = HashedAddressMapping<Self::Hashing>;257	type Precompiles = ();258	type Currency = Balances;259	type Event = Event;260	type OnMethodCall = (261		pallet_evm_migration::OnMethodCall<Self>,262		pallet_nft::NftErcSupport<Self>,263		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,264	);265	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;266	type ChainId = ChainId;267	type Runner = pallet_evm::runner::stack::Runner<Self>;268	type OnChargeTransaction = pallet_evm_transaction_payment::OnChargeTransaction<Self>;269	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;270	type FindAuthor = EthereumFindAuthor<Aura>;271}272273impl pallet_evm_migration::Config for Runtime {274	type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;275}276277pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);278impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {279	fn find_author<'a, I>(digests: I) -> Option<H160>280	where281		I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,282	{283		if let Some(author_index) = F::find_author(digests) {284			let authority_id = Aura::authorities()[author_index as usize].clone();285			return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));286		}287		None288	}289}290291parameter_types! {292	pub BlockGasLimit: U256 = U256::from(u32::max_value());293}294295impl pallet_ethereum::Config for Runtime {296	type Event = Event;297	type StateRoot = pallet_ethereum::IntermediateStateRoot;298	type EvmSubmitLog = pallet_evm::Pallet<Self>;299}300301impl pallet_randomness_collective_flip::Config for Runtime {}302303impl system::Config for Runtime {304	/// The data to be stored in an account.305	type AccountData = pallet_balances::AccountData<Balance>;306	/// The identifier used to distinguish between accounts.307	type AccountId = AccountId;308	/// The basic call filter to use in dispatchable.309	type BaseCallFilter = Everything;310	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).311	type BlockHashCount = BlockHashCount;312	/// The maximum length of a block (in bytes).313	type BlockLength = RuntimeBlockLength;314	/// The index type for blocks.315	type BlockNumber = BlockNumber;316	/// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.317	type BlockWeights = RuntimeBlockWeights;318	/// The aggregated dispatch type that is available for extrinsics.319	type Call = Call;320	/// The weight of database operations that the runtime can invoke.321	type DbWeight = RocksDbWeight;322	/// The ubiquitous event type.323	type Event = Event;324	/// The type for hashing blocks and tries.325	type Hash = Hash;326	/// The hashing algorithm used.327	type Hashing = BlakeTwo256;328	/// The header type.329	type Header = generic::Header<BlockNumber, BlakeTwo256>;330	/// The index type for storing how many extrinsics an account has signed.331	type Index = Index;332	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.333	type Lookup = AccountIdLookup<AccountId, ()>;334	/// What to do if an account is fully reaped from the system.335	type OnKilledAccount = ();336	/// What to do if a new account is created.337	type OnNewAccount = ();338	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;339	/// The ubiquitous origin type.340	type Origin = Origin;341	/// This type is being generated by `construct_runtime!`.342	type PalletInfo = PalletInfo;343	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.344	type SS58Prefix = SS58Prefix;345	/// Weight information for the extrinsics of this pallet.346	type SystemWeightInfo = system::weights::SubstrateWeight<Self>;347	/// Version of the runtime.348	type Version = Version;349}350351parameter_types! {352	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;353}354355impl pallet_timestamp::Config for Runtime {356	/// A timestamp: milliseconds since the unix epoch.357	type Moment = u64;358	type OnTimestampSet = ();359	type MinimumPeriod = MinimumPeriod;360	type WeightInfo = ();361}362363parameter_types! {364	// pub const ExistentialDeposit: u128 = 500;365	pub const ExistentialDeposit: u128 = 0;366	pub const MaxLocks: u32 = 50;367}368369impl pallet_balances::Config for Runtime {370	type MaxLocks = MaxLocks;371	type MaxReserves = ();372	type ReserveIdentifier = [u8; 8];373	/// The type for recording an account's balance.374	type Balance = Balance;375	/// The ubiquitous event type.376	type Event = Event;377	type DustRemoval = Treasury;378	type ExistentialDeposit = ExistentialDeposit;379	type AccountStore = System;380	type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;381}382383pub const MICROUNIQUE: Balance = 1_000_000_000;384pub const MILLIUNIQUE: Balance = 1_000 * MICROUNIQUE;385pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE;386pub const UNIQUE: Balance = 100 * CENTIUNIQUE;387388pub const fn deposit(items: u32, bytes: u32) -> Balance {389	items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE390}391392/*393parameter_types! {394	pub TombstoneDeposit: Balance = deposit(395		1,396		sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,397	);398	pub DepositPerContract: Balance = TombstoneDeposit::get();399	pub const DepositPerStorageByte: Balance = deposit(0, 1);400	pub const DepositPerStorageItem: Balance = deposit(1, 0);401	pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);402	pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;403	pub const SignedClaimHandicap: u32 = 2;404	pub const MaxDepth: u32 = 32;405	pub const MaxValueSize: u32 = 16 * 1024;406	pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb407	// The lazy deletion runs inside on_initialize.408	pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *409		RuntimeBlockWeights::get().max_block;410	// The weight needed for decoding the queue should be less or equal than a fifth411	// of the overall weight dedicated to the lazy deletion.412	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (413			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -414			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)415		)) / 5) as u32;416	pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();417}418419impl pallet_contracts::Config for Runtime {420	type Time = Timestamp;421	type Randomness = RandomnessCollectiveFlip;422	type Currency = Balances;423	type Event = Event;424	type RentPayment = ();425	type SignedClaimHandicap = SignedClaimHandicap;426	type TombstoneDeposit = TombstoneDeposit;427	type DepositPerContract = DepositPerContract;428	type DepositPerStorageByte = DepositPerStorageByte;429	type DepositPerStorageItem = DepositPerStorageItem;430	type RentFraction = RentFraction;431	type SurchargeReward = SurchargeReward;432	type WeightPrice = pallet_transaction_payment::Pallet<Self>;433	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;434	type ChainExtension = NFTExtension;435	type DeletionQueueDepth = DeletionQueueDepth;436	type DeletionWeightLimit = DeletionWeightLimit;437	type Schedule = Schedule;438	type CallStack = [pallet_contracts::Frame<Self>; 31];439}440*/441442parameter_types! {443	pub const TransactionByteFee: Balance = 501 * MICROUNIQUE; // Targeting 0.1 Unique per NFT transfer444	/// This value increases the priority of `Operational` transactions by adding445	/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.446	pub const OperationalFeeMultiplier: u8 = 5;447}448449/// Linear implementor of `WeightToFeePolynomial`450pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);451452impl<T> WeightToFeePolynomial for LinearFee<T>453where454	T: BaseArithmetic + From<u32> + Copy + Unsigned,455{456	type Balance = T;457458	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {459		smallvec!(WeightToFeeCoefficient {460			coeff_integer: 146_700u32.into(), // Targeting 0.1 Unique per NFT transfer461			coeff_frac: Perbill::zero(),462			negative: false,463			degree: 1,464		})465	}466}467468impl pallet_transaction_payment::Config for Runtime {469	type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;470	type TransactionByteFee = TransactionByteFee;471	type OperationalFeeMultiplier = OperationalFeeMultiplier;472	type WeightToFee = LinearFee<Balance>;473	type FeeMultiplierUpdate = ();474}475476parameter_types! {477	pub const ProposalBond: Permill = Permill::from_percent(5);478	pub const ProposalBondMinimum: Balance = 1 * UNIQUE;479	pub const SpendPeriod: BlockNumber = 5 * MINUTES;480	pub const Burn: Permill = Permill::from_percent(0);481	pub const TipCountdown: BlockNumber = 1 * DAYS;482	pub const TipFindersFee: Percent = Percent::from_percent(20);483	pub const TipReportDepositBase: Balance = 1 * UNIQUE;484	pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;485	pub const BountyDepositBase: Balance = 1 * UNIQUE;486	pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;487	pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");488	pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;489	pub const MaximumReasonLength: u32 = 16384;490	pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);491	pub const BountyValueMinimum: Balance = 5 * UNIQUE;492	pub const MaxApprovals: u32 = 100;493}494495impl pallet_treasury::Config for Runtime {496	type PalletId = TreasuryModuleId;497	type Currency = Balances;498	type ApproveOrigin = EnsureRoot<AccountId>;499	type RejectOrigin = EnsureRoot<AccountId>;500	type Event = Event;501	type OnSlash = ();502	type ProposalBond = ProposalBond;503	type ProposalBondMinimum = ProposalBondMinimum;504	type SpendPeriod = SpendPeriod;505	type Burn = Burn;506	type BurnDestination = ();507	type SpendFunds = ();508	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;509	type MaxApprovals = MaxApprovals;510}511512impl pallet_sudo::Config for Runtime {513	type Event = Event;514	type Call = Call;515}516517pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);518519impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider520	for RelayChainBlockNumberProvider<T>521{522	type BlockNumber = BlockNumber;523524	fn current_block_number() -> Self::BlockNumber {525		cumulus_pallet_parachain_system::Pallet::<T>::validation_data()526			.map(|d| d.relay_parent_number)527			.unwrap_or_default()528	}529}530531parameter_types! {532	pub const MinVestedTransfer: Balance = 10 * UNIQUE;533	pub const MaxVestingSchedules: u32 = 28;534}535536impl orml_vesting::Config for Runtime {537	type Event = Event;538	type Currency = pallet_balances::Pallet<Runtime>;539	type MinVestedTransfer = MinVestedTransfer;540	type VestedTransferOrigin = EnsureSigned<AccountId>;541	type WeightInfo = ();542	type MaxVestingSchedules = MaxVestingSchedules;543	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;544}545546parameter_types! {547	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;548	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;549}550551impl cumulus_pallet_parachain_system::Config for Runtime {552	type Event = Event;553	type OnValidationData = ();554	type SelfParaId = parachain_info::Pallet<Self>;555	// type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<556	// 	MaxDownwardMessageWeight,557	// 	XcmExecutor<XcmConfig>,558	// 	Call,559	// >;560	type OutboundXcmpMessageSource = XcmpQueue;561	type DmpMessageHandler = DmpQueue;562	type ReservedDmpWeight = ReservedDmpWeight;563	type ReservedXcmpWeight = ReservedXcmpWeight;564	type XcmpMessageHandler = XcmpQueue;565}566567impl parachain_info::Config for Runtime {}568569impl cumulus_pallet_aura_ext::Config for Runtime {}570571parameter_types! {572	pub const RelayLocation: MultiLocation = MultiLocation::parent();573	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;574	pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();575	pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();576}577578/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used579/// when determining ownership of accounts for asset transacting and when attempting to use XCM580/// `Transact` in order to determine the dispatch Origin.581pub type LocationToAccountId = (582	// The parent (Relay-chain) origin converts to the default `AccountId`.583	ParentIsDefault<AccountId>,584	// Sibling parachain origins convert to AccountId via the `ParaId::into`.585	SiblingParachainConvertsVia<Sibling, AccountId>,586	// Straight up local `AccountId32` origins just alias directly to `AccountId`.587	AccountId32Aliases<RelayNetwork, AccountId>,588);589590/// Means for transacting assets on this chain.591pub type LocalAssetTransactor = CurrencyAdapter<592	// Use this currency:593	Balances,594	// Use this currency when it is a fungible asset matching the given location or name:595	IsConcrete<RelayLocation>,596	// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:597	LocationToAccountId,598	// Our chain's account ID type (we can't get away without mentioning it explicitly):599	AccountId,600	// We don't track any teleports.601	(),602>;603604/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,605/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can606/// biases the kind of local `Origin` it will become.607pub type XcmOriginToTransactDispatchOrigin = (608	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location609	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for610	// foreign chains who want to have a local sovereign account on this chain which they control.611	SovereignSignedViaLocation<LocationToAccountId, Origin>,612	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when613	// recognised.614	RelayChainAsNative<RelayOrigin, Origin>,615	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when616	// recognised.617	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,618	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a619	// transaction from the Root origin.620	ParentAsSuperuser<Origin>,621	// Native signed account converter; this just converts an `AccountId32` origin into a normal622	// `Origin::Signed` origin of the same 32-byte value.623	SignedAccountId32AsNative<RelayNetwork, Origin>,624	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.625	XcmPassthrough<Origin>,626);627628parameter_types! {629	// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.630	pub UnitWeightCost: Weight = 1_000_000;631	// 1200 UNIQUEs buy 1 second of weight.632	pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);633	pub const MaxInstructions: u32 = 100;634	pub const MaxAuthorities: u32 = 100_000;635}636637match_type! {638	pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {639		MultiLocation { parents: 1, interior: Here } |640		MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }641	};642}643644pub type Barrier = (645	TakeWeightCredit,646	AllowTopLevelPaidExecutionFrom<Everything>,647	AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,648	// ^^^ Parent & its unit plurality gets free execution649);650651pub struct XcmConfig;652impl Config for XcmConfig {653	type Call = Call;654	type XcmSender = XcmRouter;655	// How to withdraw and deposit an asset.656	type AssetTransactor = LocalAssetTransactor;657	type OriginConverter = XcmOriginToTransactDispatchOrigin;658	type IsReserve = NativeAsset;659	type IsTeleporter = (); // Teleportation is disabled660	type LocationInverter = LocationInverter<Ancestry>;661	type Barrier = Barrier;662	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;663	type Trader = UsingComponents<IdentityFee<Balance>, RelayLocation, AccountId, Balances, ()>;664	type ResponseHandler = (); // Don't handle responses for now.665	type SubscriptionService = PolkadotXcm;666667	type AssetTrap = PolkadotXcm;668	type AssetClaims = PolkadotXcm;669}670671// parameter_types! {672// 	pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;673// }674675/// No local origins on this chain are allowed to dispatch XCM sends/executions.676pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);677678/// The means for routing XCM messages which are not for local execution into the right message679/// queues.680pub type XcmRouter = (681	// Two routers - use UMP to communicate with the relay chain:682	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,683	// ..and XCMP to communicate with the sibling chains.684	XcmpQueue,685);686687impl pallet_evm_coder_substrate::Config for Runtime {688	type EthereumTransactionSender = pallet_ethereum::Pallet<Self>;689}690691impl pallet_xcm::Config for Runtime {692	type Event = Event;693	type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;694	type XcmRouter = XcmRouter;695	type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;696	type XcmExecuteFilter = Everything;697	type XcmExecutor = XcmExecutor<XcmConfig>;698	type XcmTeleportFilter = Everything;699	type XcmReserveTransferFilter = Everything;700	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;701	type LocationInverter = LocationInverter<Ancestry>;702	type Origin = Origin;703	type Call = Call;704	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;705	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;706}707708impl cumulus_pallet_xcm::Config for Runtime {709	type Event = Event;710	type XcmExecutor = XcmExecutor<XcmConfig>;711}712713impl cumulus_pallet_xcmp_queue::Config for Runtime {714	type Event = Event;715	type XcmExecutor = XcmExecutor<XcmConfig>;716	type ChannelInfo = ParachainSystem;717	type VersionWrapper = ();718}719720impl cumulus_pallet_dmp_queue::Config for Runtime {721	type Event = Event;722	type XcmExecutor = XcmExecutor<XcmConfig>;723	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;724}725726impl pallet_aura::Config for Runtime {727	type AuthorityId = AuraId;728	type DisabledValidators = ();729	type MaxAuthorities = MaxAuthorities;730}731732parameter_types! {733	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();734	pub const CollectionCreationPrice: Balance = 100 * UNIQUE;735}736737impl pallet_common::Config for Runtime {738	type Event = Event;739	type EvmBackwardsAddressMapping = up_evm_mapping::MapBackwardsAddressTruncated;740	type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;741	type CrossAccountId = pallet_common::account::BasicCrossAccountId<Self>;742743	type Currency = Balances;744	type CollectionCreationPrice = CollectionCreationPrice;745	type TreasuryAccountId = TreasuryAccountId;746}747748impl pallet_fungible::Config for Runtime {749	type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;750}751impl pallet_refungible::Config for Runtime {752	type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;753}754impl pallet_nonfungible::Config for Runtime {755	type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;756}757758/// Used for the pallet nft in `./nft.rs`759impl pallet_nft::Config for Runtime {760	type WeightInfo = pallet_nft::weights::SubstrateWeight<Self>;761}762763parameter_types! {764	pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied765}766767/// Used for the pallet inflation768impl pallet_inflation::Config for Runtime {769	type Currency = Balances;770	type TreasuryAccountId = TreasuryAccountId;771	type InflationBlockInterval = InflationBlockInterval;772}773774// parameter_types! {775// 	pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *776// 		RuntimeBlockWeights::get().max_block;777// 	pub const MaxScheduledPerBlock: u32 = 50;778// }779780type EvmSponsorshipHandler = (781	pallet_nft::NftEthSponsorshipHandler<Runtime>,782	pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,783);784type SponsorshipHandler = (785	pallet_nft::NftSponsorshipHandler<Runtime>,786	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,787	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,788);789790// impl pallet_unq_scheduler::Config for Runtime {791// 	type Event = Event;792// 	type Origin = Origin;793// 	type PalletsOrigin = OriginCaller;794// 	type Call = Call;795// 	type MaximumWeight = MaximumSchedulerWeight;796// 	type ScheduleOrigin = EnsureSigned<AccountId>;797// 	type MaxScheduledPerBlock = MaxScheduledPerBlock;798// 	type SponsorshipHandler = SponsorshipHandler;799// 	type WeightInfo = ();800// }801802impl pallet_evm_transaction_payment::Config for Runtime {803	type EvmSponsorshipHandler = EvmSponsorshipHandler;804	type Currency = Balances;805	type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;806	type EvmBackwardsAddressMapping = up_evm_mapping::MapBackwardsAddressTruncated;807}808809impl pallet_nft_charge_transaction::Config for Runtime {810	type SponsorshipHandler = SponsorshipHandler;811}812813// impl pallet_contract_helpers::Config for Runtime {814//	 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;815// }816817parameter_types! {818	// 0x842899ECF380553E8a4de75bF534cdf6fBF64049819	pub const HelpersContractAddress: H160 = H160([820		0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,821	]);822}823824impl pallet_evm_contract_helpers::Config for Runtime {825	type ContractAddress = HelpersContractAddress;826	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;827}828829construct_runtime!(830	pub enum Runtime where831		Block = Block,832		NodeBlock = opaque::Block,833		UncheckedExtrinsic = UncheckedExtrinsic834	{835		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,836		ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,837838		Aura: pallet_aura::{Pallet, Config<T>} = 22,839		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,840841		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,842		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,843		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,844		TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,845		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,846		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,847		System: system::{Pallet, Call, Storage, Config, Event<T>} = 36,848		Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,849		// Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,850		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,851852		// XCM helpers.853		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,854		PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,855		CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,856		DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,857858		// Unique Pallets859		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,860		Nft: pallet_nft::{Pallet, Call, Storage} = 61,861		// Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,862		// free = 63863		Charging: pallet_nft_charge_transaction::{Pallet, Call, Storage } = 64,864		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,865		Common: pallet_common::{Pallet, Storage, Event<T>} = 66,866		Fungible: pallet_fungible::{Pallet, Storage} = 67,867		Refungible: pallet_refungible::{Pallet, Storage} = 68,868		Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,869870		// Frontier871		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,872		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,873874		EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,875		EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,876		EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,877		EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,878	}879);880881pub struct TransactionConverter;882883impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {884	fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {885		UncheckedExtrinsic::new_unsigned(886			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),887		)888	}889}890891impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {892	fn convert_transaction(893		&self,894		transaction: pallet_ethereum::Transaction,895	) -> opaque::UncheckedExtrinsic {896		let extrinsic = UncheckedExtrinsic::new_unsigned(897			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),898		);899		let encoded = extrinsic.encode();900		opaque::UncheckedExtrinsic::decode(&mut &encoded[..])901			.expect("Encoded extrinsic is always valid")902	}903}904905/// The address format for describing accounts.906pub type Address = sp_runtime::MultiAddress<AccountId, ()>;907/// Block header type as expected by this runtime.908pub type Header = generic::Header<BlockNumber, BlakeTwo256>;909/// Block type as expected by this runtime.910pub type Block = generic::Block<Header, UncheckedExtrinsic>;911/// A Block signed with a Justification912pub type SignedBlock = generic::SignedBlock<Block>;913/// BlockId type as expected by this runtime.914pub type BlockId = generic::BlockId<Block>;915/// The SignedExtension to the basic transaction logic.916pub type SignedExtra = (917	system::CheckSpecVersion<Runtime>,918	// system::CheckTxVersion<Runtime>,919	system::CheckGenesis<Runtime>,920	system::CheckEra<Runtime>,921	system::CheckNonce<Runtime>,922	system::CheckWeight<Runtime>,923	pallet_nft_charge_transaction::ChargeTransactionPayment<Runtime>,924	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,925);926/// Unchecked extrinsic type as expected by this runtime.927pub type UncheckedExtrinsic =928	fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;929/// Extrinsic type that has already been checked.930pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;931/// Executive: handles dispatch to the various modules.932pub type Executive = frame_executive::Executive<933	Runtime,934	Block,935	frame_system::ChainContext<Runtime>,936	Runtime,937	AllPallets,938>;939940impl_opaque_keys! {941	pub struct SessionKeys {942		pub aura: Aura,943	}944}945946impl fp_self_contained::SelfContainedCall for Call {947	type SignedInfo = H160;948949	fn is_self_contained(&self) -> bool {950		match self {951			Call::Ethereum(call) => call.is_self_contained(),952			_ => false,953		}954	}955956	fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {957		match self {958			Call::Ethereum(call) => call.check_self_contained(),959			_ => None,960		}961	}962963	fn validate_self_contained(&self, info: &Self::SignedInfo) -> Option<TransactionValidity> {964		match self {965			Call::Ethereum(call) => call.validate_self_contained(info),966			_ => None,967		}968	}969970	fn pre_dispatch_self_contained(971		&self,972		info: &Self::SignedInfo,973	) -> Option<Result<(), TransactionValidityError>> {974		match self {975			Call::Ethereum(call) => call.pre_dispatch_self_contained(info),976			_ => None,977		}978	}979980	fn apply_self_contained(981		self,982		info: Self::SignedInfo,983	) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {984		match self {985			call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(986				Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),987			)),988			_ => None,989		}990	}991}992993macro_rules! dispatch_nft_runtime {994	($collection:ident.$method:ident($($name:ident),*)) => {{995		use pallet_nft::dispatch::Dispatched;996997		let collection = Dispatched::dispatch(<pallet_common::CollectionHandle<Runtime>>::new($collection).unwrap());998		let dispatch = collection.as_dyn();9991000		dispatch.$method($($name),*)1001	}};1002}1003impl_runtime_apis! {1004	impl up_rpc::NftApi<Block, CrossAccountId, AccountId>1005		for Runtime1006	{1007		fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId> {1008			dispatch_nft_runtime!(collection.account_tokens(account))1009		}1010		fn token_exists(collection: CollectionId, token: TokenId) -> bool {1011			dispatch_nft_runtime!(collection.token_exists(token))1012		}10131014		fn token_owner(collection: CollectionId, token: TokenId) -> CrossAccountId {1015			dispatch_nft_runtime!(collection.token_owner(token))1016		}1017		fn const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8> {1018			dispatch_nft_runtime!(collection.const_metadata(token))1019		}1020		fn variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8> {1021			dispatch_nft_runtime!(collection.variable_metadata(token))1022		}10231024		fn collection_tokens(collection: CollectionId) -> u32 {1025			dispatch_nft_runtime!(collection.collection_tokens())1026		}1027		fn account_balance(collection: CollectionId, account: CrossAccountId) -> u32 {1028			dispatch_nft_runtime!(collection.account_balance(account))1029		}1030		fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> u128 {1031			dispatch_nft_runtime!(collection.balance(account, token))1032		}1033		fn allowance(1034			collection: CollectionId,1035			sender: CrossAccountId,1036			spender: CrossAccountId,1037			token: TokenId,1038		) -> u128 {1039			dispatch_nft_runtime!(collection.allowance(sender, spender, token))1040		}10411042		fn eth_contract_code(account: H160) -> Option<Vec<u8>> {1043			<pallet_nft::NftErcSupport<Runtime>>::get_code(&account)1044				.or_else(|| <pallet_evm_migration::OnMethodCall<Runtime>>::get_code(&account))1045				.or_else(|| <pallet_evm_contract_helpers::HelpersOnMethodCall<Self>>::get_code(&account))1046		}1047		fn adminlist(collection: CollectionId) -> Vec<CrossAccountId> {1048			<pallet_common::Pallet<Runtime>>::adminlist(collection)1049		}1050		fn allowlist(collection: CollectionId) -> Vec<CrossAccountId> {1051			<pallet_common::Pallet<Runtime>>::allowlist(collection)1052		}1053		fn allowed(collection: CollectionId, user: CrossAccountId) -> bool {1054			<pallet_common::Pallet<Runtime>>::allowed(collection, user)1055		}1056		fn last_token_id(collection: CollectionId) -> TokenId {1057			dispatch_nft_runtime!(collection.last_token_id())1058		}1059		fn collection_by_id(collection: CollectionId) -> Option<Collection<AccountId>> {1060			<pallet_common::CollectionById<Runtime>>::get(collection)1061		}1062		fn collection_stats() -> CollectionStats {1063			<pallet_common::Pallet<Runtime>>::collection_stats()1064		}1065	}10661067	impl sp_api::Core<Block> for Runtime {1068		fn version() -> RuntimeVersion {1069			VERSION1070		}10711072		fn execute_block(block: Block) {1073			Executive::execute_block(block)1074		}10751076		fn initialize_block(header: &<Block as BlockT>::Header) {1077			Executive::initialize_block(header)1078		}1079	}10801081	impl sp_api::Metadata<Block> for Runtime {1082		fn metadata() -> OpaqueMetadata {1083			OpaqueMetadata::new(Runtime::metadata().into())1084		}1085	}10861087	impl sp_block_builder::BlockBuilder<Block> for Runtime {1088		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {1089			Executive::apply_extrinsic(extrinsic)1090		}10911092		fn finalize_block() -> <Block as BlockT>::Header {1093			Executive::finalize_block()1094		}10951096		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {1097			data.create_extrinsics()1098		}10991100		fn check_inherents(1101			block: Block,1102			data: sp_inherents::InherentData,1103		) -> sp_inherents::CheckInherentsResult {1104			data.check_extrinsics(&block)1105		}11061107		// fn random_seed() -> <Block as BlockT>::Hash {1108		//     RandomnessCollectiveFlip::random_seed().01109		// }1110	}11111112	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {1113		fn validate_transaction(1114			source: TransactionSource,1115			tx: <Block as BlockT>::Extrinsic,1116			hash: <Block as BlockT>::Hash,1117		) -> TransactionValidity {1118			Executive::validate_transaction(source, tx, hash)1119		}1120	}11211122	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {1123		fn offchain_worker(header: &<Block as BlockT>::Header) {1124			Executive::offchain_worker(header)1125		}1126	}11271128	impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {1129		fn chain_id() -> u64 {1130			<Runtime as pallet_evm::Config>::ChainId::get()1131		}11321133		fn account_basic(address: H160) -> EVMAccount {1134			EVM::account_basic(&address)1135		}11361137		fn gas_price() -> U256 {1138			<Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price()1139		}11401141		fn account_code_at(address: H160) -> Vec<u8> {1142			EVM::account_codes(address)1143		}11441145		fn author() -> H160 {1146			<pallet_evm::Pallet<Runtime>>::find_author()1147		}11481149		fn storage_at(address: H160, index: U256) -> H256 {1150			let mut tmp = [0u8; 32];1151			index.to_big_endian(&mut tmp);1152			EVM::account_storages(address, H256::from_slice(&tmp[..]))1153		}11541155		fn call(1156			from: H160,1157			to: H160,1158			data: Vec<u8>,1159			value: U256,1160			gas_limit: U256,1161			gas_price: Option<U256>,1162			nonce: Option<U256>,1163			estimate: bool,1164		) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {1165			let config = if estimate {1166				let mut config = <Runtime as pallet_evm::Config>::config().clone();1167				config.estimate = true;1168				Some(config)1169			} else {1170				None1171			};11721173			<Runtime as pallet_evm::Config>::Runner::call(1174				from,1175				to,1176				data,1177				value,1178				gas_limit.low_u64(),1179				gas_price,1180				nonce,1181				config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),1182			).map_err(|err| err.into())1183		}11841185		fn create(1186			from: H160,1187			data: Vec<u8>,1188			value: U256,1189			gas_limit: U256,1190			gas_price: Option<U256>,1191			nonce: Option<U256>,1192			estimate: bool,1193		) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {1194			let config = if estimate {1195				let mut config = <Runtime as pallet_evm::Config>::config().clone();1196				config.estimate = true;1197				Some(config)1198			} else {1199				None1200			};12011202			<Runtime as pallet_evm::Config>::Runner::create(1203				from,1204				data,1205				value,1206				gas_limit.low_u64(),1207				gas_price,1208				nonce,1209				config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),1210			).map_err(|err| err.into())1211		}12121213		fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {1214			Ethereum::current_transaction_statuses()1215		}12161217		fn current_block() -> Option<pallet_ethereum::Block> {1218			Ethereum::current_block()1219		}12201221		fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {1222			Ethereum::current_receipts()1223		}12241225		fn current_all() -> (1226			Option<pallet_ethereum::Block>,1227			Option<Vec<pallet_ethereum::Receipt>>,1228			Option<Vec<TransactionStatus>>1229		) {1230			(1231				Ethereum::current_block(),1232				Ethereum::current_receipts(),1233				Ethereum::current_transaction_statuses()1234			)1235		}12361237		fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {1238			xts.into_iter().filter_map(|xt| match xt.0.function {1239				Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),1240				_ => None1241			}).collect()1242		}1243	}12441245	impl sp_session::SessionKeys<Block> for Runtime {1246		fn decode_session_keys(1247			encoded: Vec<u8>,1248		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {1249			SessionKeys::decode_into_raw_public_keys(&encoded)1250		}12511252		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {1253			SessionKeys::generate(seed)1254		}1255	}12561257	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {1258		fn slot_duration() -> sp_consensus_aura::SlotDuration {1259			sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())1260		}12611262		fn authorities() -> Vec<AuraId> {1263			Aura::authorities().to_vec()1264		}1265	}12661267	impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {1268		fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {1269			ParachainSystem::collect_collation_info()1270		}1271	}12721273	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {1274		fn account_nonce(account: AccountId) -> Index {1275			System::account_nonce(account)1276		}1277	}12781279	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {1280		fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {1281			TransactionPayment::query_info(uxt, len)1282		}1283		fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {1284			TransactionPayment::query_fee_details(uxt, len)1285		}1286	}12871288	/*1289	impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>1290		for Runtime1291	{1292		fn call(1293			origin: AccountId,1294			dest: AccountId,1295			value: Balance,1296			gas_limit: u64,1297			input_data: Vec<u8>,1298		) -> pallet_contracts_primitives::ContractExecResult {1299			Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)1300		}13011302		fn instantiate(1303			origin: AccountId,1304			endowment: Balance,1305			gas_limit: u64,1306			code: pallet_contracts_primitives::Code<Hash>,1307			data: Vec<u8>,1308			salt: Vec<u8>,1309		) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>1310		{1311			Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)1312		}13131314		fn get_storage(1315			address: AccountId,1316			key: [u8; 32],1317		) -> pallet_contracts_primitives::GetStorageResult {1318			Contracts::get_storage(address, key)1319		}13201321		fn rent_projection(1322			address: AccountId,1323		) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {1324			Contracts::rent_projection(address)1325		}1326	}1327	*/13281329	#[cfg(feature = "runtime-benchmarks")]1330	impl frame_benchmarking::Benchmark<Block> for Runtime {1331		fn benchmark_metadata(extra: bool) -> (1332			Vec<frame_benchmarking::BenchmarkList>,1333			Vec<frame_support::traits::StorageInfo>,1334		) {1335			use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};1336			use frame_support::traits::StorageInfoTrait;13371338			let mut list = Vec::<BenchmarkList>::new();13391340			list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);1341			list_benchmark!(list, extra, pallet_nft, Nft);1342			list_benchmark!(list, extra, pallet_inflation, Inflation);1343			list_benchmark!(list, extra, pallet_fungible, Fungible);1344			list_benchmark!(list, extra, pallet_refungible, Refungible);1345			list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);13461347			let storage_info = AllPalletsWithSystem::storage_info();13481349			return (list, storage_info)1350		}13511352		fn dispatch_benchmark(1353			config: frame_benchmarking::BenchmarkConfig1354		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {1355			use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};13561357			let allowlist: Vec<TrackedStorageKey> = vec![1358				// Block Number1359				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),1360				// Total Issuance1361				hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),1362				// Execution Phase1363				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),1364				// Event Count1365				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),1366				// System Events1367				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),1368			];13691370			let mut batches = Vec::<BenchmarkBatch>::new();1371			let params = (&config, &allowlist);13721373			add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);1374			add_benchmark!(params, batches, pallet_nft, Nft);1375			add_benchmark!(params, batches, pallet_inflation, Inflation);1376			add_benchmark!(params, batches, pallet_fungible, Fungible);1377			add_benchmark!(params, batches, pallet_refungible, Refungible);1378			add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);13791380			if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }1381			Ok(batches)1382		}1383	}1384}13851386struct CheckInherents;13871388impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1389	fn check_inherents(1390		block: &Block,1391		relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1392	) -> sp_inherents::CheckInherentsResult {1393		let relay_chain_slot = relay_state_proof1394			.read_slot()1395			.expect("Could not read the relay chain slot from the proof");13961397		let inherent_data =1398			cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1399				relay_chain_slot,1400				sp_std::time::Duration::from_secs(6),1401			)1402			.create_inherent_data()1403			.expect("Could not create the timestamp inherent data");14041405		inherent_data.check_extrinsics(block)1406	}1407}14081409cumulus_pallet_parachain_system::register_validate_block!(1410	Runtime = Runtime,1411	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,1412	CheckInherents = CheckInherents,1413);
after · runtime/src/lib.rs
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.78#![cfg_attr(not(feature = "std"), no_std)]9// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.10#![recursion_limit = "1024"]11#![allow(clippy::from_over_into, clippy::identity_op)]12#![allow(clippy::fn_to_numeric_cast_with_truncation)]13// Make the WASM binary available.14#[cfg(feature = "std")]15include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));1617use sp_api::impl_runtime_apis;18use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};19// #[cfg(any(feature = "std", test))]20// pub use sp_runtime::BuildStorage;2122use sp_runtime::{23	Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,24	traits::{25		AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, AccountIdConversion,26	},27	transaction_validity::{TransactionSource, TransactionValidity},28	ApplyExtrinsicResult, MultiSignature,29};3031use sp_std::prelude::*;3233#[cfg(feature = "std")]34use sp_version::NativeVersion;35use sp_version::RuntimeVersion;36pub use pallet_transaction_payment::{37	Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,38};39// A few exports that help ease life for downstream crates.40pub use pallet_balances::Call as BalancesCall;41pub use pallet_evm::{EnsureAddressTruncated, HashedAddressMapping, Runner};42pub use frame_support::{43	construct_runtime, match_type,44	dispatch::DispatchResult,45	PalletId, parameter_types, StorageValue, ConsensusEngineId,46	traits::{47		Everything, Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem,48		LockIdentifier, OnUnbalanced, Randomness, FindAuthor,49	},50	weights::{51		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},52		DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,53		WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients,54	},55};56use up_data_structs::*;57// use pallet_contracts::weights::WeightInfo;58// #[cfg(any(feature = "std", test))]59use frame_system::{60	self as system, EnsureRoot, EnsureSigned,61	limits::{BlockWeights, BlockLength},62};63use sp_arithmetic::{64	traits::{BaseArithmetic, Unsigned},65};66use smallvec::smallvec;67use codec::{Encode, Decode};68use pallet_evm::{Account as EVMAccount, FeeCalculator, OnMethodCall};69use fp_rpc::TransactionStatus;70use sp_core::crypto::Public;71use sp_runtime::{72	traits::{BlockNumberProvider, Dispatchable, PostDispatchInfoOf},73	transaction_validity::TransactionValidityError,74};7576// pub use pallet_timestamp::Call as TimestampCall;77pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;7879// Polkadot imports80use pallet_xcm::XcmPassthrough;81use polkadot_parachain::primitives::Sibling;82use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};83use xcm_builder::{84	AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,85	EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset,86	ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,87	SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,88	SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,89};90use xcm_executor::{Config, XcmExecutor};9192// mod chain_extension;93// use crate::chain_extension::{NFTExtension, Imbalance};9495/// An index to a block.96pub type BlockNumber = u32;9798/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.99pub type Signature = MultiSignature;100101/// Some way of identifying an account on the chain. We intentionally make it equivalent102/// to the public key of our transaction signing scheme.103pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;104105pub type CrossAccountId = pallet_common::account::BasicCrossAccountId<Runtime>;106107/// The type for looking up accounts. We don't expect more than 4 billion of them, but you108/// never know...109pub type AccountIndex = u32;110111/// Balance of an account.112pub type Balance = u128;113114/// Index of a transaction in the chain.115pub type Index = u32;116117/// A hash of some data used by the chain.118pub type Hash = sp_core::H256;119120/// Digest item type.121pub type DigestItem = generic::DigestItem<Hash>;122123/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know124/// the specifics of the runtime. They can then be made to be agnostic over specific formats125/// of data like extrinsics, allowing for them to continue syncing the network through upgrades126/// to even the core data structures.127pub mod opaque {128	use super::*;129130	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;131132	/// Opaque block type.133	pub type Block = generic::Block<Header, UncheckedExtrinsic>;134135	pub type SessionHandlers = ();136137	impl_opaque_keys! {138		pub struct SessionKeys {139			pub aura: Aura,140		}141	}142}143144/// This runtime version.145pub const VERSION: RuntimeVersion = RuntimeVersion {146	spec_name: create_runtime_str!("opal"),147	impl_name: create_runtime_str!("opal"),148	authoring_version: 1,149	spec_version: 912202,150	impl_version: 1,151	apis: RUNTIME_API_VERSIONS,152	transaction_version: 1,153};154155pub const MILLISECS_PER_BLOCK: u64 = 12000;156157pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;158159// These time units are defined in number of blocks.160pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);161pub const HOURS: BlockNumber = MINUTES * 60;162pub const DAYS: BlockNumber = HOURS * 24;163164parameter_types! {165	pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;166}167168#[derive(codec::Encode, codec::Decode)]169pub enum XCMPMessage<XAccountId, XBalance> {170	/// Transfer tokens to the given account from the Parachain account.171	TransferToken(XAccountId, XBalance),172}173174/// The version information used to identify this runtime when compiled natively.175#[cfg(feature = "std")]176pub fn native_version() -> NativeVersion {177	NativeVersion {178		runtime_version: VERSION,179		can_author_with: Default::default(),180	}181}182183type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;184185pub struct DealWithFees;186impl OnUnbalanced<NegativeImbalance> for DealWithFees {187	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {188		if let Some(fees) = fees_then_tips.next() {189			// for fees, 100% to treasury190			let mut split = fees.ration(100, 0);191			if let Some(tips) = fees_then_tips.next() {192				// for tips, if any, 100% to treasury193				tips.ration_merge_into(100, 0, &mut split);194			}195			Treasury::on_unbalanced(split.0);196			// Author::on_unbalanced(split.1);197		}198	}199}200201/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.202/// This is used to limit the maximal weight of a single extrinsic.203const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);204/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used205/// by  Operational  extrinsics.206const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);207/// We allow for 2 seconds of compute with a 6 second average block time.208const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2;209210parameter_types! {211	pub const BlockHashCount: BlockNumber = 2400;212	pub RuntimeBlockLength: BlockLength =213		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);214	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);215	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;216	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()217		.base_block(BlockExecutionWeight::get())218		.for_class(DispatchClass::all(), |weights| {219			weights.base_extrinsic = ExtrinsicBaseWeight::get();220		})221		.for_class(DispatchClass::Normal, |weights| {222			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);223		})224		.for_class(DispatchClass::Operational, |weights| {225			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);226			// Operational transactions have some extra reserved space, so that they227			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.228			weights.reserved = Some(229				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT230			);231		})232		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)233		.build_or_panic();234	pub const Version: RuntimeVersion = VERSION;235	pub const SS58Prefix: u8 = 42;236}237238parameter_types! {239	pub const ChainId: u64 = 8888;240}241242pub struct FixedFee;243impl FeeCalculator for FixedFee {244	fn min_gas_price() -> U256 {245		1.into()246	}247}248249impl pallet_evm::Config for Runtime {250	type BlockGasLimit = BlockGasLimit;251	type FeeCalculator = FixedFee;252	type GasWeightMapping = ();253	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;254	type CallOrigin = EnsureAddressTruncated;255	type WithdrawOrigin = EnsureAddressTruncated;256	type AddressMapping = HashedAddressMapping<Self::Hashing>;257	type Precompiles = ();258	type Currency = Balances;259	type Event = Event;260	type OnMethodCall = (261		pallet_evm_migration::OnMethodCall<Self>,262		pallet_unique::UniqueErcSupport<Self>,263		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,264	);265	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;266	type ChainId = ChainId;267	type Runner = pallet_evm::runner::stack::Runner<Self>;268	type OnChargeTransaction = pallet_evm_transaction_payment::OnChargeTransaction<Self>;269	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;270	type FindAuthor = EthereumFindAuthor<Aura>;271}272273impl pallet_evm_migration::Config for Runtime {274	type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;275}276277pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);278impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {279	fn find_author<'a, I>(digests: I) -> Option<H160>280	where281		I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,282	{283		if let Some(author_index) = F::find_author(digests) {284			let authority_id = Aura::authorities()[author_index as usize].clone();285			return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));286		}287		None288	}289}290291parameter_types! {292	pub BlockGasLimit: U256 = U256::from(u32::max_value());293}294295impl pallet_ethereum::Config for Runtime {296	type Event = Event;297	type StateRoot = pallet_ethereum::IntermediateStateRoot;298	type EvmSubmitLog = pallet_evm::Pallet<Self>;299}300301impl pallet_randomness_collective_flip::Config for Runtime {}302303impl system::Config for Runtime {304	/// The data to be stored in an account.305	type AccountData = pallet_balances::AccountData<Balance>;306	/// The identifier used to distinguish between accounts.307	type AccountId = AccountId;308	/// The basic call filter to use in dispatchable.309	type BaseCallFilter = Everything;310	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).311	type BlockHashCount = BlockHashCount;312	/// The maximum length of a block (in bytes).313	type BlockLength = RuntimeBlockLength;314	/// The index type for blocks.315	type BlockNumber = BlockNumber;316	/// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.317	type BlockWeights = RuntimeBlockWeights;318	/// The aggregated dispatch type that is available for extrinsics.319	type Call = Call;320	/// The weight of database operations that the runtime can invoke.321	type DbWeight = RocksDbWeight;322	/// The ubiquitous event type.323	type Event = Event;324	/// The type for hashing blocks and tries.325	type Hash = Hash;326	/// The hashing algorithm used.327	type Hashing = BlakeTwo256;328	/// The header type.329	type Header = generic::Header<BlockNumber, BlakeTwo256>;330	/// The index type for storing how many extrinsics an account has signed.331	type Index = Index;332	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.333	type Lookup = AccountIdLookup<AccountId, ()>;334	/// What to do if an account is fully reaped from the system.335	type OnKilledAccount = ();336	/// What to do if a new account is created.337	type OnNewAccount = ();338	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;339	/// The ubiquitous origin type.340	type Origin = Origin;341	/// This type is being generated by `construct_runtime!`.342	type PalletInfo = PalletInfo;343	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.344	type SS58Prefix = SS58Prefix;345	/// Weight information for the extrinsics of this pallet.346	type SystemWeightInfo = system::weights::SubstrateWeight<Self>;347	/// Version of the runtime.348	type Version = Version;349}350351parameter_types! {352	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;353}354355impl pallet_timestamp::Config for Runtime {356	/// A timestamp: milliseconds since the unix epoch.357	type Moment = u64;358	type OnTimestampSet = ();359	type MinimumPeriod = MinimumPeriod;360	type WeightInfo = ();361}362363parameter_types! {364	// pub const ExistentialDeposit: u128 = 500;365	pub const ExistentialDeposit: u128 = 0;366	pub const MaxLocks: u32 = 50;367}368369impl pallet_balances::Config for Runtime {370	type MaxLocks = MaxLocks;371	type MaxReserves = ();372	type ReserveIdentifier = [u8; 8];373	/// The type for recording an account's balance.374	type Balance = Balance;375	/// The ubiquitous event type.376	type Event = Event;377	type DustRemoval = Treasury;378	type ExistentialDeposit = ExistentialDeposit;379	type AccountStore = System;380	type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;381}382383pub const MICROUNIQUE: Balance = 1_000_000_000;384pub const MILLIUNIQUE: Balance = 1_000 * MICROUNIQUE;385pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE;386pub const UNIQUE: Balance = 100 * CENTIUNIQUE;387388pub const fn deposit(items: u32, bytes: u32) -> Balance {389	items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE390}391392/*393parameter_types! {394	pub TombstoneDeposit: Balance = deposit(395		1,396		sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,397	);398	pub DepositPerContract: Balance = TombstoneDeposit::get();399	pub const DepositPerStorageByte: Balance = deposit(0, 1);400	pub const DepositPerStorageItem: Balance = deposit(1, 0);401	pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);402	pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;403	pub const SignedClaimHandicap: u32 = 2;404	pub const MaxDepth: u32 = 32;405	pub const MaxValueSize: u32 = 16 * 1024;406	pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb407	// The lazy deletion runs inside on_initialize.408	pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *409		RuntimeBlockWeights::get().max_block;410	// The weight needed for decoding the queue should be less or equal than a fifth411	// of the overall weight dedicated to the lazy deletion.412	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (413			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -414			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)415		)) / 5) as u32;416	pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();417}418419impl pallet_contracts::Config for Runtime {420	type Time = Timestamp;421	type Randomness = RandomnessCollectiveFlip;422	type Currency = Balances;423	type Event = Event;424	type RentPayment = ();425	type SignedClaimHandicap = SignedClaimHandicap;426	type TombstoneDeposit = TombstoneDeposit;427	type DepositPerContract = DepositPerContract;428	type DepositPerStorageByte = DepositPerStorageByte;429	type DepositPerStorageItem = DepositPerStorageItem;430	type RentFraction = RentFraction;431	type SurchargeReward = SurchargeReward;432	type WeightPrice = pallet_transaction_payment::Pallet<Self>;433	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;434	type ChainExtension = NFTExtension;435	type DeletionQueueDepth = DeletionQueueDepth;436	type DeletionWeightLimit = DeletionWeightLimit;437	type Schedule = Schedule;438	type CallStack = [pallet_contracts::Frame<Self>; 31];439}440*/441442parameter_types! {443	pub const TransactionByteFee: Balance = 501 * MICROUNIQUE; // Targeting 0.1 Unique per NFT transfer444	/// This value increases the priority of `Operational` transactions by adding445	/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.446	pub const OperationalFeeMultiplier: u8 = 5;447}448449/// Linear implementor of `WeightToFeePolynomial`450pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);451452impl<T> WeightToFeePolynomial for LinearFee<T>453where454	T: BaseArithmetic + From<u32> + Copy + Unsigned,455{456	type Balance = T;457458	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {459		smallvec!(WeightToFeeCoefficient {460			coeff_integer: 146_700u32.into(), // Targeting 0.1 Unique per NFT transfer461			coeff_frac: Perbill::zero(),462			negative: false,463			degree: 1,464		})465	}466}467468impl pallet_transaction_payment::Config for Runtime {469	type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;470	type TransactionByteFee = TransactionByteFee;471	type OperationalFeeMultiplier = OperationalFeeMultiplier;472	type WeightToFee = LinearFee<Balance>;473	type FeeMultiplierUpdate = ();474}475476parameter_types! {477	pub const ProposalBond: Permill = Permill::from_percent(5);478	pub const ProposalBondMinimum: Balance = 1 * UNIQUE;479	pub const SpendPeriod: BlockNumber = 5 * MINUTES;480	pub const Burn: Permill = Permill::from_percent(0);481	pub const TipCountdown: BlockNumber = 1 * DAYS;482	pub const TipFindersFee: Percent = Percent::from_percent(20);483	pub const TipReportDepositBase: Balance = 1 * UNIQUE;484	pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;485	pub const BountyDepositBase: Balance = 1 * UNIQUE;486	pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;487	pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");488	pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;489	pub const MaximumReasonLength: u32 = 16384;490	pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);491	pub const BountyValueMinimum: Balance = 5 * UNIQUE;492	pub const MaxApprovals: u32 = 100;493}494495impl pallet_treasury::Config for Runtime {496	type PalletId = TreasuryModuleId;497	type Currency = Balances;498	type ApproveOrigin = EnsureRoot<AccountId>;499	type RejectOrigin = EnsureRoot<AccountId>;500	type Event = Event;501	type OnSlash = ();502	type ProposalBond = ProposalBond;503	type ProposalBondMinimum = ProposalBondMinimum;504	type SpendPeriod = SpendPeriod;505	type Burn = Burn;506	type BurnDestination = ();507	type SpendFunds = ();508	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;509	type MaxApprovals = MaxApprovals;510}511512impl pallet_sudo::Config for Runtime {513	type Event = Event;514	type Call = Call;515}516517pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);518519impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider520	for RelayChainBlockNumberProvider<T>521{522	type BlockNumber = BlockNumber;523524	fn current_block_number() -> Self::BlockNumber {525		cumulus_pallet_parachain_system::Pallet::<T>::validation_data()526			.map(|d| d.relay_parent_number)527			.unwrap_or_default()528	}529}530531parameter_types! {532	pub const MinVestedTransfer: Balance = 10 * UNIQUE;533	pub const MaxVestingSchedules: u32 = 28;534}535536impl orml_vesting::Config for Runtime {537	type Event = Event;538	type Currency = pallet_balances::Pallet<Runtime>;539	type MinVestedTransfer = MinVestedTransfer;540	type VestedTransferOrigin = EnsureSigned<AccountId>;541	type WeightInfo = ();542	type MaxVestingSchedules = MaxVestingSchedules;543	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;544}545546parameter_types! {547	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;548	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;549}550551impl cumulus_pallet_parachain_system::Config for Runtime {552	type Event = Event;553	type OnValidationData = ();554	type SelfParaId = parachain_info::Pallet<Self>;555	// type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<556	// 	MaxDownwardMessageWeight,557	// 	XcmExecutor<XcmConfig>,558	// 	Call,559	// >;560	type OutboundXcmpMessageSource = XcmpQueue;561	type DmpMessageHandler = DmpQueue;562	type ReservedDmpWeight = ReservedDmpWeight;563	type ReservedXcmpWeight = ReservedXcmpWeight;564	type XcmpMessageHandler = XcmpQueue;565}566567impl parachain_info::Config for Runtime {}568569impl cumulus_pallet_aura_ext::Config for Runtime {}570571parameter_types! {572	pub const RelayLocation: MultiLocation = MultiLocation::parent();573	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;574	pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();575	pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();576}577578/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used579/// when determining ownership of accounts for asset transacting and when attempting to use XCM580/// `Transact` in order to determine the dispatch Origin.581pub type LocationToAccountId = (582	// The parent (Relay-chain) origin converts to the default `AccountId`.583	ParentIsDefault<AccountId>,584	// Sibling parachain origins convert to AccountId via the `ParaId::into`.585	SiblingParachainConvertsVia<Sibling, AccountId>,586	// Straight up local `AccountId32` origins just alias directly to `AccountId`.587	AccountId32Aliases<RelayNetwork, AccountId>,588);589590/// Means for transacting assets on this chain.591pub type LocalAssetTransactor = CurrencyAdapter<592	// Use this currency:593	Balances,594	// Use this currency when it is a fungible asset matching the given location or name:595	IsConcrete<RelayLocation>,596	// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:597	LocationToAccountId,598	// Our chain's account ID type (we can't get away without mentioning it explicitly):599	AccountId,600	// We don't track any teleports.601	(),602>;603604/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,605/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can606/// biases the kind of local `Origin` it will become.607pub type XcmOriginToTransactDispatchOrigin = (608	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location609	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for610	// foreign chains who want to have a local sovereign account on this chain which they control.611	SovereignSignedViaLocation<LocationToAccountId, Origin>,612	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when613	// recognised.614	RelayChainAsNative<RelayOrigin, Origin>,615	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when616	// recognised.617	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,618	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a619	// transaction from the Root origin.620	ParentAsSuperuser<Origin>,621	// Native signed account converter; this just converts an `AccountId32` origin into a normal622	// `Origin::Signed` origin of the same 32-byte value.623	SignedAccountId32AsNative<RelayNetwork, Origin>,624	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.625	XcmPassthrough<Origin>,626);627628parameter_types! {629	// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.630	pub UnitWeightCost: Weight = 1_000_000;631	// 1200 UNIQUEs buy 1 second of weight.632	pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);633	pub const MaxInstructions: u32 = 100;634	pub const MaxAuthorities: u32 = 100_000;635}636637match_type! {638	pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {639		MultiLocation { parents: 1, interior: Here } |640		MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }641	};642}643644pub type Barrier = (645	TakeWeightCredit,646	AllowTopLevelPaidExecutionFrom<Everything>,647	AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,648	// ^^^ Parent & its unit plurality gets free execution649);650651pub struct XcmConfig;652impl Config for XcmConfig {653	type Call = Call;654	type XcmSender = XcmRouter;655	// How to withdraw and deposit an asset.656	type AssetTransactor = LocalAssetTransactor;657	type OriginConverter = XcmOriginToTransactDispatchOrigin;658	type IsReserve = NativeAsset;659	type IsTeleporter = (); // Teleportation is disabled660	type LocationInverter = LocationInverter<Ancestry>;661	type Barrier = Barrier;662	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;663	type Trader = UsingComponents<IdentityFee<Balance>, RelayLocation, AccountId, Balances, ()>;664	type ResponseHandler = (); // Don't handle responses for now.665	type SubscriptionService = PolkadotXcm;666667	type AssetTrap = PolkadotXcm;668	type AssetClaims = PolkadotXcm;669}670671// parameter_types! {672// 	pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;673// }674675/// No local origins on this chain are allowed to dispatch XCM sends/executions.676pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);677678/// The means for routing XCM messages which are not for local execution into the right message679/// queues.680pub type XcmRouter = (681	// Two routers - use UMP to communicate with the relay chain:682	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,683	// ..and XCMP to communicate with the sibling chains.684	XcmpQueue,685);686687impl pallet_evm_coder_substrate::Config for Runtime {688	type EthereumTransactionSender = pallet_ethereum::Pallet<Self>;689}690691impl pallet_xcm::Config for Runtime {692	type Event = Event;693	type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;694	type XcmRouter = XcmRouter;695	type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;696	type XcmExecuteFilter = Everything;697	type XcmExecutor = XcmExecutor<XcmConfig>;698	type XcmTeleportFilter = Everything;699	type XcmReserveTransferFilter = Everything;700	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;701	type LocationInverter = LocationInverter<Ancestry>;702	type Origin = Origin;703	type Call = Call;704	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;705	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;706}707708impl cumulus_pallet_xcm::Config for Runtime {709	type Event = Event;710	type XcmExecutor = XcmExecutor<XcmConfig>;711}712713impl cumulus_pallet_xcmp_queue::Config for Runtime {714	type Event = Event;715	type XcmExecutor = XcmExecutor<XcmConfig>;716	type ChannelInfo = ParachainSystem;717	type VersionWrapper = ();718}719720impl cumulus_pallet_dmp_queue::Config for Runtime {721	type Event = Event;722	type XcmExecutor = XcmExecutor<XcmConfig>;723	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;724}725726impl pallet_aura::Config for Runtime {727	type AuthorityId = AuraId;728	type DisabledValidators = ();729	type MaxAuthorities = MaxAuthorities;730}731732parameter_types! {733	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();734	pub const CollectionCreationPrice: Balance = 100 * UNIQUE;735}736737impl pallet_common::Config for Runtime {738	type Event = Event;739	type EvmBackwardsAddressMapping = up_evm_mapping::MapBackwardsAddressTruncated;740	type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;741	type CrossAccountId = pallet_common::account::BasicCrossAccountId<Self>;742743	type Currency = Balances;744	type CollectionCreationPrice = CollectionCreationPrice;745	type TreasuryAccountId = TreasuryAccountId;746}747748impl pallet_fungible::Config for Runtime {749	type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;750}751impl pallet_refungible::Config for Runtime {752	type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;753}754impl pallet_nonfungible::Config for Runtime {755	type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;756}757758impl pallet_unique::Config for Runtime {759	type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;760}761762parameter_types! {763	pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied764}765766/// Used for the pallet inflation767impl pallet_inflation::Config for Runtime {768	type Currency = Balances;769	type TreasuryAccountId = TreasuryAccountId;770	type InflationBlockInterval = InflationBlockInterval;771}772773// parameter_types! {774// 	pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *775// 		RuntimeBlockWeights::get().max_block;776// 	pub const MaxScheduledPerBlock: u32 = 50;777// }778779type EvmSponsorshipHandler = (780	pallet_unique::UniqueEthSponsorshipHandler<Runtime>,781	pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,782);783type SponsorshipHandler = (784	pallet_unique::UniqueSponsorshipHandler<Runtime>,785	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,786	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,787);788789// impl pallet_unq_scheduler::Config for Runtime {790// 	type Event = Event;791// 	type Origin = Origin;792// 	type PalletsOrigin = OriginCaller;793// 	type Call = Call;794// 	type MaximumWeight = MaximumSchedulerWeight;795// 	type ScheduleOrigin = EnsureSigned<AccountId>;796// 	type MaxScheduledPerBlock = MaxScheduledPerBlock;797// 	type SponsorshipHandler = SponsorshipHandler;798// 	type WeightInfo = ();799// }800801impl pallet_evm_transaction_payment::Config for Runtime {802	type EvmSponsorshipHandler = EvmSponsorshipHandler;803	type Currency = Balances;804	type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;805	type EvmBackwardsAddressMapping = up_evm_mapping::MapBackwardsAddressTruncated;806}807808impl pallet_charge_transaction::Config for Runtime {809	type SponsorshipHandler = SponsorshipHandler;810}811812// impl pallet_contract_helpers::Config for Runtime {813//	 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;814// }815816parameter_types! {817	// 0x842899ECF380553E8a4de75bF534cdf6fBF64049818	pub const HelpersContractAddress: H160 = H160([819		0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,820	]);821}822823impl pallet_evm_contract_helpers::Config for Runtime {824	type ContractAddress = HelpersContractAddress;825	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;826}827828construct_runtime!(829	pub enum Runtime where830		Block = Block,831		NodeBlock = opaque::Block,832		UncheckedExtrinsic = UncheckedExtrinsic833	{834		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,835		ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,836837		Aura: pallet_aura::{Pallet, Config<T>} = 22,838		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,839840		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,841		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,842		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,843		TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,844		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,845		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,846		System: system::{Pallet, Call, Storage, Config, Event<T>} = 36,847		Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,848		// Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,849		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,850851		// XCM helpers.852		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,853		PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,854		CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,855		DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,856857		// Unique Pallets858		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,859		Unique: pallet_unique::{Pallet, Call, Storage} = 61,860		// Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,861		// free = 63862		Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,863		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,864		Common: pallet_common::{Pallet, Storage, Event<T>} = 66,865		Fungible: pallet_fungible::{Pallet, Storage} = 67,866		Refungible: pallet_refungible::{Pallet, Storage} = 68,867		Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,868869		// Frontier870		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,871		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,872873		EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,874		EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,875		EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,876		EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,877	}878);879880pub struct TransactionConverter;881882impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {883	fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {884		UncheckedExtrinsic::new_unsigned(885			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),886		)887	}888}889890impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {891	fn convert_transaction(892		&self,893		transaction: pallet_ethereum::Transaction,894	) -> opaque::UncheckedExtrinsic {895		let extrinsic = UncheckedExtrinsic::new_unsigned(896			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),897		);898		let encoded = extrinsic.encode();899		opaque::UncheckedExtrinsic::decode(&mut &encoded[..])900			.expect("Encoded extrinsic is always valid")901	}902}903904/// The address format for describing accounts.905pub type Address = sp_runtime::MultiAddress<AccountId, ()>;906/// Block header type as expected by this runtime.907pub type Header = generic::Header<BlockNumber, BlakeTwo256>;908/// Block type as expected by this runtime.909pub type Block = generic::Block<Header, UncheckedExtrinsic>;910/// A Block signed with a Justification911pub type SignedBlock = generic::SignedBlock<Block>;912/// BlockId type as expected by this runtime.913pub type BlockId = generic::BlockId<Block>;914/// The SignedExtension to the basic transaction logic.915pub type SignedExtra = (916	system::CheckSpecVersion<Runtime>,917	// system::CheckTxVersion<Runtime>,918	system::CheckGenesis<Runtime>,919	system::CheckEra<Runtime>,920	system::CheckNonce<Runtime>,921	system::CheckWeight<Runtime>,922	pallet_charge_transaction::ChargeTransactionPayment<Runtime>,923	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,924);925/// Unchecked extrinsic type as expected by this runtime.926pub type UncheckedExtrinsic =927	fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;928/// Extrinsic type that has already been checked.929pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;930/// Executive: handles dispatch to the various modules.931pub type Executive = frame_executive::Executive<932	Runtime,933	Block,934	frame_system::ChainContext<Runtime>,935	Runtime,936	AllPallets,937>;938939impl_opaque_keys! {940	pub struct SessionKeys {941		pub aura: Aura,942	}943}944945impl fp_self_contained::SelfContainedCall for Call {946	type SignedInfo = H160;947948	fn is_self_contained(&self) -> bool {949		match self {950			Call::Ethereum(call) => call.is_self_contained(),951			_ => false,952		}953	}954955	fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {956		match self {957			Call::Ethereum(call) => call.check_self_contained(),958			_ => None,959		}960	}961962	fn validate_self_contained(&self, info: &Self::SignedInfo) -> Option<TransactionValidity> {963		match self {964			Call::Ethereum(call) => call.validate_self_contained(info),965			_ => None,966		}967	}968969	fn pre_dispatch_self_contained(970		&self,971		info: &Self::SignedInfo,972	) -> Option<Result<(), TransactionValidityError>> {973		match self {974			Call::Ethereum(call) => call.pre_dispatch_self_contained(info),975			_ => None,976		}977	}978979	fn apply_self_contained(980		self,981		info: Self::SignedInfo,982	) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {983		match self {984			call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(985				Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),986			)),987			_ => None,988		}989	}990}991992macro_rules! dispatch_unique_runtime {993	($collection:ident.$method:ident($($name:ident),*)) => {{994		use pallet_unique::dispatch::Dispatched;995996		let collection = Dispatched::dispatch(<pallet_common::CollectionHandle<Runtime>>::new($collection).unwrap());997		let dispatch = collection.as_dyn();998999		dispatch.$method($($name),*)1000	}};1001}1002impl_runtime_apis! {1003	impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId>1004		for Runtime1005	{1006		fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId> {1007			dispatch_unique_runtime!(collection.account_tokens(account))1008		}1009		fn token_exists(collection: CollectionId, token: TokenId) -> bool {1010			dispatch_unique_runtime!(collection.token_exists(token))1011		}10121013		fn token_owner(collection: CollectionId, token: TokenId) -> CrossAccountId {1014			dispatch_unique_runtime!(collection.token_owner(token))1015		}1016		fn const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8> {1017			dispatch_unique_runtime!(collection.const_metadata(token))1018		}1019		fn variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8> {1020			dispatch_unique_runtime!(collection.variable_metadata(token))1021		}10221023		fn collection_tokens(collection: CollectionId) -> u32 {1024			dispatch_unique_runtime!(collection.collection_tokens())1025		}1026		fn account_balance(collection: CollectionId, account: CrossAccountId) -> u32 {1027			dispatch_unique_runtime!(collection.account_balance(account))1028		}1029		fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> u128 {1030			dispatch_unique_runtime!(collection.balance(account, token))1031		}1032		fn allowance(1033			collection: CollectionId,1034			sender: CrossAccountId,1035			spender: CrossAccountId,1036			token: TokenId,1037		) -> u128 {1038			dispatch_unique_runtime!(collection.allowance(sender, spender, token))1039		}10401041		fn eth_contract_code(account: H160) -> Option<Vec<u8>> {1042			<pallet_unique::UniqueErcSupport<Runtime>>::get_code(&account)1043				.or_else(|| <pallet_evm_migration::OnMethodCall<Runtime>>::get_code(&account))1044				.or_else(|| <pallet_evm_contract_helpers::HelpersOnMethodCall<Self>>::get_code(&account))1045		}1046		fn adminlist(collection: CollectionId) -> Vec<CrossAccountId> {1047			<pallet_common::Pallet<Runtime>>::adminlist(collection)1048		}1049		fn allowlist(collection: CollectionId) -> Vec<CrossAccountId> {1050			<pallet_common::Pallet<Runtime>>::allowlist(collection)1051		}1052		fn allowed(collection: CollectionId, user: CrossAccountId) -> bool {1053			<pallet_common::Pallet<Runtime>>::allowed(collection, user)1054		}1055		fn last_token_id(collection: CollectionId) -> TokenId {1056			dispatch_unique_runtime!(collection.last_token_id())1057		}1058		fn collection_by_id(collection: CollectionId) -> Option<Collection<AccountId>> {1059			<pallet_common::CollectionById<Runtime>>::get(collection)1060		}1061		fn collection_stats() -> CollectionStats {1062			<pallet_common::Pallet<Runtime>>::collection_stats()1063		}1064	}10651066	impl sp_api::Core<Block> for Runtime {1067		fn version() -> RuntimeVersion {1068			VERSION1069		}10701071		fn execute_block(block: Block) {1072			Executive::execute_block(block)1073		}10741075		fn initialize_block(header: &<Block as BlockT>::Header) {1076			Executive::initialize_block(header)1077		}1078	}10791080	impl sp_api::Metadata<Block> for Runtime {1081		fn metadata() -> OpaqueMetadata {1082			OpaqueMetadata::new(Runtime::metadata().into())1083		}1084	}10851086	impl sp_block_builder::BlockBuilder<Block> for Runtime {1087		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {1088			Executive::apply_extrinsic(extrinsic)1089		}10901091		fn finalize_block() -> <Block as BlockT>::Header {1092			Executive::finalize_block()1093		}10941095		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {1096			data.create_extrinsics()1097		}10981099		fn check_inherents(1100			block: Block,1101			data: sp_inherents::InherentData,1102		) -> sp_inherents::CheckInherentsResult {1103			data.check_extrinsics(&block)1104		}11051106		// fn random_seed() -> <Block as BlockT>::Hash {1107		//     RandomnessCollectiveFlip::random_seed().01108		// }1109	}11101111	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {1112		fn validate_transaction(1113			source: TransactionSource,1114			tx: <Block as BlockT>::Extrinsic,1115			hash: <Block as BlockT>::Hash,1116		) -> TransactionValidity {1117			Executive::validate_transaction(source, tx, hash)1118		}1119	}11201121	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {1122		fn offchain_worker(header: &<Block as BlockT>::Header) {1123			Executive::offchain_worker(header)1124		}1125	}11261127	impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {1128		fn chain_id() -> u64 {1129			<Runtime as pallet_evm::Config>::ChainId::get()1130		}11311132		fn account_basic(address: H160) -> EVMAccount {1133			EVM::account_basic(&address)1134		}11351136		fn gas_price() -> U256 {1137			<Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price()1138		}11391140		fn account_code_at(address: H160) -> Vec<u8> {1141			EVM::account_codes(address)1142		}11431144		fn author() -> H160 {1145			<pallet_evm::Pallet<Runtime>>::find_author()1146		}11471148		fn storage_at(address: H160, index: U256) -> H256 {1149			let mut tmp = [0u8; 32];1150			index.to_big_endian(&mut tmp);1151			EVM::account_storages(address, H256::from_slice(&tmp[..]))1152		}11531154		fn call(1155			from: H160,1156			to: H160,1157			data: Vec<u8>,1158			value: U256,1159			gas_limit: U256,1160			gas_price: Option<U256>,1161			nonce: Option<U256>,1162			estimate: bool,1163		) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {1164			let config = if estimate {1165				let mut config = <Runtime as pallet_evm::Config>::config().clone();1166				config.estimate = true;1167				Some(config)1168			} else {1169				None1170			};11711172			<Runtime as pallet_evm::Config>::Runner::call(1173				from,1174				to,1175				data,1176				value,1177				gas_limit.low_u64(),1178				gas_price,1179				nonce,1180				config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),1181			).map_err(|err| err.into())1182		}11831184		fn create(1185			from: H160,1186			data: Vec<u8>,1187			value: U256,1188			gas_limit: U256,1189			gas_price: Option<U256>,1190			nonce: Option<U256>,1191			estimate: bool,1192		) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {1193			let config = if estimate {1194				let mut config = <Runtime as pallet_evm::Config>::config().clone();1195				config.estimate = true;1196				Some(config)1197			} else {1198				None1199			};12001201			<Runtime as pallet_evm::Config>::Runner::create(1202				from,1203				data,1204				value,1205				gas_limit.low_u64(),1206				gas_price,1207				nonce,1208				config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),1209			).map_err(|err| err.into())1210		}12111212		fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {1213			Ethereum::current_transaction_statuses()1214		}12151216		fn current_block() -> Option<pallet_ethereum::Block> {1217			Ethereum::current_block()1218		}12191220		fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {1221			Ethereum::current_receipts()1222		}12231224		fn current_all() -> (1225			Option<pallet_ethereum::Block>,1226			Option<Vec<pallet_ethereum::Receipt>>,1227			Option<Vec<TransactionStatus>>1228		) {1229			(1230				Ethereum::current_block(),1231				Ethereum::current_receipts(),1232				Ethereum::current_transaction_statuses()1233			)1234		}12351236		fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {1237			xts.into_iter().filter_map(|xt| match xt.0.function {1238				Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),1239				_ => None1240			}).collect()1241		}1242	}12431244	impl sp_session::SessionKeys<Block> for Runtime {1245		fn decode_session_keys(1246			encoded: Vec<u8>,1247		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {1248			SessionKeys::decode_into_raw_public_keys(&encoded)1249		}12501251		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {1252			SessionKeys::generate(seed)1253		}1254	}12551256	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {1257		fn slot_duration() -> sp_consensus_aura::SlotDuration {1258			sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())1259		}12601261		fn authorities() -> Vec<AuraId> {1262			Aura::authorities().to_vec()1263		}1264	}12651266	impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {1267		fn collect_collation_info() -> cumulus_primitives_core::CollationInfo {1268			ParachainSystem::collect_collation_info()1269		}1270	}12711272	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {1273		fn account_nonce(account: AccountId) -> Index {1274			System::account_nonce(account)1275		}1276	}12771278	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {1279		fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {1280			TransactionPayment::query_info(uxt, len)1281		}1282		fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {1283			TransactionPayment::query_fee_details(uxt, len)1284		}1285	}12861287	/*1288	impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>1289		for Runtime1290	{1291		fn call(1292			origin: AccountId,1293			dest: AccountId,1294			value: Balance,1295			gas_limit: u64,1296			input_data: Vec<u8>,1297		) -> pallet_contracts_primitives::ContractExecResult {1298			Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)1299		}13001301		fn instantiate(1302			origin: AccountId,1303			endowment: Balance,1304			gas_limit: u64,1305			code: pallet_contracts_primitives::Code<Hash>,1306			data: Vec<u8>,1307			salt: Vec<u8>,1308		) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>1309		{1310			Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)1311		}13121313		fn get_storage(1314			address: AccountId,1315			key: [u8; 32],1316		) -> pallet_contracts_primitives::GetStorageResult {1317			Contracts::get_storage(address, key)1318		}13191320		fn rent_projection(1321			address: AccountId,1322		) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {1323			Contracts::rent_projection(address)1324		}1325	}1326	*/13271328	#[cfg(feature = "runtime-benchmarks")]1329	impl frame_benchmarking::Benchmark<Block> for Runtime {1330		fn benchmark_metadata(extra: bool) -> (1331			Vec<frame_benchmarking::BenchmarkList>,1332			Vec<frame_support::traits::StorageInfo>,1333		) {1334			use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};1335			use frame_support::traits::StorageInfoTrait;13361337			let mut list = Vec::<BenchmarkList>::new();13381339			list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);1340			list_benchmark!(list, extra, pallet_unique, Unique);1341			list_benchmark!(list, extra, pallet_inflation, Inflation);1342			list_benchmark!(list, extra, pallet_fungible, Fungible);1343			list_benchmark!(list, extra, pallet_refungible, Refungible);1344			list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);13451346			let storage_info = AllPalletsWithSystem::storage_info();13471348			return (list, storage_info)1349		}13501351		fn dispatch_benchmark(1352			config: frame_benchmarking::BenchmarkConfig1353		) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {1354			use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};13551356			let allowlist: Vec<TrackedStorageKey> = vec![1357				// Block Number1358				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),1359				// Total Issuance1360				hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),1361				// Execution Phase1362				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),1363				// Event Count1364				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),1365				// System Events1366				hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),1367			];13681369			let mut batches = Vec::<BenchmarkBatch>::new();1370			let params = (&config, &allowlist);13711372			add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);1373			add_benchmark!(params, batches, pallet_unique, Unique);1374			add_benchmark!(params, batches, pallet_inflation, Inflation);1375			add_benchmark!(params, batches, pallet_fungible, Fungible);1376			add_benchmark!(params, batches, pallet_refungible, Refungible);1377			add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);13781379			if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }1380			Ok(batches)1381		}1382	}1383}13841385struct CheckInherents;13861387impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1388	fn check_inherents(1389		block: &Block,1390		relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1391	) -> sp_inherents::CheckInherentsResult {1392		let relay_chain_slot = relay_state_proof1393			.read_slot()1394			.expect("Could not read the relay chain slot from the proof");13951396		let inherent_data =1397			cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1398				relay_chain_slot,1399				sp_std::time::Duration::from_secs(6),1400			)1401			.create_inherent_data()1402			.expect("Could not create the timestamp inherent data");14031404		inherent_data.check_extrinsics(block)1405	}1406}14071408cumulus_pallet_parachain_system::register_validate_block!(1409	Runtime = Runtime,1410	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,1411	CheckInherents = CheckInherents,1412);
modifiedtests/Dockerfile-testsdiffbeforeafterboth
--- a/tests/Dockerfile-tests
+++ b/tests/Dockerfile-tests
@@ -7,8 +7,8 @@
 RUN apt -y update; apt -y upgrade; apt -y install curl
 
 
-RUN mkdir nft_parachain
-WORKDIR /nft_parachain
+RUN mkdir unique_parachain
+WORKDIR /unique_parachain
 
 RUN apt-get -y update && \
       apt-get -y upgrade && \
modifiedtests/README.mddiffbeforeafterboth
--- a/tests/README.md
+++ b/tests/README.md
@@ -5,7 +5,7 @@
 1. Checkout polkadot in sibling folder with this project
 ```bash
 git clone https://github.com/paritytech/polkadot.git && cd polkadot
-git checkout release-v0.9.9
+git checkout release-v0.9.12
 ```
 
 2. Build with nightly-2021-06-28
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -1,7 +1,7 @@
 {
-  "name": "nfttests",
+  "name": "unique-tests",
   "version": "1.0.0",
-  "description": "Substrate Nft tests",
+  "description": "Unique Chain Tests",
   "main": "",
   "devDependencies": {
     "@polkadot/dev": "0.63.18",
modifiedtests/src/addCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -23,7 +23,7 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.equal(alice.address);
 
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await submitTransactionAsync(alice, changeAdminTx);
 
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
@@ -41,13 +41,13 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.equal(alice.address);
 
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await submitTransactionAsync(alice, changeAdminTx);
 
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
       expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
 
-      const changeAdminTxCharlie = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
+      const changeAdminTxCharlie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
       await submitTransactionAsync(bob, changeAdminTxCharlie);
       const adminListAfterAddNewAdmin = await getAdminList(api, collectionId);
       expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
@@ -63,7 +63,7 @@
       const alice = privateKey('//Alice');
       const nonOwner = privateKey('//Bob_stash');
 
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(alice.address));
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(alice.address));
       await expect(submitTransactionExpectFailAsync(nonOwner, changeAdminTx)).to.be.rejected;
 
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
@@ -80,7 +80,7 @@
       const alice = privateKey('//Alice');
       const bob = privateKey('//Bob');
 
-      const changeOwnerTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const changeOwnerTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
 
       // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
@@ -94,7 +94,7 @@
       const alice = privateKey('//Alice');
       const bob = privateKey('//Bob');
       await destroyCollectionExpectSuccess(collectionId);
-      const changeOwnerTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const changeOwnerTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
 
       // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
@@ -125,7 +125,7 @@
         expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(accounts[i]));
       }
 
-      const tx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(accounts[chainAdminLimit]));
+      const tx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(accounts[chainAdminLimit]));
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
modifiedtests/src/addToAllowList.test.tsdiffbeforeafterboth
--- a/tests/src/addToAllowList.test.ts
+++ b/tests/src/addToAllowList.test.ts
@@ -59,7 +59,7 @@
       const collectionId = await getCreatedCollectionCount(api) + 1;
       const bob = privateKey('//Bob');
 
-      const tx = api.tx.nft.addToAllowList(collectionId, normalizeAccountId(bob.address));
+      const tx = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(bob.address));
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
@@ -71,7 +71,7 @@
       // tslint:disable-next-line: no-bitwise
       const collectionId = await createCollectionExpectSuccess();
       await destroyCollectionExpectSuccess(collectionId);
-      const tx = api.tx.nft.addToAllowList(collectionId, normalizeAccountId(bob.address));
+      const tx = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(bob.address));
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
@@ -83,7 +83,7 @@
       const collectionId = await createCollectionExpectSuccess();
       await enableAllowListExpectSuccess(alice, collectionId);
       await enablePublicMintingExpectSuccess(alice, collectionId);
-      const tx = api.tx.nft.createItem(collectionId, normalizeAccountId(ferdie.address), 'NFT');
+      const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(ferdie.address), 'NFT');
       await expect(submitTransactionExpectFailAsync(ferdie, tx)).to.be.rejected;
     });
   });
modifiedtests/src/addToContractAllowList.test.tsdiffbeforeafterboth
--- a/tests/src/addToContractAllowList.test.ts
+++ b/tests/src/addToContractAllowList.test.ts
@@ -24,10 +24,10 @@
       const bob = privateKey('//Bob');
       const [contract, deployer] = await deployFlipper(api);
 
-      const allowListedBefore = (await api.query.nft.contractAllowList(contract.address, bob.address)).toJSON();
-      const addTx = api.tx.nft.addToContractAllowList(contract.address, bob.address);
+      const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON();
+      const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address);
       const addEvents = await submitTransactionAsync(deployer, addTx);
-      const allowListedAfter = (await api.query.nft.contractAllowList(contract.address, bob.address)).toJSON();
+      const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON();
 
       expect(getGenericResult(addEvents).success).to.be.true;
       expect(allowListedBefore).to.be.false;
@@ -40,12 +40,12 @@
       const bob = privateKey('//Bob');
       const [contract, deployer] = await deployFlipper(api);
 
-      const allowListedBefore = (await api.query.nft.contractAllowList(contract.address, bob.address)).toJSON();
-      const addTx = api.tx.nft.addToContractAllowList(contract.address, bob.address);
+      const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON();
+      const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address);
       const addEvents = await submitTransactionAsync(deployer, addTx);
-      const allowListedAfter = (await api.query.nft.contractAllowList(contract.address, bob.address)).toJSON();
+      const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON();
       const addAgainEvents = await submitTransactionAsync(deployer, addTx);
-      const allowListedAgainAfter = (await api.query.nft.contractAllowList(contract.address, bob.address)).toJSON();
+      const allowListedAgainAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON();
 
       expect(getGenericResult(addEvents).success).to.be.true;
       expect(allowListedBefore).to.be.false;
@@ -64,10 +64,10 @@
       const bob = privateKey('//Bob');
       const charlieGuineaPig = privateKey('//Charlie');
 
-      const allowListedBefore = (await api.query.nft.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON();
-      const addTx = api.tx.nft.addToContractAllowList(charlieGuineaPig.address, bob.address);
+      const allowListedBefore = (await api.query.unique.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON();
+      const addTx = api.tx.unique.addToContractAllowList(charlieGuineaPig.address, bob.address);
       await expect(submitTransactionExpectFailAsync(alice, addTx)).to.be.rejected;
-      const allowListedAfter = (await api.query.nft.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON();
+      const allowListedAfter = (await api.query.unique.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON();
 
       expect(allowListedBefore).to.be.false;
       expect(allowListedAfter).to.be.false;
@@ -79,10 +79,10 @@
       const bob = privateKey('//Bob');
       const [contract] = await deployFlipper(api);
 
-      const allowListedBefore = (await api.query.nft.contractAllowList(contract.address, bob.address)).toJSON();
-      const addTx = api.tx.nft.addToContractAllowList(contract.address, bob.address);
+      const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON();
+      const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address);
       await expect(submitTransactionExpectFailAsync(bob, addTx)).to.be.rejected;
-      const allowListedAfter = (await api.query.nft.contractAllowList(contract.address, bob.address)).toJSON();
+      const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON();
 
       expect(allowListedBefore).to.be.false;
       expect(allowListedAfter).to.be.false;
modifiedtests/src/allowLists.test.tsdiffbeforeafterboth
--- a/tests/src/allowLists.test.ts
+++ b/tests/src/allowLists.test.ts
@@ -189,7 +189,7 @@
     await enableAllowListExpectSuccess(alice, collectionId);
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnItem(collectionId, itemId, /*normalizeAccountId(Alice.address),*/ 11);
+      const tx = api.tx.unique.burnItem(collectionId, itemId, /*normalizeAccountId(Alice.address),*/ 11);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(alice, tx);
       };
modifiedtests/src/approve.test.tsdiffbeforeafterboth
--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -102,13 +102,13 @@
   });
 
   it('Fungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'Fungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
   });
 
   it('ReFungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'ReFungible' } });
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
   });
@@ -135,14 +135,14 @@
   });
 
   it('Fungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'Fungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
     await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');
   });
 
   it('ReFungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'ReFungible' } });
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
     await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'ReFungible');
@@ -171,7 +171,7 @@
   });
 
   it('Fungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'Fungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
     await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');
@@ -179,7 +179,7 @@
   });
 
   it('ReFungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'ReFungible' } });
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
     await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'ReFungible');
@@ -203,7 +203,7 @@
   });  
 
   it('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'Fungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address); 
     await approveExpectSuccess(collectionId, itemId, alice, bob.address, 10);
     await transferFromExpectSuccess(collectionId, itemId, bob, alice, charlie, 2, 'Fungible');
@@ -306,7 +306,7 @@
   });
 
   it('Fungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'Fungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', charlie.address); 
     await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'Fungible');
     await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
@@ -314,7 +314,7 @@
   });
 
   it('ReFungible up to an approved amount', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'ReFungible' } });
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', charlie.address);
     await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'ReFungible');
     await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
@@ -338,7 +338,7 @@
   });  
 
   it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'Fungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
     await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address);
     await approveExpectSuccess(collectionId, 0, alice, bob.address, 1);
     await approveExpectSuccess(collectionId, 0, alice, charlie.address, 1);
@@ -348,7 +348,7 @@
   });
 
   it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. ReFungible', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'ReFungible' } });
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);
     await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);
     await approveExpectSuccess(collectionId, itemId, alice, charlie.address, 1);
@@ -359,7 +359,7 @@
 
   // Canceled by changing approve logic
   it.skip('Cannot approve for more than total user`s amount (owned: 10, approval 1: 5 - should succeed, approval 2: 6 - should fail). Fungible', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'Fungible', decimalPoints: 0 }});
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
     await createItemExpectSuccess(alice, collectionId, 'Fungible', dave.address);
     await approveExpectSuccess(collectionId, 0, dave, bob.address, 5);
     await approveExpectFail(collectionId, 0, dave, charlie, 6);
@@ -367,7 +367,7 @@
 
   // Canceled by changing approve logic
   it.skip('Cannot approve for more than total users amount (owned: 100, approval 1: 50 - should succeed, approval 2: 51 - should fail). ReFungible', async () => {
-    const collectionId = await createCollectionExpectSuccess({ mode:{ type: 'ReFungible' } });
+    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', dave.address);
     await approveExpectSuccess(collectionId, itemId, dave, bob.address, 50);
     await approveExpectFail(collectionId, itemId, dave, charlie, 51);
modifiedtests/src/burnItem.test.tsdiffbeforeafterboth
--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -40,7 +40,7 @@
     const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 1);
       const events = await submitTransactionAsync(alice, tx);
       const result = getGenericResult(events);
 
@@ -58,7 +58,7 @@
 
     await usingApi(async (api) => {
       // Destroy 1 of 10
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 1);
       const events = await submitTransactionAsync(alice, tx);
       const result = getGenericResult(events);
 
@@ -77,7 +77,7 @@
     const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 100);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 100);
       const events = await submitTransactionAsync(alice, tx);
       const result = getGenericResult(events);
 
@@ -97,7 +97,7 @@
 
     await usingApi(async (api) => {
       // Transfer 1/100 of the token to Bob
-      const transfertx = api.tx.nft.transfer(normalizeAccountId(bob.address), collectionId, tokenId, 1);
+      const transfertx = api.tx.unique.transfer(normalizeAccountId(bob.address), collectionId, tokenId, 1);
       const events1 = await submitTransactionAsync(alice, transfertx);
       const result1 = getGenericResult(events1);
 
@@ -106,7 +106,7 @@
       const aliceBalanceBefore = await getBalance(api, collectionId, alice.address, tokenId);
 
       // Bob burns his portion
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 1);
       const events2 = await submitTransactionAsync(bob, tx);
       const result2 = getGenericResult(events2);
 
@@ -146,7 +146,7 @@
     await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 1);
       const events = await submitTransactionAsync(bob, tx);
       const result = getGenericResult(events);
 
@@ -165,7 +165,7 @@
 
     await usingApi(async (api) => {
       // Destroy 1 of 10
-      const tx = api.tx.nft.burnFrom(collectionId, normalizeAccountId(alice.address), tokenId, 1);
+      const tx = api.tx.unique.burnFrom(collectionId, normalizeAccountId(alice.address), tokenId, 1);
       const events = await submitTransactionAsync(bob, tx);
       const result = getGenericResult(events);
 
@@ -186,7 +186,7 @@
     await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnFrom(collectionId, normalizeAccountId(alice.address), tokenId, 100);
+      const tx = api.tx.unique.burnFrom(collectionId, normalizeAccountId(alice.address), tokenId, 100);
       const events = await submitTransactionAsync(bob, tx);
       const result = getGenericResult(events);
       // Get alice balance
@@ -213,7 +213,7 @@
     await destroyCollectionExpectSuccess(collectionId);
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 0);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(alice, tx);
       };
@@ -228,7 +228,7 @@
     const tokenId = 10;
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 1);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(alice, tx);
       };
@@ -243,7 +243,7 @@
     const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
 
     await usingApi(async (api) => {
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 1);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(bob, tx);
       };
@@ -259,12 +259,12 @@
 
     await usingApi(async (api) => {
 
-      const burntx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+      const burntx = api.tx.unique.burnItem(collectionId, tokenId, 1);
       const events1 = await submitTransactionAsync(alice, burntx);
       const result1 = getGenericResult(events1);
       expect(result1.success).to.be.true;
 
-      const tx = api.tx.nft.transfer(normalizeAccountId(bob.address), collectionId, tokenId, 1);
+      const tx = api.tx.unique.transfer(normalizeAccountId(bob.address), collectionId, tokenId, 1);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(alice, tx);
       };
@@ -282,7 +282,7 @@
 
     await usingApi(async (api) => {
       // Destroy 11 of 10
-      const tx = api.tx.nft.burnItem(collectionId, tokenId, 11);
+      const tx = api.tx.unique.burnItem(collectionId, tokenId, 11);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(alice, tx);
       };
modifiedtests/src/change-collection-owner.test.tsdiffbeforeafterboth
--- a/tests/src/change-collection-owner.test.ts
+++ b/tests/src/change-collection-owner.test.ts
@@ -38,7 +38,7 @@
       const collection =await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.deep.eq(alice.address);
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await submitTransactionAsync(alice, changeOwnerTx);
 
       const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);
@@ -57,10 +57,10 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.deep.eq(alice.address);
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await submitTransactionAsync(alice, changeOwnerTx);
 
-      const badChangeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, alice.address);
+      const badChangeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, alice.address);
       await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected;
 
       const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);
@@ -78,7 +78,7 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.deep.eq(alice.address);
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await submitTransactionAsync(alice, changeOwnerTx);
 
       const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);
@@ -99,7 +99,7 @@
         ownerCanTransfer: true,
         ownerCanDestroy: true,
       };
-      const tx1 = api.tx.nft.setCollectionLimits(
+      const tx1 = api.tx.unique.setCollectionLimits(
         collectionId,
         collectionLimits,
       );
@@ -122,13 +122,13 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.deep.eq(alice.address);
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await submitTransactionAsync(alice, changeOwnerTx);
 
       const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);
       expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(bob.address);
 
-      const changeOwnerTx2 = api.tx.nft.changeCollectionOwner(collectionId, charlie.address);
+      const changeOwnerTx2 = api.tx.unique.changeCollectionOwner(collectionId, charlie.address);
       await submitTransactionAsync(bob, changeOwnerTx2);
 
       // ownership lost
@@ -145,7 +145,7 @@
       const alice = privateKey('//Alice');
       const bob = privateKey('//Bob');
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await expect(submitTransactionExpectFailAsync(bob, changeOwnerTx)).to.be.rejected;
 
       const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);
@@ -164,7 +164,7 @@
 
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await expect(submitTransactionExpectFailAsync(bob, changeOwnerTx)).to.be.rejected;
 
       const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);
@@ -181,7 +181,7 @@
       const alice = privateKey('//Alice');
       const bob = privateKey('//Bob');
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
 
       // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
@@ -199,10 +199,10 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.deep.eq(alice.address);
 
-      const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
+      const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);
       await submitTransactionAsync(alice, changeOwnerTx);
 
-      const badChangeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, alice.address);
+      const badChangeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, alice.address);
       await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected;
 
       const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);
@@ -220,7 +220,7 @@
         ownerCanTransfer: true,
         ownerCanDestroy: true,
       };
-      const tx1 = api.tx.nft.setCollectionLimits(
+      const tx1 = api.tx.unique.setCollectionLimits(
         collectionId,
         collectionLimits,
       );
modifiedtests/src/check-event/burnItemEvent.test.tsdiffbeforeafterboth
--- a/tests/src/check-event/burnItemEvent.test.ts
+++ b/tests/src/check-event/burnItemEvent.test.ts
@@ -10,7 +10,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from '../substrate/privateKey';
 import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, createItemExpectSuccess, nftEventMessage} from '../util/helpers';
+import {createCollectionExpectSuccess, createItemExpectSuccess, uniqueEventMessage} from '../util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -29,9 +29,9 @@
     await usingApi(async (api: ApiPromise) => {
       const collectionID = await createCollectionExpectSuccess();
       const itemID = await createItemExpectSuccess(alice, collectionID, 'NFT');
-      const burnItem = api.tx.nft.burnItem(collectionID, itemID, 1);
+      const burnItem = api.tx.unique.burnItem(collectionID, itemID, 1);
       const events = await submitTransactionAsync(alice, burnItem);
-      const msg = JSON.stringify(nftEventMessage(events));
+      const msg = JSON.stringify(uniqueEventMessage(events));
       expect(msg).to.be.contain(checkSection);
       expect(msg).to.be.contain(checkTreasury);
       expect(msg).to.be.contain(checkSystem);
modifiedtests/src/check-event/createCollectionEvent.test.tsdiffbeforeafterboth
--- a/tests/src/check-event/createCollectionEvent.test.ts
+++ b/tests/src/check-event/createCollectionEvent.test.ts
@@ -10,7 +10,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from '../substrate/privateKey';
 import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';
-import {nftEventMessage} from '../util/helpers';
+import {uniqueEventMessage} from '../util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -27,9 +27,9 @@
   });
   it('Check event from createCollection(): ', async () => {
     await usingApi(async (api: ApiPromise) => {
-      const tx = api.tx.nft.createCollection([0x31], [0x32], '0x33', 'NFT');
+      const tx = api.tx.unique.createCollection([0x31], [0x32], '0x33', 'NFT');
       const events = await submitTransactionAsync(alice, tx);
-      const msg = JSON.stringify(nftEventMessage(events));
+      const msg = JSON.stringify(uniqueEventMessage(events));
       expect(msg).to.be.contain(checkSection);
       expect(msg).to.be.contain(checkTreasury);
       expect(msg).to.be.contain(checkSystem);
modifiedtests/src/check-event/createItemEvent.test.tsdiffbeforeafterboth
--- a/tests/src/check-event/createItemEvent.test.ts
+++ b/tests/src/check-event/createItemEvent.test.ts
@@ -10,7 +10,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from '../substrate/privateKey';
 import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, nftEventMessage, normalizeAccountId} from '../util/helpers';
+import {createCollectionExpectSuccess, uniqueEventMessage, normalizeAccountId} from '../util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -28,9 +28,9 @@
   it('Check event from createItem(): ', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionID = await createCollectionExpectSuccess();
-      const createItem = api.tx.nft.createItem(collectionID, normalizeAccountId(alice.address), 'NFT');
+      const createItem = api.tx.unique.createItem(collectionID, normalizeAccountId(alice.address), 'NFT');
       const events = await submitTransactionAsync(alice, createItem);
-      const msg = JSON.stringify(nftEventMessage(events));
+      const msg = JSON.stringify(uniqueEventMessage(events));
       expect(msg).to.be.contain(checkSection);
       expect(msg).to.be.contain(checkTreasury);
       expect(msg).to.be.contain(checkSystem);
modifiedtests/src/check-event/createMultipleItemsEvent.test.tsdiffbeforeafterboth
--- a/tests/src/check-event/createMultipleItemsEvent.test.ts
+++ b/tests/src/check-event/createMultipleItemsEvent.test.ts
@@ -10,7 +10,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from '../substrate/privateKey';
 import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, nftEventMessage, normalizeAccountId} from '../util/helpers';
+import {createCollectionExpectSuccess, uniqueEventMessage, normalizeAccountId} from '../util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -29,9 +29,9 @@
     await usingApi(async (api: ApiPromise) => {
       const collectionID = await createCollectionExpectSuccess();
       const args = [{NFT: ['0x31', '0x31']}, {NFT: ['0x32', '0x32']}, {NFT: ['0x33', '0x33']}];
-      const createMultipleItems = api.tx.nft.createMultipleItems(collectionID, normalizeAccountId(alice.address), args);
+      const createMultipleItems = api.tx.unique.createMultipleItems(collectionID, normalizeAccountId(alice.address), args);
       const events = await submitTransactionAsync(alice, createMultipleItems);
-      const msg = JSON.stringify(nftEventMessage(events));
+      const msg = JSON.stringify(uniqueEventMessage(events));
       expect(msg).to.be.contain(checkSection);
       expect(msg).to.be.contain(checkTreasury);
       expect(msg).to.be.contain(checkSystem);
modifiedtests/src/check-event/destroyCollectionEvent.test.tsdiffbeforeafterboth
--- a/tests/src/check-event/destroyCollectionEvent.test.ts
+++ b/tests/src/check-event/destroyCollectionEvent.test.ts
@@ -10,7 +10,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from '../substrate/privateKey';
 import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, nftEventMessage} from '../util/helpers';
+import {createCollectionExpectSuccess, uniqueEventMessage} from '../util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -27,9 +27,9 @@
   it('Check event from destroyCollection(): ', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionID = await createCollectionExpectSuccess();
-      const destroyCollection = api.tx.nft.destroyCollection(collectionID);
+      const destroyCollection = api.tx.unique.destroyCollection(collectionID);
       const events = await submitTransactionAsync(alice, destroyCollection);
-      const msg = JSON.stringify(nftEventMessage(events));
+      const msg = JSON.stringify(uniqueEventMessage(events));
       expect(msg).to.be.contain(checkTreasury);
       expect(msg).to.be.contain(checkSystem);
     });
modifiedtests/src/check-event/transferEvent.test.tsdiffbeforeafterboth
--- a/tests/src/check-event/transferEvent.test.ts
+++ b/tests/src/check-event/transferEvent.test.ts
@@ -10,7 +10,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from '../substrate/privateKey';
 import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, createItemExpectSuccess, nftEventMessage, normalizeAccountId} from '../util/helpers';
+import {createCollectionExpectSuccess, createItemExpectSuccess, uniqueEventMessage, normalizeAccountId} from '../util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -31,9 +31,9 @@
     await usingApi(async (api: ApiPromise) => {
       const collectionID = await createCollectionExpectSuccess();
       const itemID = await createItemExpectSuccess(alice, collectionID, 'NFT');
-      const transfer = api.tx.nft.transfer(normalizeAccountId(bob.address), collectionID, itemID, 1);
+      const transfer = api.tx.unique.transfer(normalizeAccountId(bob.address), collectionID, itemID, 1);
       const events = await submitTransactionAsync(alice, transfer);
-      const msg = JSON.stringify(nftEventMessage(events));
+      const msg = JSON.stringify(uniqueEventMessage(events));
       expect(msg).to.be.contain(checkSection);
       expect(msg).to.be.contain(checkTreasury);
       expect(msg).to.be.contain(checkSystem);
modifiedtests/src/check-event/transferFromEvent.test.tsdiffbeforeafterboth
--- a/tests/src/check-event/transferFromEvent.test.ts
+++ b/tests/src/check-event/transferFromEvent.test.ts
@@ -10,7 +10,7 @@
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from '../substrate/privateKey';
 import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, createItemExpectSuccess, nftEventMessage, normalizeAccountId} from '../util/helpers';
+import {createCollectionExpectSuccess, createItemExpectSuccess, uniqueEventMessage, normalizeAccountId} from '../util/helpers';
 
 chai.use(chaiAsPromised);
 const expect = chai.expect;
@@ -31,9 +31,9 @@
     await usingApi(async (api: ApiPromise) => {
       const collectionID = await createCollectionExpectSuccess();
       const itemID = await createItemExpectSuccess(alice, collectionID, 'NFT');
-      const transferFrom = api.tx.nft.transferFrom(normalizeAccountId(alice.address), normalizeAccountId(bob.address), collectionID, itemID, 1);
+      const transferFrom = api.tx.unique.transferFrom(normalizeAccountId(alice.address), normalizeAccountId(bob.address), collectionID, itemID, 1);
       const events = await submitTransactionAsync(alice, transferFrom);
-      const msg = JSON.stringify(nftEventMessage(events));
+      const msg = JSON.stringify(uniqueEventMessage(events));
       expect(msg).to.be.contain(checkSection);
       expect(msg).to.be.contain(checkTreasury);
       expect(msg).to.be.contain(checkSystem);
modifiedtests/src/collision-tests/admVsOwnerChanges.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/admVsOwnerChanges.test.ts
+++ b/tests/src/collision-tests/admVsOwnerChanges.test.ts
@@ -34,21 +34,21 @@
 
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const changeAdminTxBob = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const changeAdminTxBob = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await submitTransactionAsync(Alice, changeAdminTxBob);
-      const changeAdminTxFerdie = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address));
+      const changeAdminTxFerdie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address));
       await submitTransactionAsync(Bob, changeAdminTxFerdie);
       const itemId = await createItemExpectSuccess(Ferdie, collectionId, 'NFT');
 
-      const changeOwner = api.tx.nft.transferFrom(normalizeAccountId(Ferdie.address), normalizeAccountId(Bob.address), collectionId, itemId, 1);
-      const approve = api.tx.nft.approve(normalizeAccountId(Bob.address), collectionId, itemId, 1);
-      const sendItem = api.tx.nft.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1);
+      const changeOwner = api.tx.unique.transferFrom(normalizeAccountId(Ferdie.address), normalizeAccountId(Bob.address), collectionId, itemId, 1);
+      const approve = api.tx.unique.approve(normalizeAccountId(Bob.address), collectionId, itemId, 1);
+      const sendItem = api.tx.unique.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1);
       await Promise.all([
         changeOwner.signAndSend(Alice),
         approve.signAndSend(Bob),
         sendItem.signAndSend(Ferdie),
       ]);
-      const itemBefore: any = await api.query.nft.nftItemList(collectionId, itemId);
+      const itemBefore: any = await api.query.unique.nftItemList(collectionId, itemId);
       expect(itemBefore.owner).not.to.be.eq(Bob.address);
       await waitNewBlocks(2);
     });
modifiedtests/src/collision-tests/admVsOwnerData.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/admVsOwnerData.test.ts
+++ b/tests/src/collision-tests/admVsOwnerData.test.ts
@@ -32,19 +32,19 @@
       const AliceData = 1;
       const BobData = 2;
       const collectionId = await createCollectionExpectSuccess();
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await submitTransactionAsync(Alice, changeAdminTx);
       const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT');
       //
       // tslint:disable-next-line: max-line-length
-      const AliceTx = api.tx.nft.setVariableMetaData(collectionId, itemId, AliceData.toString());
+      const AliceTx = api.tx.unique.setVariableMetaData(collectionId, itemId, AliceData.toString());
       // tslint:disable-next-line: max-line-length
-      const BobTx = api.tx.nft.setVariableMetaData(collectionId, itemId, BobData.toString());
+      const BobTx = api.tx.unique.setVariableMetaData(collectionId, itemId, BobData.toString());
       await Promise.all([
         AliceTx.signAndSend(Alice),
         BobTx.signAndSend(Bob),
       ]);
-      const item: any = await api.query.nft.nftItemList(collectionId, itemId);
+      const item: any = await api.query.unique.nftItemList(collectionId, itemId);
       expect(item.variableData).not.to.be.eq(null); // Pseudo-random selection of one of two values
       await waitNewBlocks(2);
     });
modifiedtests/src/collision-tests/admVsOwnerTake.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/admVsOwnerTake.test.ts
+++ b/tests/src/collision-tests/admVsOwnerTake.test.ts
@@ -33,19 +33,19 @@
   it('The collection admin burns the token and in the same block the token owner performs a transaction on it ', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await submitTransactionAsync(Alice, changeAdminTx);
       const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT');
       //
-      const sendItem = api.tx.nft.transfer(normalizeAccountId(Ferdie.address), collectionId, itemId, 1);
-      const burnItem = api.tx.nft.burnItem(collectionId, itemId, 1);
+      const sendItem = api.tx.unique.transfer(normalizeAccountId(Ferdie.address), collectionId, itemId, 1);
+      const burnItem = api.tx.unique.burnItem(collectionId, itemId, 1);
       await Promise.all([
         sendItem.signAndSend(Bob),
         burnItem.signAndSend(Alice),
       ]);
       await waitNewBlocks(2);
       let itemBurn = false;
-      itemBurn = (await (api.query.nft.nftItemList(collectionId, itemId))).toJSON() as boolean;
+      itemBurn = (await (api.query.unique.nftItemList(collectionId, itemId))).toJSON() as boolean;
       // tslint:disable-next-line: no-unused-expression
       expect(itemBurn).to.be.null;
       await waitNewBlocks(2);
modifiedtests/src/collision-tests/adminDestroyCollection.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/adminDestroyCollection.test.ts
+++ b/tests/src/collision-tests/adminDestroyCollection.test.ts
@@ -32,19 +32,19 @@
   it('Adding an address to the collection allowlist in a block by the admin, and deleting the collection by the owner ', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await submitTransactionAsync(Alice, changeAdminTx);
       await waitNewBlocks(1);
       //
-      const addAllowlistAdm = api.tx.nft.addToAllowList(collectionId, normalizeAccountId(Ferdie.address));
-      const destroyCollection = api.tx.nft.destroyCollection(collectionId);
+      const addAllowlistAdm = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(Ferdie.address));
+      const destroyCollection = api.tx.unique.destroyCollection(collectionId);
       await Promise.all([
         addAllowlistAdm.signAndSend(Bob),
         destroyCollection.signAndSend(Alice),
       ]);
       await waitNewBlocks(1);
       let allowList = false;
-      allowList = (await api.query.nft.allowList(collectionId, Ferdie.address)).toJSON() as boolean;
+      allowList = (await api.query.unique.allowList(collectionId, Ferdie.address)).toJSON() as boolean;
       // tslint:disable-next-line: no-unused-expression
       expect(allowList).to.be.false;
       await waitNewBlocks(2);
modifiedtests/src/collision-tests/adminLimitsOff.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/adminLimitsOff.test.ts
+++ b/tests/src/collision-tests/adminLimitsOff.test.ts
@@ -39,27 +39,27 @@
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
 
-      const chainAdminLimit = (api.consts.nft.collectionAdminsLimit as any).toNumber();
+      const chainAdminLimit = (api.consts.unique.collectionAdminsLimit as any).toNumber();
       expect(chainAdminLimit).to.be.equal(5);
 
-      const changeAdminTx1 = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Eve.address));
+      const changeAdminTx1 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Eve.address));
       await submitTransactionAsync(Alice, changeAdminTx1);
-      const changeAdminTx2 = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Dave.address));
+      const changeAdminTx2 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Dave.address));
       await submitTransactionAsync(Alice, changeAdminTx2);
-      const changeAdminTx3 = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const changeAdminTx3 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await submitTransactionAsync(Alice, changeAdminTx3);
 
-      const addAdmOne = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address));
-      const addAdmTwo = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Charlie.address));
+      const addAdmOne = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address));
+      const addAdmTwo = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Charlie.address));
       await Promise.all([
         addAdmOne.signAndSend(Bob),
         addAdmTwo.signAndSend(Alice),
       ]);
       await waitNewBlocks(2);
-      const changeAdminTx4 = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Alice.address));
+      const changeAdminTx4 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Alice.address));
       await expect(submitTransactionExpectFailAsync(Alice, changeAdminTx4)).to.be.rejected;
 
-      const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
+      const adminListAfterAddAdmin: any = (await api.query.unique.adminList(collectionId));
       expect(adminListAfterAddAdmin).to.be.contains(normalizeAccountId(Eve.address));
       expect(adminListAfterAddAdmin).to.be.contains(normalizeAccountId(Ferdie.address));
       expect(adminListAfterAddAdmin).not.to.be.contains(normalizeAccountId(Alice.address));
modifiedtests/src/collision-tests/adminRightsOff.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/adminRightsOff.test.ts
+++ b/tests/src/collision-tests/adminRightsOff.test.ts
@@ -31,20 +31,20 @@
   it('In the block, the collection admin adds a token or changes data, and the collection owner deprives the admin of rights ', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await submitTransactionAsync(Alice, changeAdminTx);
       await waitNewBlocks(1);
       const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];
-      const addItemAdm = api.tx.nft.createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);
-      const removeAdm = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const addItemAdm = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);
+      const removeAdm = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await Promise.all([
         addItemAdm.signAndSend(Bob),
         removeAdm.signAndSend(Alice),
       ]);
       await waitNewBlocks(2);
-      const itemsListIndex = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      const itemsListIndex = await api.query.unique.itemListIndex(collectionId) as unknown as BN;
       expect(itemsListIndex.toNumber()).to.be.equal(0);
-      const adminList: any = (await api.query.nft.adminList(collectionId));
+      const adminList: any = (await api.query.unique.adminList(collectionId));
       expect(adminList).not.to.be.contains(normalizeAccountId(Bob.address));
       await waitNewBlocks(2);
     });
modifiedtests/src/collision-tests/setSponsorNewOwner.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/setSponsorNewOwner.test.ts
+++ b/tests/src/collision-tests/setSponsorNewOwner.test.ts
@@ -34,14 +34,14 @@
       const collectionId = await createCollectionExpectSuccess();
       await setCollectionSponsorExpectSuccess(collectionId, Bob.address);
       await waitNewBlocks(2);
-      const confirmSponsorship = api.tx.nft.confirmSponsorship(collectionId);
-      const changeCollectionOwner = api.tx.nft.changeCollectionOwner(collectionId, Ferdie.address);
+      const confirmSponsorship = api.tx.unique.confirmSponsorship(collectionId);
+      const changeCollectionOwner = api.tx.unique.changeCollectionOwner(collectionId, Ferdie.address);
       await Promise.all([
         confirmSponsorship.signAndSend(Bob),
         changeCollectionOwner.signAndSend(Alice),
       ]);
       await waitNewBlocks(2);
-      const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+      const collection: any = (await api.query.unique.collectionById(collectionId)).toJSON();
       expect(collection.sponsorship.confirmed).to.be.eq(Bob.address);
       expect(collection.owner).to.be.eq(Ferdie.address);
       await waitNewBlocks(2);
modifiedtests/src/collision-tests/sponsorPayments.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/sponsorPayments.test.ts
+++ b/tests/src/collision-tests/sponsorPayments.test.ts
@@ -35,15 +35,15 @@
   it('Payment of commission if one block contains transactions for payment from the sponsor\'s balance and his (sponsor\'s) exclusion from the collection ', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const changeAdminTxBob = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
+      const changeAdminTxBob = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address));
       await submitTransactionAsync(Alice, changeAdminTxBob);
       const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT');
       await setCollectionSponsorExpectSuccess(collectionId, Bob.address);
       await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
 
       const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);
-      const sendItem = api.tx.nft.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1);
-      const revokeSponsor = api.tx.nft.removeCollectionSponsor(collectionId);
+      const sendItem = api.tx.unique.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1);
+      const revokeSponsor = api.tx.unique.removeCollectionSponsor(collectionId);
       await Promise.all([
         sendItem.signAndSend(Bob),
         revokeSponsor.signAndSend(Alice),
modifiedtests/src/collision-tests/tokenLimitsOff.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/tokenLimitsOff.test.ts
+++ b/tests/src/collision-tests/tokenLimitsOff.test.ts
@@ -46,7 +46,7 @@
       await setMintPermissionExpectSuccess(Alice, collectionId, true);
       await addToAllowListExpectSuccess(Alice, collectionId, Ferdie.address);
       await addToAllowListExpectSuccess(Alice, collectionId, Bob.address);
-      const setCollectionLim = api.tx.nft.setCollectionLimits(
+      const setCollectionLim = api.tx.unique.setCollectionLimits(
         collectionId,
         {
           accountTokenOwnershipLimit,
@@ -65,16 +65,16 @@
       await waitNewBlocks(2);
 
       const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];
-      const mintItemOne = api.tx.nft
+      const mintItemOne = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(Ferdie.address), args);
-      const mintItemTwo = api.tx.nft
+      const mintItemTwo = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);
       await Promise.all([
         mintItemOne.signAndSend(Ferdie),
         mintItemTwo.signAndSend(Bob),
       ]);
       await waitNewBlocks(2);
-      const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;
+      const itemsListIndexAfter = await api.query.unique.itemListIndex(collectionId) as unknown as BN;
       expect(itemsListIndexAfter.toNumber()).to.be.equal(3);
       // TokenLimit = 4. The first transaction is successful. The second should fail.
       await waitNewBlocks(2);
modifiedtests/src/collision-tests/turnsOffMinting.test.tsdiffbeforeafterboth
--- a/tests/src/collision-tests/turnsOffMinting.test.ts
+++ b/tests/src/collision-tests/turnsOffMinting.test.ts
@@ -35,14 +35,14 @@
       await setMintPermissionExpectSuccess(Alice, collectionId, true);
       await addToAllowListExpectSuccess(Alice, collectionId, Ferdie.address);
 
-      const mintItem = api.tx.nft.createItem(collectionId, normalizeAccountId(Ferdie.address), 'NFT');
-      const offMinting = api.tx.nft.setMintPermission(collectionId, false);
+      const mintItem = api.tx.unique.createItem(collectionId, normalizeAccountId(Ferdie.address), 'NFT');
+      const offMinting = api.tx.unique.setMintPermission(collectionId, false);
       await Promise.all([
         mintItem.signAndSend(Ferdie),
         offMinting.signAndSend(Alice),
       ]);
       let itemList = false;
-      itemList = (await (api.query.nft.nftItemList(collectionId, mintItem))).toJSON() as boolean;
+      itemList = (await (api.query.unique.nftItemList(collectionId, mintItem))).toJSON() as boolean;
       // tslint:disable-next-line: no-unused-expression
       expect(itemList).to.be.null;
       await waitNewBlocks(2);
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -76,7 +76,7 @@
       const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);
 
       // Transfer this tokens from unused address to Alice
-      const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);
+      const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);
       const events = await submitTransactionAsync(zeroBalance, zeroToAlice);
       const result = getGenericResult(events);
       expect(result.success).to.be.true;
@@ -103,7 +103,7 @@
       const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);
 
       // Transfer this tokens from unused address to Alice
-      const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);
+      const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);
       const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);
       const result1 = getGenericResult(events1);
       expect(result1.success).to.be.true;
@@ -129,7 +129,7 @@
       const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);
 
       // Transfer this tokens from unused address to Alice
-      const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);
+      const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);
       const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);
       const result1 = getGenericResult(events1);
 
@@ -184,13 +184,13 @@
 
       // Transfer this token from Alice to unused address and back
       // Alice to Zero gets sponsored
-      const aliceToZero = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);
+      const aliceToZero = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);
       const events1 = await submitTransactionAsync(alice, aliceToZero);
       const result1 = getGenericResult(events1);
 
       // Second transfer should fail
       const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();
-      const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);
+      const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);
       };
@@ -222,7 +222,7 @@
       const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);
 
       // Transfer this tokens in parts from unused address to Alice
-      const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);
+      const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);
       const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);
       const result1 = getGenericResult(events1);
       expect(result1.success).to.be.true;
@@ -254,7 +254,7 @@
       // Mint token for alice
       const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);
 
-      const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(alice.address), collectionId, itemId, 1);
+      const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 1);
 
       // Zero to alice gets sponsored
       const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);
modifiedtests/src/contracts.test.tsdiffbeforeafterboth
--- a/tests/src/contracts.test.ts
+++ b/tests/src/contracts.test.ts
@@ -73,7 +73,7 @@
       const collectionId = await createCollectionExpectSuccess();
       const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
       const [contract] = await deployTransferContract(api);
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, contract.address);
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, contract.address);
       await submitTransactionAsync(alice, changeAdminTx);
 
       expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));
@@ -105,7 +105,7 @@
       const result = getGenericResult(events);
       expect(result.success).to.be.true;
 
-      const tokensAfter = (await api.query.nft.nftItemList.entries(collectionId)).map((kv: any) => kv[1].toJSON());
+      const tokensAfter = (await api.query.unique.nftItemList.entries(collectionId)).map((kv: any) => kv[1].toJSON());
       expect(tokensAfter).to.be.deep.equal([
         {
           owner: bob.address,
@@ -137,7 +137,7 @@
       const result = getGenericResult(events);
       expect(result.success).to.be.true;
 
-      const tokensAfter: any = (await api.query.nft.nftItemList.entries(collectionId) as any)
+      const tokensAfter: any = (await api.query.unique.nftItemList.entries(collectionId) as any)
         .map((kv: any) => kv[1].toJSON())
         .sort((a: any, b: any) => a.constData.localeCompare(b.constData));
       expect(tokensAfter).to.be.deep.equal([
@@ -195,7 +195,7 @@
       const result = getGenericResult(events);
       expect(result.success).to.be.true;
 
-      const token: any = (await api.query.nft.nftItemList(collectionId, tokenId) as any).unwrap();
+      const token: any = (await api.query.unique.nftItemList(collectionId, tokenId) as any).unwrap();
       expect(token.owner.toString()).to.be.equal(charlie.address);
     });
   });
@@ -213,7 +213,7 @@
       const result = getGenericResult(events);
       expect(result.success).to.be.true;
 
-      const token: any = (await api.query.nft.nftItemList(collectionId, tokenId) as any).unwrap();
+      const token: any = (await api.query.unique.nftItemList(collectionId, tokenId) as any).unwrap();
       expect(token.variableData.toString()).to.be.equal('0x121314');
     });
   });
@@ -225,7 +225,7 @@
 
       const collectionId = await createCollectionExpectSuccess();
       const [contract] = await deployTransferContract(api);
-      const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, contract.address);
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, contract.address);
       await submitTransactionAsync(alice, changeAdminTx);
 
       expect(await isAllowlisted(api, collectionId, bob.address)).to.be.false;
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -34,7 +34,7 @@
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
       const args = [{NFT: ['0x31', '0x31']}, {NFT: ['0x32', '0x32']}, {NFT: ['0x33', '0x33']}];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
       const itemsListIndexAfter = await getLastTokenId(api, collectionId);
@@ -65,7 +65,7 @@
         {Fungible: {value: 2}},
         {Fungible: {value: 3}},
       ];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
       const token1Data = await getBalance(api, collectionId, alice.address, 0);
@@ -85,7 +85,7 @@
         {ReFungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
         {ReFungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
       ];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
       const itemsListIndexAfter = await getLastTokenId(api, collectionId);
@@ -117,7 +117,7 @@
         {NFT: ['A', 'A']},
         {NFT: ['B', 'B']},
       ];
-      const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       const events = await submitTransactionAsync(alice, createMultipleItemsTx);
       const result = getGenericResult(events);
       expect(result.success).to.be.true;
@@ -144,7 +144,7 @@
       expect(itemsListIndexBefore).to.be.equal(0);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
       const args = [{NFT: ['0x31', '0x31']}, {NFT: ['0x32', '0x32']}, {NFT: ['0x33', '0x33']}];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);
       await submitTransactionAsync(bob, createMultipleItemsTx);
       const itemsListIndexAfter = await getLastTokenId(api, collectionId);
@@ -175,7 +175,7 @@
         {Fungible: {value: 2}},
         {Fungible: {value: 3}},
       ];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);
       await submitTransactionAsync(bob, createMultipleItemsTx);
       const token1Data = await getBalance(api, collectionId, bob.address, 0);
@@ -195,7 +195,7 @@
         {ReFungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
         {ReFungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
       ];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);
       await submitTransactionAsync(bob, createMultipleItemsTx);
       const itemsListIndexAfter = await getLastTokenId(api, collectionId);
@@ -234,7 +234,7 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const args = [{NFT: ['0x31', '0x31']}, {NFT: ['0x32', '0x32']}, {NFT: ['0x33', '0x33']}];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionAsync(bob, createMultipleItemsTx)).to.be.rejected;
     });
@@ -250,7 +250,7 @@
         {Fungible: {value: 2}},
         {Fungible: {value: 3}},
       ];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionAsync(bob, createMultipleItemsTx)).to.be.rejected;
     });
@@ -266,7 +266,7 @@
         {ReFungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
         {ReFungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
       ];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionAsync(bob, createMultipleItemsTx)).to.be.rejected;
     });
@@ -275,7 +275,7 @@
   it('Create token in not existing collection', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await getCreatedCollectionCount(api) + 1;
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'NFT', 'NFT']);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
     });
@@ -291,7 +291,7 @@
         {NFT: ['B'.repeat(2049), 'B'.repeat(2049)]},
         {NFT: ['C'.repeat(2049), 'C'.repeat(2049)]},
       ];
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
 
@@ -303,7 +303,7 @@
         {ReFungible: ['2'.repeat(2049), '2'.repeat(2049), 10]},
         {ReFungible: ['3'.repeat(2049), '3'.repeat(2049), 10]},
       ];
-      const createMultipleItemsTxFungible = api.tx.nft
+      const createMultipleItemsTxFungible = api.tx.unique
         .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;
     });
@@ -312,7 +312,7 @@
   it('Create tokens with different types', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess();
-      const createMultipleItemsTx = api.tx.nft
+      const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'Fungible', 'ReFungible']);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
       // garbage collection :-D
@@ -328,7 +328,7 @@
         {NFT: ['B', 'B'.repeat(2049)]},
         {NFT: ['C'.repeat(2049), 'C']},
       ];
-      const createMultipleItemsTx = await api.tx.nft
+      const createMultipleItemsTx = await api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
     });
@@ -345,7 +345,7 @@
         {NFT: ['A', 'A']},
         {NFT: ['B', 'B']},
       ];
-      const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
     });
   });
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -70,7 +70,7 @@
     const alice = privateKey('//Alice');
 
     const caller = await createEthAccountWithBalance(api, web3);
-    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: caller});
+    const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});
     await submitTransactionAsync(alice, changeAdminTx);
     const receiver = createEthAccount(web3);
 
@@ -109,7 +109,7 @@
     const alice = privateKey('//Alice');
 
     const caller = await createEthAccountWithBalance(api, web3);
-    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: caller});
+    const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});
     await submitTransactionAsync(alice, changeAdminTx);
     const receiver = createEthAccount(web3);
 
modifiedtests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth
--- a/tests/src/eth/proxy/nonFungibleProxy.test.ts
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -88,7 +88,7 @@
     const address = collectionIdToAddress(collection);
     const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
 
-    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});
+    const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
     await submitTransactionAsync(alice, changeAdminTx);
 
     {
@@ -127,7 +127,7 @@
 
     const address = collectionIdToAddress(collection);
     const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
-    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});
+    const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
     await submitTransactionAsync(alice, changeAdminTx);
 
     {
@@ -190,7 +190,7 @@
     const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
 
-    const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: contract.options.address});
+    const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
     await submitTransactionAsync(alice, changeAdminTx);
 
     {
modifiedtests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-consts.ts
+++ b/tests/src/interfaces/augment-api-consts.ts
@@ -159,7 +159,6 @@
       [key: string]: Codec;
     };
     vesting: {
-      maxVestingSchedules: u32 & AugmentedConst<ApiType>;
       /**
        * The minimum amount transferred to call `vested_transfer`.
        **/
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -241,32 +241,6 @@
        **/
       [key: string]: AugmentedError<ApiType>;
     };
-    nft: {
-      /**
-       * Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.
-       **/
-      CollectionDecimalPointLimitExceeded: AugmentedError<ApiType>;
-      /**
-       * Collection limit bounds per collection exceeded
-       **/
-      CollectionLimitBoundsExceeded: AugmentedError<ApiType>;
-      /**
-       * This address is not set as sponsor, use setCollectionSponsor first.
-       **/
-      ConfirmUnsetSponsorFail: AugmentedError<ApiType>;
-      /**
-       * Length of items properties must be greater than 0.
-       **/
-      EmptyArgument: AugmentedError<ApiType>;
-      /**
-       * Tried to enable permissions which are only permitted to be disabled
-       **/
-      OwnerPermissionsCantBeReverted: AugmentedError<ApiType>;
-      /**
-       * Generic error
-       **/
-      [key: string]: AugmentedError<ApiType>;
-    };
     nonfungible: {
       /**
        * Used amount > 1 with NFT
@@ -390,28 +364,6 @@
        * Maximum refungibility exceeded
        **/
       WrongRefungiblePieces: AugmentedError<ApiType>;
-      /**
-       * Generic error
-       **/
-      [key: string]: AugmentedError<ApiType>;
-    };
-    scheduler: {
-      /**
-       * Failed to schedule a call
-       **/
-      FailedToSchedule: AugmentedError<ApiType>;
-      /**
-       * Cannot find the scheduled call.
-       **/
-      NotFound: AugmentedError<ApiType>;
-      /**
-       * Reschedule failed because it does not change scheduled time.
-       **/
-      RescheduleNoChange: AugmentedError<ApiType>;
-      /**
-       * Given target block number is in the past.
-       **/
-      TargetBlockNumberInPast: AugmentedError<ApiType>;
       /**
        * Generic error
        **/
@@ -475,28 +427,57 @@
        **/
       [key: string]: AugmentedError<ApiType>;
     };
+    unique: {
+      /**
+       * Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.
+       **/
+      CollectionDecimalPointLimitExceeded: AugmentedError<ApiType>;
+      /**
+       * Collection limit bounds per collection exceeded
+       **/
+      CollectionLimitBoundsExceeded: AugmentedError<ApiType>;
+      /**
+       * This address is not set as sponsor, use setCollectionSponsor first.
+       **/
+      ConfirmUnsetSponsorFail: AugmentedError<ApiType>;
+      /**
+       * Length of items properties must be greater than 0.
+       **/
+      EmptyArgument: AugmentedError<ApiType>;
+      /**
+       * Tried to enable permissions which are only permitted to be disabled
+       **/
+      OwnerPermissionsCantBeReverted: AugmentedError<ApiType>;
+      /**
+       * Generic error
+       **/
+      [key: string]: AugmentedError<ApiType>;
+    };
     vesting: {
       /**
-       * Amount being transferred is too low to create a vesting schedule.
+       * The vested transfer amount is too low
        **/
       AmountLow: AugmentedError<ApiType>;
       /**
-       * The account already has `MaxVestingSchedules` count of schedules and thus
-       * cannot add another one. Consider merging existing schedules in order to add another.
+       * Insufficient amount of balance to lock
+       **/
+      InsufficientBalanceToLock: AugmentedError<ApiType>;
+      /**
+       * Failed because the maximum vesting schedules was exceeded
        **/
-      AtMaxVestingSchedules: AugmentedError<ApiType>;
+      MaxVestingSchedulesExceeded: AugmentedError<ApiType>;
       /**
-       * Failed to create a new schedule because some parameter was invalid.
+       * This account have too many vesting schedules
        **/
-      InvalidScheduleParams: AugmentedError<ApiType>;
+      TooManyVestingSchedules: AugmentedError<ApiType>;
       /**
-       * The account given is not vesting.
+       * Vesting period is zero
        **/
-      NotVesting: AugmentedError<ApiType>;
+      ZeroVestingPeriod: AugmentedError<ApiType>;
       /**
-       * An index was out of bounds of the vesting schedules.
+       * Number of vests is zero
        **/
-      ScheduleIndexOutOfBounds: AugmentedError<ApiType>;
+      ZeroVestingPeriodCount: AugmentedError<ApiType>;
       /**
        * Generic error
        **/
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -2,12 +2,11 @@
 /* eslint-disable */
 
 import type { EthereumLog, EvmCoreErrorExitReason } from './ethereum';
-import type { PalletCommonAccountBasicCrossAccountIdRepr } from './nft';
+import type { PalletCommonAccountBasicCrossAccountIdRepr } from './unique';
 import type { ApiTypes } from '@polkadot/api/types';
-import type { Bytes, Null, Option, Result, U256, U8aFixed, u128, u32, u64, u8 } from '@polkadot/types';
+import type { Null, Option, Result, U256, U8aFixed, u128, u32, u64, u8 } from '@polkadot/types';
 import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';
 import type { FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchInfo, SpRuntimeDispatchError, XcmV1MultiLocation, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup';
-import type { ITuple } from '@polkadot/types/types';
 
 declare module '@polkadot/api/types/events' {
   export interface AugmentedEvents<ApiType> {
@@ -389,24 +388,6 @@
        **/
       [key: string]: AugmentedEvent<ApiType>;
     };
-    scheduler: {
-      /**
-       * Canceled some task. \[when, index\]
-       **/
-      Canceled: AugmentedEvent<ApiType, [u32, u32]>;
-      /**
-       * Dispatched some task. \[task, id, result\]
-       **/
-      Dispatched: AugmentedEvent<ApiType, [ITuple<[u32, u32]>, Option<Bytes>, Result<Null, SpRuntimeDispatchError>]>;
-      /**
-       * Scheduled some task. \[when, index\]
-       **/
-      Scheduled: AugmentedEvent<ApiType, [u32, u32]>;
-      /**
-       * Generic event
-       **/
-      [key: string]: AugmentedEvent<ApiType>;
-    };
     sudo: {
       /**
        * The \[sudoer\] just switched identity; the old key is supplied.
@@ -492,15 +473,17 @@
     };
     vesting: {
       /**
-       * An \[account\] has become fully vested.
+       * Claimed vesting. \[who, locked_amount\]
+       **/
+      Claimed: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      /**
+       * Added new vesting schedule. \[from, to, vesting_schedule\]
        **/
-      VestingCompleted: AugmentedEvent<ApiType, [AccountId32]>;
+      VestingScheduleAdded: AugmentedEvent<ApiType, [AccountId32, AccountId32, OrmlVestingVestingSchedule]>;
       /**
-       * The amount vested has been updated. This could indicate a change in funds available.
-       * The balance given is the amount which is left unvested (and thus locked).
-       * \[account, unvested\]
+       * Updated vesting schedules. \[who\]
        **/
-      VestingUpdated: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      VestingSchedulesUpdated: AugmentedEvent<ApiType, [AccountId32]>;
       /**
        * Generic event
        **/
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -2,12 +2,12 @@
 /* eslint-disable */
 
 import type { EthereumBlock, EthereumReceipt, EthereumTransactionLegacyTransaction, FpRpcTransactionStatus } from './ethereum';
-import type { NftDataStructsCollection, PalletCommonAccountBasicCrossAccountIdRepr, PalletNonfungibleItemData, PalletRefungibleItemData, PalletUnqSchedulerCallSpec, PalletUnqSchedulerReleases, PalletUnqSchedulerScheduledV2 } from './nft';
 import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundStatus, CumulusPalletXcmpQueueOutboundStatus, CumulusPalletXcmpQueueQueueConfigData, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData } from './polkadot';
+import type { PalletCommonAccountBasicCrossAccountIdRepr, PalletNonfungibleItemData, PalletRefungibleItemData, UpDataStructsCollection, UpDataStructsCollectionStats } from './unique';
 import type { ApiTypes } from '@polkadot/api/types';
 import type { BTreeMap, Bytes, Option, U256, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types';
 import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';
-import type { FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletVestingReleases, PalletVestingVestingInfo, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV1UpgradeRestriction, SpRuntimeGenericDigest } from '@polkadot/types/lookup';
+import type { FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV1UpgradeRestriction, SpRuntimeGenericDigest } from '@polkadot/types/lookup';
 import type { AnyNumber, ITuple, Observable } from '@polkadot/types/types';
 
 declare module '@polkadot/api/types/storage' {
@@ -58,10 +58,14 @@
       /**
        * Collection info
        **/
-      collectionById: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<NftDataStructsCollection>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
+      collectionById: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<UpDataStructsCollection>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
       createdCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
       destroyedCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
       /**
+       * Not used by code, exists only to provide some types to metadata
+       **/
+      dummyStorageValue: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[UpDataStructsCollectionStats, u32, u32]>>>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
        * List of collection admins
        **/
       isAdmin: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
@@ -171,44 +175,6 @@
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
-    nft: {
-      /**
-       * Used for migrations
-       **/
-      chainVersion: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;
-      /**
-       * (Collection id (controlled?2), who created (real))
-       * TODO: Off chain worker should remove from this map when collection gets removed
-       **/
-      createItemBasket: AugmentedQuery<ApiType, (arg: ITuple<[u32, AccountId32]> | [u32 | AnyNumber | Uint8Array, AccountId32 | string | Uint8Array]) => Observable<u32>, [ITuple<[u32, AccountId32]>]> & QueryableStorageEntry<ApiType, [ITuple<[u32, AccountId32]>]>;
-      /**
-       * Collection id (controlled?2), owning user (real)
-       **/
-      fungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: AccountId32 | string | Uint8Array) => Observable<u32>, [u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, AccountId32]>;
-      /**
-       * Collection id (controlled?2), token id (controlled?2)
-       **/
-      nftTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
-      /**
-       * Collection id (controlled?2), token id (controlled?2)
-       **/
-      reFungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
-      /**
-       * Variable metadata sponsoring
-       * Collection id (controlled?2), token id (controlled?2)
-       **/
-      variableMetaDataBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
-      /**
-       * Generic query
-       **/
-      [key: string]: QueryableStorageEntry<ApiType>;
-    };
-    nftPayment: {
-      /**
-       * Generic query
-       **/
-      [key: string]: QueryableStorageEntry<ApiType>;
-    };
     nonfungible: {
       accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
       allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletCommonAccountBasicCrossAccountIdRepr>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
@@ -383,27 +349,6 @@
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
-    scheduler: {
-      /**
-       * Items to be executed, indexed by the block number that they should be executed on.
-       **/
-      agenda: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<Option<PalletUnqSchedulerScheduledV2>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
-      /**
-       * Lookup from identity to the block number and index of the task.
-       **/
-      lookup: AugmentedQuery<ApiType, (arg: Bytes | string | Uint8Array) => Observable<Option<ITuple<[u32, u32]>>>, [Bytes]> & QueryableStorageEntry<ApiType, [Bytes]>;
-      specAgenda: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<Option<PalletUnqSchedulerCallSpec>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
-      /**
-       * Storage version of the pallet.
-       * 
-       * New networks start with last version.
-       **/
-      storageVersion: AugmentedQuery<ApiType, () => Observable<PalletUnqSchedulerReleases>, []> & QueryableStorageEntry<ApiType, []>;
-      /**
-       * Generic query
-       **/
-      [key: string]: QueryableStorageEntry<ApiType>;
-    };
     sudo: {
       /**
        * The `AccountId` of the sudo key.
@@ -537,17 +482,51 @@
        **/
       [key: string]: QueryableStorageEntry<ApiType>;
     };
+    unique: {
+      /**
+       * Used for migrations
+       **/
+      chainVersion: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * (Collection id (controlled?2), who created (real))
+       * TODO: Off chain worker should remove from this map when collection gets removed
+       **/
+      createItemBasket: AugmentedQuery<ApiType, (arg: ITuple<[u32, AccountId32]> | [u32 | AnyNumber | Uint8Array, AccountId32 | string | Uint8Array]) => Observable<Option<u32>>, [ITuple<[u32, AccountId32]>]> & QueryableStorageEntry<ApiType, [ITuple<[u32, AccountId32]>]>;
+      fungibleApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, AccountId32]>;
+      /**
+       * Collection id (controlled?2), owning user (real)
+       **/
+      fungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, AccountId32]>;
+      /**
+       * Approval sponsoring
+       **/
+      nftApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
+      /**
+       * Collection id (controlled?2), token id (controlled?2)
+       **/
+      nftTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
+      refungibleApproveBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, u32, AccountId32]>;
+      /**
+       * Collection id (controlled?2), token id (controlled?2)
+       **/
+      reFungibleTransferBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: AccountId32 | string | Uint8Array) => Observable<Option<u32>>, [u32, u32, AccountId32]> & QueryableStorageEntry<ApiType, [u32, u32, AccountId32]>;
+      /**
+       * Variable metadata sponsoring
+       * Collection id (controlled?2), token id (controlled?2)
+       **/
+      variableMetaDataBasket: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<u32>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;
+      /**
+       * Generic query
+       **/
+      [key: string]: QueryableStorageEntry<ApiType>;
+    };
     vesting: {
       /**
-       * Storage version of the pallet.
+       * Vesting schedules of an account.
        * 
-       * New networks start with latest version, as determined by the genesis build.
+       * VestingSchedules: map AccountId => Vec<VestingSchedule>
        **/
-      storageVersion: AugmentedQuery<ApiType, () => Observable<PalletVestingReleases>, []> & QueryableStorageEntry<ApiType, []>;
-      /**
-       * Information regarding the vesting of a given account.
-       **/
-      vesting: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Option<Vec<PalletVestingVestingInfo>>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      vestingSchedules: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<Vec<OrmlVestingVestingSchedule>>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
       /**
        * Generic query
        **/
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-rpc.ts
+++ b/tests/src/interfaces/augment-api-rpc.ts
@@ -1,7 +1,7 @@
 // Auto-generated via `yarn polkadot-types-from-chain`, do not edit
 /* eslint-disable */
 
-import type { NftDataStructsCollection, NftDataStructsCollectionId, NftDataStructsCollectionStats, NftDataStructsTokenId, PalletCommonAccountBasicCrossAccountIdRepr } from './nft';
+import type { PalletCommonAccountBasicCrossAccountIdRepr, UpDataStructsCollection, UpDataStructsCollectionId, UpDataStructsCollectionStats, UpDataStructsTokenId } from './unique';
 import type { Bytes, HashMap, Json, Metadata, Null, Option, StorageKey, Text, U256, U64, Vec, bool, u128, u32, u64 } from '@polkadot/types';
 import type { ExtrinsicOrHash, ExtrinsicStatus } from '@polkadot/types/interfaces/author';
 import type { EpochAuthorship } from '@polkadot/types/interfaces/babe';
@@ -354,68 +354,6 @@
        * Returns protocol version.
        **/
       version: AugmentedRpc<() => Observable<Text>>;
-    };
-    nft: {
-      /**
-       * Get amount of different user tokens
-       **/
-      accountBalance: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u32>>;
-      /**
-       * Get tokens owned by account
-       **/
-      accountTokens: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<NftDataStructsTokenId>>>;
-      /**
-       * Get admin list
-       **/
-      adminlist: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<PalletCommonAccountBasicCrossAccountIdRepr>>>;
-      /**
-       * Get allowed amount
-       **/
-      allowance: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, sender: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, spender: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, tokenId: NftDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u128>>;
-      /**
-       * Check if user is allowed to use collection
-       **/
-      allowed: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<bool>>;
-      /**
-       * Get allowlist
-       **/
-      allowlist: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<PalletCommonAccountBasicCrossAccountIdRepr>>>;
-      /**
-       * Get amount of specific account token
-       **/
-      balance: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, tokenId: NftDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u128>>;
-      /**
-       * Get collection by specified id
-       **/
-      collectionById: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<NftDataStructsCollection>>>;
-      /**
-       * Get collection stats
-       **/
-      collectionStats: AugmentedRpc<(at?: Hash | string | Uint8Array) => Observable<NftDataStructsCollectionStats>>;
-      /**
-       * Get tokens contained in collection
-       **/
-      collectionTokens: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<NftDataStructsTokenId>>>;
-      /**
-       * Get token constant metadata
-       **/
-      constMetadata: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: NftDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Bytes>>;
-      /**
-       * Get last token id
-       **/
-      lastTokenId: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<NftDataStructsTokenId>>;
-      /**
-       * Check if token exists
-       **/
-      tokenExists: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: NftDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<bool>>;
-      /**
-       * Get token owner
-       **/
-      tokenOwner: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: NftDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<PalletCommonAccountBasicCrossAccountIdRepr>>;
-      /**
-       * Get token variable metadata
-       **/
-      variableMetadata: AugmentedRpc<(collection: NftDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: NftDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Bytes>>;
     };
     offchain: {
       /**
@@ -609,6 +547,68 @@
        **/
       version: AugmentedRpc<() => Observable<Text>>;
     };
+    unique: {
+      /**
+       * Get amount of different user tokens
+       **/
+      accountBalance: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u32>>;
+      /**
+       * Get tokens owned by account
+       **/
+      accountTokens: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsTokenId>>>;
+      /**
+       * Get admin list
+       **/
+      adminlist: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<PalletCommonAccountBasicCrossAccountIdRepr>>>;
+      /**
+       * Get allowed amount
+       **/
+      allowance: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, sender: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, spender: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, tokenId: UpDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u128>>;
+      /**
+       * Check if user is allowed to use collection
+       **/
+      allowed: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<bool>>;
+      /**
+       * Get allowlist
+       **/
+      allowlist: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<PalletCommonAccountBasicCrossAccountIdRepr>>>;
+      /**
+       * Get amount of specific account token
+       **/
+      balance: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, tokenId: UpDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u128>>;
+      /**
+       * Get collection by specified id
+       **/
+      collectionById: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<UpDataStructsCollection>>>;
+      /**
+       * Get collection stats
+       **/
+      collectionStats: AugmentedRpc<(at?: Hash | string | Uint8Array) => Observable<UpDataStructsCollectionStats>>;
+      /**
+       * Get tokens contained in collection
+       **/
+      collectionTokens: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsTokenId>>>;
+      /**
+       * Get token constant metadata
+       **/
+      constMetadata: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: UpDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Bytes>>;
+      /**
+       * Get last token id
+       **/
+      lastTokenId: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<UpDataStructsTokenId>>;
+      /**
+       * Check if token exists
+       **/
+      tokenExists: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: UpDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<bool>>;
+      /**
+       * Get token owner
+       **/
+      tokenOwner: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: UpDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<PalletCommonAccountBasicCrossAccountIdRepr>>;
+      /**
+       * Get token variable metadata
+       **/
+      variableMetadata: AugmentedRpc<(collection: UpDataStructsCollectionId | AnyNumber | Uint8Array, tokenId: UpDataStructsTokenId | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Bytes>>;
+    };
     web3: {
       /**
        * Returns current client version.
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -2,13 +2,13 @@
 /* eslint-disable */
 
 import type { EthereumTransactionLegacyTransaction } from './ethereum';
-import type { NftDataStructsAccessMode, NftDataStructsCollectionLimits, NftDataStructsCollectionMode, NftDataStructsCreateItemData, NftDataStructsMetaUpdatePermission, NftDataStructsSchemaVersion, PalletCommonAccountBasicCrossAccountIdRepr } from './nft';
 import type { CumulusPrimitivesParachainInherentParachainInherentData } from './polkadot';
+import type { PalletCommonAccountBasicCrossAccountIdRepr, UpDataStructsAccessMode, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCreateItemData, UpDataStructsMetaUpdatePermission, UpDataStructsSchemaVersion } from './unique';
 import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types';
-import type { Bytes, Compact, Option, U256, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types';
+import type { Bytes, Compact, Option, U256, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types';
 import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';
 import type { AccountId32, Call, H160, H256, MultiAddress, Perbill } from '@polkadot/types/interfaces/runtime';
-import type { PalletVestingVestingInfo, SpCoreChangesTrieChangesTrieConfiguration, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { SpCoreChangesTrieChangesTrieConfiguration, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 import type { AnyNumber, ITuple } from '@polkadot/types/types';
 
 declare module '@polkadot/api/types/submittable' {
@@ -196,441 +196,11 @@
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
     inflation: {
-      /**
-       * Generic tx
-       **/
-      [key: string]: SubmittableExtrinsicFunction<ApiType>;
-    };
-    nft: {
-      /**
-       * Adds an admin of the Collection.
-       * NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * * Collection Admin.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the Collection to add admin for.
-       * 
-       * * new_admin_id: Address of new admin to add.
-       **/
-      addCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newAdminId: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Add an address to allow list.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * address.
-       **/
-      addToAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Set, change, or remove approved address to transfer the ownership of the NFT.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * * Current NFT owner
-       * 
-       * # Arguments
-       * 
-       * * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).
-       * 
-       * * collection_id.
-       * 
-       * * item_id: ID of the item.
-       **/
-      approve: AugmentedSubmittable<(spender: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletCommonAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
-      /**
-       * Destroys a concrete instance of NFT on behalf of the owner
-       * See also: [`approve`]
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * * Collection Admin.
-       * * Current NFT Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the collection.
-       * 
-       * * item_id: ID of NFT to burn.
-       * 
-       * * from: owner of item
-       **/
-      burnFrom: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, from: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr, u32, u128]>;
-      /**
-       * Destroys a concrete instance of NFT.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * * Collection Admin.
-       * * Current NFT Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the collection.
-       * 
-       * * item_id: ID of NFT to burn.
-       **/
-      burnItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u128]>;
-      /**
-       * Change the owner of the collection.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * new_owner.
-       **/
-      changeCollectionOwner: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newOwner: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;
-      /**
-       * # Permissions
-       * 
-       * * Sponsor.
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       **/
-      confirmSponsorship: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
-      /**
-       * This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner and admin of the collection are set to the address that signed the transaction. Both addresses can be changed later.
-       * 
-       * # Permissions
-       * 
-       * * Anyone.
-       * 
-       * # Arguments
-       * 
-       * * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.
-       * 
-       * * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.
-       * 
-       * * token_prefix: UTF-8 string with token prefix.
-       * 
-       * * mode: [CollectionMode] collection type and type dependent data.
-       **/
-      createCollection: AugmentedSubmittable<(collectionName: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], collectionDescription: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], tokenPrefix: Bytes | string | Uint8Array, mode: NftDataStructsCollectionMode | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Vec<u16>, Vec<u16>, Bytes, NftDataStructsCollectionMode]>;
-      /**
-       * This method creates a concrete instance of NFT Collection created with CreateCollection method.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * * Collection Admin.
-       * * Anyone if
-       * * Allow List is enabled, and
-       * * Address is added to allow list, and
-       * * MintPermission is enabled (see SetMintPermission method)
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the collection.
-       * 
-       * * owner: Address, initial owner of the NFT.
-       * 
-       * * data: Token data to store on chain.
-       **/
-      createItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, data: NftDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr, NftDataStructsCreateItemData]>;
-      /**
-       * This method creates multiple items in a collection created with CreateCollection method.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * * Collection Admin.
-       * * Anyone if
-       * * Allow List is enabled, and
-       * * Address is added to allow list, and
-       * * MintPermission is enabled (see SetMintPermission method)
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the collection.
-       * 
-       * * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].
-       * 
-       * * owner: Address, initial owner of the NFT.
-       **/
-      createMultipleItems: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemsData: Vec<NftDataStructsCreateItemData> | (NftDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr, Vec<NftDataStructsCreateItemData>]>;
-      /**
-       * **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: collection to destroy.
-       **/
-      destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
-      /**
-       * Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * * Collection Admin.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the Collection to remove admin for.
-       * 
-       * * account_id: Address of admin to remove.
-       **/
-      removeCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, accountId: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Switch back to pay-per-own-transaction model.
-       * 
-       * # Permissions
-       * 
-       * * Collection owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       **/
-      removeCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
-      /**
-       * Remove an address from allow list.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * address.
-       **/
-      removeFromAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
-      setCollectionLimits: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newLimit: NftDataStructsCollectionLimits | { accountTokenOwnershipLimit?: any; sponsoredDataSize?: any; sponsoredDataRateLimit?: any; tokenLimit?: any; sponsorTransferTimeout?: any; ownerCanTransfer?: any; ownerCanDestroy?: any; transfersEnabled?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, NftDataStructsCollectionLimits]>;
-      /**
-       * # Permissions
-       * 
-       * * Collection Owner
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * new_sponsor.
-       **/
-      setCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newSponsor: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;
-      /**
-       * Set const on-chain data schema.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * schema: String representing the const on-chain data schema.
-       **/
-      setConstOnChainSchema: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, schema: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, Bytes]>;
-      /**
-       * Set meta_update_permission value for particular collection
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the collection.
-       * 
-       * * value: New flag value.
-       **/
-      setMetaUpdatePermissionFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: NftDataStructsMetaUpdatePermission | 'ItemOwner' | 'Admin' | 'None' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, NftDataStructsMetaUpdatePermission]>;
-      /**
-       * Allows Anyone to create tokens if:
-       * * Allow List is enabled, and
-       * * Address is added to allow list, and
-       * * This method was called with True parameter
-       * 
-       * # Permissions
-       * * Collection Owner
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.
-       **/
-      setMintPermission: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, mintPermission: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, bool]>;
-      /**
-       * Set off-chain data schema.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * schema: String representing the offchain data schema.
-       **/
-      setOffchainSchema: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, schema: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, Bytes]>;
-      /**
-       * Toggle between normal and allow list access for the methods with access for `Anyone`.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * mode: [AccessMode]
-       **/
-      setPublicAccessMode: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, mode: NftDataStructsAccessMode | 'Normal' | 'AllowList' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, NftDataStructsAccessMode]>;
-      /**
-       * Set schema standard
-       * ImageURL
-       * Unique
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * schema: SchemaVersion: enum
-       **/
-      setSchemaVersion: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, version: NftDataStructsSchemaVersion | 'ImageURL' | 'Unique' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, NftDataStructsSchemaVersion]>;
-      /**
-       * Set transfers_enabled value for particular collection
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the collection.
-       * 
-       * * value: New flag value.
-       **/
-      setTransfersEnabledFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, bool]>;
-      /**
-       * Set off-chain data schema.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * schema: String representing the offchain data schema.
-       **/
-      setVariableMetaData: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, data: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, Bytes]>;
-      /**
-       * Set variable on-chain data schema.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * schema: String representing the variable on-chain data schema.
-       **/
-      setVariableOnChainSchema: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, schema: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, Bytes]>;
-      /**
-       * Change ownership of the token.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * * Current NFT owner
-       * 
-       * # Arguments
-       * 
-       * * recipient: Address of token recipient.
-       * 
-       * * collection_id.
-       * 
-       * * item_id: ID of the item
-       * * Non-Fungible Mode: Required.
-       * * Fungible Mode: Ignored.
-       * * Re-Fungible Mode: Required.
-       * 
-       * * value: Amount to transfer.
-       * * Non-Fungible Mode: Ignored
-       * * Fungible Mode: Must specify transferred amount
-       * * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)
-       **/
-      transfer: AugmentedSubmittable<(recipient: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletCommonAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
       /**
-       * Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
-       * 
-       * # Permissions
-       * * Collection Owner
-       * * Collection Admin
-       * * Current NFT owner
-       * * Address approved by current NFT owner
-       * 
-       * # Arguments
-       * 
-       * * from: Address that owns token.
-       * 
-       * * recipient: Address of token recipient.
-       * 
-       * * collection_id.
-       * 
-       * * item_id: ID of the item.
-       * 
-       * * value: Amount to transfer.
-       **/
-      transferFrom: AugmentedSubmittable<(from: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, recipient: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletCommonAccountBasicCrossAccountIdRepr, PalletCommonAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
-      /**
        * Generic tx
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
-    nftPayment: {
-      /**
-       * Generic tx
-       **/
-      [key: string]: SubmittableExtrinsicFunction<ApiType>;
-    };
     parachainSystem: {
       authorizeUpgrade: AugmentedSubmittable<(codeHash: H256 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H256]>;
       enactAuthorizedUpgrade: AugmentedSubmittable<(code: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Bytes]>;
@@ -778,80 +348,6 @@
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
-    scheduler: {
-      /**
-       * Cancel an anonymously scheduled task.
-       * 
-       * # <weight>
-       * - S = Number of already scheduled calls
-       * - Base Weight: 22.15 + 2.869 * S µs
-       * - DB Weight:
-       * - Read: Agenda
-       * - Write: Agenda, Lookup
-       * - Will use base weight of 100 which should be good for up to 30 scheduled calls
-       * # </weight>
-       **/
-      cancel: AugmentedSubmittable<(when: u32 | AnyNumber | Uint8Array, index: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
-      /**
-       * Cancel a named scheduled task.
-       * 
-       * # <weight>
-       * - S = Number of already scheduled calls
-       * - Base Weight: 24.91 + 2.907 * S µs
-       * - DB Weight:
-       * - Read: Agenda, Lookup
-       * - Write: Agenda, Lookup
-       * - Will use base weight of 100 which should be good for up to 30 scheduled calls
-       * # </weight>
-       **/
-      cancelNamed: AugmentedSubmittable<(id: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Bytes]>;
-      /**
-       * Anonymously schedule a task.
-       * 
-       * # <weight>
-       * - S = Number of already scheduled calls
-       * - Base Weight: 22.29 + .126 * S µs
-       * - DB Weight:
-       * - Read: Agenda
-       * - Write: Agenda
-       * - Will use base weight of 25 which should be good for up to 30 scheduled calls
-       * # </weight>
-       **/
-      schedule: AugmentedSubmittable<(when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option<ITuple<[u32, u32]>> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call) => SubmittableExtrinsic<ApiType>, [u32, Option<ITuple<[u32, u32]>>, u8, Call]>;
-      /**
-       * Anonymously schedule a task after a delay.
-       * 
-       * # <weight>
-       * Same as [`schedule`].
-       * # </weight>
-       **/
-      scheduleAfter: AugmentedSubmittable<(after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option<ITuple<[u32, u32]>> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call) => SubmittableExtrinsic<ApiType>, [u32, Option<ITuple<[u32, u32]>>, u8, Call]>;
-      /**
-       * Schedule a named task.
-       * 
-       * # <weight>
-       * - S = Number of already scheduled calls
-       * - Base Weight: 29.6 + .159 * S µs
-       * - DB Weight:
-       * - Read: Agenda, Lookup
-       * - Write: Agenda, Lookup
-       * - Will use base weight of 35 which should be good for more than 30 scheduled calls
-       * # </weight>
-       **/
-      scheduleNamed: AugmentedSubmittable<(id: Bytes | string | Uint8Array, when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option<ITuple<[u32, u32]>> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call) => SubmittableExtrinsic<ApiType>, [Bytes, u32, Option<ITuple<[u32, u32]>>, u8, Call]>;
-      /**
-       * Schedule a named task after a delay.
-       * 
-       * # <weight>
-       * Same as [`schedule_named`].
-       * # </weight>
-       **/
-      scheduleNamedAfter: AugmentedSubmittable<(id: Bytes | string | Uint8Array, after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option<ITuple<[u32, u32]>> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call) => SubmittableExtrinsic<ApiType>, [Bytes, u32, Option<ITuple<[u32, u32]>>, u8, Call]>;
-      /**
-       * Generic tx
-       **/
-      [key: string]: SubmittableExtrinsicFunction<ApiType>;
-    };
     sudo: {
       /**
        * Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo
@@ -878,7 +374,7 @@
        * - Weight of derivative `call` execution + 10,000.
        * # </weight>
        **/
-      sudo: AugmentedSubmittable<(call: Call) => SubmittableExtrinsic<ApiType>, [Call]>;
+       sudo: AugmentedSubmittable<(call: Call) => SubmittableExtrinsic<ApiType>, [Call]>;
       /**
        * Authenticates the sudo key and dispatches a function call with `Signed` origin from
        * a given account.
@@ -892,7 +388,7 @@
        * - Weight of derivative `call` execution + 10,000.
        * # </weight>
        **/
-      sudoAs: AugmentedSubmittable<(who: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, call: Call) => SubmittableExtrinsic<ApiType>, [MultiAddress, Call]>;
+      sudoAs: AugmentedSubmittable<(who: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, ) => SubmittableExtrinsic<ApiType>, [MultiAddress, Call]>;
       /**
        * Authenticates the sudo key and dispatches a function call with `Root` origin.
        * This function does not check the weight of the call, and instead allows the
@@ -905,7 +401,7 @@
        * - The weight of this call is defined by the caller.
        * # </weight>
        **/
-      sudoUncheckedWeight: AugmentedSubmittable<(call: Call, weight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Call, u64]>;
+       sudoUncheckedWeight: AugmentedSubmittable<(call: Call, weight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [Call, u64]>;
       /**
        * Generic tx
        **/
@@ -1094,106 +590,435 @@
        **/
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
-    vesting: {
+    unique: {
+      /**
+       * Adds an admin of the Collection.
+       * NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * * Collection Admin.
+       * 
+       * # Arguments
+       * 
+       * * collection_id: ID of the Collection to add admin for.
+       * 
+       * * new_admin_id: Address of new admin to add.
+       **/
+      addCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newAdminId: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
       /**
-       * Force a vested transfer.
+       * Add an address to allow list.
        * 
-       * The dispatch origin for this call must be _Root_.
+       * # Permissions
        * 
-       * - `source`: The account whose funds should be transferred.
-       * - `target`: The account that should be transferred the vested funds.
-       * - `schedule`: The vesting schedule attached to the transfer.
+       * * Collection Owner
+       * * Collection Admin
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * address.
+       **/
+      addToAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
+      /**
+       * Set, change, or remove approved address to transfer the ownership of the NFT.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * * Current NFT owner
+       * 
+       * # Arguments
+       * 
+       * * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).
+       * 
+       * * collection_id.
+       * 
+       * * item_id: ID of the item.
+       **/
+      approve: AugmentedSubmittable<(spender: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletCommonAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
+      /**
+       * Destroys a concrete instance of NFT on behalf of the owner
+       * See also: [`approve`]
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * * Collection Admin.
+       * * Current NFT Owner.
+       * 
+       * # Arguments
+       * 
+       * * collection_id: ID of the collection.
+       * 
+       * * item_id: ID of NFT to burn.
+       * 
+       * * from: owner of item
+       **/
+      burnFrom: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, from: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr, u32, u128]>;
+      /**
+       * Destroys a concrete instance of NFT.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * * Collection Admin.
+       * * Current NFT Owner.
+       * 
+       * # Arguments
+       * 
+       * * collection_id: ID of the collection.
+       * 
+       * * item_id: ID of NFT to burn.
+       **/
+      burnItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u128]>;
+      /**
+       * Change the owner of the collection.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * new_owner.
+       **/
+      changeCollectionOwner: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newOwner: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;
+      /**
+       * # Permissions
        * 
-       * Emits `VestingCreated`.
+       * * Sponsor.
        * 
-       * NOTE: This will unlock all schedules through the current block.
+       * # Arguments
        * 
-       * # <weight>
-       * - `O(1)`.
-       * - DbWeight: 4 Reads, 4 Writes
-       * - Reads: Vesting Storage, Balances Locks, Target Account, Source Account
-       * - Writes: Vesting Storage, Balances Locks, Target Account, Source Account
-       * # </weight>
+       * * collection_id.
        **/
-      forceVestedTransfer: AugmentedSubmittable<(source: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, target: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, schedule: PalletVestingVestingInfo | { locked?: any; perBlock?: any; startingBlock?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress, MultiAddress, PalletVestingVestingInfo]>;
+      confirmSponsorship: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
       /**
-       * Merge two vesting schedules together, creating a new vesting schedule that unlocks over
-       * the highest possible start and end blocks. If both schedules have already started the
-       * current block will be used as the schedule start; with the caveat that if one schedule
-       * is finished by the current block, the other will be treated as the new merged schedule,
-       * unmodified.
+       * This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.
        * 
-       * NOTE: If `schedule1_index == schedule2_index` this is a no-op.
-       * NOTE: This will unlock all schedules through the current block prior to merging.
-       * NOTE: If both schedules have ended by the current block, no new schedule will be created
-       * and both will be removed.
+       * # Permissions
+       * 
+       * * Anyone.
+       * 
+       * # Arguments
+       * 
+       * * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.
        * 
-       * Merged schedule attributes:
-       * - `starting_block`: `MAX(schedule1.starting_block, scheduled2.starting_block,
-       * current_block)`.
-       * - `ending_block`: `MAX(schedule1.ending_block, schedule2.ending_block)`.
-       * - `locked`: `schedule1.locked_at(current_block) + schedule2.locked_at(current_block)`.
+       * * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.
        * 
-       * The dispatch origin for this call must be _Signed_.
+       * * token_prefix: UTF-8 string with token prefix.
        * 
-       * - `schedule1_index`: index of the first schedule to merge.
-       * - `schedule2_index`: index of the second schedule to merge.
+       * * mode: [CollectionMode] collection type and type dependent data.
        **/
-      mergeSchedules: AugmentedSubmittable<(schedule1Index: u32 | AnyNumber | Uint8Array, schedule2Index: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
+      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]>;
       /**
-       * Unlock any vested funds of the sender account.
+       * This method creates a concrete instance of NFT Collection created with CreateCollection method.
        * 
-       * The dispatch origin for this call must be _Signed_ and the sender must have funds still
-       * locked under this pallet.
+       * # Permissions
        * 
-       * Emits either `VestingCompleted` or `VestingUpdated`.
+       * * Collection Owner.
+       * * Collection Admin.
+       * * Anyone if
+       * * Allow List is enabled, and
+       * * Address is added to allow list, and
+       * * MintPermission is enabled (see SetMintPermission method)
+       * 
+       * # Arguments
+       * 
+       * * collection_id: ID of the collection.
+       * 
+       * * owner: Address, initial owner of the NFT.
        * 
-       * # <weight>
-       * - `O(1)`.
-       * - DbWeight: 2 Reads, 2 Writes
-       * - Reads: Vesting Storage, Balances Locks, [Sender Account]
-       * - Writes: Vesting Storage, Balances Locks, [Sender Account]
-       * # </weight>
+       * * data: Token data to store on chain.
        **/
-      vest: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      createItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, data: UpDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr, UpDataStructsCreateItemData]>;
       /**
-       * Create a vested transfer.
+       * This method creates multiple items in a collection created with CreateCollection method.
        * 
-       * The dispatch origin for this call must be _Signed_.
+       * # Permissions
        * 
-       * - `target`: The account receiving the vested funds.
-       * - `schedule`: The vesting schedule attached to the transfer.
+       * * Collection Owner.
+       * * Collection Admin.
+       * * Anyone if
+       * * Allow List is enabled, and
+       * * Address is added to allow list, and
+       * * MintPermission is enabled (see SetMintPermission method)
        * 
-       * Emits `VestingCreated`.
+       * # Arguments
        * 
-       * NOTE: This will unlock all schedules through the current block.
+       * * collection_id: ID of the collection.
+       * 
+       * * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].
        * 
-       * # <weight>
-       * - `O(1)`.
-       * - DbWeight: 3 Reads, 3 Writes
-       * - Reads: Vesting Storage, Balances Locks, Target Account, [Sender Account]
-       * - Writes: Vesting Storage, Balances Locks, Target Account, [Sender Account]
-       * # </weight>
+       * * owner: Address, initial owner of the NFT.
        **/
-      vestedTransfer: AugmentedSubmittable<(target: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, schedule: PalletVestingVestingInfo | { locked?: any; perBlock?: any; startingBlock?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress, PalletVestingVestingInfo]>;
+      createMultipleItems: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemsData: Vec<UpDataStructsCreateItemData> | (UpDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr, Vec<UpDataStructsCreateItemData>]>;
       /**
-       * Unlock any vested funds of a `target` account.
+       * **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.
        * 
-       * The dispatch origin for this call must be _Signed_.
+       * # Permissions
        * 
-       * - `target`: The account whose vested funds should be unlocked. Must have funds still
-       * locked under this pallet.
+       * * Collection Owner.
        * 
-       * Emits either `VestingCompleted` or `VestingUpdated`.
+       * # Arguments
        * 
-       * # <weight>
-       * - `O(1)`.
-       * - DbWeight: 3 Reads, 3 Writes
-       * - Reads: Vesting Storage, Balances Locks, Target Account
-       * - Writes: Vesting Storage, Balances Locks, Target Account
-       * # </weight>
+       * * collection_id: collection to destroy.
        **/
-      vestOther: AugmentedSubmittable<(target: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress]>;
+      destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      /**
+       * Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * * Collection Admin.
+       * 
+       * # Arguments
+       * 
+       * * collection_id: ID of the Collection to remove admin for.
+       * 
+       * * account_id: Address of admin to remove.
+       **/
+      removeCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, accountId: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
+      /**
+       * Switch back to pay-per-own-transaction model.
+       * 
+       * # Permissions
+       * 
+       * * Collection owner.
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       **/
+      removeCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      /**
+       * Remove an address from allow list.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * address.
+       **/
+      removeFromAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletCommonAccountBasicCrossAccountIdRepr]>;
+      setCollectionLimits: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newLimit: UpDataStructsCollectionLimits | { accountTokenOwnershipLimit?: any; sponsoredDataSize?: any; sponsoredDataRateLimit?: any; tokenLimit?: any; sponsorTransferTimeout?: any; sponsorApproveTimeout?: any; ownerCanTransfer?: any; ownerCanDestroy?: any; transfersEnabled?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsCollectionLimits]>;
+      /**
+       * # Permissions
+       * 
+       * * Collection Owner
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * new_sponsor.
+       **/
+      setCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newSponsor: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;
+      /**
+       * Set const on-chain data schema.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * schema: String representing the const on-chain data schema.
+       **/
+      setConstOnChainSchema: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, schema: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, Bytes]>;
+      /**
+       * Set meta_update_permission value for particular collection
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * 
+       * # Arguments
+       * 
+       * * collection_id: ID of the collection.
+       * 
+       * * value: New flag value.
+       **/
+      setMetaUpdatePermissionFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: UpDataStructsMetaUpdatePermission | 'ItemOwner' | 'Admin' | 'None' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsMetaUpdatePermission]>;
+      /**
+       * Allows Anyone to create tokens if:
+       * * Allow List is enabled, and
+       * * Address is added to allow list, and
+       * * This method was called with True parameter
+       * 
+       * # Permissions
+       * * Collection Owner
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.
+       **/
+      setMintPermission: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, mintPermission: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, bool]>;
+      /**
+       * Set off-chain data schema.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * schema: String representing the offchain data schema.
+       **/
+      setOffchainSchema: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, schema: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, Bytes]>;
+      /**
+       * Toggle between normal and allow list access for the methods with access for `Anyone`.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * mode: [AccessMode]
+       **/
+      setPublicAccessMode: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, mode: UpDataStructsAccessMode | 'Normal' | 'AllowList' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsAccessMode]>;
+      /**
+       * Set schema standard
+       * ImageURL
+       * Unique
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * schema: SchemaVersion: enum
+       **/
+      setSchemaVersion: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, version: UpDataStructsSchemaVersion | 'ImageURL' | 'Unique' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsSchemaVersion]>;
+      /**
+       * Set transfers_enabled value for particular collection
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner.
+       * 
+       * # Arguments
+       * 
+       * * collection_id: ID of the collection.
+       * 
+       * * value: New flag value.
+       **/
+      setTransfersEnabledFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, bool]>;
+      /**
+       * Set off-chain data schema.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * schema: String representing the offchain data schema.
+       **/
+      setVariableMetaData: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, data: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, Bytes]>;
+      /**
+       * Set variable on-chain data schema.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * 
+       * # Arguments
+       * 
+       * * collection_id.
+       * 
+       * * schema: String representing the variable on-chain data schema.
+       **/
+      setVariableOnChainSchema: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, schema: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, Bytes]>;
+      /**
+       * Change ownership of the token.
+       * 
+       * # Permissions
+       * 
+       * * Collection Owner
+       * * Collection Admin
+       * * Current NFT owner
+       * 
+       * # Arguments
+       * 
+       * * recipient: Address of token recipient.
+       * 
+       * * collection_id.
+       * 
+       * * item_id: ID of the item
+       * * Non-Fungible Mode: Required.
+       * * Fungible Mode: Ignored.
+       * * Re-Fungible Mode: Required.
+       * 
+       * * value: Amount to transfer.
+       * * Non-Fungible Mode: Ignored
+       * * Fungible Mode: Must specify transferred amount
+       * * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)
+       **/
+      transfer: AugmentedSubmittable<(recipient: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletCommonAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
+      /**
+       * Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
+       * 
+       * # Permissions
+       * * Collection Owner
+       * * Collection Admin
+       * * Current NFT owner
+       * * Address approved by current NFT owner
+       * 
+       * # Arguments
+       * 
+       * * from: Address that owns token.
+       * 
+       * * recipient: Address of token recipient.
+       * 
+       * * collection_id.
+       * 
+       * * item_id: ID of the item.
+       * 
+       * * value: Amount to transfer.
+       **/
+      transferFrom: AugmentedSubmittable<(from: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, recipient: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletCommonAccountBasicCrossAccountIdRepr, PalletCommonAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
+      /**
+       * Generic tx
+       **/
+      [key: string]: SubmittableExtrinsicFunction<ApiType>;
+    };
+    vesting: {
+      claim: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      claimFor: AugmentedSubmittable<(dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress]>;
+      updateVestingSchedules: AugmentedSubmittable<(who: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, vestingSchedules: Vec<OrmlVestingVestingSchedule> | (OrmlVestingVestingSchedule | { start?: any; period?: any; periodCount?: any; perPeriod?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [MultiAddress, Vec<OrmlVestingVestingSchedule>]>;
+      vestedTransfer: AugmentedSubmittable<(dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, schedule: OrmlVestingVestingSchedule | { start?: any; period?: any; periodCount?: any; perPeriod?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [MultiAddress, OrmlVestingVestingSchedule]>;
       /**
        * Generic tx
        **/
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -2,8 +2,8 @@
 /* eslint-disable */
 
 import type { EthereumBlock, EthereumLog, EthereumReceipt, EthereumTransactionLegacyTransaction, EvmCoreErrorExitReason, FpRpcTransactionStatus } from './ethereum';
-import type { NftDataStructsAccessMode, NftDataStructsCollection, NftDataStructsCollectionId, NftDataStructsCollectionLimits, NftDataStructsCollectionMode, NftDataStructsCollectionStats, NftDataStructsCreateItemData, NftDataStructsMetaUpdatePermission, NftDataStructsSchemaVersion, NftDataStructsSponsorshipState, NftDataStructsTokenId, PalletCommonAccountBasicCrossAccountIdRepr, PalletNonfungibleItemData, PalletRefungibleItemData, PalletUnqSchedulerCallSpec, PalletUnqSchedulerReleases, PalletUnqSchedulerScheduledV2 } from './nft';
 import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundStatus, CumulusPalletXcmpQueueOutboundStatus, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData } from './polkadot';
+import type { PalletCommonAccountBasicCrossAccountIdRepr, PalletNonfungibleItemData, PalletRefungibleItemData, PalletUnqSchedulerCallSpec, PalletUnqSchedulerReleases, PalletUnqSchedulerScheduledV2, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionId, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionStats, UpDataStructsCreateItemData, UpDataStructsMetaUpdatePermission, UpDataStructsSchemaVersion, UpDataStructsSponsorshipState, UpDataStructsTokenId } from './unique';
 import type { BitVec, Bool, Bytes, Data, I128, I16, I256, I32, I64, I8, Json, Null, Raw, StorageKey, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types';
 import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
 import type { BlockAttestations, IncludedBlocks, MoreAttestations } from '@polkadot/types/interfaces/attestations';
@@ -622,17 +622,6 @@
     NextAuthority: NextAuthority;
     NextConfigDescriptor: NextConfigDescriptor;
     NextConfigDescriptorV1: NextConfigDescriptorV1;
-    NftDataStructsAccessMode: NftDataStructsAccessMode;
-    NftDataStructsCollection: NftDataStructsCollection;
-    NftDataStructsCollectionId: NftDataStructsCollectionId;
-    NftDataStructsCollectionLimits: NftDataStructsCollectionLimits;
-    NftDataStructsCollectionMode: NftDataStructsCollectionMode;
-    NftDataStructsCollectionStats: NftDataStructsCollectionStats;
-    NftDataStructsCreateItemData: NftDataStructsCreateItemData;
-    NftDataStructsMetaUpdatePermission: NftDataStructsMetaUpdatePermission;
-    NftDataStructsSchemaVersion: NftDataStructsSchemaVersion;
-    NftDataStructsSponsorshipState: NftDataStructsSponsorshipState;
-    NftDataStructsTokenId: NftDataStructsTokenId;
     NodeRole: NodeRole;
     Nominations: Nominations;
     NominatorIndex: NominatorIndex;
@@ -1026,6 +1015,17 @@
     UnlockChunk: UnlockChunk;
     UnrewardedRelayer: UnrewardedRelayer;
     UnrewardedRelayersState: UnrewardedRelayersState;
+    UpDataStructsAccessMode: UpDataStructsAccessMode;
+    UpDataStructsCollection: UpDataStructsCollection;
+    UpDataStructsCollectionId: UpDataStructsCollectionId;
+    UpDataStructsCollectionLimits: UpDataStructsCollectionLimits;
+    UpDataStructsCollectionMode: UpDataStructsCollectionMode;
+    UpDataStructsCollectionStats: UpDataStructsCollectionStats;
+    UpDataStructsCreateItemData: UpDataStructsCreateItemData;
+    UpDataStructsMetaUpdatePermission: UpDataStructsMetaUpdatePermission;
+    UpDataStructsSchemaVersion: UpDataStructsSchemaVersion;
+    UpDataStructsSponsorshipState: UpDataStructsSponsorshipState;
+    UpDataStructsTokenId: UpDataStructsTokenId;
     UpgradeGoAhead: UpgradeGoAhead;
     UpgradeRestriction: UpgradeRestriction;
     UpwardMessage: UpwardMessage;
modifiedtests/src/interfaces/definitions.tsdiffbeforeafterboth
--- a/tests/src/interfaces/definitions.ts
+++ b/tests/src/interfaces/definitions.ts
@@ -1,3 +1,3 @@
-export {default as nft} from './nft/definitions';
+export {default as unique} from './unique/definitions';
 export {default as ethereum} from './ethereum/definitions';
 export {default as polkadot} from './polkadot/definitions';
deletedtests/src/interfaces/nft/definitions.tsdiffbeforeafterboth
--- a/tests/src/interfaces/nft/definitions.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-function mkDummy(name: string) {
-  return {
-    ['dummy' + name]: 'u32',
-  };
-}
-
-type RpcParam = {
-  name: string;
-  type: string;
-  isOptional?: true;
-};
-
-const CROSS_ACCOUNT_ID_TYPE = 'PalletCommonAccountBasicCrossAccountIdRepr';
-const TOKEN_ID_TYPE = 'NftDataStructsTokenId';
-
-const collectionParam = {name: 'collection', type: 'NftDataStructsCollectionId'};
-const tokenParam = {name: 'tokenId', type: TOKEN_ID_TYPE};
-const crossAccountParam = (name = 'account') => ({name, type: CROSS_ACCOUNT_ID_TYPE});
-const atParam = {name: 'at', type: 'Hash', isOptional: true};
-
-const fun = (description: string, params: RpcParam[], type: string) => ({
-  description,
-  params: [...params, atParam],
-  type,
-});
-
-export default {
-  rpc: {
-    adminlist: fun('Get admin list', [collectionParam], 'Vec<PalletCommonAccountBasicCrossAccountIdRepr>'),
-    allowlist: fun('Get allowlist', [collectionParam], 'Vec<PalletCommonAccountBasicCrossAccountIdRepr>'),
-
-    accountTokens: fun('Get tokens owned by account', [collectionParam, crossAccountParam()], 'Vec<NftDataStructsTokenId>'),
-    collectionTokens: fun('Get tokens contained in collection', [collectionParam], 'Vec<NftDataStructsTokenId>'),
-
-    lastTokenId: fun('Get last token id', [collectionParam], TOKEN_ID_TYPE),
-    accountBalance: fun('Get amount of different user tokens', [collectionParam, crossAccountParam()], 'u32'),
-    balance: fun('Get amount of specific account token', [collectionParam, crossAccountParam(), tokenParam], 'u128'),
-    allowance: fun('Get allowed amount', [collectionParam, crossAccountParam('sender'), crossAccountParam('spender'), tokenParam], 'u128'),
-    tokenOwner: fun('Get token owner', [collectionParam, tokenParam], CROSS_ACCOUNT_ID_TYPE),
-    constMetadata: fun('Get token constant metadata', [collectionParam, tokenParam], 'Vec<u8>'),
-    variableMetadata: fun('Get token variable metadata', [collectionParam, tokenParam], 'Vec<u8>'),
-    tokenExists: fun('Check if token exists', [collectionParam, tokenParam], 'bool'),
-    collectionById: fun('Get collection by specified id', [collectionParam], 'Option<NftDataStructsCollection>'),
-    collectionStats: fun('Get collection stats', [], 'NftDataStructsCollectionStats'),
-    allowed: fun('Check if user is allowed to use collection', [collectionParam, crossAccountParam()], 'bool'),
-  },
-  types: {
-    PalletCommonAccountBasicCrossAccountIdRepr: {
-      _enum: {
-        Substrate: 'AccountId',
-        Ethereum: 'H160',
-      },
-    },
-    NftDataStructsCollection: {
-      owner: 'AccountId',
-      mode: 'NftDataStructsCollectionMode',
-      access: 'NftDataStructsAccessMode',
-      name: 'Vec<u16>',
-      description: 'Vec<u16>',
-      tokenPrefix: 'Vec<u8>',
-      mintMode: 'bool',
-      offchainSchema: 'Vec<u8>',
-      schemaVersion: 'NftDataStructsSchemaVersion',
-      sponsorship: 'NftDataStructsSponsorshipState',
-      limits: 'NftDataStructsCollectionLimits',
-      variableOnChainSchema: 'Vec<u8>',
-      constOnChainSchema: 'Vec<u8>',
-      metaUpdatePermission: 'NftDataStructsMetaUpdatePermission',
-    },
-    NftDataStructsCollectionStats: {
-      created: 'u32',
-      destroyed: 'u32',
-      alive: 'u32',
-    },
-    NftDataStructsCollectionId: 'u32',
-    NftDataStructsTokenId: 'u32',
-    PalletNonfungibleItemData: mkDummy('NftItemData'),
-    PalletRefungibleItemData: mkDummy('RftItemData'),
-    NftDataStructsCollectionMode: mkDummy('CollectionMode'),
-    NftDataStructsCreateItemData: mkDummy('CreateItemData'),
-    NftDataStructsCollectionLimits: {
-      accountTokenOwnershipLimit: 'Option<u32>',
-      sponsoredDataSize: 'Option<u32>',
-      sponsoredDataRateLimit: 'Option<u32>',
-      tokenLimit: 'Option<u32>',
-      sponsorTransferTimeout: 'Option<u32>',
-      ownerCanTransfer: 'Option<bool>',
-      ownerCanDestroy: 'Option<bool>',
-      transfersEnabled: 'Option<bool>',
-    },
-    NftDataStructsMetaUpdatePermission: {
-      _enum: ['ItemOwner', 'Admin', 'None'],
-    },
-    NftDataStructsSponsorshipState: {
-      _enum: {
-        Disabled: null,
-        Unconfirmed: 'AccountId',
-        Confirmed: 'AccountId',
-      },
-    },
-    NftDataStructsAccessMode: {
-      _enum: ['Normal', 'AllowList'],
-    },
-    NftDataStructsSchemaVersion: mkDummy('SchemaVersion'),
-
-    PalletUnqSchedulerScheduledV2: mkDummy('ScheduledV2'),
-    PalletUnqSchedulerCallSpec: mkDummy('CallSpec'),
-    PalletUnqSchedulerReleases: mkDummy('Releases'),
-  },
-};
deletedtests/src/interfaces/nft/index.tsdiffbeforeafterboth
--- a/tests/src/interfaces/nft/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
-/* eslint-disable */
-
-export * from './types';
deletedtests/src/interfaces/nft/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/nft/types.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
-/* eslint-disable */
-
-import type { Bytes, Enum, Option, Struct, Vec, bool, u16, u32 } from '@polkadot/types';
-import type { AccountId, H160 } from '@polkadot/types/interfaces/runtime';
-
-/** @name NftDataStructsAccessMode */
-export interface NftDataStructsAccessMode extends Enum {
-  readonly isNormal: boolean;
-  readonly isAllowList: boolean;
-}
-
-/** @name NftDataStructsCollection */
-export interface NftDataStructsCollection extends Struct {
-  readonly owner: AccountId;
-  readonly mode: NftDataStructsCollectionMode;
-  readonly access: NftDataStructsAccessMode;
-  readonly name: Vec<u16>;
-  readonly description: Vec<u16>;
-  readonly tokenPrefix: Bytes;
-  readonly mintMode: bool;
-  readonly offchainSchema: Bytes;
-  readonly schemaVersion: NftDataStructsSchemaVersion;
-  readonly sponsorship: NftDataStructsSponsorshipState;
-  readonly limits: NftDataStructsCollectionLimits;
-  readonly variableOnChainSchema: Bytes;
-  readonly constOnChainSchema: Bytes;
-  readonly metaUpdatePermission: NftDataStructsMetaUpdatePermission;
-}
-
-/** @name NftDataStructsCollectionId */
-export interface NftDataStructsCollectionId extends u32 {}
-
-/** @name NftDataStructsCollectionLimits */
-export interface NftDataStructsCollectionLimits extends Struct {
-  readonly accountTokenOwnershipLimit: Option<u32>;
-  readonly sponsoredDataSize: Option<u32>;
-  readonly sponsoredDataRateLimit: Option<u32>;
-  readonly tokenLimit: Option<u32>;
-  readonly sponsorTransferTimeout: Option<u32>;
-  readonly ownerCanTransfer: Option<bool>;
-  readonly ownerCanDestroy: Option<bool>;
-  readonly transfersEnabled: Option<bool>;
-}
-
-/** @name NftDataStructsCollectionMode */
-export interface NftDataStructsCollectionMode extends Struct {
-  readonly dummyCollectionMode: u32;
-}
-
-/** @name NftDataStructsCollectionStats */
-export interface NftDataStructsCollectionStats extends Struct {
-  readonly created: u32;
-  readonly destroyed: u32;
-  readonly alive: u32;
-}
-
-/** @name NftDataStructsCreateItemData */
-export interface NftDataStructsCreateItemData extends Struct {
-  readonly dummyCreateItemData: u32;
-}
-
-/** @name NftDataStructsMetaUpdatePermission */
-export interface NftDataStructsMetaUpdatePermission extends Enum {
-  readonly isItemOwner: boolean;
-  readonly isAdmin: boolean;
-  readonly isNone: boolean;
-}
-
-/** @name NftDataStructsSchemaVersion */
-export interface NftDataStructsSchemaVersion extends Struct {
-  readonly dummySchemaVersion: u32;
-}
-
-/** @name NftDataStructsSponsorshipState */
-export interface NftDataStructsSponsorshipState extends Enum {
-  readonly isDisabled: boolean;
-  readonly isUnconfirmed: boolean;
-  readonly asUnconfirmed: AccountId;
-  readonly isConfirmed: boolean;
-  readonly asConfirmed: AccountId;
-}
-
-/** @name NftDataStructsTokenId */
-export interface NftDataStructsTokenId extends u32 {}
-
-/** @name PalletCommonAccountBasicCrossAccountIdRepr */
-export interface PalletCommonAccountBasicCrossAccountIdRepr extends Enum {
-  readonly isSubstrate: boolean;
-  readonly asSubstrate: AccountId;
-  readonly isEthereum: boolean;
-  readonly asEthereum: H160;
-}
-
-/** @name PalletNonfungibleItemData */
-export interface PalletNonfungibleItemData extends Struct {
-  readonly dummyNftItemData: u32;
-}
-
-/** @name PalletRefungibleItemData */
-export interface PalletRefungibleItemData extends Struct {
-  readonly dummyRftItemData: u32;
-}
-
-/** @name PalletUnqSchedulerCallSpec */
-export interface PalletUnqSchedulerCallSpec extends Struct {
-  readonly dummyCallSpec: u32;
-}
-
-/** @name PalletUnqSchedulerReleases */
-export interface PalletUnqSchedulerReleases extends Struct {
-  readonly dummyReleases: u32;
-}
-
-/** @name PalletUnqSchedulerScheduledV2 */
-export interface PalletUnqSchedulerScheduledV2 extends Struct {
-  readonly dummyScheduledV2: u32;
-}
-
-export type PHANTOM_NFT = 'nft';
modifiedtests/src/interfaces/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types.ts
+++ b/tests/src/interfaces/types.ts
@@ -1,6 +1,6 @@
 // Auto-generated via `yarn polkadot-types-from-defs`, do not edit
 /* eslint-disable */
 
-export * from './nft/types';
+export * from './unique/types';
 export * from './ethereum/types';
 export * from './polkadot/types';
addedtests/src/interfaces/unique/definitions.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/interfaces/unique/definitions.ts
@@ -0,0 +1,110 @@
+function mkDummy(name: string) {
+  return {
+    ['dummy' + name]: 'u32',
+  };
+}
+
+type RpcParam = {
+  name: string;
+  type: string;
+  isOptional?: true;
+};
+
+const CROSS_ACCOUNT_ID_TYPE = 'PalletCommonAccountBasicCrossAccountIdRepr';
+const TOKEN_ID_TYPE = 'UpDataStructsTokenId';
+
+const collectionParam = {name: 'collection', type: 'UpDataStructsCollectionId'};
+const tokenParam = {name: 'tokenId', type: TOKEN_ID_TYPE};
+const crossAccountParam = (name = 'account') => ({name, type: CROSS_ACCOUNT_ID_TYPE});
+const atParam = {name: 'at', type: 'Hash', isOptional: true};
+
+const fun = (description: string, params: RpcParam[], type: string) => ({
+  description,
+  params: [...params, atParam],
+  type,
+});
+
+export default {
+  rpc: {
+    adminlist: fun('Get admin list', [collectionParam], 'Vec<PalletCommonAccountBasicCrossAccountIdRepr>'),
+    allowlist: fun('Get allowlist', [collectionParam], 'Vec<PalletCommonAccountBasicCrossAccountIdRepr>'),
+
+    accountTokens: fun('Get tokens owned by account', [collectionParam, crossAccountParam()], 'Vec<UpDataStructsTokenId>'),
+    collectionTokens: fun('Get tokens contained in collection', [collectionParam], 'Vec<UpDataStructsTokenId>'),
+
+    lastTokenId: fun('Get last token id', [collectionParam], TOKEN_ID_TYPE),
+    accountBalance: fun('Get amount of different user tokens', [collectionParam, crossAccountParam()], 'u32'),
+    balance: fun('Get amount of specific account token', [collectionParam, crossAccountParam(), tokenParam], 'u128'),
+    allowance: fun('Get allowed amount', [collectionParam, crossAccountParam('sender'), crossAccountParam('spender'), tokenParam], 'u128'),
+    tokenOwner: fun('Get token owner', [collectionParam, tokenParam], CROSS_ACCOUNT_ID_TYPE),
+    constMetadata: fun('Get token constant metadata', [collectionParam, tokenParam], 'Vec<u8>'),
+    variableMetadata: fun('Get token variable metadata', [collectionParam, tokenParam], 'Vec<u8>'),
+    tokenExists: fun('Check if token exists', [collectionParam, tokenParam], 'bool'),
+    collectionById: fun('Get collection by specified id', [collectionParam], 'Option<UpDataStructsCollection>'),
+    collectionStats: fun('Get collection stats', [], 'UpDataStructsCollectionStats'),
+    allowed: fun('Check if user is allowed to use collection', [collectionParam, crossAccountParam()], 'bool'),
+  },
+  types: {
+    PalletCommonAccountBasicCrossAccountIdRepr: {
+      _enum: {
+        Substrate: 'AccountId',
+        Ethereum: 'H160',
+      },
+    },
+    UpDataStructsCollection: {
+      owner: 'AccountId',
+      mode: 'UpDataStructsCollectionMode',
+      access: 'UpDataStructsAccessMode',
+      name: 'Vec<u16>',
+      description: 'Vec<u16>',
+      tokenPrefix: 'Vec<u8>',
+      mintMode: 'bool',
+      offchainSchema: 'Vec<u8>',
+      schemaVersion: 'UpDataStructsSchemaVersion',
+      sponsorship: 'UpDataStructsSponsorshipState',
+      limits: 'UpDataStructsCollectionLimits',
+      variableOnChainSchema: 'Vec<u8>',
+      constOnChainSchema: 'Vec<u8>',
+      metaUpdatePermission: 'UpDataStructsMetaUpdatePermission',
+    },
+    UpDataStructsCollectionStats: {
+      created: 'u32',
+      destroyed: 'u32',
+      alive: 'u32',
+    },
+    UpDataStructsCollectionId: 'u32',
+    UpDataStructsTokenId: 'u32',
+    PalletNonfungibleItemData: mkDummy('NftItemData'),
+    PalletRefungibleItemData: mkDummy('RftItemData'),
+    UpDataStructsCollectionMode: mkDummy('CollectionMode'),
+    UpDataStructsCreateItemData: mkDummy('CreateItemData'),
+    UpDataStructsCollectionLimits: {
+      accountTokenOwnershipLimit: 'Option<u32>',
+      sponsoredDataSize: 'Option<u32>',
+      sponsoredDataRateLimit: 'Option<u32>',
+      tokenLimit: 'Option<u32>',
+      sponsorTransferTimeout: 'Option<u32>',
+      ownerCanTransfer: 'Option<bool>',
+      ownerCanDestroy: 'Option<bool>',
+      transfersEnabled: 'Option<bool>',
+    },
+    UpDataStructsMetaUpdatePermission: {
+      _enum: ['ItemOwner', 'Admin', 'None'],
+    },
+    UpDataStructsSponsorshipState: {
+      _enum: {
+        Disabled: null,
+        Unconfirmed: 'AccountId',
+        Confirmed: 'AccountId',
+      },
+    },
+    UpDataStructsAccessMode: {
+      _enum: ['Normal', 'AllowList'],
+    },
+    UpDataStructsSchemaVersion: mkDummy('SchemaVersion'),
+
+    PalletUnqSchedulerScheduledV2: mkDummy('ScheduledV2'),
+    PalletUnqSchedulerCallSpec: mkDummy('CallSpec'),
+    PalletUnqSchedulerReleases: mkDummy('Releases'),
+  },
+};
addedtests/src/interfaces/unique/index.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/interfaces/unique/index.ts
@@ -0,0 +1,4 @@
+// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
+/* eslint-disable */
+
+export * from './types';
addedtests/src/interfaces/unique/types.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/interfaces/unique/types.ts
@@ -0,0 +1,120 @@
+// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
+/* eslint-disable */
+
+import type { Bytes, Enum, Option, Struct, Vec, bool, u16, u32 } from '@polkadot/types';
+import type { AccountId, H160 } from '@polkadot/types/interfaces/runtime';
+
+/** @name PalletCommonAccountBasicCrossAccountIdRepr */
+export interface PalletCommonAccountBasicCrossAccountIdRepr extends Enum {
+  readonly isSubstrate: boolean;
+  readonly asSubstrate: AccountId;
+  readonly isEthereum: boolean;
+  readonly asEthereum: H160;
+}
+
+/** @name PalletNonfungibleItemData */
+export interface PalletNonfungibleItemData extends Struct {
+  readonly dummyNftItemData: u32;
+}
+
+/** @name PalletRefungibleItemData */
+export interface PalletRefungibleItemData extends Struct {
+  readonly dummyRftItemData: u32;
+}
+
+/** @name PalletUnqSchedulerCallSpec */
+export interface PalletUnqSchedulerCallSpec extends Struct {
+  readonly dummyCallSpec: u32;
+}
+
+/** @name PalletUnqSchedulerReleases */
+export interface PalletUnqSchedulerReleases extends Struct {
+  readonly dummyReleases: u32;
+}
+
+/** @name PalletUnqSchedulerScheduledV2 */
+export interface PalletUnqSchedulerScheduledV2 extends Struct {
+  readonly dummyScheduledV2: u32;
+}
+
+/** @name UpDataStructsAccessMode */
+export interface UpDataStructsAccessMode extends Enum {
+  readonly isNormal: boolean;
+  readonly isAllowList: boolean;
+}
+
+/** @name UpDataStructsCollection */
+export interface UpDataStructsCollection extends Struct {
+  readonly owner: AccountId;
+  readonly mode: UpDataStructsCollectionMode;
+  readonly access: UpDataStructsAccessMode;
+  readonly name: Vec<u16>;
+  readonly description: Vec<u16>;
+  readonly tokenPrefix: Bytes;
+  readonly mintMode: bool;
+  readonly offchainSchema: Bytes;
+  readonly schemaVersion: UpDataStructsSchemaVersion;
+  readonly sponsorship: UpDataStructsSponsorshipState;
+  readonly limits: UpDataStructsCollectionLimits;
+  readonly variableOnChainSchema: Bytes;
+  readonly constOnChainSchema: Bytes;
+  readonly metaUpdatePermission: UpDataStructsMetaUpdatePermission;
+}
+
+/** @name UpDataStructsCollectionId */
+export interface UpDataStructsCollectionId extends u32 {}
+
+/** @name UpDataStructsCollectionLimits */
+export interface UpDataStructsCollectionLimits extends Struct {
+  readonly accountTokenOwnershipLimit: Option<u32>;
+  readonly sponsoredDataSize: Option<u32>;
+  readonly sponsoredDataRateLimit: Option<u32>;
+  readonly tokenLimit: Option<u32>;
+  readonly sponsorTransferTimeout: Option<u32>;
+  readonly ownerCanTransfer: Option<bool>;
+  readonly ownerCanDestroy: Option<bool>;
+  readonly transfersEnabled: Option<bool>;
+}
+
+/** @name UpDataStructsCollectionMode */
+export interface UpDataStructsCollectionMode extends Struct {
+  readonly dummyCollectionMode: u32;
+}
+
+/** @name UpDataStructsCollectionStats */
+export interface UpDataStructsCollectionStats extends Struct {
+  readonly created: u32;
+  readonly destroyed: u32;
+  readonly alive: u32;
+}
+
+/** @name UpDataStructsCreateItemData */
+export interface UpDataStructsCreateItemData extends Struct {
+  readonly dummyCreateItemData: u32;
+}
+
+/** @name UpDataStructsMetaUpdatePermission */
+export interface UpDataStructsMetaUpdatePermission extends Enum {
+  readonly isItemOwner: boolean;
+  readonly isAdmin: boolean;
+  readonly isNone: boolean;
+}
+
+/** @name UpDataStructsSchemaVersion */
+export interface UpDataStructsSchemaVersion extends Struct {
+  readonly dummySchemaVersion: u32;
+}
+
+/** @name UpDataStructsSponsorshipState */
+export interface UpDataStructsSponsorshipState extends Enum {
+  readonly isDisabled: boolean;
+  readonly isUnconfirmed: boolean;
+  readonly asUnconfirmed: AccountId;
+  readonly isConfirmed: boolean;
+  readonly asConfirmed: AccountId;
+}
+
+/** @name UpDataStructsTokenId */
+export interface UpDataStructsTokenId extends u32 {}
+
+export type PHANTOM_UNIQUE = 'unique';
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -35,10 +35,10 @@
   'cumulusxcm',
   'dmpqueue',
   'inflation',
-  'nft',
+  'unique',
   'nonfungible',
   'refungible',
-  'scheduler',
+  //'scheduler',
   'charging',
 ];
 
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -22,14 +22,14 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.deep.eq(alice.address);
       // first - add collection admin Bob
-      const addAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await submitTransactionAsync(alice, addAdminTx);
 
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
       expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
 
       // then remove bob from admins of collection
-      const removeAdminTx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await submitTransactionAsync(alice, removeAdminTx);
 
       const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
@@ -46,17 +46,17 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.eq(alice.address);
       // first - add collection admin Bob
-      const addAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await submitTransactionAsync(alice, addAdminTx);
 
-      const addAdminTx2 = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
+      const addAdminTx2 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
       await submitTransactionAsync(alice, addAdminTx2);
 
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
       expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
 
       // then remove bob from admins of collection
-      const removeAdminTx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await submitTransactionAsync(charlie, removeAdminTx);
 
       const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
@@ -72,7 +72,7 @@
       const adminListBeforeAddAdmin = await getAdminList(api, collectionId);
       expect(adminListBeforeAddAdmin).to.have.lengthOf(0);
 
-      const tx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(alice.address));
+      const tx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(alice.address));
       await submitTransactionAsync(alice, tx);
     });
   });
@@ -86,7 +86,7 @@
       const alice = privateKey('//Alice');
       const bob = privateKey('//Bob');
 
-      const changeOwnerTx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
 
       // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
@@ -103,7 +103,7 @@
 
       await destroyCollectionExpectSuccess(collectionId);
 
-      const changeOwnerTx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
 
       // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
@@ -118,10 +118,10 @@
       const bob = privateKey('//Bob');
       const charlie = privateKey('//Charlie');
 
-      const addAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await submitTransactionAsync(alice, addAdminTx);
 
-      const changeOwnerTx = api.tx.nft.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
       await expect(submitTransactionExpectFailAsync(charlie, changeOwnerTx)).to.be.rejected;
 
       // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
modifiedtests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionSponsor.test.ts
+++ b/tests/src/removeCollectionSponsor.test.ts
@@ -54,7 +54,7 @@
 
       // Transfer this tokens from unused address to Alice - should fail
       const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();
-      const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);
+      const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);
       const badTransaction = async function () {
         await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);
       };
modifiedtests/src/scheduler.test.tsdiffbeforeafterboth
--- a/tests/src/scheduler.test.ts
+++ b/tests/src/scheduler.test.ts
@@ -17,7 +17,7 @@
 
 chai.use(chaiAsPromised);
 
-describe('Integration Test scheduler base transaction', () => {
+describe.skip('Integration Test scheduler base transaction', () => {
   it('User can transfer owned token with delay (scheduler)', async () => {
     await usingApi(async () => {
       const alice = privateKey('//Alice');
modifiedtests/src/setCollectionLimits.test.tsdiffbeforeafterboth
--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -41,7 +41,7 @@
   });
   it('execute setCollectionLimits with predefined params ', async () => {
     await usingApi(async (api: ApiPromise) => {
-      tx = api.tx.nft.setCollectionLimits(
+      tx = api.tx.unique.setCollectionLimits(
         collectionIdForTesting,
         {
           accountTokenOwnershipLimit: accountTokenOwnershipLimit,
@@ -82,7 +82,7 @@
       };
 
       // The first time
-      const tx1 = api.tx.nft.setCollectionLimits(
+      const tx1 = api.tx.unique.setCollectionLimits(
         collectionIdForTesting,
         collectionLimits,
       );
@@ -93,7 +93,7 @@
       expect(collectionInfo1.limits.tokenLimit.unwrap().toNumber()).to.be.equal(tokenLimit);
 
       // The second time
-      const tx2 = api.tx.nft.setCollectionLimits(
+      const tx2 = api.tx.unique.setCollectionLimits(
         collectionIdForTesting,
         collectionLimits,
       );
@@ -121,7 +121,7 @@
     await usingApi(async (api: ApiPromise) => {
       const collectionCount = await getCreatedCollectionCount(api);
       const nonExistedCollectionId = collectionCount + 1;
-      tx = api.tx.nft.setCollectionLimits(
+      tx = api.tx.unique.setCollectionLimits(
         nonExistedCollectionId,
         {
           accountTokenOwnershipLimit,
@@ -135,7 +135,7 @@
   });
   it('execute setCollectionLimits from user who is not owner of this collection', async () => {
     await usingApi(async (api: ApiPromise) => {
-      tx = api.tx.nft.setCollectionLimits(
+      tx = api.tx.unique.setCollectionLimits(
         collectionIdForTesting,
         {
           accountTokenOwnershipLimit,
@@ -150,7 +150,7 @@
   it('execute setCollectionLimits from admin collection', async () => {
     await addCollectionAdminExpectSuccess(alice, collectionIdForTesting, bob.address);
     await usingApi(async (api: ApiPromise) => {
-      tx = api.tx.nft.setCollectionLimits(
+      tx = api.tx.unique.setCollectionLimits(
         collectionIdForTesting,
         {
           accountTokenOwnershipLimit,
modifiedtests/src/setConstOnChainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setConstOnChainSchema.test.ts
+++ b/tests/src/setConstOnChainSchema.test.ts
@@ -41,7 +41,7 @@
       const collectionId = await createCollectionExpectSuccess();
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.eq(alice.address);
-      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, shema);
+      const setShema = api.tx.unique.setConstOnChainSchema(collectionId, shema);
       await submitTransactionAsync(alice, setShema);
     });
   });
@@ -52,7 +52,7 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.eq(alice.address);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, shema);
+      const setShema = api.tx.unique.setConstOnChainSchema(collectionId, shema);
       await submitTransactionAsync(bob, setShema);
     });
   });
@@ -60,7 +60,7 @@
   it('Checking collection data using the ConstOnChainSchema parameter', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, shema);
+      const setShema = api.tx.unique.setConstOnChainSchema(collectionId, shema);
       await submitTransactionAsync(alice, setShema);
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.constOnChainSchema.toString()).to.be.eq(shema);
@@ -74,7 +74,7 @@
     await usingApi(async (api) => {
       // tslint:disable-next-line: radix
       const collectionId = await getCreatedCollectionCount(api) + 1;
-      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, shema);
+      const setShema = api.tx.unique.setConstOnChainSchema(collectionId, shema);
       await expect(submitTransactionExpectFailAsync(alice, setShema)).to.be.rejected;
     });
   });
@@ -83,7 +83,7 @@
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
       await destroyCollectionExpectSuccess(collectionId);
-      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, shema);
+      const setShema = api.tx.unique.setConstOnChainSchema(collectionId, shema);
       await expect(submitTransactionExpectFailAsync(alice, setShema)).to.be.rejected;
     });
   });
@@ -91,7 +91,7 @@
   it('Set invalid data in schema (size too large:> 1024b)', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, largeShema);
+      const setShema = api.tx.unique.setConstOnChainSchema(collectionId, largeShema);
       await expect(submitTransactionExpectFailAsync(alice, setShema)).to.be.rejected;
     });
   });
@@ -101,7 +101,7 @@
       const collectionId = await createCollectionExpectSuccess();
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.eq(alice.address);
-      const setShema = api.tx.nft.setConstOnChainSchema(collectionId, shema);
+      const setShema = api.tx.unique.setConstOnChainSchema(collectionId, shema);
       await expect(submitTransactionExpectFailAsync(bob, setShema)).to.be.rejected;
     });
   });
modifiedtests/src/setPublicAccessMode.test.tsdiffbeforeafterboth
--- a/tests/src/setPublicAccessMode.test.ts
+++ b/tests/src/setPublicAccessMode.test.ts
@@ -51,7 +51,7 @@
       const collectionId = await createCollectionExpectSuccess();
       await enableAllowListExpectSuccess(alice, collectionId);
       await enablePublicMintingExpectSuccess(alice, collectionId);
-      const tx = api.tx.nft.createItem(collectionId, normalizeAccountId(bob.address), 'NFT');
+      const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(bob.address), 'NFT');
       await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
     });
   });
@@ -62,7 +62,7 @@
     await usingApi(async (api: ApiPromise) => {
       // tslint:disable-next-line: radix
       const collectionId = await getCreatedCollectionCount(api) + 1;
-      const tx = api.tx.nft.setPublicAccessMode(collectionId, 'AllowList');
+      const tx = api.tx.unique.setPublicAccessMode(collectionId, 'AllowList');
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
@@ -72,7 +72,7 @@
       // tslint:disable-next-line: no-bitwise
       const collectionId = await createCollectionExpectSuccess();
       await destroyCollectionExpectSuccess(collectionId);
-      const tx = api.tx.nft.setPublicAccessMode(collectionId, 'AllowList');
+      const tx = api.tx.unique.setPublicAccessMode(collectionId, 'AllowList');
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
@@ -89,7 +89,7 @@
     await usingApi(async (api: ApiPromise) => {
       // tslint:disable-next-line: no-bitwise
       const collectionId = await createCollectionExpectSuccess();
-      const tx = api.tx.nft.setPublicAccessMode(collectionId, 'AllowList');
+      const tx = api.tx.unique.setPublicAccessMode(collectionId, 'AllowList');
       await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
     });
   });
@@ -107,7 +107,7 @@
       // tslint:disable-next-line: no-bitwise
       const collectionId = await createCollectionExpectSuccess();
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const tx = api.tx.nft.setPublicAccessMode(collectionId, 'AllowList');
+      const tx = api.tx.unique.setPublicAccessMode(collectionId, 'AllowList');
       await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
     });
   });
modifiedtests/src/setSchemaVersion.test.tsdiffbeforeafterboth
--- a/tests/src/setSchemaVersion.test.ts
+++ b/tests/src/setSchemaVersion.test.ts
@@ -41,7 +41,7 @@
   it('execute setSchemaVersion with image url and unique ', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});
-      tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'Unique');
+      tx = api.tx.unique.setSchemaVersion(collectionIdForTesting, 'Unique');
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateItemResult(events);
       const collectionInfo = await getDetailedCollectionInfo(api, collectionIdForTesting);
@@ -70,7 +70,7 @@
   });
   it('execute setSchemaVersion with image url and unique ', async () => {
     await usingApi(async (api: ApiPromise) => {
-      tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'Unique');
+      tx = api.tx.unique.setSchemaVersion(collectionIdForTesting, 'Unique');
       const events = await submitTransactionAsync(bob, tx);
       const result = getCreateItemResult(events);
       const collectionInfo = await getDetailedCollectionInfo(api, collectionIdForTesting);
@@ -85,7 +85,7 @@
 
   it('validate schema version with just entered data', async () => {
     await usingApi(async (api: ApiPromise) => {
-      tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'ImageURL');
+      tx = api.tx.unique.setSchemaVersion(collectionIdForTesting, 'ImageURL');
       const events = await submitTransactionAsync(bob, tx);
       const result = getCreateItemResult(events);
       const collectionInfo = await getDetailedCollectionInfo(api, collectionIdForTesting);
@@ -114,20 +114,20 @@
     await usingApi(async (api: ApiPromise) => {
       const collectionCount = await getCreatedCollectionCount(api);
       const nonExistedCollectionId = collectionCount + 1;
-      tx = api.tx.nft.setSchemaVersion(nonExistedCollectionId, 'ImageURL');
+      tx = api.tx.unique.setSchemaVersion(nonExistedCollectionId, 'ImageURL');
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
   it('execute setSchemaVersion for deleted collection', async () => {
     await usingApi(async (api: ApiPromise) => {
       await destroyCollectionExpectSuccess(collectionIdForTesting);
-      tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'ImageURL');
+      tx = api.tx.unique.setSchemaVersion(collectionIdForTesting, 'ImageURL');
       await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
     });
   });
   it('Regular user can`t execute setSchemaVersion with image url and unique ', async () => {
     await usingApi(async (api: ApiPromise) => {
-      tx = api.tx.nft.setSchemaVersion(collectionIdForTesting, 'Unique');
+      tx = api.tx.unique.setSchemaVersion(collectionIdForTesting, 'Unique');
       await expect(submitTransactionAsync(charlie, tx)).to.be.rejected;
     });
   });
modifiedtests/src/setVariableOnChainSchema.test.tsdiffbeforeafterboth
--- a/tests/src/setVariableOnChainSchema.test.ts
+++ b/tests/src/setVariableOnChainSchema.test.ts
@@ -41,7 +41,7 @@
       const collectionId = await createCollectionExpectSuccess();
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.eq(alice.address);
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, schema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, schema);
       await submitTransactionAsync(alice, setSchema);
     });
   });
@@ -49,7 +49,7 @@
   it('Checking collection data using the setVariableOnChainSchema parameter', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, schema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, schema);
       await submitTransactionAsync(alice, setSchema);
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.variableOnChainSchema.toString()).to.be.eq(schema);
@@ -66,7 +66,7 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.eq(alice.address);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, schema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, schema);
       await submitTransactionAsync(bob, setSchema);
     });
   });
@@ -75,7 +75,7 @@
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, schema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, schema);
       await submitTransactionAsync(bob, setSchema);
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.variableOnChainSchema.toString()).to.be.eq(schema);
@@ -90,7 +90,7 @@
     await usingApi(async (api) => {
       // tslint:disable-next-line: radix
       const collectionId = await getCreatedCollectionCount(api) + 1;
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, schema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, schema);
       await expect(submitTransactionExpectFailAsync(alice, setSchema)).to.be.rejected;
     });
   });
@@ -99,7 +99,7 @@
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
       await destroyCollectionExpectSuccess(collectionId);
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, schema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, schema);
       await expect(submitTransactionExpectFailAsync(alice, setSchema)).to.be.rejected;
     });
   });
@@ -107,7 +107,7 @@
   it('Set invalid data in schema (size too large:> 1024b)', async () => {
     await usingApi(async (api) => {
       const collectionId = await createCollectionExpectSuccess();
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, largeSchema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, largeSchema);
       await expect(submitTransactionExpectFailAsync(alice, setSchema)).to.be.rejected;
     });
   });
@@ -117,7 +117,7 @@
       const collectionId = await createCollectionExpectSuccess();
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.eq(alice.address);
-      const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, schema);
+      const setSchema = api.tx.unique.setVariableOnChainSchema(collectionId, schema);
       await expect(submitTransactionExpectFailAsync(bob, setSchema)).to.be.rejected;
     });
   });
modifiedtests/src/substrate/substrate-api.tsdiffbeforeafterboth
--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -24,7 +24,7 @@
       },
     },
     rpc: {
-      nft: defs.nft.rpc,
+      unique: defs.unique.rpc,
     },
   };
 }
modifiedtests/src/toggleContractAllowList.test.tsdiffbeforeafterboth
--- a/tests/src/toggleContractAllowList.test.ts
+++ b/tests/src/toggleContractAllowList.test.ts
@@ -27,10 +27,10 @@
     await usingApi(async api => {
       const [contract, deployer] = await deployFlipper(api);
 
-      const enabledBefore = (await api.query.nft.contractAllowListEnabled(contract.address)).toJSON();
-      const enableAllowListTx = api.tx.nft.toggleContractAllowList(contract.address, true);
+      const enabledBefore = (await api.query.unique.contractAllowListEnabled(contract.address)).toJSON();
+      const enableAllowListTx = api.tx.unique.toggleContractAllowList(contract.address, true);
       const enableEvents = await submitTransactionAsync(deployer, enableAllowListTx);
-      const enabled = (await api.query.nft.contractAllowListEnabled(contract.address)).toJSON();
+      const enabled = (await api.query.unique.contractAllowListEnabled(contract.address)).toJSON();
 
       expect(getGenericResult(enableEvents).success).to.be.true;
       expect(enabledBefore).to.be.false;
@@ -60,7 +60,7 @@
       await deployerCanFlip();
 
       flipValueBefore = await getFlipValue(contract, deployer);
-      const enableAllowListTx = api.tx.nft.toggleContractAllowList(contract.address, true);
+      const enableAllowListTx = api.tx.unique.toggleContractAllowList(contract.address, true);
       await submitTransactionAsync(deployer, enableAllowListTx);
       const flipWithEnabledAllowList = contract.tx.flip(value, gasLimit);
       await expect(submitTransactionExpectFailAsync(bob, flipWithEnabledAllowList)).to.be.rejected;
@@ -70,7 +70,7 @@
       await deployerCanFlip();
 
       flipValueBefore = await getFlipValue(contract, deployer);
-      const addBobToAllowListTx = api.tx.nft.addToContractAllowList(contract.address, bob.address);
+      const addBobToAllowListTx = api.tx.unique.addToContractAllowList(contract.address, bob.address);
       await submitTransactionAsync(deployer, addBobToAllowListTx);
       const flipWithAllowlistedBob = contract.tx.flip(value, gasLimit);
       await submitTransactionAsync(bob, flipWithAllowlistedBob);
@@ -80,7 +80,7 @@
       await deployerCanFlip();
 
       flipValueBefore = await getFlipValue(contract, deployer);
-      const removeBobFromAllowListTx = api.tx.nft.removeFromContractAllowList(contract.address, bob.address);
+      const removeBobFromAllowListTx = api.tx.unique.removeFromContractAllowList(contract.address, bob.address);
       await submitTransactionAsync(deployer, removeBobFromAllowListTx);
       const bobRemoved = contract.tx.flip(value, gasLimit);
       await expect(submitTransactionExpectFailAsync(bob, bobRemoved)).to.be.rejected;
@@ -90,7 +90,7 @@
       await deployerCanFlip();
 
       flipValueBefore = await getFlipValue(contract, deployer);
-      const disableAllowListTx = api.tx.nft.toggleContractAllowList(contract.address, false);
+      const disableAllowListTx = api.tx.unique.toggleContractAllowList(contract.address, false);
       await submitTransactionAsync(deployer, disableAllowListTx);
       const allowListDisabledFlip = contract.tx.flip(value, gasLimit);
       await submitTransactionAsync(bob, allowListDisabledFlip);
@@ -104,12 +104,12 @@
     await usingApi(async api => {
       const [contract, deployer] = await deployFlipper(api);
 
-      const enabledBefore = (await api.query.nft.contractAllowListEnabled(contract.address)).toJSON();
-      const enableAllowListTx = api.tx.nft.toggleContractAllowList(contract.address, true);
+      const enabledBefore = (await api.query.unique.contractAllowListEnabled(contract.address)).toJSON();
+      const enableAllowListTx = api.tx.unique.toggleContractAllowList(contract.address, true);
       const enableEvents = await submitTransactionAsync(deployer, enableAllowListTx);
-      const enabled = (await api.query.nft.contractAllowListEnabled(contract.address)).toJSON();
+      const enabled = (await api.query.unique.contractAllowListEnabled(contract.address)).toJSON();
       const enableAgainEvents = await submitTransactionAsync(deployer, enableAllowListTx);
-      const enabledAgain = (await api.query.nft.contractAllowListEnabled(contract.address)).toJSON();
+      const enabledAgain = (await api.query.unique.contractAllowListEnabled(contract.address)).toJSON();
 
       expect(getGenericResult(enableEvents).success).to.be.true;
       expect(enabledBefore).to.be.false;
@@ -128,10 +128,10 @@
       const alice = privateKey('//Alice');
       const bobGuineaPig = privateKey('//Bob');
 
-      const enabledBefore = (await api.query.nft.contractAllowListEnabled(bobGuineaPig.address)).toJSON();
-      const enableAllowListTx = api.tx.nft.toggleContractAllowList(bobGuineaPig.address, true);
+      const enabledBefore = (await api.query.unique.contractAllowListEnabled(bobGuineaPig.address)).toJSON();
+      const enableAllowListTx = api.tx.unique.toggleContractAllowList(bobGuineaPig.address, true);
       await expect(submitTransactionExpectFailAsync(alice, enableAllowListTx)).to.be.rejected;
-      const enabled = (await api.query.nft.contractAllowListEnabled(bobGuineaPig.address)).toJSON();
+      const enabled = (await api.query.unique.contractAllowListEnabled(bobGuineaPig.address)).toJSON();
 
       expect(enabledBefore).to.be.false;
       expect(enabled).to.be.false;
@@ -143,10 +143,10 @@
       const bob = privateKey('//Bob');
       const [contract] = await deployFlipper(api);
 
-      const enabledBefore = (await api.query.nft.contractAllowListEnabled(contract.address)).toJSON();
-      const enableAllowListTx = api.tx.nft.toggleContractAllowList(contract.address, true);
+      const enabledBefore = (await api.query.unique.contractAllowListEnabled(contract.address)).toJSON();
+      const enableAllowListTx = api.tx.unique.toggleContractAllowList(contract.address, true);
       await expect(submitTransactionExpectFailAsync(bob, enableAllowListTx)).to.be.rejected;
-      const enabled = (await api.query.nft.contractAllowListEnabled(contract.address)).toJSON();
+      const enabled = (await api.query.unique.contractAllowListEnabled(contract.address)).toJSON();
 
       expect(enabledBefore).to.be.false;
       expect(enabled).to.be.false;
modifiedtests/src/transfer.test.tsdiffbeforeafterboth
--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -249,7 +249,7 @@
       const nftCollectionId = await createCollectionExpectSuccess();
       const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
 
-      const transferTx = api.tx.nft.transfer(normalizeAccountId(bob), nftCollectionId, newNftTokenId, 0);
+      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), nftCollectionId, newNftTokenId, 0);
       await submitTransactionAsync(alice, transferTx);
       const address = normalizeAccountId(await getTokenOwner(api, nftCollectionId, newNftTokenId));
 
@@ -264,7 +264,7 @@
       const balanceBeforeAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);
       const balanceBeforeBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);
 
-      const transferTx = api.tx.nft.transfer(normalizeAccountId(bob), reFungibleCollectionId, newReFungibleTokenId, 0);
+      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), reFungibleCollectionId, newReFungibleTokenId, 0);
       await submitTransactionAsync(alice, transferTx);
 
       const balanceAfterAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);
@@ -282,7 +282,7 @@
       const balanceBeforeAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);
       const balanceBeforeBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);
 
-      const transferTx = api.tx.nft.transfer(normalizeAccountId(bob), fungibleCollectionId, newFungibleTokenId, 0);
+      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), fungibleCollectionId, newFungibleTokenId, 0);
       await submitTransactionAsync(alice, transferTx);
 
       const balanceAfterAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -11,7 +11,7 @@
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
 import {alicesPublicKey} from '../accounts';
-import {NftDataStructsCollection} from '../interfaces';
+import {UpDataStructsCollection} from '../interfaces';
 import privateKey from '../substrate/privateKey';
 import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from '../substrate/substrate-api';
 import {hexToStr, strToUTF16, utf16ToStr} from './util';
@@ -105,7 +105,7 @@
 }
 
 interface IGetMessage {
-  checkMsgNftMethod: string;
+  checkMsgUnqMethod: string;
   checkMsgTrsMethod: string;
   checkMsgSysMethod: string;
 }
@@ -133,13 +133,13 @@
   variableData: number[];
 }
 
-export function nftEventMessage(events: EventRecord[]): IGetMessage {
-  let checkMsgNftMethod = '';
+export function uniqueEventMessage(events: EventRecord[]): IGetMessage {
+  let checkMsgUnqMethod = '';
   let checkMsgTrsMethod = '';
   let checkMsgSysMethod = '';
   events.forEach(({event: {method, section}}) => {
     if (section === 'common') {
-      checkMsgNftMethod = method;
+      checkMsgUnqMethod = method;
     } else if (section === 'treasury') {
       checkMsgTrsMethod = method;
     } else if (section === 'system') {
@@ -147,7 +147,7 @@
     } else { return null; }
   });
   const result: IGetMessage = {
-    checkMsgNftMethod,
+    checkMsgUnqMethod,
     checkMsgTrsMethod,
     checkMsgSysMethod,
   };
@@ -283,7 +283,7 @@
       modeprm = {refungible: null};
     }
 
-    const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm as any);
+    const tx = api.tx.unique.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm as any);
     const events = await submitTransactionAsync(alicePrivateKey, tx);
     const result = getCreateCollectionResult(events);
 
@@ -329,7 +329,7 @@
 
     // Run the CreateCollection transaction
     const alicePrivateKey = privateKey('//Alice');
-    const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm as any);
+    const tx = api.tx.unique.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm as any);
     const events = await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;
     const result = getCreateCollectionResult(events);
 
@@ -356,7 +356,7 @@
 }
 
 export async function getAllowance(api: ApiPromise, collectionId: number, owner: CrossAccountId | string, approved: CrossAccountId | string, tokenId: number) {
-  return (await api.rpc.nft.allowance(collectionId, normalizeAccountId(owner), normalizeAccountId(approved), tokenId)).toBigInt();
+  return (await api.rpc.unique.allowance(collectionId, normalizeAccountId(owner), normalizeAccountId(approved), tokenId)).toBigInt();
 }
 
 export function findUnusedAddresses(api: ApiPromise, amount: number): Promise<IKeyringPair[]> {
@@ -383,7 +383,7 @@
   await usingApi(async (api) => {
     // Run the DestroyCollection transaction
     const alicePrivateKey = privateKey(senderSeed);
-    const tx = api.tx.nft.destroyCollection(collectionId);
+    const tx = api.tx.unique.destroyCollection(collectionId);
     await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;
   });
 }
@@ -392,7 +392,7 @@
   await usingApi(async (api) => {
     // Run the DestroyCollection transaction
     const alicePrivateKey = privateKey(senderSeed);
-    const tx = api.tx.nft.destroyCollection(collectionId);
+    const tx = api.tx.unique.destroyCollection(collectionId);
     const events = await submitTransactionAsync(alicePrivateKey, tx);
     const result = getDestroyResult(events);
     expect(result).to.be.true;
@@ -404,7 +404,7 @@
 
 export async function setCollectionLimitsExpectSuccess(sender: IKeyringPair, collectionId: number, limits: any) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setCollectionLimits(collectionId, limits);
+    const tx = api.tx.unique.setCollectionLimits(collectionId, limits);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -414,7 +414,7 @@
 
 export async function setCollectionLimitsExpectFailure(sender: IKeyringPair, collectionId: number, limits: any) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setCollectionLimits(collectionId, limits);
+    const tx = api.tx.unique.setCollectionLimits(collectionId, limits);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -427,7 +427,7 @@
 
     // Run the transaction
     const senderPrivateKey = privateKey(sender);
-    const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);
+    const tx = api.tx.unique.setCollectionSponsor(collectionId, sponsor);
     const events = await submitTransactionAsync(senderPrivateKey, tx);
     const result = getGenericResult(events);
 
@@ -447,7 +447,7 @@
 
     // Run the transaction
     const alicePrivateKey = privateKey(sender);
-    const tx = api.tx.nft.removeCollectionSponsor(collectionId);
+    const tx = api.tx.unique.removeCollectionSponsor(collectionId);
     const events = await submitTransactionAsync(alicePrivateKey, tx);
     const result = getGenericResult(events);
 
@@ -465,7 +465,7 @@
 
     // Run the transaction
     const alicePrivateKey = privateKey(senderSeed);
-    const tx = api.tx.nft.removeCollectionSponsor(collectionId);
+    const tx = api.tx.unique.removeCollectionSponsor(collectionId);
     await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;
   });
 }
@@ -475,7 +475,7 @@
 
     // Run the transaction
     const alicePrivateKey = privateKey(senderSeed);
-    const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor);
+    const tx = api.tx.unique.setCollectionSponsor(collectionId, sponsor);
     await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;
   });
 }
@@ -485,7 +485,7 @@
 
     // Run the transaction
     const sender = privateKey(senderSeed);
-    const tx = api.tx.nft.confirmSponsorship(collectionId);
+    const tx = api.tx.unique.confirmSponsorship(collectionId);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -506,7 +506,7 @@
 
     // Run the transaction
     const sender = privateKey(senderSeed);
-    const tx = api.tx.nft.confirmSponsorship(collectionId);
+    const tx = api.tx.unique.confirmSponsorship(collectionId);
     await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
   });
 }
@@ -514,7 +514,7 @@
 export async function setMetadataUpdatePermissionFlagExpectSuccess(sender: IKeyringPair, collectionId: number, flag: string) {
 
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setMetaUpdatePermissionFlag(collectionId, flag as any);
+    const tx = api.tx.unique.setMetaUpdatePermissionFlag(collectionId, flag as any);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -525,7 +525,7 @@
 export async function setMetadataUpdatePermissionFlagExpectFailure(sender: IKeyringPair, collectionId: number, flag: string) {
 
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setMetaUpdatePermissionFlag(collectionId, flag as any);
+    const tx = api.tx.unique.setMetaUpdatePermissionFlag(collectionId, flag as any);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -535,7 +535,7 @@
 
 export async function enableContractSponsoringExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);
+    const tx = api.tx.unique.enableContractSponsoring(contractAddress, enable);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -545,7 +545,7 @@
 
 export async function enableContractSponsoringExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, enable: boolean) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.enableContractSponsoring(contractAddress, enable);
+    const tx = api.tx.unique.enableContractSponsoring(contractAddress, enable);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -557,7 +557,7 @@
 
   await usingApi(async (api) => {
 
-    const tx = api.tx.nft.setTransfersEnabledFlag (collectionId, enabled);
+    const tx = api.tx.unique.setTransfersEnabledFlag (collectionId, enabled);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -569,7 +569,7 @@
 
   await usingApi(async (api) => {
 
-    const tx = api.tx.nft.setTransfersEnabledFlag (collectionId, enabled);
+    const tx = api.tx.unique.setTransfersEnabledFlag (collectionId, enabled);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -579,7 +579,7 @@
 
 export async function setContractSponsoringRateLimitExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);
+    const tx = api.tx.unique.setContractSponsoringRateLimit(contractAddress, rateLimit);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -589,7 +589,7 @@
 
 export async function setContractSponsoringRateLimitExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, rateLimit: number) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setContractSponsoringRateLimit(contractAddress, rateLimit);
+    const tx = api.tx.unique.setContractSponsoringRateLimit(contractAddress, rateLimit);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -599,7 +599,7 @@
 
 export async function toggleContractAllowlistExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, value = true) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.toggleContractAllowList(contractAddress, value);
+    const tx = api.tx.unique.toggleContractAllowList(contractAddress, value);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -610,14 +610,14 @@
 export async function isAllowlistedInContract(contractAddress: AccountId | string, user: string) {
   let allowlisted = false;
   await usingApi(async (api) => {
-    allowlisted = (await api.query.nft.contractAllowList(contractAddress, user)).toJSON() as boolean;
+    allowlisted = (await api.query.unique.contractAllowList(contractAddress, user)).toJSON() as boolean;
   });
   return allowlisted;
 }
 
 export async function addToContractAllowListExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, user: AccountId | string) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.addToContractAllowList(contractAddress.toString(), user.toString());
+    const tx = api.tx.unique.addToContractAllowList(contractAddress.toString(), user.toString());
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -627,7 +627,7 @@
 
 export async function removeFromContractAllowListExpectSuccess(sender: IKeyringPair, contractAddress: AccountId | string, user: AccountId | string) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.removeFromContractAllowList(contractAddress.toString(), user.toString());
+    const tx = api.tx.unique.removeFromContractAllowList(contractAddress.toString(), user.toString());
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -637,7 +637,7 @@
 
 export async function removeFromContractAllowListExpectFailure(sender: IKeyringPair, contractAddress: AccountId | string, user: AccountId | string) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.removeFromContractAllowList(contractAddress.toString(), user.toString());
+    const tx = api.tx.unique.removeFromContractAllowList(contractAddress.toString(), user.toString());
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -647,7 +647,7 @@
 
 export async function setVariableMetaDataExpectSuccess(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
+    const tx = api.tx.unique.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -657,14 +657,14 @@
 
 export async function setVariableMetaDataExpectFailure(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
+    const tx = api.tx.unique.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
     await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
   });
 }
 
 export async function setOffchainSchemaExpectSuccess(sender: IKeyringPair, collectionId: number, data: number[]) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setOffchainSchema(collectionId, '0x' + Buffer.from(data).toString('hex'));
+    const tx = api.tx.unique.setOffchainSchema(collectionId, '0x' + Buffer.from(data).toString('hex'));
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -674,7 +674,7 @@
 
 export async function setOffchainSchemaExpectFailure(sender: IKeyringPair, collectionId: number, data: number[]) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.setOffchainSchema(collectionId, '0x' + Buffer.from(data).toString('hex'));
+    const tx = api.tx.unique.setOffchainSchema(collectionId, '0x' + Buffer.from(data).toString('hex'));
     await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
   });
 }
@@ -700,7 +700,7 @@
     // if burning token by admin - use adminButnItemExpectSuccess
     expect(balanceBefore >= BigInt(value)).to.be.true;
 
-    const tx = api.tx.nft.burnItem(collectionId, tokenId, value);
+    const tx = api.tx.unique.burnItem(collectionId, tokenId, value);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
     expect(result.success).to.be.true;
@@ -716,8 +716,8 @@
   tokenId: number, owner: IKeyringPair, approved: CrossAccountId | string, amount: number | bigint = 1,
 ) {
   await usingApi(async (api: ApiPromise) => {
-    const approveNftTx = api.tx.nft.approve(normalizeAccountId(approved), collectionId, tokenId, amount);
-    const events = await submitTransactionAsync(owner, approveNftTx);
+    const approveUniqueTx = api.tx.unique.approve(normalizeAccountId(approved), collectionId, tokenId, amount);
+    const events = await submitTransactionAsync(owner, approveUniqueTx);
     const result = getGenericResult(events);
     expect(result.success).to.be.true;
 
@@ -730,8 +730,8 @@
   tokenId: number, admin: IKeyringPair, owner: CrossAccountId | string, approved: CrossAccountId | string, amount: number | bigint = 1,
 ) {
   await usingApi(async (api: ApiPromise) => {
-    const approveNftTx = api.tx.nft.approve(normalizeAccountId(approved), collectionId, tokenId, amount);
-    const events = await submitTransactionAsync(admin, approveNftTx);
+    const approveUniqueTx = api.tx.unique.approve(normalizeAccountId(approved), collectionId, tokenId, amount);
+    const events = await submitTransactionAsync(admin, approveUniqueTx);
     const result = getGenericResult(events);
     expect(result.success).to.be.true;
 
@@ -755,7 +755,7 @@
     if (type === 'Fungible') {
       balanceBefore = await getBalance(api, collectionId, to, tokenId);
     }
-    const transferFromTx = api.tx.nft.transferFrom(normalizeAccountId(accountFrom), to, collectionId, tokenId, value);
+    const transferFromTx = api.tx.unique.transferFrom(normalizeAccountId(accountFrom), to, collectionId, tokenId, value);
     const events = await submitTransactionAsync(accountApproved, transferFromTx);
     const result = getCreateItemResult(events);
     // tslint:disable-next-line:no-unused-expression
@@ -783,7 +783,7 @@
   value: number | bigint = 1,
 ) {
   await usingApi(async (api: ApiPromise) => {
-    const transferFromTx = api.tx.nft.transferFrom(normalizeAccountId(accountFrom.address), normalizeAccountId(accountTo.address), collectionId, tokenId, value);
+    const transferFromTx = api.tx.unique.transferFrom(normalizeAccountId(accountFrom.address), normalizeAccountId(accountTo.address), collectionId, tokenId, value);
     const events = await expect(submitTransactionExpectFailAsync(accountApproved, transferFromTx)).to.be.rejected;
     const result = getCreateCollectionResult(events);
     // tslint:disable-next-line:no-unused-expression
@@ -803,7 +803,7 @@
 
 export async function addCollectionAdminExpectSuccess(sender: IKeyringPair, collectionId: number, address: string | CrossAccountId) {
   await usingApi(async (api) => {
-    const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, normalizeAccountId(address));
+    const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(address));
     const events = await submitTransactionAsync(sender, changeAdminTx);
     const result = getCreateCollectionResult(events);
     expect(result.success).to.be.true;
@@ -835,7 +835,7 @@
     const expectedBlockNumber = blockNumber + blockSchedule;
 
     expect(blockNumber).to.be.greaterThan(0);
-    const transferTx = api.tx.nft.transfer(normalizeAccountId(recipient.address), collectionId, tokenId, value);
+    const transferTx = api.tx.unique.transfer(normalizeAccountId(recipient.address), collectionId, tokenId, value);
     const scheduleTx = api.tx.scheduler.schedule(expectedBlockNumber, null, 0, transferTx as any);
 
     await submitTransactionAsync(sender, scheduleTx);
@@ -871,7 +871,7 @@
     if (type === 'Fungible') {
       balanceBefore = await getBalance(api, collectionId, to, tokenId);
     }
-    const transferTx = api.tx.nft.transfer(to, collectionId, tokenId, value);
+    const transferTx = api.tx.unique.transfer(to, collectionId, tokenId, value);
     const events = await submitTransactionAsync(sender, transferTx);
     const result = getTransferResult(events);
     // tslint:disable-next-line:no-unused-expression
@@ -903,7 +903,7 @@
   value: number | bigint = 1,
 ) {
   await usingApi(async (api: ApiPromise) => {
-    const transferTx = api.tx.nft.transfer(normalizeAccountId(recipient.address), collectionId, tokenId, value);
+    const transferTx = api.tx.unique.transfer(normalizeAccountId(recipient.address), collectionId, tokenId, value);
     const events = await expect(submitTransactionExpectFailAsync(sender, transferTx)).to.be.rejected;
     const result = getGenericResult(events);
     // if (events && Array.isArray(events)) {
@@ -920,8 +920,8 @@
   tokenId: number, owner: IKeyringPair, approved: IKeyringPair, amount: number | bigint = 1,
 ) {
   await usingApi(async (api: ApiPromise) => {
-    const approveNftTx = api.tx.nft.approve(normalizeAccountId(approved.address), collectionId, tokenId, amount);
-    const events = await expect(submitTransactionExpectFailAsync(owner, approveNftTx)).to.be.rejected;
+    const approveUniqueTx = api.tx.unique.approve(normalizeAccountId(approved.address), collectionId, tokenId, amount);
+    const events = await expect(submitTransactionExpectFailAsync(owner, approveUniqueTx)).to.be.rejected;
     const result = getCreateCollectionResult(events);
     // tslint:disable-next-line:no-unused-expression
     expect(result.success).to.be.false;
@@ -934,47 +934,47 @@
   owner: string | CrossAccountId,
   token: number,
 ): Promise<bigint> {
-  return (await api.rpc.nft.balance(collectionId, normalizeAccountId(owner), token)).toBigInt();
+  return (await api.rpc.unique.balance(collectionId, normalizeAccountId(owner), token)).toBigInt();
 }
 export async function getTokenOwner(
   api: ApiPromise,
   collectionId: number,
   token: number,
 ): Promise<CrossAccountId> {
-  return normalizeAccountId((await api.rpc.nft.tokenOwner(collectionId, token)).toJSON() as any);
+  return normalizeAccountId((await api.rpc.unique.tokenOwner(collectionId, token)).toJSON() as any);
 }
 export async function isTokenExists(
   api: ApiPromise,
   collectionId: number,
   token: number,
 ): Promise<boolean> {
-  return (await api.rpc.nft.tokenExists(collectionId, token)).toJSON();
+  return (await api.rpc.unique.tokenExists(collectionId, token)).toJSON();
 }
 export async function getLastTokenId(
   api: ApiPromise,
   collectionId: number,
 ): Promise<number> {
-  return (await api.rpc.nft.lastTokenId(collectionId)).toJSON();
+  return (await api.rpc.unique.lastTokenId(collectionId)).toJSON();
 }
 export async function getAdminList(
   api: ApiPromise,
   collectionId: number,
 ): Promise<string[]> {
-  return (await api.rpc.nft.adminlist(collectionId)).toHuman() as any;
+  return (await api.rpc.unique.adminlist(collectionId)).toHuman() as any;
 }
 export async function getVariableMetadata(
   api: ApiPromise,
   collectionId: number,
   tokenId: number,
 ): Promise<number[]> {
-  return [...(await api.rpc.nft.variableMetadata(collectionId, tokenId))];
+  return [...(await api.rpc.unique.variableMetadata(collectionId, tokenId))];
 }
 export async function getConstMetadata(
   api: ApiPromise,
   collectionId: number,
   tokenId: number,
 ): Promise<number[]> {
-  return [...(await api.rpc.nft.constMetadata(collectionId, tokenId))];
+  return [...(await api.rpc.unique.constMetadata(collectionId, tokenId))];
 }
 
 export async function createFungibleItemExpectSuccess(
@@ -984,7 +984,7 @@
   owner: CrossAccountId | string = sender.address,
 ) {
   return await usingApi(async (api) => {
-    const tx = api.tx.nft.createItem(collectionId, normalizeAccountId(owner), {Fungible: data});
+    const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(owner), {Fungible: data});
 
     const events = await submitTransactionAsync(sender, tx);
     const result = getCreateItemResult(events);
@@ -1004,13 +1004,13 @@
     let tx;
     if (createMode === 'Fungible') {
       const createData = {fungible: {value: 10}};
-      tx = api.tx.nft.createItem(collectionId, to, createData as any);
+      tx = api.tx.unique.createItem(collectionId, to, createData as any);
     } else if (createMode === 'ReFungible') {
       const createData = {refungible: {const_data: [], variable_data: [], pieces: 100}};
-      tx = api.tx.nft.createItem(collectionId, to, createData as any);
+      tx = api.tx.unique.createItem(collectionId, to, createData as any);
     } else {
       const createData = {nft: {const_data: [], variable_data: []}};
-      tx = api.tx.nft.createItem(collectionId, to, createData as any);
+      tx = api.tx.unique.createItem(collectionId, to, createData as any);
     }
 
     const events = await submitTransactionAsync(sender, tx);
@@ -1037,7 +1037,7 @@
 
 export async function createItemExpectFailure(sender: IKeyringPair, collectionId: number, createMode: string, owner: string = sender.address) {
   await usingApi(async (api) => {
-    const tx = api.tx.nft.createItem(collectionId, normalizeAccountId(owner), createMode);
+    const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(owner), createMode);
 
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getCreateItemResult(events);
@@ -1053,7 +1053,7 @@
   await usingApi(async (api) => {
 
     // Run the transaction
-    const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode);
+    const tx = api.tx.unique.setPublicAccessMode(collectionId, accessMode);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -1074,7 +1074,7 @@
   await usingApi(async (api) => {
 
     // Run the transaction
-    const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode);
+    const tx = api.tx.unique.setPublicAccessMode(collectionId, accessMode);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -1100,7 +1100,7 @@
   await usingApi(async (api) => {
 
     // Run the transaction
-    const tx = api.tx.nft.setMintPermission(collectionId, enabled);
+    const tx = api.tx.unique.setMintPermission(collectionId, enabled);
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
     expect(result.success).to.be.true;
@@ -1119,7 +1119,7 @@
 export async function setMintPermissionExpectFailure(sender: IKeyringPair, collectionId: number, enabled: boolean) {
   await usingApi(async (api) => {
     // Run the transaction
-    const tx = api.tx.nft.setMintPermission(collectionId, enabled);
+    const tx = api.tx.unique.setMintPermission(collectionId, enabled);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getCreateCollectionResult(events);
     // tslint:disable-next-line:no-unused-expression
@@ -1130,7 +1130,7 @@
 export async function setChainLimitsExpectFailure(sender: IKeyringPair, limits: IChainLimits) {
   await usingApi(async (api) => {
     // Run the transaction
-    const tx = api.tx.nft.setChainLimits(limits);
+    const tx = api.tx.unique.setChainLimits(limits);
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getCreateCollectionResult(events);
     // tslint:disable-next-line:no-unused-expression
@@ -1139,7 +1139,7 @@
 }
 
 export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId) {
-  return (await api.rpc.nft.allowed(collectionId, normalizeAccountId(address))).toJSON();
+  return (await api.rpc.unique.allowed(collectionId, normalizeAccountId(address))).toJSON();
 }
 
 export async function addToAllowListExpectSuccess(sender: IKeyringPair, collectionId: number, address: string | AccountId | CrossAccountId) {
@@ -1147,7 +1147,7 @@
     expect(await isAllowlisted(api, collectionId, normalizeAccountId(address))).to.be.false;
 
     // Run the transaction
-    const tx = api.tx.nft.addToAllowList(collectionId, normalizeAccountId(address));
+    const tx = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(address));
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
     expect(result.success).to.be.true;
@@ -1162,7 +1162,7 @@
     expect(await isAllowlisted(api, collectionId, normalizeAccountId(address))).to.be.true;
 
     // Run the transaction
-    const tx = api.tx.nft.addToAllowList(collectionId, normalizeAccountId(address));
+    const tx = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(address));
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
     expect(result.success).to.be.true;
@@ -1175,7 +1175,7 @@
   await usingApi(async (api) => {
 
     // Run the transaction
-    const tx = api.tx.nft.addToAllowList(collectionId, normalizeAccountId(address));
+    const tx = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(address));
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -1188,7 +1188,7 @@
 export async function removeFromAllowListExpectSuccess(sender: IKeyringPair, collectionId: number, address: CrossAccountId) {
   await usingApi(async (api) => {
     // Run the transaction
-    const tx = api.tx.nft.removeFromAllowList(collectionId, normalizeAccountId(address));
+    const tx = api.tx.unique.removeFromAllowList(collectionId, normalizeAccountId(address));
     const events = await submitTransactionAsync(sender, tx);
     const result = getGenericResult(events);
 
@@ -1201,7 +1201,7 @@
 export async function removeFromAllowListExpectFailure(sender: IKeyringPair, collectionId: number, address: CrossAccountId) {
   await usingApi(async (api) => {
     // Run the transaction
-    const tx = api.tx.nft.removeFromAllowList(collectionId, normalizeAccountId(address));
+    const tx = api.tx.unique.removeFromAllowList(collectionId, normalizeAccountId(address));
     const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
     const result = getGenericResult(events);
 
@@ -1212,17 +1212,17 @@
 }
 
 export const getDetailedCollectionInfo = async (api: ApiPromise, collectionId: number)
-  : Promise<NftDataStructsCollection | null> => {
-  return (await api.rpc.nft.collectionById(collectionId)).unwrapOr(null);
+  : Promise<UpDataStructsCollection | null> => {
+  return (await api.rpc.unique.collectionById(collectionId)).unwrapOr(null);
 };
 
 export const getCreatedCollectionCount = async (api: ApiPromise): Promise<number> => {
   // set global object - collectionsCount
-  return (await api.rpc.nft.collectionStats()).created.toNumber();
+  return (await api.rpc.unique.collectionStats()).created.toNumber();
 };
 
-export async function queryCollectionExpectSuccess(api: ApiPromise, collectionId: number): Promise<NftDataStructsCollection> {
-  return (await api.rpc.nft.collectionById(collectionId)).unwrap();
+export async function queryCollectionExpectSuccess(api: ApiPromise, collectionId: number): Promise<UpDataStructsCollection> {
+  return (await api.rpc.unique.collectionById(collectionId)).unwrap();
 }
 
 export async function waitNewBlocks(blocksCount = 1): Promise<void> {