git.delta.rocks / unique-network / refs/commits / 3d7ffe75f2a8

difftreelog

fix skip refungible and scheduler tests on qtz/unq

Daniel Shiposha2022-08-09parent: #5eadf5f.patch.diff
in: master

43 files changed

modifiedtests/src/approve.test.tsdiffbeforeafterboth
--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -32,6 +32,8 @@
   getCreatedCollectionCount,
   transferFromExpectSuccess,
   transferFromExpectFail,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -49,34 +51,44 @@
     });
   });
 
-  it('Execute the extrinsic and check approvedList', async () => {
+  it('[nft] Execute the extrinsic and check approvedList', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
-    // nft
     const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
     await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
-    // fungible
+  });
+
+  it('[fungible] Execute the extrinsic and check approvedList', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
     await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
-    // reFungible
+  });
+
+  it('[refungible] Execute the extrinsic and check approvedList', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId =
       await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
     await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
   });
 
-  it('Remove approval by using 0 amount', async () => {
+  it('[nft] Remove approval by using 0 amount', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
-    // nft
     const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
     await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);
     await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);
-    // fungible
+  });
+
+  it('[fungible] Remove approval by using 0 amount', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
     await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);
     await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);
-    // reFungible
+  });
+
+  it('[refungible] Remove approval by using 0 amount', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId =
       await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -117,7 +129,9 @@
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
   });
 
-  it('ReFungible up to an approved amount', async () => {
+  it('ReFungible up to an approved amount', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
@@ -151,7 +165,9 @@
     await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');
   });
 
-  it('ReFungible up to an approved amount', async () => {
+  it('ReFungible up to an approved amount', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
@@ -188,7 +204,9 @@
     await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);
   });
 
-  it('ReFungible up to an approved amount', async () => {
+  it('ReFungible up to an approved amount', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
     await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
@@ -250,7 +268,9 @@
     await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);
   });
 
-  it('ReFungible', async () => {
+  it('ReFungible', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId =
       await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -285,7 +305,9 @@
     await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);
   });
 
-  it('ReFungible', async () => {
+  it('ReFungible', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
     await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, charlie, 101);
@@ -325,7 +347,9 @@
     await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');
   });
 
-  it('ReFungible up to an approved amount', async () => {
+  it('ReFungible up to an approved amount', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
     await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
     const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', charlie.address);
@@ -422,63 +446,87 @@
     });
   });
 
-  it('Approve for a collection that does not exist', async () => {
+  it('[nft] Approve for a collection that does not exist', async () => {
     await usingApi(async (api: ApiPromise) => {
-      // nft
       const nftCollectionCount = await getCreatedCollectionCount(api);
       await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);
-      // fungible
+    });
+  });
+
+  it('[fungible] Approve for a collection that does not exist', async () => {
+    await usingApi(async (api: ApiPromise) => {
       const fungibleCollectionCount = await getCreatedCollectionCount(api);
       await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);
-      // reFungible
+    });
+  });
+
+  it('[refungible] Approve for a collection that does not exist', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    await usingApi(async (api: ApiPromise) => {
       const reFungibleCollectionCount = await getCreatedCollectionCount(api);
       await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
     });
   });
 
-  it('Approve for a collection that was destroyed', async () => {
-    // nft
+  it('[nft] Approve for a collection that was destroyed', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
     await destroyCollectionExpectSuccess(nftCollectionId);
     await approveExpectFail(nftCollectionId, 1, alice, bob);
-    // fungible
+  });
+
+  it('Approve for a collection that was destroyed', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     await destroyCollectionExpectSuccess(fungibleCollectionId);
     await approveExpectFail(fungibleCollectionId, 0, alice, bob);
-    // reFungible
+  });
+
+  it('[refungible] Approve for a collection that was destroyed', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId =
       await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await destroyCollectionExpectSuccess(reFungibleCollectionId);
     await approveExpectFail(reFungibleCollectionId, 1, alice, bob);
   });
 
-  it('Approve transfer of a token that does not exist', async () => {
-    // nft
+  it('[nft] Approve transfer of a token that does not exist', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
     await approveExpectFail(nftCollectionId, 2, alice, bob);
-    // reFungible
+  });
+
+  it('[refungible] Approve transfer of a token that does not exist', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId =
       await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await approveExpectFail(reFungibleCollectionId, 2, alice, bob);
   });
 
-  it('Approve using the address that does not own the approved token', async () => {
+  it('[nft] Approve using the address that does not own the approved token', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
-    // nft
     const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
     await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);
-    // fungible
+  });
+
+  it('[fungible] Approve using the address that does not own the approved token', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
     await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);
-    // reFungible
+  });
+
+  it('[refungible] Approve using the address that does not own the approved token', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId =
       await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
     await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);
   });
 
-  it('should fail if approved more ReFungibles than owned', async () => {
+  it('should fail if approved more ReFungibles than owned', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');
     await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 100, 'ReFungible');
modifiedtests/src/burnItem.test.tsdiffbeforeafterboth
--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -25,6 +25,8 @@
   getBalance,
   setCollectionLimitsExpectSuccess,
   isTokenExists,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 
 import chai from 'chai';
@@ -80,7 +82,9 @@
     });
   });
 
-  it('Burn item in ReFungible collection', async () => {
+  it('Burn item in ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const createMode = 'ReFungible';
     const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
     const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
@@ -99,7 +103,9 @@
     });
   });
 
-  it('Burn owned portion of item in ReFungible collection', async () => {
+  it('Burn owned portion of item in ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const createMode = 'ReFungible';
     const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
     const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
@@ -189,7 +195,9 @@
   });
 
   // TODO: burnFrom
-  it('Burn item in ReFungible collection', async () => {
+  it('Burn item in ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const createMode = 'ReFungible';
     const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
     await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -33,6 +33,8 @@
   addCollectionAdminExpectSuccess,
   getCreatedCollectionCount,
   UNIQUE,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 import {IKeyringPair} from '@polkadot/types/types';
 
@@ -124,7 +126,9 @@
     });
   });
 
-  it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {
+  it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
     await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
@@ -252,7 +256,9 @@
     });
   });
 
-  it('ReFungible: Sponsoring is rate limited', async () => {
+  it('ReFungible: Sponsoring is rate limited', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
     await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
modifiedtests/src/createCollection.test.tsdiffbeforeafterboth
--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -16,7 +16,7 @@
 
 import {expect} from 'chai';
 import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';
-import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess} from './util/helpers';
+import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess, requirePallets, Pallets} from './util/helpers';
 
 describe('integration test: ext. createCollection():', () => {
   it('Create new NFT collection', async () => {
@@ -34,7 +34,9 @@
   it('Create new Fungible collection', async () => {
     await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
   });
-  it('Create new ReFungible collection', async () => {
+  it('Create new ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
   });
 
modifiedtests/src/createItem.test.tsdiffbeforeafterboth
--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -29,6 +29,8 @@
   itApi,
   normalizeAccountId,
   getCreateItemResult,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 
 const expect = chai.expect;
@@ -79,7 +81,9 @@
     }
 
   });
-  it('Create new item in ReFungible collection', async () => {
+  it('Create new item in ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const createMode = 'ReFungible';
     const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
     await createItemExpectSuccess(alice, newCollectionID, createMode);
@@ -96,7 +100,9 @@
     await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
     await createItemExpectSuccess(bob, newCollectionID, createMode);
   });
-  it('Create new item in ReFungible collection with collection admin permissions', async () => {
+  it('Create new item in ReFungible collection with collection admin permissions', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const createMode = 'ReFungible';
     const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
     await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
@@ -175,7 +181,9 @@
     });
   });
 
-  it('Check total pieces of ReFungible token', async () => {
+  it('Check total pieces of ReFungible token', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async api => {
       const createMode = 'ReFungible';
       const createCollectionResult = await createCollection(api, alice, {mode: {type: createMode}});
@@ -219,7 +227,9 @@
     const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
     await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
   });
-  it('Regular user cannot create new item in ReFungible collection', async () => {
+  it('Regular user cannot create new item in ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const createMode = 'ReFungible';
     const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
     await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
@@ -296,7 +306,9 @@
     });
   });
 
-  it('Check total pieces for invalid Refungible token', async () => {
+  it('Check total pieces for invalid Refungible token', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async api => {
       const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});
       const collectionId  = createCollectionResult.collectionId;
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -33,6 +33,9 @@
   createCollectionWithPropsExpectSuccess,
   createMultipleItemsWithPropsExpectSuccess,
   getTokenProperties,
+  requirePallets,
+  Pallets,
+  checkPalletsPresence
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -91,7 +94,9 @@
     });
   });
 
-  it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
+  it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api, privateKeyWrapper) => {
       const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
@@ -272,7 +277,9 @@
     });
   });
 
-  it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
+  it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
@@ -335,7 +342,9 @@
     });
   });
 
-  it('Regular user cannot create items in active ReFungible collection', async () => {
+  it('Regular user cannot create items in active ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
@@ -358,9 +367,8 @@
     });
   });
 
-  it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {
+  it('Create NFTs that has reached the maximum data limit', async function() {
     await usingApi(async (api, privateKeyWrapper) => {
-      // NFT
       const collectionId = await createCollectionWithPropsExpectSuccess({
         propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],
       });
@@ -372,8 +380,13 @@
       ];
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
+    });
+  });
 
-      // ReFungible
+  it('Create Refungible tokens that has reached the maximum data limit', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    await usingApi(async api => {
       const collectionIdReFungible =
         await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       {
@@ -402,8 +415,15 @@
   it('Create tokens with different types', async () => {
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess();
+
+      let types = ['NFT', 'Fungible'];
+
+      if (await checkPalletsPresence([Pallets.ReFungible])) {
+        types.push('ReFungible');
+      }
+
       const createMultipleItemsTx = api.tx.unique
-        .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'Fungible', 'ReFungible']);
+        .createMultipleItems(collectionId, normalizeAccountId(alice.address), types);
       await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);
       // garbage collection :-D // lol
       await destroyCollectionExpectSuccess(collectionId);
modifiedtests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItemsEx.test.ts
+++ b/tests/src/createMultipleItemsEx.test.ts
@@ -16,7 +16,7 @@
 
 import {expect} from 'chai';
 import usingApi, {executeTransaction} from './substrate/substrate-api';
-import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties} from './util/helpers';
+import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties, requirePallets, Pallets} from './util/helpers';
 
 describe.only('Integration Test: createMultipleItemsEx', () => {
   it('can initialize multiple NFT with different owners', async () => {
@@ -146,7 +146,9 @@
     });
   });
 
-  it('can initialize an RFT with multiple owners', async () => {
+  it('can initialize an RFT with multiple owners', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api, privateKeyWrapper) => {
       const alice = privateKeyWrapper('//Alice');
       const bob = privateKeyWrapper('//Bob');
@@ -178,7 +180,9 @@
     });
   });
 
-  it('can initialize multiple RFTs with the same owner', async () => {
+  it('can initialize multiple RFTs with the same owner', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api, privateKeyWrapper) => {
       const alice = privateKeyWrapper('//Alice');
       const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
@@ -389,7 +393,9 @@
     });
   });
 
-  it('fails when trying to set multiple owners when creating multiple refungibles', async () => {
+  it('fails when trying to set multiple owners when creating multiple refungibles', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
 
     await usingApi(async (api, privateKeyWrapper) => {
modifiedtests/src/destroyCollection.test.tsdiffbeforeafterboth
--- a/tests/src/destroyCollection.test.ts
+++ b/tests/src/destroyCollection.test.ts
@@ -25,6 +25,8 @@
   addCollectionAdminExpectSuccess,
   getCreatedCollectionCount,
   createItemExpectSuccess,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -38,7 +40,9 @@
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     await destroyCollectionExpectSuccess(collectionId);
   });
-  it('ReFungible collection can be destroyed', async () => {
+  it('ReFungible collection can be destroyed', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await destroyCollectionExpectSuccess(collectionId);
   });
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -16,7 +16,7 @@
 
 import {evmToAddress} from '@polkadot/util-crypto';
 import {expect} from 'chai';
-import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';
+import {getCreatedCollectionCount, getDetailedCollectionInfo, requirePallets, Pallets} from '../util/helpers';
 import {
   evmCollectionHelpers,
   collectionIdToAddress,
@@ -28,6 +28,10 @@
 } from './util/helpers';
 
 describe('Create RFT collection from EVM', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelper = evmCollectionHelpers(web3, owner);
@@ -146,6 +150,10 @@
 });
 
 describe('(!negative tests!) Create RFT collection from EVM', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, owner);
@@ -228,4 +236,4 @@
       .setCollectionLimit('badLimit', 'true')
       .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
   });
-});
\ No newline at end of file
+});
modifiedtests/src/eth/reFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -14,12 +14,16 @@
 // You should have received a copy of the GNU General Public License
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
-import {createCollectionExpectSuccess, UNIQUE} from '../util/helpers';
+import {createCollectionExpectSuccess, UNIQUE, requirePallets, Pallets} from '../util/helpers';
 import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress} from './util/helpers';
 import reFungibleTokenAbi from './reFungibleTokenAbi.json';
 import {expect} from 'chai';
 
 describe('Refungible: Information getting', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
     const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, caller);
@@ -120,6 +124,10 @@
 });
 
 describe('Refungible: Plain calls', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, owner);
@@ -399,6 +407,10 @@
 });
 
 describe('RFT: Fees', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
     const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, caller);
@@ -435,6 +447,10 @@
 });
 
 describe('Common metadata', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
     const collection = await createCollectionExpectSuccess({
       name: 'token name',
@@ -462,4 +478,4 @@
 
     expect(symbol).to.equal('TOK');
   });
-});
\ No newline at end of file
+});
modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
-import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE} from '../util/helpers';
+import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';
 import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';
 import reFungibleTokenAbi from './reFungibleTokenAbi.json';
 
@@ -24,6 +24,10 @@
 const expect = chai.expect;
 
 describe('Refungible token: Information getting', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
@@ -75,6 +79,10 @@
 
 // FIXME: Need erc721 for ReFubgible.
 describe('Check ERC721 token URI for ReFungible', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, owner);
@@ -216,6 +224,10 @@
 });
 
 describe('Refungible: Plain calls', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
@@ -477,6 +489,10 @@
 });
 
 describe('Refungible: Fees', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
@@ -532,6 +548,10 @@
 });
 
 describe('Refungible: Substrate calls', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+  });
+
   itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
modifiedtests/src/eth/scheduling.test.tsdiffbeforeafterboth
--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -16,9 +16,13 @@
 
 import {expect} from 'chai';
 import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
-import {scheduleExpectSuccess, waitNewBlocks} from '../util/helpers';
+import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../util/helpers';
 
 describe('Scheduing EVM smart contracts', () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.Scheduler]);
+  });
+
   itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {
     const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, deployer);
@@ -51,4 +55,4 @@
       expect(await flipper.methods.getValue().call()).to.be.equal(initialValue);
     }
   });
-});
\ No newline at end of file
+});
modifiedtests/src/limits.test.tsdiffbeforeafterboth
--- a/tests/src/limits.test.ts
+++ b/tests/src/limits.test.ts
@@ -27,6 +27,8 @@
   transferExpectSuccess,
   getFreeBalance,
   waitNewBlocks, burnItemExpectSuccess,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 import {expect} from 'chai';
 
@@ -67,7 +69,9 @@
 describe('Number of tokens per address (ReFungible)', () => {
   let alice: IKeyringPair;
 
-  before(async () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api, privateKeyWrapper) => {
       alice = privateKeyWrapper('//Alice');
     });
@@ -367,7 +371,9 @@
   let bob: IKeyringPair;
   let charlie: IKeyringPair;
 
-  before(async () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api, privateKeyWrapper) => {
       alice = privateKeyWrapper('//Alice');
       bob = privateKeyWrapper('//Bob');
modifiedtests/src/nesting/nest.test.tsdiffbeforeafterboth
before · tests/src/nesting/nest.test.ts
1import {expect} from 'chai';2import {tokenIdToAddress} from '../eth/util/helpers';3import usingApi, {executeTransaction} from '../substrate/substrate-api';4import {5  addCollectionAdminExpectSuccess,6  addToAllowListExpectSuccess,7  createCollectionExpectSuccess,8  createItemExpectSuccess,9  enableAllowListExpectSuccess,10  enablePublicMintingExpectSuccess,11  getTokenChildren,12  getTokenOwner,13  getTopmostTokenOwner,14  normalizeAccountId,15  setCollectionPermissionsExpectSuccess,16  transferExpectFailure,17  transferExpectSuccess,18  transferFromExpectSuccess,19  setCollectionLimitsExpectSuccess,20} from '../util/helpers';21import {IKeyringPair} from '@polkadot/types/types';2223let alice: IKeyringPair;24let bob: IKeyringPair;25let charlie: IKeyringPair;2627describe('Integration Test: Composite nesting tests', () => {28  before(async () => {29    await usingApi(async (_, privateKeyWrapper) => {30      alice = privateKeyWrapper('//Alice');31      bob = privateKeyWrapper('//Bob');32    });33  });3435  it('Performs the full suite: bundles a token, transfers, and unnests', async () => {36    await usingApi(async api => {37      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});38      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});39      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');4041      // Create a nested token42      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});43      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});44      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});4546      // Create a token to be nested47      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');4849      // Nest50      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});51      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});52      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});5354      // Move bundle to different user55      await transferExpectSuccess(collection, targetToken, alice, {Substrate: bob.address});56      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: bob.address});57      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});5859      // Unnest60      await transferFromExpectSuccess(collection, newToken, bob, {Ethereum: tokenIdToAddress(collection, targetToken)}, {Substrate: bob.address});61      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});62    });63  });6465  it('Transfers an already bundled token', async () => {66    await usingApi(async api => {67      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});68      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});6970      const tokenA = await createItemExpectSuccess(alice, collection, 'NFT');71      const tokenB = await createItemExpectSuccess(alice, collection, 'NFT');7273      // Create a nested token74      const tokenC = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, tokenA)});75      expect(await getTopmostTokenOwner(api, collection, tokenC)).to.be.deep.equal({Substrate: alice.address});76      expect(await getTokenOwner(api, collection, tokenC)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, tokenA).toLowerCase()});7778      // Transfer the nested token to another token79      await expect(executeTransaction(80        api,81        alice,82        api.tx.unique.transferFrom(83          normalizeAccountId({Ethereum: tokenIdToAddress(collection, tokenA)}),84          normalizeAccountId({Ethereum: tokenIdToAddress(collection, tokenB)}),85          collection,86          tokenC,87          1,88        ),89      )).to.not.be.rejected;90      expect(await getTopmostTokenOwner(api, collection, tokenC)).to.be.deep.equal({Substrate: alice.address});91      expect(await getTokenOwner(api, collection, tokenC)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, tokenB).toLowerCase()});92    });93  });9495  it('Checks token children', async () => {96    await usingApi(async api => {97      const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});98      await setCollectionLimitsExpectSuccess(alice, collectionA, {ownerCanTransfer: true});99      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {tokenOwner: true}});100      const collectionB = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});101102      const targetToken = await createItemExpectSuccess(alice, collectionA, 'NFT');103      const targetAddress = {Ethereum: tokenIdToAddress(collectionA, targetToken)};104      let children = await getTokenChildren(api, collectionA, targetToken);105      expect(children.length).to.be.equal(0, 'Children length check at creation');106107      // Create a nested NFT token108      const tokenA = await createItemExpectSuccess(alice, collectionA, 'NFT', targetAddress);109      children = await getTokenChildren(api, collectionA, targetToken);110      expect(children.length).to.be.equal(1, 'Children length check at nesting #1');111      expect(children).to.have.deep.members([112        {token: tokenA, collection: collectionA},113      ], 'Children contents check at nesting #1');114115      // Create then nest116      const tokenB = await createItemExpectSuccess(alice, collectionA, 'NFT');117      await transferExpectSuccess(collectionA, tokenB, alice, targetAddress);118      children = await getTokenChildren(api, collectionA, targetToken);119      expect(children.length).to.be.equal(2, 'Children length check at nesting #2');120      expect(children).to.have.deep.members([121        {token: tokenA, collection: collectionA},122        {token: tokenB, collection: collectionA},123      ], 'Children contents check at nesting #2');124125      // Move token B to a different user outside the nesting tree126      await transferFromExpectSuccess(collectionA, tokenB, alice, targetAddress, bob);127      children = await getTokenChildren(api, collectionA, targetToken);128      expect(children.length).to.be.equal(1, 'Children length check at unnesting');129      expect(children).to.be.have.deep.members([130        {token: tokenA, collection: collectionA},131      ], 'Children contents check at unnesting');132133      // Create a fungible token in another collection and then nest134      const tokenC = await createItemExpectSuccess(alice, collectionB, 'Fungible');135      await transferExpectSuccess(collectionB, tokenC, alice, targetAddress, 1, 'Fungible');136      children = await getTokenChildren(api, collectionA, targetToken);137      expect(children.length).to.be.equal(2, 'Children length check at nesting #3 (from another collection)');138      expect(children).to.be.have.deep.members([139        {token: tokenA, collection: collectionA},140        {token: tokenC, collection: collectionB},141      ], 'Children contents check at nesting #3 (from another collection)');142143      // Move the fungible token inside token A deeper in the nesting tree144      await transferFromExpectSuccess(collectionB, tokenC, alice, targetAddress, {Ethereum: tokenIdToAddress(collectionA, tokenA)}, 1, 'Fungible');145      children = await getTokenChildren(api, collectionA, targetToken);146      expect(children.length).to.be.equal(1, 'Children length check at deeper nesting');147      expect(children).to.be.have.deep.members([148        {token: tokenA, collection: collectionA},149      ], 'Children contents check at deeper nesting');150    });151  });152});153154describe('Integration Test: Various token type nesting', async () => {155  before(async () => {156    await usingApi(async (_, privateKeyWrapper) => {157      alice = privateKeyWrapper('//Alice');158      bob = privateKeyWrapper('//Bob');159      charlie = privateKeyWrapper('//Charlie');160    });161  });162163  it('Admin (NFT): allows an Admin to nest a token', async () => {164    await usingApi(async api => {165      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});166      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {collectionAdmin: true}});167      await addCollectionAdminExpectSuccess(alice, collection, bob.address);168      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT', charlie.address);169170      // Create a nested token171      const nestedToken = await createItemExpectSuccess(bob, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});172      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: charlie.address});173      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});174175      // Create a token to be nested and nest176      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');177      await transferExpectSuccess(collection, newToken, bob, {Ethereum: tokenIdToAddress(collection, targetToken)});178      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: charlie.address});179      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});180    });181  });182183  it('Admin (NFT): Admin and Token Owner can operate together', async () => {184    await usingApi(async api => {185      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});186      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, collectionAdmin: true}});187      await addCollectionAdminExpectSuccess(alice, collection, bob.address);188      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT', charlie.address);189190      // Create a nested token by an administrator191      const nestedToken = await createItemExpectSuccess(bob, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});192      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: charlie.address});193      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});194195      // Create a token and allow the owner to nest too196      const newToken = await createItemExpectSuccess(alice, collection, 'NFT', charlie.address);197      await transferExpectSuccess(collection, newToken, charlie, {Ethereum: tokenIdToAddress(collection, nestedToken)});198      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: charlie.address});199      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, nestedToken).toLowerCase()});200    });201  });202203  it('Admin (NFT): allows an Admin to nest a token (Restricted nesting)', async () => {204    await usingApi(async api => {205      const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});206      await addCollectionAdminExpectSuccess(alice, collectionA, bob.address);207      const collectionB = await createCollectionExpectSuccess({mode: {type: 'NFT'}});208      await addCollectionAdminExpectSuccess(alice, collectionB, bob.address);209      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {collectionAdmin: true, restricted:[collectionA, collectionB]}});210      const targetToken = await createItemExpectSuccess(alice, collectionA, 'NFT', charlie.address);211212      // Create a nested token213      const nestedToken = await createItemExpectSuccess(bob, collectionB, 'NFT', {Ethereum: tokenIdToAddress(collectionA, targetToken)});214      expect(await getTopmostTokenOwner(api, collectionB, nestedToken)).to.be.deep.equal({Substrate: charlie.address});215      expect(await getTokenOwner(api, collectionB, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collectionA, targetToken).toLowerCase()});216217      // Create a token to be nested and nest218      const newToken = await createItemExpectSuccess(bob, collectionB, 'NFT');219      await transferExpectSuccess(collectionB, newToken, bob, {Ethereum: tokenIdToAddress(collectionA, targetToken)});220      expect(await getTopmostTokenOwner(api, collectionB, newToken)).to.be.deep.equal({Substrate: charlie.address});221      expect(await getTokenOwner(api, collectionB, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collectionA, targetToken).toLowerCase()});222    });223  });224225  // ---------- Non-Fungible ----------226227  it('NFT: allows an Owner to nest/unnest their token', async () => {228    await usingApi(async api => {229      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});230      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});231      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');232233      // Create a nested token234      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});235      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});236      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});237238      // Create a token to be nested and nest239      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');240      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});241      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});242      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});243    });244  });245246  it('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {247    await usingApi(async api => {248      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});249      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[collection]}});250      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');251252      // Create a nested token253      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});254      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});255      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});256257      // Create a token to be nested and nest258      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');259      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});260      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});261      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});262    });263  });264265  // ---------- Fungible ----------266267  it('Fungible: allows an Owner to nest/unnest their token', async () => {268    await usingApi(async api => {269      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});270      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});271      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});272      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};273274      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});275276      // Create a nested token277      await expect(executeTransaction(api, alice, api.tx.unique.createItem(278        collectionFT,279        targetAddress,280        {Fungible: {Value: 10}},281      ))).to.not.be.rejected;282283      // Nest a new token284      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');285      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');286    });287  });288289  it('Fungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {290    await usingApi(async api => {291      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});292      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});293      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};294295      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});296297      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted: [collectionFT]}});298299      // Create a nested token300      await expect(executeTransaction(api, alice, api.tx.unique.createItem(301        collectionFT,302        targetAddress,303        {Fungible: {Value: 10}},304      ))).to.not.be.rejected;305306      // Nest a new token307      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');308      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');309    });310  });311312  // ---------- Re-Fungible ----------313314  it('ReFungible: allows an Owner to nest/unnest their token', async () => {315    await usingApi(async api => {316      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});317      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});318      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});319      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};320321      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});322323      // Create a nested token324      await expect(executeTransaction(api, alice, api.tx.unique.createItem(325        collectionRFT,326        targetAddress,327        {ReFungible: {pieces: 100}},328      ))).to.not.be.rejected;329330      // Nest a new token331      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');332      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');333    });334  });335336  it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {337    await usingApi(async api => {338      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});339      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});340      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};341342      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});343344      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionRFT]}});345346      // Create a nested token347      await expect(executeTransaction(api, alice, api.tx.unique.createItem(348        collectionRFT,349        targetAddress,350        {ReFungible: {pieces: 100}},351      ))).to.not.be.rejected;352353      // Nest a new token354      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');355      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');356    });357  });358});359360describe('Negative Test: Nesting', async() => {361  before(async () => {362    await usingApi(async (_, privateKeyWrapper) => {363      alice = privateKeyWrapper('//Alice');364      bob = privateKeyWrapper('//Bob');365    });366  });367368  it('Disallows excessive token nesting', async () => {369    await usingApi(async api => {370      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});371      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});372      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');373374      const maxNestingLevel = 5;375      let prevToken = targetToken;376377      // Create a nested-token matryoshka378      for (let i = 0; i < maxNestingLevel; i++) {379        const nestedToken = await createItemExpectSuccess(380          alice,381          collection,382          'NFT',383          {Ethereum: tokenIdToAddress(collection, prevToken)},384        );385386        prevToken = nestedToken;387      }388389      // The nesting depth is limited by `maxNestingLevel`390      await expect(executeTransaction(api, alice, api.tx.unique.createItem(391        collection,392        {Ethereum: tokenIdToAddress(collection, prevToken)},393          {nft: {}} as any,394      )), 'while creating nested token').to.be.rejectedWith(/^structure\.DepthLimit$/);395396      expect(await getTopmostTokenOwner(api, collection, prevToken)).to.be.deep.equal({Substrate: alice.address});397    });398  });399400  // ---------- Admin ------------401402  it('Admin (NFT): disallows an Admin to operate nesting when only TokenOwner is allowed', async () => {403    await usingApi(async api => {404      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});405      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});406      await addCollectionAdminExpectSuccess(alice, collection, bob.address);407      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');408409      // Try to create a nested token as collection admin when it's disallowed410      await expect(executeTransaction(api, bob, api.tx.unique.createItem(411        collection,412        {Ethereum: tokenIdToAddress(collection, targetToken)},413          {nft: {}} as any,414      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);415416      // Try to create and nest a token in the wrong collection417      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');418      await expect(executeTransaction(419        api, 420        bob, 421        api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1),422      ), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);423      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});424    });425  });426427  it('Admin (NFT): disallows a Token Owner to operate nesting when only Admin is allowed', async () => {428    await usingApi(async api => {429      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});430      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {collectionAdmin: true}});431      await addToAllowListExpectSuccess(alice, collection, bob.address);432      await enableAllowListExpectSuccess(alice, collection);433      await enablePublicMintingExpectSuccess(alice, collection);434      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');435436      // Try to create a nested token as collection admin when it's disallowed437      await expect(executeTransaction(api, bob, api.tx.unique.createItem(438        collection,439        {Ethereum: tokenIdToAddress(collection, targetToken)},440          {nft: {}} as any,441      )), 'while creating nested token').to.be.rejectedWith(/common\.AddressNotInAllowlist/); 442443      // Try to create and nest a token in the wrong collection444      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');445      await expect(executeTransaction(446        api, 447        bob, 448        api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1),449      ), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);450      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});451    });452  });453454  it('Admin (NFT): disallows an Admin to nest and unnest someone else\'s token', async () => {455    await usingApi(async api => {456      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});457      await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});458      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {collectionAdmin: true}});459460      await addToAllowListExpectSuccess(alice, collection, bob.address);461      await enableAllowListExpectSuccess(alice, collection);462      await enablePublicMintingExpectSuccess(alice, collection);463464      // Create a token to attempt to be nested into465      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');466      const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()};467468      // Try to nest somebody else's token469      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');470      await expect(executeTransaction(471        api, 472        alice, 473        api.tx.unique.transferFrom(targetAddress, {Substrate: bob.address}, collection, newToken, 1),474      ), 'while nesting another\'s token token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);475      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});476477      // Nest a token as admin and try to unnest it, now belonging to someone else478      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', targetAddress);479      await expect(executeTransaction(480        api, 481        alice, 482        api.tx.unique.transferFrom(targetAddress, normalizeAccountId(alice), collection, nestedToken, 1),483      ), 'while unnesting another\'s token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);484      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal(targetAddress);485      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: bob.address});486    });487  });488489  it('Admin (NFT): disallows an Admin to nest a token from an unlisted collection (Restricted nesting)', async () => {490    await usingApi(async api => {491      const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});492      const collectionB = await createCollectionExpectSuccess({mode: {type: 'NFT'}});493      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {collectionAdmin: true, restricted:[collectionA]}});494495      // Create a token to attempt to be nested into496      const targetToken = await createItemExpectSuccess(alice, collectionA, 'NFT');497498      // Try to create and nest a token in the wrong collection499      const newToken = await createItemExpectSuccess(alice, collectionB, 'NFT');500      await expect(executeTransaction(501        api, 502        alice, 503        api.tx.unique.transfer({Ethereum: tokenIdToAddress(collectionA, targetToken)}, collectionB, newToken, 1),504      ), 'while nesting a foreign token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);505      expect(await getTokenOwner(api, collectionB, newToken)).to.be.deep.equal({Substrate: alice.address});506    });507  });508509  // ---------- Non-Fungible ----------510511  it('NFT: disallows to nest token if nesting is disabled', async () => {512    await usingApi(async api => {513      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});514      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {}});515      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');516517      // Try to create a nested token518      await expect(executeTransaction(api, alice, api.tx.unique.createItem(519        collection,520        {Ethereum: tokenIdToAddress(collection, targetToken)},521          {nft: {}} as any,522      )), 'while creating nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);523524      // Create a token to be nested525      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');526      // Try to nest527      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);528      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});529      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});530    });531  });532533  it('NFT: disallows a non-Owner to nest someone else\'s token', async () => {534    await usingApi(async api => {535      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});536      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});537538      await addToAllowListExpectSuccess(alice, collection, bob.address);539      await enableAllowListExpectSuccess(alice, collection);540      await enablePublicMintingExpectSuccess(alice, collection);541542      // Create a token to attempt to be nested into543      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');544545      // Try to create a nested token in the wrong collection546      await expect(executeTransaction(api, alice, api.tx.unique.createItem(547        collection,548        {Ethereum: tokenIdToAddress(collection, targetToken)},549          {nft: {}} as any,550      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);551552      // Try to create and nest a token in the wrong collection553      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');554      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);555      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});556    });557  });558559  it('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {560    await usingApi(async api => {561      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});562      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[collection]}});563564      await addToAllowListExpectSuccess(alice, collection, bob.address);565      await enableAllowListExpectSuccess(alice, collection);566      await enablePublicMintingExpectSuccess(alice, collection);567568      // Create a token to attempt to be nested into569      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');570571      // Try to create a nested token in the wrong collection572      await expect(executeTransaction(api, alice, api.tx.unique.createItem(573        collection,574        {Ethereum: tokenIdToAddress(collection, targetToken)},575          {nft: {}} as any,576      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);577578      // Try to create and nest a token in the wrong collection579      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');580      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);581      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});582    });583  });584585  it('NFT: disallows to nest token in an unlisted collection', async () => {586    await usingApi(async api => {587      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});588      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[]}});589590      // Create a token to attempt to be nested into591      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');592593      // Try to create a nested token in the wrong collection594      await expect(executeTransaction(api, alice, api.tx.unique.createItem(595        collection,596        {Ethereum: tokenIdToAddress(collection, targetToken)},597          {nft: {}} as any,598      )), 'while creating nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);599600      // Try to create and nest a token in the wrong collection601      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');602      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);603      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});604    });605  });606607  // ---------- Fungible ----------608609  it('Fungible: disallows to nest token if nesting is disabled', async () => {610    await usingApi(async api => {611      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});612      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {}});613      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');614      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};615616      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});617618      // Try to create a nested token619      await expect(executeTransaction(api, alice, api.tx.unique.createItem(620        collectionFT,621        targetAddress,622        {Fungible: {Value: 10}},623      )), 'while creating nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);624625      // Create a token to be nested626      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');627      // Try to nest628      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);629630      // Create another token to be nested631      const newToken2 = await createItemExpectSuccess(alice, collectionFT, 'Fungible');632      // Try to nest inside a fungible token633      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collectionFT, newToken)}, collectionFT, newToken2, 1)), 'while nesting new token inside fungible').to.be.rejectedWith(/fungible\.FungibleDisallowsNesting/);634    });635  });636637  it('Fungible: disallows a non-Owner to nest someone else\'s token', async () => {638    await usingApi(async api => {639      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});640      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});641642      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);643      await enableAllowListExpectSuccess(alice, collectionNFT);644      await enablePublicMintingExpectSuccess(alice, collectionNFT);645646      // Create a token to attempt to be nested into647      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');648      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};649650      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});651652      // Try to create a nested token in the wrong collection653      await expect(executeTransaction(api, alice, api.tx.unique.createItem(654        collectionFT,655        targetAddress,656        {Fungible: {Value: 10}},657      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);658659      // Try to create and nest a token in the wrong collection660      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');661      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);662    });663  });664665  it('Fungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {666    await usingApi(async api => {667      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});668      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);669      await enableAllowListExpectSuccess(alice, collectionNFT);670      await enablePublicMintingExpectSuccess(alice, collectionNFT);671672      // Create a token to attempt to be nested into673      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');674      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};675676      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});677      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionFT]}});678679      // Try to create a nested token in the wrong collection680      await expect(executeTransaction(api, alice, api.tx.unique.createItem(681        collectionFT,682        targetAddress,683        {Fungible: {Value: 10}},684      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);685686      // Try to create and nest a token in the wrong collection687      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');688      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);689    });690  });691692  it('Fungible: disallows to nest token in an unlisted collection', async () => {693    await usingApi(async api => {694      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});695      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[]}});696697      // Create a token to attempt to be nested into698      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');699      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};700701      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});702703      // Try to create a nested token in the wrong collection704      await expect(executeTransaction(api, alice, api.tx.unique.createItem(705        collectionFT,706        targetAddress,707        {Fungible: {Value: 10}},708      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);709710      // Try to create and nest a token in the wrong collection711      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');712      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);713    });714  });715716  // ---------- Re-Fungible ----------717718  it('ReFungible: disallows to nest token if nesting is disabled', async () => {719    await usingApi(async api => {720      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});721      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {}});722      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');723      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};724725      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});726727      // Create a nested token728      await expect(executeTransaction(api, alice, api.tx.unique.createItem(729        collectionRFT,730        targetAddress,731        {ReFungible: {pieces: 100}},732      )), 'while creating a nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);733734      // Create a token to be nested735      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');736      // Try to nest737      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);738      // Try to nest739      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);740741      // Create another token to be nested742      const newToken2 = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');743      // Try to nest inside a fungible token744      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collectionRFT, newToken)}, collectionRFT, newToken2, 1)), 'while nesting new token inside refungible').to.be.rejectedWith(/refungible\.RefungibleDisallowsNesting/);745    });746  });747748  it('ReFungible: disallows a non-Owner to nest someone else\'s token', async () => {749    await usingApi(async api => {750      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});751      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});752753      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);754      await enableAllowListExpectSuccess(alice, collectionNFT);755      await enablePublicMintingExpectSuccess(alice, collectionNFT);756757      // Create a token to attempt to be nested into758      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');759      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};760761      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});762763      // Try to create a nested token in the wrong collection764      await expect(executeTransaction(api, alice, api.tx.unique.createItem(765        collectionRFT,766        targetAddress,767        {ReFungible: {pieces: 100}},768      )), 'while creating a nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);769770      // Try to create and nest a token in the wrong collection771      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');772      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);773    });774  });775776  it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {777    await usingApi(async api => {778      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});779      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);780      await enableAllowListExpectSuccess(alice, collectionNFT);781      await enablePublicMintingExpectSuccess(alice, collectionNFT);782783      // Create a token to attempt to be nested into784      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');785      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};786787      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});788      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionRFT]}});789790      // Try to create a nested token in the wrong collection791      await expect(executeTransaction(api, alice, api.tx.unique.createItem(792        collectionRFT,793        targetAddress,794        {ReFungible: {pieces: 100}},795      )), 'while creating a nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);796797      // Try to create and nest a token in the wrong collection798      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');799      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);800    });801  });802803  it('ReFungible: disallows to nest token to an unlisted collection', async () => {804    await usingApi(async api => {805      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});806      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[]}});807808      // Create a token to attempt to be nested into809      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');810      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};811812      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});813814      // Try to create a nested token in the wrong collection815      await expect(executeTransaction(api, alice, api.tx.unique.createItem(816        collectionRFT,817        targetAddress,818        {ReFungible: {pieces: 100}},819      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);820821      // Try to create and nest a token in the wrong collection822      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');823      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);824    });825  });826});
after · tests/src/nesting/nest.test.ts
1import {expect} from 'chai';2import {tokenIdToAddress} from '../eth/util/helpers';3import usingApi, {executeTransaction} from '../substrate/substrate-api';4import {5  addCollectionAdminExpectSuccess,6  addToAllowListExpectSuccess,7  createCollectionExpectSuccess,8  createItemExpectSuccess,9  enableAllowListExpectSuccess,10  enablePublicMintingExpectSuccess,11  getTokenChildren,12  getTokenOwner,13  getTopmostTokenOwner,14  normalizeAccountId,15  setCollectionPermissionsExpectSuccess,16  transferExpectFailure,17  transferExpectSuccess,18  transferFromExpectSuccess,19  setCollectionLimitsExpectSuccess,20  requirePallets,21  Pallets22} from '../util/helpers';23import {IKeyringPair} from '@polkadot/types/types';2425let alice: IKeyringPair;26let bob: IKeyringPair;27let charlie: IKeyringPair;2829describe('Integration Test: Composite nesting tests', () => {30  before(async () => {31    await usingApi(async (_, privateKeyWrapper) => {32      alice = privateKeyWrapper('//Alice');33      bob = privateKeyWrapper('//Bob');34    });35  });3637  it('Performs the full suite: bundles a token, transfers, and unnests', async () => {38    await usingApi(async api => {39      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});40      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});41      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');4243      // Create a nested token44      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});45      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});46      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});4748      // Create a token to be nested49      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');5051      // Nest52      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});53      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});54      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});5556      // Move bundle to different user57      await transferExpectSuccess(collection, targetToken, alice, {Substrate: bob.address});58      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: bob.address});59      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});6061      // Unnest62      await transferFromExpectSuccess(collection, newToken, bob, {Ethereum: tokenIdToAddress(collection, targetToken)}, {Substrate: bob.address});63      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});64    });65  });6667  it('Transfers an already bundled token', async () => {68    await usingApi(async api => {69      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});70      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});7172      const tokenA = await createItemExpectSuccess(alice, collection, 'NFT');73      const tokenB = await createItemExpectSuccess(alice, collection, 'NFT');7475      // Create a nested token76      const tokenC = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, tokenA)});77      expect(await getTopmostTokenOwner(api, collection, tokenC)).to.be.deep.equal({Substrate: alice.address});78      expect(await getTokenOwner(api, collection, tokenC)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, tokenA).toLowerCase()});7980      // Transfer the nested token to another token81      await expect(executeTransaction(82        api,83        alice,84        api.tx.unique.transferFrom(85          normalizeAccountId({Ethereum: tokenIdToAddress(collection, tokenA)}),86          normalizeAccountId({Ethereum: tokenIdToAddress(collection, tokenB)}),87          collection,88          tokenC,89          1,90        ),91      )).to.not.be.rejected;92      expect(await getTopmostTokenOwner(api, collection, tokenC)).to.be.deep.equal({Substrate: alice.address});93      expect(await getTokenOwner(api, collection, tokenC)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, tokenB).toLowerCase()});94    });95  });9697  it('Checks token children', async () => {98    await usingApi(async api => {99      const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});100      await setCollectionLimitsExpectSuccess(alice, collectionA, {ownerCanTransfer: true});101      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {tokenOwner: true}});102      const collectionB = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});103104      const targetToken = await createItemExpectSuccess(alice, collectionA, 'NFT');105      const targetAddress = {Ethereum: tokenIdToAddress(collectionA, targetToken)};106      let children = await getTokenChildren(api, collectionA, targetToken);107      expect(children.length).to.be.equal(0, 'Children length check at creation');108109      // Create a nested NFT token110      const tokenA = await createItemExpectSuccess(alice, collectionA, 'NFT', targetAddress);111      children = await getTokenChildren(api, collectionA, targetToken);112      expect(children.length).to.be.equal(1, 'Children length check at nesting #1');113      expect(children).to.have.deep.members([114        {token: tokenA, collection: collectionA},115      ], 'Children contents check at nesting #1');116117      // Create then nest118      const tokenB = await createItemExpectSuccess(alice, collectionA, 'NFT');119      await transferExpectSuccess(collectionA, tokenB, alice, targetAddress);120      children = await getTokenChildren(api, collectionA, targetToken);121      expect(children.length).to.be.equal(2, 'Children length check at nesting #2');122      expect(children).to.have.deep.members([123        {token: tokenA, collection: collectionA},124        {token: tokenB, collection: collectionA},125      ], 'Children contents check at nesting #2');126127      // Move token B to a different user outside the nesting tree128      await transferFromExpectSuccess(collectionA, tokenB, alice, targetAddress, bob);129      children = await getTokenChildren(api, collectionA, targetToken);130      expect(children.length).to.be.equal(1, 'Children length check at unnesting');131      expect(children).to.be.have.deep.members([132        {token: tokenA, collection: collectionA},133      ], 'Children contents check at unnesting');134135      // Create a fungible token in another collection and then nest136      const tokenC = await createItemExpectSuccess(alice, collectionB, 'Fungible');137      await transferExpectSuccess(collectionB, tokenC, alice, targetAddress, 1, 'Fungible');138      children = await getTokenChildren(api, collectionA, targetToken);139      expect(children.length).to.be.equal(2, 'Children length check at nesting #3 (from another collection)');140      expect(children).to.be.have.deep.members([141        {token: tokenA, collection: collectionA},142        {token: tokenC, collection: collectionB},143      ], 'Children contents check at nesting #3 (from another collection)');144145      // Move the fungible token inside token A deeper in the nesting tree146      await transferFromExpectSuccess(collectionB, tokenC, alice, targetAddress, {Ethereum: tokenIdToAddress(collectionA, tokenA)}, 1, 'Fungible');147      children = await getTokenChildren(api, collectionA, targetToken);148      expect(children.length).to.be.equal(1, 'Children length check at deeper nesting');149      expect(children).to.be.have.deep.members([150        {token: tokenA, collection: collectionA},151      ], 'Children contents check at deeper nesting');152    });153  });154});155156describe('Integration Test: Various token type nesting', async () => {157  before(async () => {158    await usingApi(async (_, privateKeyWrapper) => {159      alice = privateKeyWrapper('//Alice');160      bob = privateKeyWrapper('//Bob');161      charlie = privateKeyWrapper('//Charlie');162    });163  });164165  it('Admin (NFT): allows an Admin to nest a token', async () => {166    await usingApi(async api => {167      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});168      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {collectionAdmin: true}});169      await addCollectionAdminExpectSuccess(alice, collection, bob.address);170      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT', charlie.address);171172      // Create a nested token173      const nestedToken = await createItemExpectSuccess(bob, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});174      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: charlie.address});175      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});176177      // Create a token to be nested and nest178      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');179      await transferExpectSuccess(collection, newToken, bob, {Ethereum: tokenIdToAddress(collection, targetToken)});180      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: charlie.address});181      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});182    });183  });184185  it('Admin (NFT): Admin and Token Owner can operate together', async () => {186    await usingApi(async api => {187      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});188      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, collectionAdmin: true}});189      await addCollectionAdminExpectSuccess(alice, collection, bob.address);190      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT', charlie.address);191192      // Create a nested token by an administrator193      const nestedToken = await createItemExpectSuccess(bob, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});194      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: charlie.address});195      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});196197      // Create a token and allow the owner to nest too198      const newToken = await createItemExpectSuccess(alice, collection, 'NFT', charlie.address);199      await transferExpectSuccess(collection, newToken, charlie, {Ethereum: tokenIdToAddress(collection, nestedToken)});200      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: charlie.address});201      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, nestedToken).toLowerCase()});202    });203  });204205  it('Admin (NFT): allows an Admin to nest a token (Restricted nesting)', async () => {206    await usingApi(async api => {207      const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});208      await addCollectionAdminExpectSuccess(alice, collectionA, bob.address);209      const collectionB = await createCollectionExpectSuccess({mode: {type: 'NFT'}});210      await addCollectionAdminExpectSuccess(alice, collectionB, bob.address);211      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {collectionAdmin: true, restricted:[collectionA, collectionB]}});212      const targetToken = await createItemExpectSuccess(alice, collectionA, 'NFT', charlie.address);213214      // Create a nested token215      const nestedToken = await createItemExpectSuccess(bob, collectionB, 'NFT', {Ethereum: tokenIdToAddress(collectionA, targetToken)});216      expect(await getTopmostTokenOwner(api, collectionB, nestedToken)).to.be.deep.equal({Substrate: charlie.address});217      expect(await getTokenOwner(api, collectionB, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collectionA, targetToken).toLowerCase()});218219      // Create a token to be nested and nest220      const newToken = await createItemExpectSuccess(bob, collectionB, 'NFT');221      await transferExpectSuccess(collectionB, newToken, bob, {Ethereum: tokenIdToAddress(collectionA, targetToken)});222      expect(await getTopmostTokenOwner(api, collectionB, newToken)).to.be.deep.equal({Substrate: charlie.address});223      expect(await getTokenOwner(api, collectionB, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collectionA, targetToken).toLowerCase()});224    });225  });226227  // ---------- Non-Fungible ----------228229  it('NFT: allows an Owner to nest/unnest their token', async () => {230    await usingApi(async api => {231      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});232      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});233      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');234235      // Create a nested token236      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});237      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});238      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});239240      // Create a token to be nested and nest241      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');242      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});243      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});244      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});245    });246  });247248  it('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {249    await usingApi(async api => {250      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});251      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[collection]}});252      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');253254      // Create a nested token255      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});256      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});257      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});258259      // Create a token to be nested and nest260      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');261      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});262      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});263      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});264    });265  });266267  // ---------- Fungible ----------268269  it('Fungible: allows an Owner to nest/unnest their token', async () => {270    await usingApi(async api => {271      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});272      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});273      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});274      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};275276      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});277278      // Create a nested token279      await expect(executeTransaction(api, alice, api.tx.unique.createItem(280        collectionFT,281        targetAddress,282        {Fungible: {Value: 10}},283      ))).to.not.be.rejected;284285      // Nest a new token286      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');287      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');288    });289  });290291  it('Fungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {292    await usingApi(async api => {293      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});294      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});295      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};296297      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});298299      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted: [collectionFT]}});300301      // Create a nested token302      await expect(executeTransaction(api, alice, api.tx.unique.createItem(303        collectionFT,304        targetAddress,305        {Fungible: {Value: 10}},306      ))).to.not.be.rejected;307308      // Nest a new token309      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');310      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');311    });312  });313314  // ---------- Re-Fungible ----------315316  it('ReFungible: allows an Owner to nest/unnest their token', async function() {317    await requirePallets(this, [Pallets.ReFungible]);318319    await usingApi(async api => {320      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});321      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});322      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});323      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};324325      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});326327      // Create a nested token328      await expect(executeTransaction(api, alice, api.tx.unique.createItem(329        collectionRFT,330        targetAddress,331        {ReFungible: {pieces: 100}},332      ))).to.not.be.rejected;333334      // Nest a new token335      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');336      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');337    });338  });339340  it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async function() {341    await requirePallets(this, [Pallets.ReFungible]);342343    await usingApi(async api => {344      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});345      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});346      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};347348      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});349350      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionRFT]}});351352      // Create a nested token353      await expect(executeTransaction(api, alice, api.tx.unique.createItem(354        collectionRFT,355        targetAddress,356        {ReFungible: {pieces: 100}},357      ))).to.not.be.rejected;358359      // Nest a new token360      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');361      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');362    });363  });364});365366describe('Negative Test: Nesting', async() => {367  before(async () => {368    await usingApi(async (_, privateKeyWrapper) => {369      alice = privateKeyWrapper('//Alice');370      bob = privateKeyWrapper('//Bob');371    });372  });373374  it('Disallows excessive token nesting', async () => {375    await usingApi(async api => {376      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});377      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});378      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');379380      const maxNestingLevel = 5;381      let prevToken = targetToken;382383      // Create a nested-token matryoshka384      for (let i = 0; i < maxNestingLevel; i++) {385        const nestedToken = await createItemExpectSuccess(386          alice,387          collection,388          'NFT',389          {Ethereum: tokenIdToAddress(collection, prevToken)},390        );391392        prevToken = nestedToken;393      }394395      // The nesting depth is limited by `maxNestingLevel`396      await expect(executeTransaction(api, alice, api.tx.unique.createItem(397        collection,398        {Ethereum: tokenIdToAddress(collection, prevToken)},399          {nft: {}} as any,400      )), 'while creating nested token').to.be.rejectedWith(/^structure\.DepthLimit$/);401402      expect(await getTopmostTokenOwner(api, collection, prevToken)).to.be.deep.equal({Substrate: alice.address});403    });404  });405406  // ---------- Admin ------------407408  it('Admin (NFT): disallows an Admin to operate nesting when only TokenOwner is allowed', async () => {409    await usingApi(async api => {410      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});411      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});412      await addCollectionAdminExpectSuccess(alice, collection, bob.address);413      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');414415      // Try to create a nested token as collection admin when it's disallowed416      await expect(executeTransaction(api, bob, api.tx.unique.createItem(417        collection,418        {Ethereum: tokenIdToAddress(collection, targetToken)},419          {nft: {}} as any,420      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);421422      // Try to create and nest a token in the wrong collection423      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');424      await expect(executeTransaction(425        api, 426        bob, 427        api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1),428      ), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);429      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});430    });431  });432433  it('Admin (NFT): disallows a Token Owner to operate nesting when only Admin is allowed', async () => {434    await usingApi(async api => {435      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});436      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {collectionAdmin: true}});437      await addToAllowListExpectSuccess(alice, collection, bob.address);438      await enableAllowListExpectSuccess(alice, collection);439      await enablePublicMintingExpectSuccess(alice, collection);440      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');441442      // Try to create a nested token as collection admin when it's disallowed443      await expect(executeTransaction(api, bob, api.tx.unique.createItem(444        collection,445        {Ethereum: tokenIdToAddress(collection, targetToken)},446          {nft: {}} as any,447      )), 'while creating nested token').to.be.rejectedWith(/common\.AddressNotInAllowlist/); 448449      // Try to create and nest a token in the wrong collection450      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');451      await expect(executeTransaction(452        api, 453        bob, 454        api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1),455      ), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);456      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});457    });458  });459460  it('Admin (NFT): disallows an Admin to nest and unnest someone else\'s token', async () => {461    await usingApi(async api => {462      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});463      await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});464      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {collectionAdmin: true}});465466      await addToAllowListExpectSuccess(alice, collection, bob.address);467      await enableAllowListExpectSuccess(alice, collection);468      await enablePublicMintingExpectSuccess(alice, collection);469470      // Create a token to attempt to be nested into471      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');472      const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()};473474      // Try to nest somebody else's token475      const newToken = await createItemExpectSuccess(bob, collection, 'NFT');476      await expect(executeTransaction(477        api, 478        alice, 479        api.tx.unique.transferFrom(targetAddress, {Substrate: bob.address}, collection, newToken, 1),480      ), 'while nesting another\'s token token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);481      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});482483      // Nest a token as admin and try to unnest it, now belonging to someone else484      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', targetAddress);485      await expect(executeTransaction(486        api, 487        alice, 488        api.tx.unique.transferFrom(targetAddress, normalizeAccountId(alice), collection, nestedToken, 1),489      ), 'while unnesting another\'s token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);490      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal(targetAddress);491      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: bob.address});492    });493  });494495  it('Admin (NFT): disallows an Admin to nest a token from an unlisted collection (Restricted nesting)', async () => {496    await usingApi(async api => {497      const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});498      const collectionB = await createCollectionExpectSuccess({mode: {type: 'NFT'}});499      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {collectionAdmin: true, restricted:[collectionA]}});500501      // Create a token to attempt to be nested into502      const targetToken = await createItemExpectSuccess(alice, collectionA, 'NFT');503504      // Try to create and nest a token in the wrong collection505      const newToken = await createItemExpectSuccess(alice, collectionB, 'NFT');506      await expect(executeTransaction(507        api, 508        alice, 509        api.tx.unique.transfer({Ethereum: tokenIdToAddress(collectionA, targetToken)}, collectionB, newToken, 1),510      ), 'while nesting a foreign token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);511      expect(await getTokenOwner(api, collectionB, newToken)).to.be.deep.equal({Substrate: alice.address});512    });513  });514515  // ---------- Non-Fungible ----------516517  it('NFT: disallows to nest token if nesting is disabled', async () => {518    await usingApi(async api => {519      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});520      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {}});521      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');522523      // Try to create a nested token524      await expect(executeTransaction(api, alice, api.tx.unique.createItem(525        collection,526        {Ethereum: tokenIdToAddress(collection, targetToken)},527          {nft: {}} as any,528      )), 'while creating nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);529530      // Create a token to be nested531      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');532      // Try to nest533      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);534      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});535      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});536    });537  });538539  it('NFT: disallows a non-Owner to nest someone else\'s token', async () => {540    await usingApi(async api => {541      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});542      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});543544      await addToAllowListExpectSuccess(alice, collection, bob.address);545      await enableAllowListExpectSuccess(alice, collection);546      await enablePublicMintingExpectSuccess(alice, collection);547548      // Create a token to attempt to be nested into549      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');550551      // Try to create a nested token in the wrong collection552      await expect(executeTransaction(api, alice, api.tx.unique.createItem(553        collection,554        {Ethereum: tokenIdToAddress(collection, targetToken)},555          {nft: {}} as any,556      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);557558      // Try to create and nest a token in the wrong collection559      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');560      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);561      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});562    });563  });564565  it('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {566    await usingApi(async api => {567      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});568      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[collection]}});569570      await addToAllowListExpectSuccess(alice, collection, bob.address);571      await enableAllowListExpectSuccess(alice, collection);572      await enablePublicMintingExpectSuccess(alice, collection);573574      // Create a token to attempt to be nested into575      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');576577      // Try to create a nested token in the wrong collection578      await expect(executeTransaction(api, alice, api.tx.unique.createItem(579        collection,580        {Ethereum: tokenIdToAddress(collection, targetToken)},581          {nft: {}} as any,582      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);583584      // Try to create and nest a token in the wrong collection585      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');586      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);587      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});588    });589  });590591  it('NFT: disallows to nest token in an unlisted collection', async () => {592    await usingApi(async api => {593      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});594      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[]}});595596      // Create a token to attempt to be nested into597      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');598599      // Try to create a nested token in the wrong collection600      await expect(executeTransaction(api, alice, api.tx.unique.createItem(601        collection,602        {Ethereum: tokenIdToAddress(collection, targetToken)},603          {nft: {}} as any,604      )), 'while creating nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);605606      // Try to create and nest a token in the wrong collection607      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');608      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);609      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});610    });611  });612613  // ---------- Fungible ----------614615  it('Fungible: disallows to nest token if nesting is disabled', async () => {616    await usingApi(async api => {617      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});618      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {}});619      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');620      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};621622      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});623624      // Try to create a nested token625      await expect(executeTransaction(api, alice, api.tx.unique.createItem(626        collectionFT,627        targetAddress,628        {Fungible: {Value: 10}},629      )), 'while creating nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);630631      // Create a token to be nested632      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');633      // Try to nest634      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);635636      // Create another token to be nested637      const newToken2 = await createItemExpectSuccess(alice, collectionFT, 'Fungible');638      // Try to nest inside a fungible token639      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collectionFT, newToken)}, collectionFT, newToken2, 1)), 'while nesting new token inside fungible').to.be.rejectedWith(/fungible\.FungibleDisallowsNesting/);640    });641  });642643  it('Fungible: disallows a non-Owner to nest someone else\'s token', async () => {644    await usingApi(async api => {645      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});646      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});647648      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);649      await enableAllowListExpectSuccess(alice, collectionNFT);650      await enablePublicMintingExpectSuccess(alice, collectionNFT);651652      // Create a token to attempt to be nested into653      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');654      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};655656      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});657658      // Try to create a nested token in the wrong collection659      await expect(executeTransaction(api, alice, api.tx.unique.createItem(660        collectionFT,661        targetAddress,662        {Fungible: {Value: 10}},663      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);664665      // Try to create and nest a token in the wrong collection666      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');667      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);668    });669  });670671  it('Fungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {672    await usingApi(async api => {673      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});674      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);675      await enableAllowListExpectSuccess(alice, collectionNFT);676      await enablePublicMintingExpectSuccess(alice, collectionNFT);677678      // Create a token to attempt to be nested into679      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');680      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};681682      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});683      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionFT]}});684685      // Try to create a nested token in the wrong collection686      await expect(executeTransaction(api, alice, api.tx.unique.createItem(687        collectionFT,688        targetAddress,689        {Fungible: {Value: 10}},690      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);691692      // Try to create and nest a token in the wrong collection693      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');694      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);695    });696  });697698  it('Fungible: disallows to nest token in an unlisted collection', async () => {699    await usingApi(async api => {700      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});701      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[]}});702703      // Create a token to attempt to be nested into704      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');705      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};706707      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});708709      // Try to create a nested token in the wrong collection710      await expect(executeTransaction(api, alice, api.tx.unique.createItem(711        collectionFT,712        targetAddress,713        {Fungible: {Value: 10}},714      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);715716      // Try to create and nest a token in the wrong collection717      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');718      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);719    });720  });721722  // ---------- Re-Fungible ----------723724  it('ReFungible: disallows to nest token if nesting is disabled', async function() {725    await requirePallets(this, [Pallets.ReFungible]);726727    await usingApi(async api => {728      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});729      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {}});730      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');731      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};732733      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});734735      // Create a nested token736      await expect(executeTransaction(api, alice, api.tx.unique.createItem(737        collectionRFT,738        targetAddress,739        {ReFungible: {pieces: 100}},740      )), 'while creating a nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);741742      // Create a token to be nested743      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');744      // Try to nest745      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);746      // Try to nest747      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);748749      // Create another token to be nested750      const newToken2 = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');751      // Try to nest inside a fungible token752      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collectionRFT, newToken)}, collectionRFT, newToken2, 1)), 'while nesting new token inside refungible').to.be.rejectedWith(/refungible\.RefungibleDisallowsNesting/);753    });754  });755756  it('ReFungible: disallows a non-Owner to nest someone else\'s token', async function() {757    await requirePallets(this, [Pallets.ReFungible]);758759    await usingApi(async api => {760      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});761      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});762763      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);764      await enableAllowListExpectSuccess(alice, collectionNFT);765      await enablePublicMintingExpectSuccess(alice, collectionNFT);766767      // Create a token to attempt to be nested into768      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');769      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};770771      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});772773      // Try to create a nested token in the wrong collection774      await expect(executeTransaction(api, alice, api.tx.unique.createItem(775        collectionRFT,776        targetAddress,777        {ReFungible: {pieces: 100}},778      )), 'while creating a nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);779780      // Try to create and nest a token in the wrong collection781      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');782      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);783    });784  });785786  it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async function() {787    await requirePallets(this, [Pallets.ReFungible]);788789    await usingApi(async api => {790      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});791      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);792      await enableAllowListExpectSuccess(alice, collectionNFT);793      await enablePublicMintingExpectSuccess(alice, collectionNFT);794795      // Create a token to attempt to be nested into796      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');797      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};798799      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});800      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionRFT]}});801802      // Try to create a nested token in the wrong collection803      await expect(executeTransaction(api, alice, api.tx.unique.createItem(804        collectionRFT,805        targetAddress,806        {ReFungible: {pieces: 100}},807      )), 'while creating a nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);808809      // Try to create and nest a token in the wrong collection810      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');811      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);812    });813  });814815  it('ReFungible: disallows to nest token to an unlisted collection', async function() {816    await requirePallets(this, [Pallets.ReFungible]);817818    await usingApi(async api => {819      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});820      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[]}});821822      // Create a token to attempt to be nested into823      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');824      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};825826      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});827828      // Try to create a nested token in the wrong collection829      await expect(executeTransaction(api, alice, api.tx.unique.createItem(830        collectionRFT,831        targetAddress,832        {ReFungible: {pieces: 100}},833      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);834835      // Try to create and nest a token in the wrong collection836      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');837      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);838    });839  });840});
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -8,6 +8,8 @@
   createItemExpectSuccess,
   getCreateCollectionResult,
   transferExpectSuccess,
+  requirePallets,
+  Pallets
 } from '../util/helpers';
 import {IKeyringPair} from '@polkadot/types/types';
 import {tokenIdToAddress} from '../eth/util/helpers';
@@ -64,7 +66,9 @@
     await testMakeSureSuppliesRequired({type: 'NFT'});
   });
 
-  it('Makes sure collectionById supplies required fields for ReFungible', async () => {
+  it('Makes sure collectionById supplies required fields for ReFungible', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testMakeSureSuppliesRequired({type: 'ReFungible'});
   });
 });
@@ -120,7 +124,9 @@
   it('Sets properties for a NFT collection', async () => {
     await testSetsPropertiesForCollection('NFT');
   });
-  it('Sets properties for a ReFungible collection', async () => {
+  it('Sets properties for a ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testSetsPropertiesForCollection('ReFungible');
   });
 
@@ -178,7 +184,9 @@
   it('Check valid names for NFT collection properties keys', async () => {
     await testCheckValidNames('NFT');
   });
-  it('Check valid names for ReFungible collection properties keys', async () => {
+  it('Check valid names for ReFungible collection properties keys', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testCheckValidNames('ReFungible');
   });
 
@@ -209,7 +217,9 @@
   it('Changes properties of a NFT collection', async () => {
     await testChangesProperties({type: 'NFT'});
   });
-  it('Changes properties of a ReFungible collection', async () => {
+  it('Changes properties of a ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testChangesProperties({type: 'ReFungible'});
   });
 
@@ -238,7 +248,9 @@
   it('Deletes properties of a NFT collection', async () => {
     await testDeleteProperties({type: 'NFT'});
   });
-  it('Deletes properties of a ReFungible collection', async () => {
+  it('Deletes properties of a ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testDeleteProperties({type: 'ReFungible'});
   });
 });
@@ -269,7 +281,9 @@
   it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {
     await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});
   });
-  it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async () => {
+  it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});
   });
   
@@ -307,7 +321,9 @@
   it('Fails to set properties that exceed the limits (NFT)', async () => {
     await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});
   });
-  it('Fails to set properties that exceed the limits (ReFungible)', async () => {
+  it('Fails to set properties that exceed the limits (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});
   });
   
@@ -337,7 +353,9 @@
   it('Fails to set more properties than it is allowed (NFT)', async () => {
     await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});
   });
-  it('Fails to set more properties than it is allowed (ReFungible)', async () => {
+  it('Fails to set more properties than it is allowed (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});
   });
   
@@ -392,7 +410,9 @@
   it('Fails to set properties with invalid names (NFT)', async () => {
     await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});
   });
-  it('Fails to set properties with invalid names (ReFungible)', async () => {
+  it('Fails to set properties with invalid names (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});
   });
 });
@@ -443,7 +463,9 @@
   it('Sets access rights to properties of a collection (NFT)', async () => {
     await testSetsAccessRightsToProperties({type: 'NFT'});
   });
-  it('Sets access rights to properties of a collection (ReFungible)', async () => {
+  it('Sets access rights to properties of a collection (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testSetsAccessRightsToProperties({type: 'ReFungible'});
   });
   
@@ -472,7 +494,9 @@
   it('Changes access rights to properties of a NFT collection', async () => {
     await testChangesAccessRightsToProperty({type: 'NFT'});
   });
-  it('Changes access rights to properties of a ReFungible collection', async () => {
+  it('Changes access rights to properties of a ReFungible collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testChangesAccessRightsToProperty({type: 'ReFungible'});
   });
 });
@@ -502,7 +526,9 @@
   it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {
     await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});
   });
-  it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async () => {
+  it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});
   });
 
@@ -531,7 +557,9 @@
   it('Prevents from adding too many possible properties (NFT)', async () => {
     await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});
   });
-  it('Prevents from adding too many possible properties (ReFungible)', async () => {
+  it('Prevents from adding too many possible properties (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});
   });
 
@@ -560,7 +588,9 @@
   it('Prevents access rights to be modified if constant (NFT)', async () => {
     await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});
   });
-  it('Prevents access rights to be modified if constant (ReFungible)', async () => {
+  it('Prevents access rights to be modified if constant (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});
   });
 
@@ -608,7 +638,9 @@
   it('Prevents adding properties with invalid names (NFT)', async () => {
     await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});
   });
-  it('Prevents adding properties with invalid names (ReFungible)', async () => {
+  it('Prevents adding properties with invalid names (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});
   });
 });
@@ -651,7 +683,9 @@
   it('Reads yet empty properties of a token (NFT)', async () => {
     await testReadsYetEmptyProperties({type: 'NFT'});
   });
-  it('Reads yet empty properties of a token (ReFungible)', async () => {
+  it('Reads yet empty properties of a token (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testReadsYetEmptyProperties({type: 'ReFungible'});
   });
 
@@ -696,7 +730,9 @@
   it('Assigns properties to a token according to permissions (NFT)', async () => {
     await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);
   });
-  it('Assigns properties to a token according to permissions (ReFungible)', async () => {
+  it('Assigns properties to a token according to permissions (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);
   });
 
@@ -749,7 +785,9 @@
   it('Changes properties of a token according to permissions (NFT)', async () => {
     await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);
   });
-  it('Changes properties of a token according to permissions (ReFungible)', async () => {
+  it('Changes properties of a token according to permissions (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);
   });
 
@@ -802,7 +840,9 @@
   it('Deletes properties of a token according to permissions (NFT)', async () => {
     await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);
   });
-  it('Deletes properties of a token according to permissions (ReFungible)', async () => {
+  it('Deletes properties of a token according to permissions (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);
   });
 
@@ -1029,7 +1069,9 @@
   it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {
     await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);
   });
-  it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async () => {
+  it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);
   });
 
@@ -1062,7 +1104,9 @@
   it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {
     await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);
   });
-  it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async () => {
+  it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);
   });
 
@@ -1096,7 +1140,9 @@
   it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async () => {
     await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'NFT'}, 1);
   });
-  it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async () => {
+  it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);
   });
 
@@ -1140,7 +1186,9 @@
   it('Forbids adding too many properties to a token (NFT)', async () => {
     await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);
   });
-  it('Forbids adding too many properties to a token (ReFungible)', async () => {
+  it('Forbids adding too many properties to a token (ReFungible)', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);
   });
 });
@@ -1149,7 +1197,9 @@
   let collection: number;
   let token: number;
 
-  before(async () => {
+  before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api, privateKeyWrapper) => {
       alice = privateKeyWrapper('//Alice');
       bob = privateKeyWrapper('//Bob');
modifiedtests/src/nesting/rules-smoke.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/rules-smoke.test.ts
+++ b/tests/src/nesting/rules-smoke.test.ts
@@ -1,7 +1,7 @@
 import {expect} from 'chai';
 import {tokenIdToAddress} from '../eth/util/helpers';
 import usingApi, {executeTransaction} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult} from '../util/helpers';
+import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult, requirePallets, Pallets} from '../util/helpers';
 import {IKeyringPair} from '@polkadot/types/types';
 
 describe('nesting check', () => {
@@ -47,7 +47,9 @@
     });
   });
 
-  it('called for refungible', async () => {
+  it('called for refungible', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       await expect(executeTransaction(api, alice, api.tx.unique.createItem(collection, nestTarget, {ReFungible: {}})))
modifiedtests/src/nesting/unnest.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/unnest.test.ts
+++ b/tests/src/nesting/unnest.test.ts
@@ -10,6 +10,8 @@
   setCollectionPermissionsExpectSuccess,
   transferExpectSuccess,
   transferFromExpectSuccess,
+  requirePallets,
+  Pallets
 } from '../util/helpers';
 import {IKeyringPair} from '@polkadot/types/types';
 
@@ -80,7 +82,9 @@
     });
   });
 
-  it('ReFungible: allows the owner to successfully unnest a token', async () => {
+  it('ReFungible: allows the owner to successfully unnest a token', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
       await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
modifiedtests/src/nextSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/nextSponsoring.test.ts
+++ b/tests/src/nextSponsoring.test.ts
@@ -27,6 +27,8 @@
   transferExpectSuccess,
   normalizeAccountId,
   getNextSponsored,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -89,7 +91,9 @@
     });
   });
 
-  it('ReFungible', async () => {
+  it('ReFungible', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api: ApiPromise) => {
 
       const createMode = 'ReFungible';
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -49,8 +49,6 @@
   'inflation',
   'unique',
   'nonfungible',
-  'refungible',
-  'scheduler',
   'charging',
 ];
 
@@ -66,8 +64,16 @@
     await usingApi(async api => {
       const chain = await api.rpc.system.chain();
 
-      if (!chain.eq('UNIQUE')) {
-        requiredPallets.push(...['rmrkcore', 'rmrkequip']);
+      const refungible = 'refungible';
+      const scheduler = 'scheduler';
+      const rmrkPallets = ['rmrkcore', 'rmrkequip'];
+
+      if (chain.eq('OPAL by UNIQUE')) {
+        requiredPallets.push(refungible, scheduler, ...rmrkPallets);
+      } else if (chain.eq('QUARTZ by UNIQUE')) {
+        // Insert Quartz additional pallets here
+      } else if (chain.eq('UNIQUE')) {
+        // Insert Unique additional pallets here
       }
     });
   });
modifiedtests/src/refungible.test.tsdiffbeforeafterboth
--- a/tests/src/refungible.test.ts
+++ b/tests/src/refungible.test.ts
@@ -38,6 +38,7 @@
   getDestroyItemsResult,
   getModuleNames,
   Pallets,
+  requirePallets
 } from './util/helpers';
 
 import chai from 'chai';
@@ -52,6 +53,8 @@
 
 describe('integration test: Refungible functionality:', async () => {
   before(async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api, privateKeyWrapper) => {
       alice = privateKeyWrapper('//Alice');
       bob = privateKeyWrapper('//Bob');
modifiedtests/src/rmrk/acceptNft.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/acceptNft.test.ts
+++ b/tests/src/rmrk/acceptNft.test.ts
@@ -14,7 +14,7 @@
   let api: any;
   before(async function() {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
   
   
modifiedtests/src/rmrk/addResource.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/addResource.test.ts
+++ b/tests/src/rmrk/addResource.test.ts
@@ -27,7 +27,7 @@
   let api: any;
   before(async function() {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   it('add resource', async () => {
modifiedtests/src/rmrk/addTheme.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/addTheme.test.ts
+++ b/tests/src/rmrk/addTheme.test.ts
@@ -9,7 +9,7 @@
   let api: any;
   before(async function() {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkEquip]);
+    await requirePallets(this, [Pallets.RmrkEquip]);
   });
 
   const alice = '//Alice';
modifiedtests/src/rmrk/burnNft.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/burnNft.test.ts
+++ b/tests/src/rmrk/burnNft.test.ts
@@ -17,7 +17,7 @@
   let api: any;
   before(async function() {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
 
modifiedtests/src/rmrk/changeCollectionIssuer.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/changeCollectionIssuer.test.ts
+++ b/tests/src/rmrk/changeCollectionIssuer.test.ts
@@ -13,7 +13,7 @@
   let api: any;
   before(async function() {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
 
modifiedtests/src/rmrk/createBase.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/createBase.test.ts
+++ b/tests/src/rmrk/createBase.test.ts
@@ -6,7 +6,7 @@
   let api: any;
   before(async function() {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore, Pallets.RmrkEquip]);
+    await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
   });
 
   const alice = '//Alice';
modifiedtests/src/rmrk/createCollection.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/createCollection.test.ts
+++ b/tests/src/rmrk/createCollection.test.ts
@@ -6,7 +6,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
 
modifiedtests/src/rmrk/deleteCollection.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/deleteCollection.test.ts
+++ b/tests/src/rmrk/deleteCollection.test.ts
@@ -7,7 +7,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   const Alice = '//Alice';
modifiedtests/src/rmrk/equipNft.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/equipNft.test.ts
+++ b/tests/src/rmrk/equipNft.test.ts
@@ -126,7 +126,7 @@
   
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore, Pallets.RmrkEquip]);
+    await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
   });
 
   it('equip nft', async () => {
modifiedtests/src/rmrk/getOwnedNfts.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/getOwnedNfts.test.ts
+++ b/tests/src/rmrk/getOwnedNfts.test.ts
@@ -9,7 +9,7 @@
   
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
 
modifiedtests/src/rmrk/lockCollection.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/lockCollection.test.ts
+++ b/tests/src/rmrk/lockCollection.test.ts
@@ -11,7 +11,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   it('lock collection', async () => {
modifiedtests/src/rmrk/mintNft.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/mintNft.test.ts
+++ b/tests/src/rmrk/mintNft.test.ts
@@ -10,7 +10,7 @@
  
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
 
modifiedtests/src/rmrk/rejectNft.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/rejectNft.test.ts
+++ b/tests/src/rmrk/rejectNft.test.ts
@@ -14,7 +14,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
 
modifiedtests/src/rmrk/removeResource.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/removeResource.test.ts
+++ b/tests/src/rmrk/removeResource.test.ts
@@ -20,7 +20,7 @@
   before(async function() {
     api = await getApiConnection();
     ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   const Alice = '//Alice';
modifiedtests/src/rmrk/rmrkIsolation.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/rmrkIsolation.test.ts
+++ b/tests/src/rmrk/rmrkIsolation.test.ts
@@ -64,7 +64,7 @@
   before(async function() {
     await usingApi(async (api, privateKeyWrapper) => {
       alice = privateKeyWrapper('//Alice');
-      requirePallets(this, api, [Pallets.RmrkCore]);
+      await requirePallets(this, [Pallets.RmrkCore]);
     });
   });
 
modifiedtests/src/rmrk/sendNft.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/sendNft.test.ts
+++ b/tests/src/rmrk/sendNft.test.ts
@@ -9,7 +9,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   const maxNftId = 0xFFFFFFFF;
modifiedtests/src/rmrk/setCollectionProperty.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/setCollectionProperty.test.ts
+++ b/tests/src/rmrk/setCollectionProperty.test.ts
@@ -10,7 +10,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   it('set collection property', async () => {
modifiedtests/src/rmrk/setEquippableList.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/setEquippableList.test.ts
+++ b/tests/src/rmrk/setEquippableList.test.ts
@@ -7,7 +7,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   const alice = '//Alice';
modifiedtests/src/rmrk/setNftProperty.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/setNftProperty.test.ts
+++ b/tests/src/rmrk/setNftProperty.test.ts
@@ -8,7 +8,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   const alice = '//Alice';
modifiedtests/src/rmrk/setResourcePriorities.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/setResourcePriorities.test.ts
+++ b/tests/src/rmrk/setResourcePriorities.test.ts
@@ -7,7 +7,7 @@
   let api: any;
   before(async function () {
     api = await getApiConnection();
-    requirePallets(this, api, [Pallets.RmrkCore]);
+    await requirePallets(this, [Pallets.RmrkCore]);
   });
 
   const alice = '//Alice';
modifiedtests/src/setCollectionSponsor.test.tsdiffbeforeafterboth
--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -23,6 +23,8 @@
   setCollectionSponsorExpectFailure,
   addCollectionAdminExpectSuccess,
   getCreatedCollectionCount,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 import {IKeyringPair} from '@polkadot/types/types';
 
@@ -50,7 +52,9 @@
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
   });
-  it('Set ReFungible collection sponsor', async () => {
+  it('Set ReFungible collection sponsor', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await setCollectionSponsorExpectSuccess(collectionId, bob.address);
   });
modifiedtests/src/transfer.test.tsdiffbeforeafterboth
--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -35,11 +35,14 @@
   getBalance as getTokenBalance,
   transferFromExpectSuccess,
   transferFromExpectFail,
+  requirePallets,
+  Pallets,
 } from './util/helpers';
 import {
   subToEth,
   itWeb3, 
 } from './eth/util/helpers';
+import { request } from 'https';
 
 let alice: IKeyringPair;
 let bob: IKeyringPair;
@@ -89,56 +92,61 @@
     });
   });
 
-  it('User can transfer owned token', async () => {
-    await usingApi(async (api, privateKeyWrapper) => {
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');
-      // fungible
-      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
-      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
-      await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');
-      // reFungible
-      const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
-      await transferExpectSuccess(
-        reFungibleCollectionId,
-        newReFungibleTokenId,
-        alice,
-        bob,
-        100,
-        'ReFungible',
-      );
-    });
+  it('[nft] User can transfer owned token', async () => {
+    const nftCollectionId = await createCollectionExpectSuccess();
+    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
+    await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');
+  });
+
+  it('[fungible] User can transfer owned token', async () => {
+    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
+    await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');
+  });
+
+  it('[refungible] User can transfer owned token', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
+    await transferExpectSuccess(
+      reFungibleCollectionId,
+      newReFungibleTokenId,
+      alice,
+      bob,
+      100,
+      'ReFungible',
+    );
+  });
+
+  it('[nft] Collection admin can transfer owned token', async () => {
+    const nftCollectionId = await createCollectionExpectSuccess();
+    await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
+    const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);
+    await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');
+  });
+
+  it('[fungible] Collection admin can transfer owned token', async () => {
+    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+    await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);
+    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);
+    await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');
   });
 
-  it('Collection admin can transfer owned token', async () => {
-    await usingApi(async (api, privateKeyWrapper) => {
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
-      const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);
-      await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');
-      // fungible
-      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
-      await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);
-      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);
-      await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');
-      // reFungible
-      const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-      await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);
-      const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);
-      await transferExpectSuccess(
-        reFungibleCollectionId,
-        newReFungibleTokenId,
-        bob,
-        alice,
-        100,
-        'ReFungible',
-      );
-    });
+  it('[refungible] Collection admin can transfer owned token', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+    await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);
+    const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);
+    await transferExpectSuccess(
+      reFungibleCollectionId,
+      newReFungibleTokenId,
+      bob,
+      alice,
+      100,
+      'ReFungible',
+    );
   });
 });
 
@@ -150,33 +158,49 @@
       charlie = privateKeyWrapper('//Charlie');
     });
   });
-  it('Transfer with not existed collection_id', async () => {
+
+  it('[nft] Transfer with not existed collection_id', async () => {
     await usingApi(async (api) => {
-      // nft
       const nftCollectionCount = await getCreatedCollectionCount(api);
       await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);
-      // fungible
+    });
+  });
+
+  it('[fungible] Transfer with not existed collection_id', async () => {
+    await usingApi(async (api) => {
       const fungibleCollectionCount = await getCreatedCollectionCount(api);
       await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);
-      // reFungible
+    });
+  });
+
+  it('[refungible] Transfer with not existed collection_id', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    await usingApi(async (api) => {
       const reFungibleCollectionCount = await getCreatedCollectionCount(api);
       await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);
     });
   });
-  it('Transfer with deleted collection_id', async () => {
-    // nft
+
+  it('[nft] Transfer with deleted collection_id', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
     const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
     await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);
     await destroyCollectionExpectSuccess(nftCollectionId);
     await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);
-    // fungible
+  });
+
+  it('[fungible] Transfer with deleted collection_id', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
     await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
     await destroyCollectionExpectSuccess(fungibleCollectionId);
     await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);
-    // reFungible
+  });
+
+  it('[refungible] Transfer with deleted collection_id', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId = await
     createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -190,16 +214,21 @@
       1,
     );
   });
-  it('Transfer with not existed item_id', async () => {
-    // nft
+
+  it('[nft] Transfer with not existed item_id', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
     await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);
-    // fungible
+  });
+
+  it('[fungible] Transfer with not existed item_id', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);
-    // reFungible
-    const reFungibleCollectionId = await
-    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+  });
+
+  it('[refungible] Transfer with not existed item_id', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     await transferExpectFailure(
       reFungibleCollectionId,
       2,
@@ -208,18 +237,24 @@
       1,
     );
   });
-  it('Transfer with deleted item_id', async () => {
-    // nft
+
+  it('[nft] Transfer with deleted item_id', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
     const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
     await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);
     await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);
-    // fungible
+  });
+
+  it('[fungible] Transfer with deleted item_id', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
     await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
     await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);
-    // reFungible
+  });
+
+  it('[refungible] Transfer with deleted item_id', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     const reFungibleCollectionId = await
     createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -232,18 +267,23 @@
       1,
     );
   });
-  it('Transfer with recipient that is not owner', async () => {
-    // nft
+
+  it('[nft] Transfer with recipient that is not owner', async () => {
     const nftCollectionId = await createCollectionExpectSuccess();
     const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
     await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);
-    // fungible
+  });
+
+  it('[fungible] Transfer with recipient that is not owner', async () => {
     const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
     const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
     await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);
-    // reFungible
-    const reFungibleCollectionId = await
-    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+  });
+
+  it('[refungible] Transfer with recipient that is not owner', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
     const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
     await transferExpectFailure(
       reFungibleCollectionId,
@@ -276,7 +316,9 @@
     });
   });
 
-  it('RFT', async () => {
+  it('RFT', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async (api: ApiPromise) => {
       const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
modifiedtests/src/transferFrom.test.tsdiffbeforeafterboth
--- a/tests/src/transferFrom.test.ts
+++ b/tests/src/transferFrom.test.ts
@@ -31,6 +31,8 @@
   burnItemExpectSuccess,
   setCollectionLimitsExpectSuccess,
   getCreatedCollectionCount,
+  requirePallets,
+  Pallets
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -49,36 +51,36 @@
     });
   });
 
-  it('Execute the extrinsic and check nftItemList - owner of token', async () => {
-    await usingApi(async () => {
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
+  it('[nft] Execute the extrinsic and check nftItemList - owner of token', async () => {
+    const nftCollectionId = await createCollectionExpectSuccess();
+    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
+    await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
 
-      await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');
+    await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');
+  });
 
-      // fungible
-      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
-      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
-      await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
-      await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible');
+  it('[fungible] Execute the extrinsic and check nftItemList - owner of token', async () => {
+    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
+    await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
+    await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible');
+  });
 
-      // reFungible
-      const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
-      await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100);
-      await transferFromExpectSuccess(
-        reFungibleCollectionId,
-        newReFungibleTokenId,
-        bob,
-        alice,
-        charlie,
-        100,
-        'ReFungible',
-      );
-    });
+  it('[refungible] Execute the extrinsic and check nftItemList - owner of token', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
+    await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100);
+    await transferFromExpectSuccess(
+      reFungibleCollectionId,
+      newReFungibleTokenId,
+      bob,
+      alice,
+      charlie,
+      100,
+      'ReFungible',
+    );
   });
 
   it('Should reduce allowance if value is big', async () => {
@@ -119,20 +121,28 @@
     });
   });
 
-  it('transferFrom for a collection that does not exist', async () => {
+  it('[nft] transferFrom for a collection that does not exist', async () => {
     await usingApi(async (api: ApiPromise) => {
-      // nft
       const nftCollectionCount = await getCreatedCollectionCount(api);
       await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);
 
       await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1);
+    });
+  });
 
-      // fungible
+  it('[fungible] transferFrom for a collection that does not exist', async () => {
+    await usingApi(async (api: ApiPromise) => {
       const fungibleCollectionCount = await getCreatedCollectionCount(api);
       await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);
 
       await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1);
-      // reFungible
+    });
+  });
+
+  it('[refungible] transferFrom for a collection that does not exist', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    await usingApi(async (api: ApiPromise) => {
       const reFungibleCollectionCount = await getCreatedCollectionCount(api);
       await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
 
@@ -158,67 +168,70 @@
     });
   }); */
 
-  it('transferFrom for not approved address', async () => {
-    await usingApi(async () => {
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
+  it('[nft] transferFrom for not approved address', async () => {
+    const nftCollectionId = await createCollectionExpectSuccess();
+    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
 
-      await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
+    await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
+  });
 
-      // fungible
-      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
-      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
-      await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);
-      // reFungible
-      const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
-      await transferFromExpectFail(
-        reFungibleCollectionId,
-        newReFungibleTokenId,
-        bob,
-        alice,
-        charlie,
-        1,
-      );
-    });
+  it('[fungible] transferFrom for not approved address', async () => {
+    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
+    await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);
+  });
+
+  it('[refungible] transferFrom for not approved address', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    const reFungibleCollectionId = await
+    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
+    await transferFromExpectFail(
+      reFungibleCollectionId,
+      newReFungibleTokenId,
+      bob,
+      alice,
+      charlie,
+      1,
+    );
+  });
+
+  it('[nft] transferFrom incorrect token count', async () => {
+    const nftCollectionId = await createCollectionExpectSuccess();
+    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
+    await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
+
+    await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);
   });
 
-  it('transferFrom incorrect token count', async () => {
-    await usingApi(async () => {
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
+  it('[fungible] transferFrom incorrect token count', async () => {
+    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
+    await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
+    await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2);
+  });
 
-      await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);
+  it('[refungible] transferFrom incorrect token count', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
 
-      // fungible
-      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
-      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
-      await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
-      await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2);
-      // reFungible
-      const reFungibleCollectionId = await
-      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
-      await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
-      await transferFromExpectFail(
-        reFungibleCollectionId,
-        newReFungibleTokenId,
-        bob,
-        alice,
-        charlie,
-        2,
-      );
-    });
+    const reFungibleCollectionId = await
+    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
+    await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
+    await transferFromExpectFail(
+      reFungibleCollectionId,
+      newReFungibleTokenId,
+      bob,
+      alice,
+      charlie,
+      2,
+    );
   });
 
-  it('execute transferFrom from account that is not owner of collection', async () => {
+  it('[nft] execute transferFrom from account that is not owner of collection', async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const dave = privateKeyWrapper('//Dave');
-      // nft
       const nftCollectionId = await createCollectionExpectSuccess();
       const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
       try {
@@ -230,8 +243,13 @@
       }
 
       // await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1);
+    });
+  });
 
-      // fungible
+  it('[fungible] execute transferFrom from account that is not owner of collection', async () => {
+    await usingApi(async (api, privateKeyWrapper) => {
+      const dave = privateKeyWrapper('//Dave');
+
       const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
       const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
       try {
@@ -241,7 +259,14 @@
         // tslint:disable-next-line:no-unused-expression
         expect(e).to.be.exist;
       }
-      // reFungible
+    });
+  });
+
+  it('[refungible] execute transferFrom from account that is not owner of collection', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
+    await usingApi(async (api, privateKeyWrapper) => {
+      const dave = privateKeyWrapper('//Dave');
       const reFungibleCollectionId = await
       createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -276,7 +301,9 @@
 
     });
   });
-  it('transferFrom burnt token before approve ReFungible', async () => {
+  it('transferFrom burnt token before approve ReFungible', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async () => {
       const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       await setCollectionLimitsExpectSuccess(alice, reFungibleCollectionId, {ownerCanTransfer: true});
@@ -308,7 +335,9 @@
 
     });
   });
-  it('transferFrom burnt token after approve ReFungible', async () => {
+  it('transferFrom burnt token after approve ReFungible', async function() {
+    await requirePallets(this, [Pallets.ReFungible]);
+
     await usingApi(async () => {
       const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');