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

difftreelog

test(structure) extra nesting + properties refactoring

Fahrrader2022-05-13parent: #0baf86c.patch.diff
in: master

7 files changed

modifiedtests/src/createItem.test.tsdiffbeforeafterboth
before · tests/src/createItem.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {default as usingApi, executeTransaction} from './substrate/substrate-api';18import chai from 'chai';19import {Keyring} from '@polkadot/api';20import {IKeyringPair} from '@polkadot/types/types';21import {22  createCollectionExpectSuccess,23  createItemExpectSuccess,24  addCollectionAdminExpectSuccess,25  createCollectionWithPropsExpectSuccess,26} from './util/helpers';2728const expect = chai.expect;29let alice: IKeyringPair;30let bob: IKeyringPair;3132describe('integration test: ext. createItem():', () => {33  before(async () => {34    await usingApi(async () => {35      const keyring = new Keyring({type: 'sr25519'});36      alice = keyring.addFromUri('//Alice');37      bob = keyring.addFromUri('//Bob');38    });39  });4041  it('Create new item in NFT collection', async () => {42    const createMode = 'NFT';43    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});44    await createItemExpectSuccess(alice, newCollectionID, createMode);45  });46  it('Create new item in Fungible collection', async () => {47    const createMode = 'Fungible';48    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});49    await createItemExpectSuccess(alice, newCollectionID, createMode);50  });51  it('Create new item in ReFungible collection', async () => {52    const createMode = 'ReFungible';53    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});54    await createItemExpectSuccess(alice, newCollectionID, createMode);55  });56  it('Create new item in NFT collection with collection admin permissions', async () => {57    const createMode = 'NFT';58    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});59    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);60    await createItemExpectSuccess(bob, newCollectionID, createMode);61  });62  it('Create new item in Fungible collection with collection admin permissions', async () => {63    const createMode = 'Fungible';64    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});65    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);66    await createItemExpectSuccess(bob, newCollectionID, createMode);67  });68  it('Create new item in ReFungible collection with collection admin permissions', async () => {69    const createMode = 'ReFungible';70    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});71    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);72    await createItemExpectSuccess(bob, newCollectionID, createMode);73  });7475  it('Set property Admin', async () => {76    const createMode = 'NFT';77    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 78      properties: [{key: 'key1', value: 'val1'}], 79      propPerm:   [{key: 'key1', mutable: true, collectionAdmin: true, tokenOwner: false}]});80    81    await createItemExpectSuccess(alice, newCollectionID, createMode);82  });8384  it('Set property AdminConst', async () => {85    const createMode = 'NFT';86    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 87      properties: [{key: 'key1', value: 'val1'}], 88      propPerm:   [{key: 'key1', mutable: false, collectionAdmin: true, tokenOwner: false}]});89    90    await createItemExpectSuccess(alice, newCollectionID, createMode);91  });9293  it('Set property itemOwnerOrAdmin', async () => {94    const createMode = 'NFT';95    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 96      properties: [{key: 'key1', value: 'val1'}], 97      propPerm:   [{key: 'key1', mutable: true, collectionAdmin: true, tokenOwner: true}]});98    99    await createItemExpectSuccess(alice, newCollectionID, createMode);100  });101});102103describe('Negative integration test: ext. createItem():', () => {104  before(async () => {105    await usingApi(async () => {106      const keyring = new Keyring({type: 'sr25519'});107      alice = keyring.addFromUri('//Alice');108      bob = keyring.addFromUri('//Bob');109    });110  });111112  it('Regular user cannot create new item in NFT collection', async () => {113    const createMode = 'NFT';114    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});115    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;116  });117  it('Regular user cannot create new item in Fungible collection', async () => {118    const createMode = 'Fungible';119    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});120    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;121  });122  it('Regular user cannot create new item in ReFungible collection', async () => {123    const createMode = 'ReFungible';124    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});125    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;126  });127128  it('No editing rights', async () => {129    await usingApi(async api => {130      const createMode = 'NFT';131      const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 132        propPerm:   [{key: 'key1', mutable: false, collectionAdmin: false, tokenOwner: false}]});133134      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');135      await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);136137      await expect(executeTransaction(138        api, 139        alice, 140        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 141      )).to.be.rejected;142    });143  });144145  it('User doesnt have editing rights', async () => {146    await usingApi(async api => {147      const createMode = 'NFT';148      const newCollectionID = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'key1', mutable: true, collectionAdmin: false, tokenOwner: false}]});149      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');150151      await expect(executeTransaction(152        api, 153        bob, 154        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 155      )).to.be.rejected;156    });157  });158159  it('Adding property without access rights', async () => {160    await usingApi(async api => {161      const createMode = 'NFT';162      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});163164      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');165      await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);166      167      await expect(executeTransaction(168        api, 169        bob, 170        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 171      )).to.be.rejected;172    });173  });174175  it('Adding more than 64 prps', async () => {176    await usingApi(async api => {177      const createMode = 'NFT';178179      const prps = [];180181      for (let i = 0; i < 65; i++) {182        prps.push({key: `key${i}`, value: `value${i}`});183      }184185      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});186      187      await expect(executeTransaction(api, alice, api.tx.unique.setCollectionProperties(newCollectionID, prps))).to.be.rejectedWith(/common\.PropertyLimitReached/);188    });189  });190191  it('Trying to add bigger property than allowed', async () => {192    await usingApi(async api => {193      const createMode = 'NFT';194      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});195      196      await expect(executeTransaction(api, alice, api.tx.unique.setCollectionProperties(newCollectionID, [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]))).to.be.rejectedWith(/common\.NoSpaceForProperty/);197    });198  });199});
after · tests/src/createItem.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {default as usingApi, executeTransaction} from './substrate/substrate-api';18import chai from 'chai';19import {Keyring} from '@polkadot/api';20import {IKeyringPair} from '@polkadot/types/types';21import {22  createCollectionExpectSuccess,23  createItemExpectSuccess,24  addCollectionAdminExpectSuccess,25  createCollectionWithPropsExpectSuccess,26} from './util/helpers';2728const expect = chai.expect;29let alice: IKeyringPair;30let bob: IKeyringPair;3132describe('integration test: ext. createItem():', () => {33  before(async () => {34    await usingApi(async () => {35      const keyring = new Keyring({type: 'sr25519'});36      alice = keyring.addFromUri('//Alice');37      bob = keyring.addFromUri('//Bob');38    });39  });4041  it('Create new item in NFT collection', async () => {42    const createMode = 'NFT';43    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});44    await createItemExpectSuccess(alice, newCollectionID, createMode);45  });46  it('Create new item in Fungible collection', async () => {47    const createMode = 'Fungible';48    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});49    await createItemExpectSuccess(alice, newCollectionID, createMode);50  });51  it('Create new item in ReFungible collection', async () => {52    const createMode = 'ReFungible';53    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});54    await createItemExpectSuccess(alice, newCollectionID, createMode);55  });56  it('Create new item in NFT collection with collection admin permissions', async () => {57    const createMode = 'NFT';58    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});59    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);60    await createItemExpectSuccess(bob, newCollectionID, createMode);61  });62  it('Create new item in Fungible collection with collection admin permissions', async () => {63    const createMode = 'Fungible';64    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});65    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);66    await createItemExpectSuccess(bob, newCollectionID, createMode);67  });68  it('Create new item in ReFungible collection with collection admin permissions', async () => {69    const createMode = 'ReFungible';70    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});71    await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);72    await createItemExpectSuccess(bob, newCollectionID, createMode);73  });7475  it('Set property Admin', async () => {76    const createMode = 'NFT';77    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 78      properties: [{key: 'key1', value: 'val1'}], 79      propPerm:   [{key: 'key1', mutable: true, collectionAdmin: true, tokenOwner: false}]});80    81    await createItemExpectSuccess(alice, newCollectionID, createMode);82  });8384  it('Set property AdminConst', async () => {85    const createMode = 'NFT';86    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 87      properties: [{key: 'key1', value: 'val1'}], 88      propPerm:   [{key: 'key1', mutable: false, collectionAdmin: true, tokenOwner: false}]});89    90    await createItemExpectSuccess(alice, newCollectionID, createMode);91  });9293  it('Set property itemOwnerOrAdmin', async () => {94    const createMode = 'NFT';95    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 96      properties: [{key: 'key1', value: 'val1'}], 97      propPerm:   [{key: 'key1', mutable: true, collectionAdmin: true, tokenOwner: true}]});98    99    await createItemExpectSuccess(alice, newCollectionID, createMode);100  });101});102103describe('Negative integration test: ext. createItem():', () => {104  before(async () => {105    await usingApi(async () => {106      const keyring = new Keyring({type: 'sr25519'});107      alice = keyring.addFromUri('//Alice');108      bob = keyring.addFromUri('//Bob');109    });110  });111112  it('Regular user cannot create new item in NFT collection', async () => {113    const createMode = 'NFT';114    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});115    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;116  });117  it('Regular user cannot create new item in Fungible collection', async () => {118    const createMode = 'Fungible';119    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});120    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;121  });122  it('Regular user cannot create new item in ReFungible collection', async () => {123    const createMode = 'ReFungible';124    const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});125    await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;126  });127128  it('No editing rights', async () => {129    await usingApi(async api => {130      const createMode = 'NFT';131      const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 132        propPerm:   [{key: 'key1', mutable: false, collectionAdmin: false, tokenOwner: false}]});133134      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');135      await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);136137      await expect(executeTransaction(138        api, 139        alice, 140        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 141      )).to.be.rejected;142    });143  });144145  it('User doesnt have editing rights', async () => {146    await usingApi(async api => {147      const newCollectionID = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'key1', mutable: true, collectionAdmin: false, tokenOwner: false}]});148      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');149150      await expect(executeTransaction(151        api, 152        bob, 153        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 154      )).to.be.rejected;155    });156  });157158  it('Adding property without access rights', async () => {159    await usingApi(async api => {160      const createMode = 'NFT';161      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});162163      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');164      await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);165      166      await expect(executeTransaction(167        api, 168        bob, 169        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 170      )).to.be.rejected;171    });172  });173174  it('Adding more than 64 prps', async () => {175    await usingApi(async api => {176      const createMode = 'NFT';177178      const prps = [];179180      for (let i = 0; i < 65; i++) {181        prps.push({key: `key${i}`, value: `value${i}`});182      }183184      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});185      186      await expect(executeTransaction(api, alice, api.tx.unique.setCollectionProperties(newCollectionID, prps))).to.be.rejectedWith(/common\.PropertyLimitReached/);187    });188  });189190  it('Trying to add bigger property than allowed', async () => {191    await usingApi(async api => {192      const createMode = 'NFT';193      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});194      195      await expect(executeTransaction(api, alice, api.tx.unique.setCollectionProperties(newCollectionID, [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]))).to.be.rejectedWith(/common\.NoSpaceForProperty/);196    });197  });198});
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -146,7 +146,6 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
       const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
         {Nft: {const_data: '0x32', variable_data: '0x32'}},
         {Nft: {const_data: '0x33', variable_data: '0x33'}}];
@@ -182,7 +181,6 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
       const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
         {Nft: {const_data: '0x32', variable_data: '0x32'}},
         {Nft: {const_data: '0x33', variable_data: '0x33'}}];
@@ -218,7 +216,6 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
       const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
         {Nft: {const_data: '0x32', variable_data: '0x32'}},
         {Nft: {const_data: '0x33', variable_data: '0x33'}}];
modifiedtests/src/nesting/migration-check.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/migration-check.test.ts
+++ b/tests/src/nesting/migration-check.test.ts
@@ -8,8 +8,8 @@
 // Used for polkadot-launch signalling
 import find from 'find-process';
 
-// todo skip
-describe('Migration testing for pallet-common', () => {
+// todo un-skip for migrations
+describe.skip('Migration testing for pallet-common', () => {
   let alice: IKeyringPair;
 
   before(async() => {
@@ -63,16 +63,33 @@
     });
 
     // And wait for the parachain upgrade
-    while (newVersion == oldVersion! && connectionFailCounter < 2) {
-      try {
-        await usingApi(async api => {
-          await waitNewBlocks(api);
-          newVersion = (api.consts.system.version.toJSON() as any).specVersion;
-        });
-      } catch (_) {
-        connectionFailCounter++;
-        console.log(`Still waiting for the parachain upgrade from ${oldVersion!}...`);
-        await new Promise(resolve => setTimeout(resolve, 12000));
+    {
+      // Catch warnings like 'RPC methods not decorated' and keep the 'waiting' message in front
+      const stdlog = console.warn.bind(console);
+      let warnCount = 0;
+      console.warn = function(...args){
+        if (arguments.length <= 2 || !args[2].includes('RPC methods not decorated')) {
+          warnCount++;
+          stdlog.apply(console, args as any);
+        }
+      };
+
+      let oldWarnCount = 0;
+      while (newVersion == oldVersion! && connectionFailCounter < 2) {
+        try {
+          await usingApi(async api => {
+            await waitNewBlocks(api);
+            newVersion = (api.consts.system.version.toJSON() as any).specVersion;
+            if (warnCount > oldWarnCount) {
+              console.log(`Still waiting for the parachain upgrade from ${oldVersion!}...`);
+              oldWarnCount = warnCount;
+            }
+            await new Promise(resolve => setTimeout(resolve, 6000));
+          });
+        } catch (_) {
+          connectionFailCounter++;
+          await new Promise(resolve => setTimeout(resolve, 12000));
+        }
       }
     }
 
modifiedtests/src/nesting/nest.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/nest.test.ts
+++ b/tests/src/nesting/nest.test.ts
@@ -9,8 +9,7 @@
   enableAllowListExpectSuccess,
   enablePublicMintingExpectSuccess,
   getTokenOwner, 
-  getTopmostTokenOwner, 
-  normalizeAccountId, 
+  getTopmostTokenOwner,
   setCollectionLimitsExpectSuccess, 
   transferExpectFailure, 
   transferExpectSuccess, 
@@ -23,7 +22,7 @@
 
 describe('Integration Test: Nesting', () => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -196,7 +195,7 @@
 
 describe('Negative Test: Nesting', async() => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -212,14 +211,11 @@
       const nestedToken1 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});
       const nestedToken2 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, nestedToken1)});
       // The nesting depth is limited by 2
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.createItem(
-          collection, 
-          {Ethereum: tokenIdToAddress(collection, nestedToken2)}, 
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(
+        collection, 
+        {Ethereum: tokenIdToAddress(collection, nestedToken2)}, 
           {nft: {const_data: [], variable_data: []}} as any,
-        ),
-      ), 'while creating nested token').to.be.rejectedWith(/^structure\.DepthLimit$/); // OuroborosDetected?
+      )), 'while creating nested token').to.be.rejectedWith(/^structure\.DepthLimit$/);
 
       expect(await getTopmostTokenOwner(api, collection, nestedToken2)).to.be.deep.equal({Substrate: alice.address});
     });
@@ -234,24 +230,16 @@
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
       // Try to create a nested token
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.createItem(
-          collection, 
-          {Ethereum: tokenIdToAddress(collection, targetToken)}, 
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(
+        collection, 
+        {Ethereum: tokenIdToAddress(collection, targetToken)}, 
           {nft: {const_data: [], variable_data: []}} as any,
-        ),
-      ), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
+      )), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
 
       // Create a token to be nested
       const newToken = await createItemExpectSuccess(alice, collection, 'NFT');
       // Try to nest
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.transfer(
-          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,
-        ),
-      ), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/); // todo to.be.rejected for all
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);
       expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});
       expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});
     });
@@ -270,23 +258,15 @@
       const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');
 
       // Try to create a nested token in the wrong collection
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.createItem(
-          collection, 
-          {Ethereum: tokenIdToAddress(collection, targetToken)}, 
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(
+        collection, 
+        {Ethereum: tokenIdToAddress(collection, targetToken)}, 
           {nft: {const_data: [], variable_data: []}} as any,
-        ),
-      ), 'while creating nested token').to.be.rejectedWith(/structure\.DepthLimit/); // todo NestingIsDisabled?
+      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collection, 'NFT');
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.transfer(
-          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,
-        ),
-      ), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);
+      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/);
       expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});
     });
   });
@@ -304,23 +284,15 @@
       const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');
 
       // Try to create a nested token in the wrong collection
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.createItem(
-          collection, 
-          {Ethereum: tokenIdToAddress(collection, targetToken)}, 
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(
+        collection, 
+        {Ethereum: tokenIdToAddress(collection, targetToken)}, 
           {nft: {const_data: [], variable_data: []}} as any,
-        ),
-      ), 'while creating nested token').to.be.rejectedWith(/structure\.DepthLimit/);
+      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collection, 'NFT');
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.transfer(
-          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,
-        ),
-      ), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);
+      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/);
       expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});
     });
   });
@@ -334,23 +306,15 @@
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
       // Try to create a nested token in the wrong collection
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.createItem(
-          collection, 
-          {Ethereum: tokenIdToAddress(collection, targetToken)}, 
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(
+        collection, 
+        {Ethereum: tokenIdToAddress(collection, targetToken)}, 
           {nft: {const_data: [], variable_data: []}} as any,
-        ),
-      ), 'while creating nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
+      )), 'while creating nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collection, 'NFT');
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.transfer(
-          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,
-        ),
-      ), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
+      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/);
       expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});
     });
   });
@@ -367,24 +331,21 @@
       const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
 
       // Try to create a nested token
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.createItem(
-          collectionFT, 
-          targetAddress, 
-          {Fungible: {Value: 10}},
-        )
-      ), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
-
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(
+        collectionFT, 
+        targetAddress, 
+        {Fungible: {Value: 10}},
+      )), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
+      
       // Create a token to be nested
       const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
       // Try to nest
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.transfer(
-          normalizeAccountId({Ethereum: tokenIdToAddress(collectionFT, targetToken)}), collectionFT, newToken, 1,
-        ),
-      ), 'while nesting new token').to.be.rejectedWith(/fungible\.FungibleDisallowsNesting/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);
+
+      // Create another token to be nested
+      const newToken2 = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
+      // Try to nest inside a fungible token
+      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/);
     });
   });
 
@@ -404,31 +365,21 @@
       const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
 
       // Try to create a nested token in the wrong collection
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.createItem(
-          collectionFT, 
-          targetAddress, 
-          {Fungible: {Value: 10}},
-        )
-      ), 'while creating nested token').to.be.rejectedWith(/structure\.DepthLimit/);
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(
+        collectionFT, 
+        targetAddress, 
+        {Fungible: {Value: 10}},
+      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
-      await expect(executeTransaction(
-        api, alice, 
-        api.tx.unique.transfer(
-          normalizeAccountId({Ethereum: tokenIdToAddress(collectionFT, targetToken)}), collectionFT, newToken, 1,
-        ),
-      ), 'while nesting new token').to.be.rejectedWith(/fungible\.FungibleDisallowsNesting/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
     });
   });
 
   it('Fungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionNFT]}}); // todo clear redundant restrictions?
-
       await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);
       await enableAllowListExpectSuccess(alice, collectionNFT);
       await enablePublicMintingExpectSuccess(alice, collectionNFT);
@@ -438,17 +389,18 @@
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
       const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionFT]}});
 
       // Try to create a nested token in the wrong collection
       await expect(executeTransaction(api, alice, api.tx.unique.createItem(
         collectionFT, 
         targetAddress, 
         {Fungible: {Value: 10}},
-      ))).to.be.rejected;
+      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
-      await transferExpectFailure(collectionFT, newToken, alice, targetAddress, 1);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
     });
   });
 
@@ -468,11 +420,11 @@
         collectionFT, 
         targetAddress, 
         {Fungible: {Value: 10}},
-      ))).to.be.rejected;
+      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
-      await transferExpectFailure(collectionFT, newToken, alice, targetAddress, 1);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
     });
   });
 
@@ -492,12 +444,19 @@
         collectionRFT, 
         targetAddress, 
         {ReFungible: {const_data: [], pieces: 100}},
-      ))).to.be.rejectedWith(/^common\.NestingIsDisabled$/);
+      )), 'while creating a nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
 
       // Create a token to be nested
       const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
       // Try to nest
       await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);
+      // Try to nest
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);
+
+      // Create another token to be nested
+      const newToken2 = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
+      // Try to nest inside a fungible token
+      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/);
     });
   });
 
@@ -521,19 +480,17 @@
         collectionRFT, 
         targetAddress, 
         {ReFungible: {const_data: [], pieces: 100}},
-      ))).to.be.rejected;
+      )), 'while creating a nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
-      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
     });
   });
 
   it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionNFT]}});
-
       await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);
       await enableAllowListExpectSuccess(alice, collectionNFT);
       await enablePublicMintingExpectSuccess(alice, collectionNFT);
@@ -543,17 +500,18 @@
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
       const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionRFT]}});
 
       // Try to create a nested token in the wrong collection
       await expect(executeTransaction(api, alice, api.tx.unique.createItem(
         collectionRFT, 
         targetAddress, 
         {ReFungible: {const_data: [], pieces: 100}},
-      ))).to.be.rejected;
+      )), 'while creating a nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
-      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
     });
   });
 
@@ -573,11 +531,11 @@
         collectionRFT, 
         targetAddress, 
         {ReFungible: {const_data: [], pieces: 100}},
-      ))).to.be.rejected;
+      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
-      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
     });
   });
 });
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -18,7 +18,7 @@
 
 describe('Integration Test: Collection Properties', () => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -113,7 +113,7 @@
 
 describe('Negative Integration Test: Collection Properties', () => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -213,13 +213,13 @@
         api, 
         alice, 
         api.tx.unique.setCollectionProperties(collection, [{key: '', value: 'nothing must not exist'}]), 
-      ), `on rejecting an unnamed property`).to.be.rejectedWith(/common\.EmptyPropertyKey/);
+      ), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);
 
       await expect(executeTransaction(
         api, 
         alice, 
         api.tx.unique.setCollectionProperties(collection, [
-          {key: 'CRISPR-Cas9', value: 'rewriting nature!'}
+          {key: 'CRISPR-Cas9', value: 'rewriting nature!'},
         ]), 
       ), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;
 
@@ -245,7 +245,7 @@
 
 describe('Integration Test: Access Rights to Token Properties', () => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -311,7 +311,7 @@
 
 describe('Negative Integration Test: Access Rights to Token Properties', () => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -400,7 +400,7 @@
         api, 
         alice, 
         api.tx.unique.setPropertyPermissions(collection, [{key: '', permission: {}}]), 
-      ), `on rejecting an unnamed property`).to.be.rejectedWith(/common\.EmptyPropertyKey/);
+      ), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);
 
       const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string
       await expect(executeTransaction(
@@ -429,7 +429,7 @@
   let permissions: {permission: any, signers: IKeyringPair[]}[];
 
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
       charlie = privateKey('//Charlie');
@@ -446,10 +446,12 @@
   });
 
   beforeEach(async () => {
-    collection = await createCollectionExpectSuccess();
-    token = await createItemExpectSuccess(alice, collection, 'NFT');
-    await addCollectionAdminExpectSuccess(alice, collection, bob.address);
-    await transferExpectSuccess(collection, token, alice, charlie);
+    await usingApi(async () => {
+      collection = await createCollectionExpectSuccess();
+      token = await createItemExpectSuccess(alice, collection, 'NFT');
+      await addCollectionAdminExpectSuccess(alice, collection, bob.address);
+      await transferExpectSuccess(collection, token, alice, charlie);
+    });
   });
   
   it('Reads yet empty properties of a token', async () => {
@@ -592,7 +594,7 @@
   let constitution: {permission: any, signers: IKeyringPair[], sinner: IKeyringPair}[];
 
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
       charlie = privateKey('//Charlie');
modifiedtests/src/nesting/unnest.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/unnest.test.ts
+++ b/tests/src/nesting/unnest.test.ts
@@ -4,11 +4,9 @@
 import usingApi, {executeTransaction} from '../substrate/substrate-api';
 import {
   createCollectionExpectSuccess,
-  createItemExpectFailure,
   createItemExpectSuccess,
   getBalance,
   getTokenOwner,
-  getTopmostTokenOwner,
   normalizeAccountId,
   setCollectionLimitsExpectSuccess,
   transferExpectSuccess,
@@ -21,7 +19,7 @@
 
 describe('Integration Test: Unnesting', () => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -112,7 +110,7 @@
 
 describe('Negative Test: Unnesting', () => {
   before(async () => {
-    await usingApi(async api => {
+    await usingApi(async () => {
       alice = privateKey('//Alice');
       bob = privateKey('//Bob');
     });
@@ -133,7 +131,7 @@
         api,
         bob,
         api.tx.unique.transferFrom(normalizeAccountId(targetAddress), normalizeAccountId(bob), collection, nestedToken, 1),
-      ), 'while unnesting').to.be.rejectedWith(/^structure\.DepthLimit$/); // todo ApprovedValueTooLow?
+      ), 'while unnesting').to.be.rejectedWith(/^common\.ApprovedValueTooLow$/);
       expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});
 
       // Try to burn
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -427,7 +427,6 @@
 export async function createCollectionWithPropsExpectFailure(params: Partial<CreateCollectionParams> = {}) {
   const {name, description, mode, tokenPrefix} = {...defaultCreateCollectionParams, ...params};
 
-  const collectionId = 0;
   await usingApi(async (api) => {
     // Get number of collections before the transaction
     const collectionCountBefore = await getCreatedCollectionCount(api);