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
before · pallets/nft/src/tests.rs
1// Tests to be written here2use super::*;3use crate::mock::*;4use crate::{AccessMode, CollectionMode, Ownership, CreateItemData};5use nft_data_structs::{6	CreateNftData, CreateFungibleData, CreateReFungibleData, CollectionId, TokenId,7	MAX_DECIMAL_POINTS,8};9use frame_support::{assert_noop, assert_ok};10use sp_std::convert::TryInto;1112fn default_nft_data() -> CreateNftData {13	CreateNftData {14		const_data: vec![1, 2, 3].try_into().unwrap(),15		variable_data: vec![3, 2, 1].try_into().unwrap(),16	}17}1819fn default_fungible_data() -> CreateFungibleData {20	CreateFungibleData { value: 5 }21}2223fn default_re_fungible_data() -> CreateReFungibleData {24	CreateReFungibleData {25		const_data: vec![1, 2, 3].try_into().unwrap(),26		variable_data: vec![3, 2, 1].try_into().unwrap(),27		pieces: 1023,28	}29}3031fn create_test_collection_for_owner(32	mode: &CollectionMode,33	owner: u64,34	id: CollectionId,35) -> CollectionId {36	let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();37	let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();38	let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();3940	let origin1 = Origin::signed(owner);41	assert_ok!(TemplateModule::create_collection(42		origin1,43		col_name1,44		col_desc1,45		token_prefix1,46		mode.clone()47	));4849	let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();50	let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();51	let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();52	assert_eq!(TemplateModule::collection_id(id).unwrap().owner, owner);53	assert_eq!(54		TemplateModule::collection_id(id).unwrap().name,55		saved_col_name56	);57	assert_eq!(TemplateModule::collection_id(id).unwrap().mode, *mode);58	assert_eq!(59		TemplateModule::collection_id(id).unwrap().description,60		saved_description61	);62	assert_eq!(63		TemplateModule::collection_id(id).unwrap().token_prefix,64		saved_prefix65	);66	id67}6869fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {70	create_test_collection_for_owner(&mode, 1, id)71}7273fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {74	let origin1 = Origin::signed(1);75	assert_ok!(TemplateModule::create_item(76		origin1,77		collection_id,78		account(1),79		data.clone()80	));81}8283fn account(sub: u64) -> TestCrossAccountId {84	TestCrossAccountId::from_sub(sub)85}8687// Use cases tests region88// #region8990#[test]91fn set_version_schema() {92	new_test_ext().execute_with(|| {93		let origin1 = Origin::signed(1);94		let collection_id = create_test_collection(&CollectionMode::NFT, 1);9596		assert_ok!(TemplateModule::set_schema_version(97			origin1,98			collection_id,99			SchemaVersion::Unique100		));101		assert_eq!(102			TemplateModule::collection_id(collection_id)103				.unwrap()104				.schema_version,105			SchemaVersion::Unique106		);107	});108}109110#[test]111fn create_fungible_collection_fails_with_large_decimal_numbers() {112	new_test_ext().execute_with(|| {113		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();114		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();115		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();116117		let origin1 = Origin::signed(1);118		assert_noop!(119			TemplateModule::create_collection(120				origin1,121				col_name1,122				col_desc1,123				token_prefix1,124				CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)125			),126			Error::<Test>::CollectionDecimalPointLimitExceeded127		);128	});129}130131#[test]132fn create_nft_item() {133	new_test_ext().execute_with(|| {134		let collection_id = create_test_collection(&CollectionMode::NFT, 1);135136		let data = default_nft_data();137		create_test_item(collection_id, &data.clone().into());138		let item = TemplateModule::nft_item_id(collection_id, 1).unwrap();139		assert_eq!(item.const_data, data.const_data.into_inner());140		assert_eq!(item.variable_data, data.variable_data.into_inner());141	});142}143144// Use cases tests region145// #region146#[test]147fn create_nft_multiple_items() {148	new_test_ext().execute_with(|| {149		create_test_collection(&CollectionMode::NFT, 1);150151		let origin1 = Origin::signed(1);152153		let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];154155		assert_ok!(TemplateModule::create_multiple_items(156			origin1,157			1,158			account(1),159			items_data160				.clone()161				.into_iter()162				.map(|d| { d.into() })163				.collect()164		));165		for (index, data) in items_data.into_iter().enumerate() {166			let item = TemplateModule::nft_item_id(1, (index + 1) as TokenId).unwrap();167			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());168			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());169		}170	});171}172173#[test]174fn create_refungible_item() {175	new_test_ext().execute_with(|| {176		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);177178		let data = default_re_fungible_data();179		create_test_item(collection_id, &data.clone().into());180		let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();181		assert_eq!(item.const_data, data.const_data.into_inner());182		assert_eq!(item.variable_data, data.variable_data.into_inner());183		assert_eq!(184			item.owner[0],185			Ownership {186				owner: account(1),187				fraction: 1023188			}189		);190	});191}192193#[test]194fn create_multiple_refungible_items() {195	new_test_ext().execute_with(|| {196		create_test_collection(&CollectionMode::ReFungible, 1);197198		let origin1 = Origin::signed(1);199200		let items_data = vec![201			default_re_fungible_data(),202			default_re_fungible_data(),203			default_re_fungible_data(),204		];205206		assert_ok!(TemplateModule::create_multiple_items(207			origin1,208			1,209			account(1),210			items_data211				.clone()212				.into_iter()213				.map(|d| { d.into() })214				.collect()215		));216		for (index, data) in items_data.into_iter().enumerate() {217			let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId).unwrap();218			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());219			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());220			assert_eq!(221				item.owner[0],222				Ownership {223					owner: account(1),224					fraction: 1023225				}226			);227		}228	});229}230231#[test]232fn create_fungible_item() {233	new_test_ext().execute_with(|| {234		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);235236		let data = default_fungible_data();237		create_test_item(collection_id, &data.into());238239		assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).value, 5);240	});241}242243//#[test]244// fn create_multiple_fungible_items() {245//     new_test_ext().execute_with(|| {246//         default_limits();247248//         create_test_collection(&CollectionMode::Fungible(3), 1);249250//         let origin1 = Origin::signed(1);251252//         let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];253254//         assert_ok!(TemplateModule::create_multiple_items(255//             origin1.clone(),256//             1,257//             1,258//             items_data.clone().into_iter().map(|d| { d.into() }).collect()259//         ));260261//         for (index, _) in items_data.iter().enumerate() {262//             assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);263//         }264//         assert_eq!(TemplateModule::balance_count(1, 1), 3000);265//         assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);266//     });267// }268269#[test]270fn transfer_fungible_item() {271	new_test_ext().execute_with(|| {272		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);273274		let origin1 = Origin::signed(1);275		let origin2 = Origin::signed(2);276277		let data = default_fungible_data();278		create_test_item(collection_id, &data.into());279280		assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 5);281		assert_eq!(TemplateModule::balance_count(1, 1), 5);282283		// change owner scenario284		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 5));285		assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 0);286		assert_eq!(TemplateModule::balance_count(1, 1), 0);287		assert_eq!(TemplateModule::balance_count(1, 2), 5);288289		// split item scenario290		assert_ok!(TemplateModule::transfer(291			origin2.clone(),292			account(3),293			1,294			1,295			3296		));297		assert_eq!(TemplateModule::balance_count(1, 2), 2);298		assert_eq!(TemplateModule::balance_count(1, 3), 3);299300		// split item and new owner has account scenario301		assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 1));302		assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 1);303		assert_eq!(TemplateModule::fungible_item_id(1, 3).value, 4);304		assert_eq!(TemplateModule::balance_count(1, 2), 1);305		assert_eq!(TemplateModule::balance_count(1, 3), 4);306	});307}308309#[test]310fn transfer_refungible_item() {311	new_test_ext().execute_with(|| {312		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);313314		let data = default_re_fungible_data();315		create_test_item(collection_id, &data.clone().into());316317		let origin1 = Origin::signed(1);318		let origin2 = Origin::signed(2);319		{320			let item = TemplateModule::refungible_item_id(collection_id, 1).unwrap();321			assert_eq!(item.const_data, data.const_data.into_inner());322			assert_eq!(item.variable_data, data.variable_data.into_inner());323			assert_eq!(324				item.owner[0],325				Ownership {326					owner: account(1),327					fraction: 1023328				}329			);330		}331		assert_eq!(TemplateModule::balance_count(1, 1), 1023);332		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);333334		// change owner scenario335		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1023));336		assert_eq!(337			TemplateModule::refungible_item_id(1, 1).unwrap().owner[0],338			Ownership {339				owner: account(2),340				fraction: 1023341			}342		);343		assert_eq!(TemplateModule::balance_count(1, 1), 0);344		assert_eq!(TemplateModule::balance_count(1, 2), 1023);345		// assert_eq!(TemplateModule::address_tokens(1, 1), []);346		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);347348		// split item scenario349		assert_ok!(TemplateModule::transfer(350			origin2.clone(),351			account(3),352			1,353			1,354			500355		));356		{357			let item = TemplateModule::refungible_item_id(1, 1).unwrap();358			assert_eq!(359				item.owner[0],360				Ownership {361					owner: account(2),362					fraction: 523363				}364			);365			assert_eq!(366				item.owner[1],367				Ownership {368					owner: account(3),369					fraction: 500370				}371			);372		}373		assert_eq!(TemplateModule::balance_count(1, 2), 523);374		assert_eq!(TemplateModule::balance_count(1, 3), 500);375		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);376		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);377378		// split item and new owner has account scenario379		assert_ok!(TemplateModule::transfer(origin2, account(3), 1, 1, 200));380		{381			let item = TemplateModule::refungible_item_id(1, 1).unwrap();382			assert_eq!(383				item.owner[0],384				Ownership {385					owner: account(2),386					fraction: 323387				}388			);389			assert_eq!(390				item.owner[1],391				Ownership {392					owner: account(3),393					fraction: 700394				}395			);396		}397		assert_eq!(TemplateModule::balance_count(1, 2), 323);398		assert_eq!(TemplateModule::balance_count(1, 3), 700);399		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);400		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);401	});402}403404#[test]405fn transfer_nft_item() {406	new_test_ext().execute_with(|| {407		let collection_id = create_test_collection(&CollectionMode::NFT, 1);408409		let data = default_nft_data();410		create_test_item(collection_id, &data.into());411		assert_eq!(TemplateModule::balance_count(1, 1), 1);412		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);413414		let origin1 = Origin::signed(1);415		// default scenario416		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));417		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));418		assert_eq!(TemplateModule::balance_count(1, 1), 0);419		assert_eq!(TemplateModule::balance_count(1, 2), 1);420		// assert_eq!(TemplateModule::address_tokens(1, 1), []);421		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);422	});423}424425#[test]426fn nft_approve_and_transfer_from() {427	new_test_ext().execute_with(|| {428		let collection_id = create_test_collection(&CollectionMode::NFT, 1);429430		let data = default_nft_data();431		create_test_item(collection_id, &data.into());432433		let origin1 = Origin::signed(1);434		let origin2 = Origin::signed(2);435436		assert_eq!(TemplateModule::balance_count(1, 1), 1);437		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);438439		// neg transfer440		assert_noop!(441			TemplateModule::transfer_from(origin2.clone(), account(1), account(2), 1, 1, 1),442			Error::<Test>::NoPermission443		);444445		// do approve446		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 5));447		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);448		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);449450		assert_ok!(TemplateModule::transfer_from(451			origin2,452			account(1),453			account(3),454			1,455			1,456			1457		));458		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);459	});460}461462#[test]463fn nft_approve_and_transfer_from_allow_list() {464	new_test_ext().execute_with(|| {465		let collection_id = create_test_collection(&CollectionMode::NFT, 1);466467		let origin1 = Origin::signed(1);468		let origin2 = Origin::signed(2);469470		let data = default_nft_data();471		create_test_item(collection_id, &data.clone().into());472473		assert_eq!(474			&TemplateModule::nft_item_id(1, 1).unwrap().const_data,475			&data.const_data.into_inner()476		);477		assert_eq!(TemplateModule::balance_count(1, 1), 1);478		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);479480		assert_ok!(TemplateModule::set_mint_permission(481			origin1.clone(),482			1,483			true484		));485		assert_ok!(TemplateModule::set_public_access_mode(486			origin1.clone(),487			1,488			AccessMode::AllowList489		));490		assert_ok!(TemplateModule::add_to_allow_list(491			origin1.clone(),492			1,493			account(1)494		));495		assert_ok!(TemplateModule::add_to_allow_list(496			origin1.clone(),497			1,498			account(2)499		));500		assert_ok!(TemplateModule::add_to_allow_list(501			origin1.clone(),502			1,503			account(3)504		));505506		// do approve507		assert_ok!(TemplateModule::approve(508			origin1.clone(),509			account(2),510			1,511			1,512			5513		));514		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);515		assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));516		assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);517518		assert_ok!(TemplateModule::transfer_from(519			origin2,520			account(1),521			account(3),522			1,523			1,524			1525		));526		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);527	});528}529530#[test]531fn refungible_approve_and_transfer_from() {532	new_test_ext().execute_with(|| {533		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);534535		let origin1 = Origin::signed(1);536		let origin2 = Origin::signed(2);537538		let data = default_re_fungible_data();539		create_test_item(collection_id, &data.into());540541		assert_eq!(TemplateModule::balance_count(1, 1), 1023);542		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);543544		assert_ok!(TemplateModule::set_mint_permission(545			origin1.clone(),546			1,547			true548		));549		assert_ok!(TemplateModule::set_public_access_mode(550			origin1.clone(),551			1,552			AccessMode::AllowList553		));554		assert_ok!(TemplateModule::add_to_allow_list(555			origin1.clone(),556			1,557			account(1)558		));559		assert_ok!(TemplateModule::add_to_allow_list(560			origin1.clone(),561			1,562			account(2)563		));564		assert_ok!(TemplateModule::add_to_allow_list(565			origin1.clone(),566			1,567			account(3)568		));569570		// do approve571		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1023));572		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023);573574		assert_ok!(TemplateModule::transfer_from(575			origin2,576			account(1),577			account(3),578			1,579			1,580			100581		));582		assert_eq!(TemplateModule::balance_count(1, 1), 923);583		assert_eq!(TemplateModule::balance_count(1, 3), 100);584		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);585		assert_eq!(TemplateModule::address_tokens(1, 3), [1]);586587		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 923);588	});589}590591#[test]592fn fungible_approve_and_transfer_from() {593	new_test_ext().execute_with(|| {594		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);595596		let data = default_fungible_data();597		create_test_item(collection_id, &data.into());598599		let origin1 = Origin::signed(1);600		let origin2 = Origin::signed(2);601602		assert_eq!(TemplateModule::balance_count(1, 1), 5);603604		assert_ok!(TemplateModule::set_mint_permission(605			origin1.clone(),606			1,607			true608		));609		assert_ok!(TemplateModule::set_public_access_mode(610			origin1.clone(),611			1,612			AccessMode::AllowList613		));614		assert_ok!(TemplateModule::add_to_allow_list(615			origin1.clone(),616			1,617			account(1)618		));619		assert_ok!(TemplateModule::add_to_allow_list(620			origin1.clone(),621			1,622			account(2)623		));624		assert_ok!(TemplateModule::add_to_allow_list(625			origin1.clone(),626			1,627			account(3)628		));629630		// do approve631		assert_ok!(TemplateModule::approve(632			origin1.clone(),633			account(2),634			1,635			1,636			5637		));638		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);639		assert_ok!(TemplateModule::approve(origin1, account(3), 1, 1, 5));640		assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);641		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);642643		assert_ok!(TemplateModule::transfer_from(644			origin2.clone(),645			account(1),646			account(3),647			1,648			1,649			4650		));651		assert_eq!(TemplateModule::balance_count(1, 1), 1);652		assert_eq!(TemplateModule::balance_count(1, 3), 4);653654		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);655656		assert_noop!(657			TemplateModule::transfer_from(origin2, account(1), account(3), 1, 1, 4),658			Error::<Test>::NoPermission659		);660	});661}662663#[test]664fn change_collection_owner() {665	new_test_ext().execute_with(|| {666		let collection_id = create_test_collection(&CollectionMode::NFT, 1);667668		let origin1 = Origin::signed(1);669		assert_ok!(TemplateModule::change_collection_owner(670			origin1,671			collection_id,672			2673		));674		assert_eq!(675			TemplateModule::collection_id(collection_id).unwrap().owner,676			2677		);678	});679}680681#[test]682fn destroy_collection() {683	new_test_ext().execute_with(|| {684		let collection_id = create_test_collection(&CollectionMode::NFT, 1);685686		let origin1 = Origin::signed(1);687		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));688	});689}690691#[test]692fn burn_nft_item() {693	new_test_ext().execute_with(|| {694		let collection_id = create_test_collection(&CollectionMode::NFT, 1);695696		let origin1 = Origin::signed(1);697		assert_ok!(TemplateModule::add_collection_admin(698			origin1.clone(),699			collection_id,700			account(2)701		));702703		let data = default_nft_data();704		create_test_item(collection_id, &data.into());705706		// check balance (collection with id = 1, user id = 1)707		assert_eq!(TemplateModule::balance_count(1, 1), 1);708709		// burn item710		assert_ok!(TemplateModule::burn_item(711			origin1.clone(),712			collection_id,713			1,714			1715		));716		assert_noop!(717			TemplateModule::burn_item(origin1, collection_id, 1, 1),718			Error::<Test>::TokenNotFound719		);720721		assert_eq!(TemplateModule::balance_count(1, 1), 0);722	});723}724725#[test]726fn burn_fungible_item() {727	new_test_ext().execute_with(|| {728		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);729730		let origin1 = Origin::signed(1);731		assert_ok!(TemplateModule::add_collection_admin(732			origin1.clone(),733			collection_id,734			account(2)735		));736737		let data = default_fungible_data();738		create_test_item(collection_id, &data.into());739740		// check balance (collection with id = 1, user id = 1)741		assert_eq!(TemplateModule::balance_count(1, 1), 5);742743		// burn item744		assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));745		assert_noop!(746			TemplateModule::burn_item(origin1, 1, 1, 5),747			Error::<Test>::TokenValueNotEnough748		);749750		assert_eq!(TemplateModule::balance_count(1, 1), 0);751	});752}753754#[test]755fn burn_refungible_item() {756	new_test_ext().execute_with(|| {757		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);758		let origin1 = Origin::signed(1);759760		assert_ok!(TemplateModule::set_mint_permission(761			origin1.clone(),762			collection_id,763			true764		));765		assert_ok!(TemplateModule::set_public_access_mode(766			origin1.clone(),767			collection_id,768			AccessMode::AllowList769		));770		assert_ok!(TemplateModule::add_to_allow_list(771			origin1.clone(),772			1,773			account(1)774		));775776		assert_ok!(TemplateModule::add_collection_admin(777			origin1.clone(),778			1,779			account(2)780		));781782		let data = default_re_fungible_data();783		create_test_item(collection_id, &data.into());784785		// check balance (collection with id = 1, user id = 2)786		assert_eq!(TemplateModule::balance_count(1, 1), 1023);787788		// burn item789		assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023));790		assert_noop!(791			TemplateModule::burn_item(origin1, 1, 1, 1023),792			Error::<Test>::TokenNotFound793		);794795		assert_eq!(TemplateModule::balance_count(1, 1), 0);796	});797}798799#[test]800fn add_collection_admin() {801	new_test_ext().execute_with(|| {802		let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);803		create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);804		create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);805806		let origin1 = Origin::signed(1);807808		// collection admin809		assert_ok!(TemplateModule::add_collection_admin(810			origin1.clone(),811			collection1_id,812			account(2)813		));814		assert_ok!(TemplateModule::add_collection_admin(815			origin1,816			collection1_id,817			account(3)818		));819820		assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(2)),);821		assert!(TemplateModule::admin_list_collection(collection1_id).contains(&account(3)),);822	});823}824825#[test]826fn remove_collection_admin() {827	new_test_ext().execute_with(|| {828		let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);829		create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);830		create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);831832		let origin1 = Origin::signed(1);833		let origin2 = Origin::signed(2);834835		// collection admin836		assert_ok!(TemplateModule::add_collection_admin(837			origin1.clone(),838			collection1_id,839			account(2)840		));841		assert_ok!(TemplateModule::add_collection_admin(842			origin1,843			collection1_id,844			account(3)845		));846847		assert!(TemplateModule::admin_list_collection(1).contains(&account(2)),);848		assert!(TemplateModule::admin_list_collection(1).contains(&account(3)),);849850		// remove admin851		assert_ok!(TemplateModule::remove_collection_admin(852			origin2,853			1,854			account(3)855		));856		assert!(!TemplateModule::admin_list_collection(1).contains(&account(3)),);857	});858}859860#[test]861fn balance_of() {862	new_test_ext().execute_with(|| {863		let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);864		let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);865		let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);866867		// check balance before868		assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);869		assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);870		assert_eq!(871			TemplateModule::balance_count(re_fungible_collection_id, 1),872			0873		);874875		let nft_data = default_nft_data();876		create_test_item(nft_collection_id, &nft_data.into());877878		let fungible_data = default_fungible_data();879		create_test_item(fungible_collection_id, &fungible_data.into());880881		let re_fungible_data = default_re_fungible_data();882		create_test_item(re_fungible_collection_id, &re_fungible_data.into());883884		// check balance (collection with id = 1, user id = 1)885		assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);886		assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);887		assert_eq!(888			TemplateModule::balance_count(re_fungible_collection_id, 1),889			1023890		);891		assert_eq!(892			TemplateModule::nft_item_id(nft_collection_id, 1)893				.unwrap()894				.owner,895			account(1)896		);897		assert_eq!(898			TemplateModule::fungible_item_id(fungible_collection_id, 1).value,899			5900		);901		assert_eq!(902			TemplateModule::refungible_item_id(re_fungible_collection_id, 1)903				.unwrap()904				.owner[0]905				.owner,906			account(1)907		);908	});909}910911#[test]912fn approve() {913	new_test_ext().execute_with(|| {914		let collection_id = create_test_collection(&CollectionMode::NFT, 1);915916		let data = default_nft_data();917		create_test_item(collection_id, &data.into());918919		let origin1 = Origin::signed(1);920921		// approve922		assert_ok!(TemplateModule::approve(origin1, account(2), 1, 1, 1));923		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);924	});925}926927#[test]928fn transfer_from() {929	new_test_ext().execute_with(|| {930		let collection_id = create_test_collection(&CollectionMode::NFT, 1);931		let origin1 = Origin::signed(1);932		let origin2 = Origin::signed(2);933934		let data = default_nft_data();935		create_test_item(collection_id, &data.into());936937		// approve938		assert_ok!(TemplateModule::approve(939			origin1.clone(),940			account(2),941			1,942			1,943			1944		));945		assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);946947		assert_ok!(TemplateModule::set_mint_permission(948			origin1.clone(),949			1,950			true951		));952		assert_ok!(TemplateModule::set_public_access_mode(953			origin1.clone(),954			1,955			AccessMode::AllowList956		));957		assert_ok!(TemplateModule::add_to_allow_list(958			origin1.clone(),959			1,960			account(1)961		));962		assert_ok!(TemplateModule::add_to_allow_list(963			origin1.clone(),964			1,965			account(2)966		));967		assert_ok!(TemplateModule::add_to_allow_list(origin1, 1, account(3)));968969		assert_ok!(TemplateModule::transfer_from(970			origin2,971			account(1),972			account(2),973			1,974			1,975			1976		));977978		// after transfer979		assert_eq!(TemplateModule::balance_count(1, 1), 0);980		assert_eq!(TemplateModule::balance_count(1, 2), 1);981	});982}983984// #endregion985986// Coverage tests region987// #region988989#[test]990fn owner_can_add_address_to_allow_list() {991	new_test_ext().execute_with(|| {992		let collection_id = create_test_collection(&CollectionMode::NFT, 1);993994		let origin1 = Origin::signed(1);995		assert_ok!(TemplateModule::add_to_allow_list(996			origin1,997			collection_id,998			account(2)999		));1000		assert!(TemplateModule::allow_list(collection_id, 2));1001	});1002}10031004#[test]1005fn admin_can_add_address_to_allow_list() {1006	new_test_ext().execute_with(|| {1007		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1008		let origin1 = Origin::signed(1);1009		let origin2 = Origin::signed(2);10101011		assert_ok!(TemplateModule::add_collection_admin(1012			origin1,1013			collection_id,1014			account(2)1015		));1016		assert_ok!(TemplateModule::add_to_allow_list(1017			origin2,1018			collection_id,1019			account(3)1020		));1021		assert!(TemplateModule::allow_list(collection_id, 3));1022	});1023}10241025#[test]1026fn nonprivileged_user_cannot_add_address_to_allow_list() {1027	new_test_ext().execute_with(|| {1028		let collection_id = create_test_collection(&CollectionMode::NFT, 1);10291030		let origin2 = Origin::signed(2);1031		assert_noop!(1032			TemplateModule::add_to_allow_list(origin2, collection_id, account(3)),1033			Error::<Test>::NoPermission1034		);1035	});1036}10371038#[test]1039fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {1040	new_test_ext().execute_with(|| {1041		let origin1 = Origin::signed(1);10421043		assert_noop!(1044			TemplateModule::add_to_allow_list(origin1, 1, account(2)),1045			Error::<Test>::CollectionNotFound1046		);1047	});1048}10491050#[test]1051fn nobody_can_add_address_to_allow_list_of_deleted_collection() {1052	new_test_ext().execute_with(|| {1053		let collection_id = create_test_collection(&CollectionMode::NFT, 1);10541055		let origin1 = Origin::signed(1);1056		assert_ok!(TemplateModule::destroy_collection(1057			origin1.clone(),1058			collection_id1059		));1060		assert_noop!(1061			TemplateModule::add_to_allow_list(origin1, collection_id, account(2)),1062			Error::<Test>::CollectionNotFound1063		);1064	});1065}10661067// If address is already added to allow list, nothing happens1068#[test]1069fn address_is_already_added_to_allow_list() {1070	new_test_ext().execute_with(|| {1071		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1072		let origin1 = Origin::signed(1);10731074		assert_ok!(TemplateModule::add_to_allow_list(1075			origin1.clone(),1076			collection_id,1077			account(2)1078		));1079		assert_ok!(TemplateModule::add_to_allow_list(1080			origin1,1081			collection_id,1082			account(2)1083		));1084		assert!(TemplateModule::allow_list(collection_id, 2));1085	});1086}10871088#[test]1089fn owner_can_remove_address_from_allow_list() {1090	new_test_ext().execute_with(|| {1091		let collection_id = create_test_collection(&CollectionMode::NFT, 1);10921093		let origin1 = Origin::signed(1);1094		assert_ok!(TemplateModule::add_to_allow_list(1095			origin1.clone(),1096			collection_id,1097			account(2)1098		));1099		assert_ok!(TemplateModule::remove_from_allow_list(1100			origin1,1101			collection_id,1102			account(2)1103		));1104		assert!(!TemplateModule::allow_list(collection_id, 2));1105	});1106}11071108#[test]1109fn admin_can_remove_address_from_allow_list() {1110	new_test_ext().execute_with(|| {1111		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1112		let origin1 = Origin::signed(1);1113		let origin2 = Origin::signed(2);11141115		assert_ok!(TemplateModule::add_collection_admin(1116			origin1.clone(),1117			collection_id,1118			account(2)1119		));11201121		assert_ok!(TemplateModule::add_to_allow_list(1122			origin1,1123			collection_id,1124			account(3)1125		));1126		assert_ok!(TemplateModule::remove_from_allow_list(1127			origin2,1128			collection_id,1129			account(3)1130		));1131		assert!(!TemplateModule::allow_list(collection_id, 3));1132	});1133}11341135#[test]1136fn nonprivileged_user_cannot_remove_address_from_allow_list() {1137	new_test_ext().execute_with(|| {1138		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1139		let origin1 = Origin::signed(1);1140		let origin2 = Origin::signed(2);11411142		assert_ok!(TemplateModule::add_to_allow_list(1143			origin1,1144			collection_id,1145			account(2)1146		));1147		assert_noop!(1148			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),1149			Error::<Test>::NoPermission1150		);1151		assert!(TemplateModule::allow_list(collection_id, 2));1152	});1153}11541155#[test]1156fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {1157	new_test_ext().execute_with(|| {1158		let origin1 = Origin::signed(1);11591160		assert_noop!(1161			TemplateModule::remove_from_allow_list(origin1, 1, account(2)),1162			Error::<Test>::CollectionNotFound1163		);1164	});1165}11661167#[test]1168fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {1169	new_test_ext().execute_with(|| {1170		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1171		let origin1 = Origin::signed(1);1172		let origin2 = Origin::signed(2);11731174		assert_ok!(TemplateModule::add_to_allow_list(1175			origin1.clone(),1176			collection_id,1177			account(2)1178		));1179		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));1180		assert_noop!(1181			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),1182			Error::<Test>::CollectionNotFound1183		);1184		assert!(!TemplateModule::allow_list(collection_id, 2));1185	});1186}11871188// If address is already removed from allow list, nothing happens1189#[test]1190fn address_is_already_removed_from_allow_list() {1191	new_test_ext().execute_with(|| {1192		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1193		let origin1 = Origin::signed(1);11941195		assert_ok!(TemplateModule::add_to_allow_list(1196			origin1.clone(),1197			collection_id,1198			account(2)1199		));1200		assert_ok!(TemplateModule::remove_from_allow_list(1201			origin1.clone(),1202			collection_id,1203			account(2)1204		));1205		assert_ok!(TemplateModule::remove_from_allow_list(1206			origin1,1207			collection_id,1208			account(2)1209		));1210		assert!(!TemplateModule::allow_list(collection_id, 2));1211	});1212}12131214// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)1215#[test]1216fn allow_list_test_1() {1217	new_test_ext().execute_with(|| {1218		let collection_id = create_test_collection(&CollectionMode::NFT, 1);12191220		let origin1 = Origin::signed(1);12211222		let data = default_nft_data();1223		create_test_item(collection_id, &data.into());12241225		assert_ok!(TemplateModule::set_public_access_mode(1226			origin1.clone(),1227			collection_id,1228			AccessMode::AllowList1229		));1230		assert_ok!(TemplateModule::add_to_allow_list(1231			origin1.clone(),1232			collection_id,1233			account(2)1234		));12351236		assert_noop!(1237			TemplateModule::transfer(origin1, account(3), 1, 1, 1),1238			Error::<Test>::AddresNotInAllowList1239		);1240	});1241}12421243#[test]1244fn allow_list_test_2() {1245	new_test_ext().execute_with(|| {1246		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1247		let origin1 = Origin::signed(1);12481249		let data = default_nft_data();1250		create_test_item(collection_id, &data.into());12511252		assert_ok!(TemplateModule::set_public_access_mode(1253			origin1.clone(),1254			collection_id,1255			AccessMode::AllowList1256		));1257		assert_ok!(TemplateModule::add_to_allow_list(1258			origin1.clone(),1259			1,1260			account(1)1261		));1262		assert_ok!(TemplateModule::add_to_allow_list(1263			origin1.clone(),1264			1,1265			account(2)1266		));12671268		// do approve1269		assert_ok!(TemplateModule::approve(1270			origin1.clone(),1271			account(1),1272			1,1273			1,1274			11275		));1276		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);12771278		assert_ok!(TemplateModule::remove_from_allow_list(1279			origin1.clone(),1280			1,1281			account(1)1282		));12831284		assert_noop!(1285			TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),1286			Error::<Test>::AddresNotInAllowList1287		);1288	});1289}12901291// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)1292#[test]1293fn allow_list_test_3() {1294	new_test_ext().execute_with(|| {1295		let collection_id = create_test_collection(&CollectionMode::NFT, 1);12961297		let origin1 = Origin::signed(1);12981299		let data = default_nft_data();1300		create_test_item(collection_id, &data.into());13011302		assert_ok!(TemplateModule::set_public_access_mode(1303			origin1.clone(),1304			collection_id,1305			AccessMode::AllowList1306		));1307		assert_ok!(TemplateModule::add_to_allow_list(1308			origin1.clone(),1309			1,1310			account(1)1311		));13121313		assert_noop!(1314			TemplateModule::transfer(origin1, account(3), 1, 1, 1),1315			Error::<Test>::AddresNotInAllowList1316		);1317	});1318}13191320#[test]1321fn allow_list_test_4() {1322	new_test_ext().execute_with(|| {1323		let collection_id = create_test_collection(&CollectionMode::NFT, 1);13241325		let origin1 = Origin::signed(1);13261327		let data = default_nft_data();1328		create_test_item(collection_id, &data.into());13291330		assert_ok!(TemplateModule::set_public_access_mode(1331			origin1.clone(),1332			collection_id,1333			AccessMode::AllowList1334		));1335		assert_ok!(TemplateModule::add_to_allow_list(1336			origin1.clone(),1337			collection_id,1338			account(1)1339		));1340		assert_ok!(TemplateModule::add_to_allow_list(1341			origin1.clone(),1342			collection_id,1343			account(2)1344		));13451346		// do approve1347		assert_ok!(TemplateModule::approve(1348			origin1.clone(),1349			account(1),1350			1,1351			1,1352			11353		));1354		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);13551356		assert_ok!(TemplateModule::remove_from_allow_list(1357			origin1.clone(),1358			collection_id,1359			account(2)1360		));13611362		assert_noop!(1363			TemplateModule::transfer_from(origin1, account(1), account(3), 1, 1, 1),1364			Error::<Test>::AddresNotInAllowList1365		);1366	});1367}13681369// 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)1370#[test]1371fn allow_list_test_5() {1372	new_test_ext().execute_with(|| {1373		let collection_id = create_test_collection(&CollectionMode::NFT, 1);13741375		let origin1 = Origin::signed(1);13761377		let data = default_nft_data();1378		create_test_item(collection_id, &data.into());13791380		assert_ok!(TemplateModule::set_public_access_mode(1381			origin1.clone(),1382			collection_id,1383			AccessMode::AllowList1384		));1385		assert_noop!(1386			TemplateModule::burn_item(origin1.clone(), 1, 1, 5),1387			Error::<Test>::AddresNotInAllowList1388		);1389	});1390}13911392// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).1393#[test]1394fn allow_list_test_6() {1395	new_test_ext().execute_with(|| {1396		let collection_id = create_test_collection(&CollectionMode::NFT, 1);13971398		let origin1 = Origin::signed(1);13991400		let data = default_nft_data();1401		create_test_item(collection_id, &data.into());14021403		assert_ok!(TemplateModule::set_public_access_mode(1404			origin1.clone(),1405			collection_id,1406			AccessMode::AllowList1407		));14081409		// do approve1410		assert_noop!(1411			TemplateModule::approve(origin1, account(1), 1, 1, 5),1412			Error::<Test>::AddresNotInAllowList1413		);1414	});1415}14161417// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and1418//          tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)1419#[test]1420fn allow_list_test_7() {1421	new_test_ext().execute_with(|| {1422		let collection_id = create_test_collection(&CollectionMode::NFT, 1);14231424		let data = default_nft_data();1425		create_test_item(collection_id, &data.into());14261427		let origin1 = Origin::signed(1);14281429		assert_ok!(TemplateModule::set_public_access_mode(1430			origin1.clone(),1431			collection_id,1432			AccessMode::AllowList1433		));1434		assert_ok!(TemplateModule::add_to_allow_list(1435			origin1.clone(),1436			collection_id,1437			account(1)1438		));1439		assert_ok!(TemplateModule::add_to_allow_list(1440			origin1.clone(),1441			collection_id,1442			account(2)1443		));14441445		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1));1446	});1447}14481449#[test]1450fn allow_list_test_8() {1451	new_test_ext().execute_with(|| {1452		let collection_id = create_test_collection(&CollectionMode::NFT, 1);14531454		let data = default_nft_data();1455		create_test_item(collection_id, &data.into());14561457		let origin1 = Origin::signed(1);14581459		assert_ok!(TemplateModule::set_public_access_mode(1460			origin1.clone(),1461			collection_id,1462			AccessMode::AllowList1463		));1464		assert_ok!(TemplateModule::add_to_allow_list(1465			origin1.clone(),1466			collection_id,1467			account(1)1468		));1469		assert_ok!(TemplateModule::add_to_allow_list(1470			origin1.clone(),1471			collection_id,1472			account(2)1473		));14741475		// do approve1476		assert_ok!(TemplateModule::approve(1477			origin1.clone(),1478			account(1),1479			1,1480			1,1481			51482		));1483		assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 5);14841485		assert_ok!(TemplateModule::transfer_from(1486			origin1,1487			account(1),1488			account(2),1489			1,1490			1,1491			11492		));1493	});1494}14951496// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.1497#[test]1498fn allow_list_test_9() {1499	new_test_ext().execute_with(|| {1500		let collection_id = create_test_collection(&CollectionMode::NFT, 1);1501		let origin1 = Origin::signed(1);15021503		assert_ok!(TemplateModule::set_public_access_mode(1504			origin1.clone(),1505			collection_id,1506			AccessMode::AllowList1507		));1508		assert_ok!(TemplateModule::set_mint_permission(1509			origin1,1510			collection_id,1511			false1512		));15131514		let data = default_nft_data();1515		create_test_item(collection_id, &data.into());1516	});1517}15181519// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.1520#[test]1521fn allow_list_test_10() {1522	new_test_ext().execute_with(|| {1523		let collection_id = create_test_collection(&CollectionMode::NFT, 1);15241525		let origin1 = Origin::signed(1);1526		let origin2 = Origin::signed(2);15271528		assert_ok!(TemplateModule::set_public_access_mode(1529			origin1.clone(),1530			collection_id,1531			AccessMode::AllowList1532		));1533		assert_ok!(TemplateModule::set_mint_permission(1534			origin1.clone(),1535			collection_id,1536			false1537		));15381539		assert_ok!(TemplateModule::add_collection_admin(1540			origin1,1541			collection_id,1542			account(2)1543		));15441545		assert_ok!(TemplateModule::create_item(1546			origin2,1547			collection_id,1548			account(2),1549			default_nft_data().into()1550		));1551	});1552}15531554// 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.1555#[test]1556fn allow_list_test_11() {1557	new_test_ext().execute_with(|| {1558		let collection_id = create_test_collection(&CollectionMode::NFT, 1);15591560		let origin1 = Origin::signed(1);1561		let origin2 = Origin::signed(2);15621563		assert_ok!(TemplateModule::set_public_access_mode(1564			origin1.clone(),1565			collection_id,1566			AccessMode::AllowList1567		));1568		assert_ok!(TemplateModule::set_mint_permission(1569			origin1.clone(),1570			collection_id,1571			false1572		));1573		assert_ok!(TemplateModule::add_to_allow_list(1574			origin1,1575			collection_id,1576			account(2)1577		));15781579		assert_noop!(1580			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),1581			Error::<Test>::PublicMintingNotAllowed1582		);1583	});1584}15851586// 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.1587#[test]1588fn allow_list_test_12() {1589	new_test_ext().execute_with(|| {1590		let collection_id = create_test_collection(&CollectionMode::NFT, 1);15911592		let origin1 = Origin::signed(1);1593		let origin2 = Origin::signed(2);15941595		assert_ok!(TemplateModule::set_public_access_mode(1596			origin1.clone(),1597			collection_id,1598			AccessMode::AllowList1599		));1600		assert_ok!(TemplateModule::set_mint_permission(1601			origin1,1602			collection_id,1603			false1604		));16051606		assert_noop!(1607			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),1608			Error::<Test>::PublicMintingNotAllowed1609		);1610	});1611}16121613// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.1614#[test]1615fn allow_list_test_13() {1616	new_test_ext().execute_with(|| {1617		let collection_id = create_test_collection(&CollectionMode::NFT, 1);16181619		let origin1 = Origin::signed(1);16201621		assert_ok!(TemplateModule::set_public_access_mode(1622			origin1.clone(),1623			collection_id,1624			AccessMode::AllowList1625		));1626		assert_ok!(TemplateModule::set_mint_permission(1627			origin1,1628			collection_id,1629			true1630		));16311632		let data = default_nft_data();1633		create_test_item(collection_id, &data.into());1634	});1635}16361637// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.1638#[test]1639fn allow_list_test_14() {1640	new_test_ext().execute_with(|| {1641		let collection_id = create_test_collection(&CollectionMode::NFT, 1);16421643		let origin1 = Origin::signed(1);1644		let origin2 = Origin::signed(2);16451646		assert_ok!(TemplateModule::set_public_access_mode(1647			origin1.clone(),1648			collection_id,1649			AccessMode::AllowList1650		));1651		assert_ok!(TemplateModule::set_mint_permission(1652			origin1.clone(),1653			collection_id,1654			true1655		));16561657		assert_ok!(TemplateModule::add_collection_admin(1658			origin1,1659			collection_id,1660			account(2)1661		));16621663		assert_ok!(TemplateModule::create_item(1664			origin2,1665			1,1666			account(2),1667			default_nft_data().into()1668		));1669	});1670}16711672// 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.1673#[test]1674fn allow_list_test_15() {1675	new_test_ext().execute_with(|| {1676		let collection_id = create_test_collection(&CollectionMode::NFT, 1);16771678		let origin1 = Origin::signed(1);1679		let origin2 = Origin::signed(2);16801681		assert_ok!(TemplateModule::set_public_access_mode(1682			origin1.clone(),1683			collection_id,1684			AccessMode::AllowList1685		));1686		assert_ok!(TemplateModule::set_mint_permission(1687			origin1,1688			collection_id,1689			true1690		));16911692		assert_noop!(1693			TemplateModule::create_item(origin2, 1, account(2), default_nft_data().into()),1694			Error::<Test>::AddresNotInAllowList1695		);1696	});1697}16981699// 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.1700#[test]1701fn allow_list_test_16() {1702	new_test_ext().execute_with(|| {1703		let collection_id = create_test_collection(&CollectionMode::NFT, 1);17041705		let origin1 = Origin::signed(1);1706		let origin2 = Origin::signed(2);17071708		assert_ok!(TemplateModule::set_public_access_mode(1709			origin1.clone(),1710			collection_id,1711			AccessMode::AllowList1712		));1713		assert_ok!(TemplateModule::set_mint_permission(1714			origin1.clone(),1715			collection_id,1716			true1717		));1718		assert_ok!(TemplateModule::add_to_allow_list(1719			origin1,1720			collection_id,1721			account(2)1722		));17231724		assert_ok!(TemplateModule::create_item(1725			origin2,1726			1,1727			account(2),1728			default_nft_data().into()1729		));1730	});1731}17321733// Total number of collections. Positive test1734#[test]1735fn total_number_collections_bound() {1736	new_test_ext().execute_with(|| {1737		create_test_collection(&CollectionMode::NFT, 1);1738	});1739}17401741// Total number of collections. Negotive test1742#[test]1743fn total_number_collections_bound_neg() {1744	new_test_ext().execute_with(|| {1745		let origin1 = Origin::signed(1);17461747		for i in 0..COLLECTION_NUMBER_LIMIT {1748			create_test_collection(&CollectionMode::NFT, i + 1);1749		}17501751		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();1752		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();1753		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();17541755		// 11-th collection in chain. Expects error1756		assert_noop!(1757			TemplateModule::create_collection(1758				origin1,1759				col_name1,1760				col_desc1,1761				token_prefix1,1762				CollectionMode::NFT1763			),1764			Error::<Test>::TotalCollectionsLimitExceeded1765		);1766	});1767}17681769// Owned tokens by a single address. Positive test1770#[test]1771fn owned_tokens_bound() {1772	new_test_ext().execute_with(|| {1773		let collection_id = create_test_collection(&CollectionMode::NFT, 1);17741775		let data = default_nft_data();1776		create_test_item(collection_id, &data.clone().into());1777		create_test_item(collection_id, &data.into());1778	});1779}17801781// Owned tokens by a single address. Negotive test1782#[test]1783fn owned_tokens_bound_neg() {1784	new_test_ext().execute_with(|| {1785		let collection_id = create_test_collection(&CollectionMode::NFT, 1);17861787		let origin1 = Origin::signed(1);17881789		for _ in 0..ACCOUNT_TOKEN_OWNERSHIP_LIMIT {1790			let data = default_nft_data();1791			create_test_item(collection_id, &data.clone().into());1792		}17931794		let data = default_nft_data();1795		assert_noop!(1796			TemplateModule::create_item(origin1, 1, account(1), data.into()),1797			Error::<Test>::AccountTokenLimitExceeded1798		);1799	});1800}18011802// Number of collection admins. Positive test1803#[test]1804fn collection_admins_bound() {1805	new_test_ext().execute_with(|| {1806		let collection_id = create_test_collection(&CollectionMode::NFT, 1);18071808		let origin1 = Origin::signed(1);18091810		assert_ok!(TemplateModule::add_collection_admin(1811			origin1.clone(),1812			collection_id,1813			account(2)1814		));1815		assert_ok!(TemplateModule::add_collection_admin(1816			origin1,1817			collection_id,1818			account(3)1819		));1820	});1821}18221823// Number of collection admins. Negotive test1824#[test]1825fn collection_admins_bound_neg() {1826	new_test_ext().execute_with(|| {1827		let collection_id = create_test_collection(&CollectionMode::NFT, 1);18281829		let origin1 = Origin::signed(1);18301831		for i in 0..COLLECTION_ADMINS_LIMIT {1832			assert_ok!(TemplateModule::add_collection_admin(1833				origin1.clone(),1834				collection_id,1835				account(2 + i)1836			));1837		}1838		assert_noop!(1839			TemplateModule::add_collection_admin(1840				origin1,1841				collection_id,1842				account(3 + COLLECTION_ADMINS_LIMIT)1843			),1844			Error::<Test>::CollectionAdminsLimitExceeded1845		);1846	});1847}1848// #endregion18491850#[test]1851fn set_const_on_chain_schema() {1852	new_test_ext().execute_with(|| {1853		let collection_id = create_test_collection(&CollectionMode::NFT, 1);18541855		let origin1 = Origin::signed(1);1856		assert_ok!(TemplateModule::set_const_on_chain_schema(1857			origin1,1858			collection_id,1859			b"test const on chain schema".to_vec()1860		));18611862		assert_eq!(1863			TemplateModule::collection_id(collection_id)1864				.unwrap()1865				.const_on_chain_schema,1866			b"test const on chain schema".to_vec()1867		);1868		assert_eq!(1869			TemplateModule::collection_id(collection_id)1870				.unwrap()1871				.variable_on_chain_schema,1872			b"".to_vec()1873		);1874	});1875}18761877#[test]1878fn set_variable_on_chain_schema() {1879	new_test_ext().execute_with(|| {1880		let collection_id = create_test_collection(&CollectionMode::NFT, 1);18811882		let origin1 = Origin::signed(1);1883		assert_ok!(TemplateModule::set_variable_on_chain_schema(1884			origin1,1885			collection_id,1886			b"test variable on chain schema".to_vec()1887		));18881889		assert_eq!(1890			TemplateModule::collection_id(collection_id)1891				.unwrap()1892				.const_on_chain_schema,1893			b"".to_vec()1894		);1895		assert_eq!(1896			TemplateModule::collection_id(collection_id)1897				.unwrap()1898				.variable_on_chain_schema,1899			b"test variable on chain schema".to_vec()1900		);1901	});1902}19031904#[test]1905fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {1906	new_test_ext().execute_with(|| {1907		let collection_id = create_test_collection(&CollectionMode::NFT, 1);19081909		let origin1 = Origin::signed(1);19101911		let data = default_nft_data();1912		create_test_item(1, &data.into());19131914		let variable_data = b"test data".to_vec();1915		assert_ok!(TemplateModule::set_variable_meta_data(1916			origin1,1917			collection_id,1918			1,1919			variable_data.clone()1920		));19211922		assert_eq!(1923			TemplateModule::nft_item_id(collection_id, 1)1924				.unwrap()1925				.variable_data,1926			variable_data1927		);1928	});1929}19301931#[test]1932fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {1933	new_test_ext().execute_with(|| {1934		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);19351936		let origin1 = Origin::signed(1);19371938		let data = default_re_fungible_data();1939		create_test_item(1, &data.into());19401941		let variable_data = b"test data".to_vec();1942		assert_ok!(TemplateModule::set_variable_meta_data(1943			origin1,1944			collection_id,1945			1,1946			variable_data.clone()1947		));19481949		assert_eq!(1950			TemplateModule::refungible_item_id(collection_id, 1)1951				.unwrap()1952				.variable_data,1953			variable_data1954		);1955	});1956}19571958#[test]1959fn set_variable_meta_data_on_fungible_token_fails() {1960	new_test_ext().execute_with(|| {1961		let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);19621963		let origin1 = Origin::signed(1);19641965		let data = default_fungible_data();1966		create_test_item(1, &data.into());19671968		let variable_data = b"test data".to_vec();1969		assert_noop!(1970			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),1971			Error::<Test>::CantStoreMetadataInFungibleTokens1972		);1973	});1974}19751976#[test]1977fn set_variable_meta_data_on_nft_token_fails_for_big_data() {1978	new_test_ext().execute_with(|| {1979		let collection_id = create_test_collection(&CollectionMode::NFT, 1);19801981		let origin1 = Origin::signed(1);19821983		let data = default_nft_data();1984		create_test_item(1, &data.into());19851986		let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1987		assert_noop!(1988			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),1989			Error::<Test>::TokenVariableDataLimitExceeded1990		);1991	});1992}19931994#[test]1995fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {1996	new_test_ext().execute_with(|| {1997		let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);19981999		let origin1 = Origin::signed(1);20002001		let data = default_re_fungible_data();2002		create_test_item(1, &data.into());20032004		let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();2005		assert_noop!(2006			TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data),2007			Error::<Test>::TokenVariableDataLimitExceeded2008		);2009	});2010}20112012#[test]2013fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {2014	new_test_ext().execute_with(|| {2015		//default_limits();20162017		let collection_id = create_test_collection(&CollectionMode::NFT, 1);20182019		let origin1 = Origin::signed(1);20202021		let data = default_nft_data();2022		create_test_item(1, &data.into());20232024		assert_ok!(TemplateModule::set_meta_update_permission_flag(2025			origin1.clone(),2026			collection_id,2027			MetaUpdatePermission::ItemOwner,2028		));20292030		let variable_data = b"ten chars.".to_vec();2031		assert_ok!(TemplateModule::set_variable_meta_data(2032			origin1,2033			collection_id,2034			1,2035			variable_data.clone()2036		));20372038		assert_eq!(2039			TemplateModule::nft_item_id(collection_id, 1)2040				.unwrap()2041				.variable_data,2042			variable_data2043		);2044	});2045}20462047#[test]2048fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {2049	new_test_ext().execute_with(|| {2050		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);20512052		let origin1 = Origin::signed(1);20532054		assert_ok!(TemplateModule::set_mint_permission(2055			origin1.clone(),2056			collection_id,2057			true2058		));2059		assert_ok!(TemplateModule::add_to_allow_list(2060			origin1.clone(),2061			collection_id,2062			account(1)2063		));20642065		let data = default_nft_data();2066		create_test_item(1, &data.into());20672068		assert_ok!(TemplateModule::set_meta_update_permission_flag(2069			origin1.clone(),2070			collection_id,2071			MetaUpdatePermission::ItemOwner,2072		));20732074		let variable_data = b"1234567890123".to_vec();2075		assert_noop!(2076			TemplateModule::set_variable_meta_data(2077				origin1,2078				collection_id,2079				1,2080				variable_data.clone()2081			),2082			Error::<Test>::TokenVariableDataLimitExceeded2083		);2084	})2085}20862087#[test]2088fn collection_transfer_flag_works() {2089	new_test_ext().execute_with(|| {2090		let origin1 = Origin::signed(1);20912092		let collection_id = create_test_collection(&CollectionMode::NFT, 1);2093		assert_ok!(TemplateModule::set_transfers_enabled_flag(origin1, 1, true));20942095		let data = default_nft_data();2096		create_test_item(collection_id, &data.into());2097		assert_eq!(TemplateModule::balance_count(1, 1), 1);2098		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);20992100		let origin1 = Origin::signed(1);21012102		// default scenario2103		assert_ok!(TemplateModule::transfer(origin1, account(2), 1, 1, 1000));2104		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(2));2105		assert_eq!(TemplateModule::balance_count(1, 1), 0);2106		assert_eq!(TemplateModule::balance_count(1, 2), 1);21072108		assert_eq!(TemplateModule::address_tokens(1, 2), [1]);2109	});2110}21112112#[test]2113fn set_variable_meta_data_on_nft_with_admin_flag() {2114	new_test_ext().execute_with(|| {2115		// default_limits();21162117		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);21182119		let origin1 = Origin::signed(1);2120		let origin2 = Origin::signed(2);21212122		assert_ok!(TemplateModule::set_mint_permission(2123			origin2.clone(),2124			collection_id,2125			true2126		));2127		assert_ok!(TemplateModule::add_to_allow_list(2128			origin2.clone(),2129			collection_id,2130			account(1)2131		));21322133		assert_ok!(TemplateModule::add_collection_admin(2134			origin2.clone(),2135			collection_id,2136			account(1)2137		));21382139		let data = default_nft_data();2140		create_test_item(1, &data.into());21412142		assert_ok!(TemplateModule::set_meta_update_permission_flag(2143			origin2.clone(),2144			collection_id,2145			MetaUpdatePermission::Admin,2146		));21472148		let variable_data = b"test.".to_vec();2149		assert_ok!(TemplateModule::set_variable_meta_data(2150			origin1,2151			collection_id,2152			1,2153			variable_data.clone()2154		));21552156		assert_eq!(2157			TemplateModule::nft_item_id(collection_id, 1)2158				.unwrap()2159				.variable_data,2160			variable_data2161		);2162	});2163}21642165#[test]2166fn set_variable_meta_data_on_nft_with_admin_flag_neg() {2167	new_test_ext().execute_with(|| {2168		// default_limits();21692170		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);21712172		let origin1 = Origin::signed(1);2173		let origin2 = Origin::signed(2);21742175		assert_ok!(TemplateModule::set_mint_permission(2176			origin2.clone(),2177			collection_id,2178			true2179		));2180		assert_ok!(TemplateModule::add_to_allow_list(2181			origin2.clone(),2182			collection_id,2183			account(1)2184		));21852186		let data = default_nft_data();2187		create_test_item(1, &data.into());21882189		assert_ok!(TemplateModule::set_meta_update_permission_flag(2190			origin2.clone(),2191			collection_id,2192			MetaUpdatePermission::Admin,2193		));21942195		let variable_data = b"test.".to_vec();2196		assert_noop!(2197			TemplateModule::set_variable_meta_data(2198				origin1,2199				collection_id,2200				1,2201				variable_data.clone()2202			),2203			Error::<Test>::NoPermission2204		);2205	});2206}22072208#[test]2209fn set_variable_meta_flag_after_freeze() {2210	new_test_ext().execute_with(|| {2211		// default_limits();22122213		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);22142215		let origin2 = Origin::signed(2);22162217		assert_ok!(TemplateModule::set_meta_update_permission_flag(2218			origin2.clone(),2219			collection_id,2220			MetaUpdatePermission::None,2221		));2222		assert_noop!(2223			TemplateModule::set_meta_update_permission_flag(2224				origin2.clone(),2225				collection_id,2226				MetaUpdatePermission::Admin2227			),2228			Error::<Test>::MetadataFlagFrozen2229		);2230	});2231}22322233#[test]2234fn set_variable_meta_data_on_nft_with_none_flag_neg() {2235	new_test_ext().execute_with(|| {2236		// default_limits();22372238		let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);2239		let origin1 = Origin::signed(1);22402241		let data = default_nft_data();2242		create_test_item(1, &data.into());22432244		assert_ok!(TemplateModule::set_meta_update_permission_flag(2245			origin1.clone(),2246			collection_id,2247			MetaUpdatePermission::None,2248		));22492250		let variable_data = b"test.".to_vec();2251		assert_noop!(2252			TemplateModule::set_variable_meta_data(2253				origin1.clone(),2254				collection_id,2255				1,2256				variable_data.clone()2257			),2258			Error::<Test>::MetadataUpdateDenied2259		);2260	});2261}22622263#[test]2264fn collection_transfer_flag_works_neg() {2265	new_test_ext().execute_with(|| {2266		let origin1 = Origin::signed(1);22672268		let collection_id = create_test_collection(&CollectionMode::NFT, 1);2269		assert_ok!(TemplateModule::set_transfers_enabled_flag(2270			origin1, 1, false2271		));22722273		let data = default_nft_data();2274		create_test_item(collection_id, &data.into());2275		assert_eq!(TemplateModule::balance_count(1, 1), 1);2276		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);22772278		let origin1 = Origin::signed(1);22792280		// default scenario2281		assert_noop!(2282			TemplateModule::transfer(origin1, account(2), 1, 1, 1000),2283			Error::<Test>::TransferNotAllowed2284		);2285		assert_eq!(TemplateModule::nft_item_id(1, 1).unwrap().owner, account(1));2286		assert_eq!(TemplateModule::balance_count(1, 1), 1);2287		assert_eq!(TemplateModule::balance_count(1, 2), 0);22882289		assert_eq!(TemplateModule::address_tokens(1, 1), [1]);2290	});2291}
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
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -53,7 +53,7 @@
 		WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients,
 	},
 };
-use nft_data_structs::*;
+use up_data_structs::*;
 // use pallet_contracts::weights::WeightInfo;
 // #[cfg(any(feature = "std", test))]
 use frame_system::{
@@ -259,7 +259,7 @@
 	type Event = Event;
 	type OnMethodCall = (
 		pallet_evm_migration::OnMethodCall<Self>,
-		pallet_nft::NftErcSupport<Self>,
+		pallet_unique::UniqueErcSupport<Self>,
 		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
 	);
 	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
@@ -755,9 +755,8 @@
 	type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
 }
 
-/// Used for the pallet nft in `./nft.rs`
-impl pallet_nft::Config for Runtime {
-	type WeightInfo = pallet_nft::weights::SubstrateWeight<Self>;
+impl pallet_unique::Config for Runtime {
+	type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
 }
 
 parameter_types! {
@@ -778,11 +777,11 @@
 // }
 
 type EvmSponsorshipHandler = (
-	pallet_nft::NftEthSponsorshipHandler<Runtime>,
+	pallet_unique::UniqueEthSponsorshipHandler<Runtime>,
 	pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
 );
 type SponsorshipHandler = (
-	pallet_nft::NftSponsorshipHandler<Runtime>,
+	pallet_unique::UniqueSponsorshipHandler<Runtime>,
 	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
 	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
 );
@@ -806,7 +805,7 @@
 	type EvmBackwardsAddressMapping = up_evm_mapping::MapBackwardsAddressTruncated;
 }
 
-impl pallet_nft_charge_transaction::Config for Runtime {
+impl pallet_charge_transaction::Config for Runtime {
 	type SponsorshipHandler = SponsorshipHandler;
 }
 
@@ -857,10 +856,10 @@
 
 		// Unique Pallets
 		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
-		Nft: pallet_nft::{Pallet, Call, Storage} = 61,
+		Unique: pallet_unique::{Pallet, Call, Storage} = 61,
 		// Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
 		// free = 63
-		Charging: pallet_nft_charge_transaction::{Pallet, Call, Storage } = 64,
+		Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
 		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
 		Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
 		Fungible: pallet_fungible::{Pallet, Storage} = 67,
@@ -920,7 +919,7 @@
 	system::CheckEra<Runtime>,
 	system::CheckNonce<Runtime>,
 	system::CheckWeight<Runtime>,
-	pallet_nft_charge_transaction::ChargeTransactionPayment<Runtime>,
+	pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
 	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,
 );
 /// Unchecked extrinsic type as expected by this runtime.
@@ -990,9 +989,9 @@
 	}
 }
 
-macro_rules! dispatch_nft_runtime {
+macro_rules! dispatch_unique_runtime {
 	($collection:ident.$method:ident($($name:ident),*)) => {{
-		use pallet_nft::dispatch::Dispatched;
+		use pallet_unique::dispatch::Dispatched;
 
 		let collection = Dispatched::dispatch(<pallet_common::CollectionHandle<Runtime>>::new($collection).unwrap());
 		let dispatch = collection.as_dyn();
@@ -1001,34 +1000,34 @@
 	}};
 }
 impl_runtime_apis! {
-	impl up_rpc::NftApi<Block, CrossAccountId, AccountId>
+	impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId>
 		for Runtime
 	{
 		fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId> {
-			dispatch_nft_runtime!(collection.account_tokens(account))
+			dispatch_unique_runtime!(collection.account_tokens(account))
 		}
 		fn token_exists(collection: CollectionId, token: TokenId) -> bool {
-			dispatch_nft_runtime!(collection.token_exists(token))
+			dispatch_unique_runtime!(collection.token_exists(token))
 		}
 
 		fn token_owner(collection: CollectionId, token: TokenId) -> CrossAccountId {
-			dispatch_nft_runtime!(collection.token_owner(token))
+			dispatch_unique_runtime!(collection.token_owner(token))
 		}
 		fn const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8> {
-			dispatch_nft_runtime!(collection.const_metadata(token))
+			dispatch_unique_runtime!(collection.const_metadata(token))
 		}
 		fn variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8> {
-			dispatch_nft_runtime!(collection.variable_metadata(token))
+			dispatch_unique_runtime!(collection.variable_metadata(token))
 		}
 
 		fn collection_tokens(collection: CollectionId) -> u32 {
-			dispatch_nft_runtime!(collection.collection_tokens())
+			dispatch_unique_runtime!(collection.collection_tokens())
 		}
 		fn account_balance(collection: CollectionId, account: CrossAccountId) -> u32 {
-			dispatch_nft_runtime!(collection.account_balance(account))
+			dispatch_unique_runtime!(collection.account_balance(account))
 		}
 		fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> u128 {
-			dispatch_nft_runtime!(collection.balance(account, token))
+			dispatch_unique_runtime!(collection.balance(account, token))
 		}
 		fn allowance(
 			collection: CollectionId,
@@ -1036,11 +1035,11 @@
 			spender: CrossAccountId,
 			token: TokenId,
 		) -> u128 {
-			dispatch_nft_runtime!(collection.allowance(sender, spender, token))
+			dispatch_unique_runtime!(collection.allowance(sender, spender, token))
 		}
 
 		fn eth_contract_code(account: H160) -> Option<Vec<u8>> {
-			<pallet_nft::NftErcSupport<Runtime>>::get_code(&account)
+			<pallet_unique::UniqueErcSupport<Runtime>>::get_code(&account)
 				.or_else(|| <pallet_evm_migration::OnMethodCall<Runtime>>::get_code(&account))
 				.or_else(|| <pallet_evm_contract_helpers::HelpersOnMethodCall<Self>>::get_code(&account))
 		}
@@ -1054,7 +1053,7 @@
 			<pallet_common::Pallet<Runtime>>::allowed(collection, user)
 		}
 		fn last_token_id(collection: CollectionId) -> TokenId {
-			dispatch_nft_runtime!(collection.last_token_id())
+			dispatch_unique_runtime!(collection.last_token_id())
 		}
 		fn collection_by_id(collection: CollectionId) -> Option<Collection<AccountId>> {
 			<pallet_common::CollectionById<Runtime>>::get(collection)
@@ -1338,7 +1337,7 @@
 			let mut list = Vec::<BenchmarkList>::new();
 
 			list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);
-			list_benchmark!(list, extra, pallet_nft, Nft);
+			list_benchmark!(list, extra, pallet_unique, Unique);
 			list_benchmark!(list, extra, pallet_inflation, Inflation);
 			list_benchmark!(list, extra, pallet_fungible, Fungible);
 			list_benchmark!(list, extra, pallet_refungible, Refungible);
@@ -1371,7 +1370,7 @@
 			let params = (&config, &allowlist);
 
 			add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);
-			add_benchmark!(params, batches, pallet_nft, Nft);
+			add_benchmark!(params, batches, pallet_unique, Unique);
 			add_benchmark!(params, batches, pallet_inflation, Inflation);
 			add_benchmark!(params, batches, pallet_fungible, Fungible);
 			add_benchmark!(params, batches, pallet_refungible, Refungible);
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> {