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
--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -144,7 +144,6 @@
 
   it('User doesnt have editing rights', async () => {
     await usingApi(async api => {
-      const createMode = 'NFT';
       const newCollectionID = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'key1', mutable: true, collectionAdmin: false, tokenOwner: false}]});
       const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');
 
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
before · tests/src/nesting/nest.test.ts
1import {expect} from 'chai';2import {tokenIdToAddress} from '../eth/util/helpers';3import privateKey from '../substrate/privateKey';4import usingApi, {executeTransaction} from '../substrate/substrate-api';5import {6  addToAllowListExpectSuccess,7  createCollectionExpectSuccess,8  createItemExpectSuccess,9  enableAllowListExpectSuccess,10  enablePublicMintingExpectSuccess,11  getTokenOwner, 12  getTopmostTokenOwner, 13  normalizeAccountId, 14  setCollectionLimitsExpectSuccess, 15  transferExpectFailure, 16  transferExpectSuccess, 17  transferFromExpectSuccess,18} from '../util/helpers';19import {IKeyringPair} from '@polkadot/types/types';2021let alice: IKeyringPair;22let bob: IKeyringPair;2324describe('Integration Test: Nesting', () => {25  before(async () => {26    await usingApi(async api => {27      alice = privateKey('//Alice');28      bob = privateKey('//Bob');29    });30  });3132  it('Performs the full suite: bundles a token, transfers, and allows to unnest', async () => {33    await usingApi(async api => {34      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});35      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});36      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');3738      // Create a nested token39      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});40      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});41      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});4243      // Create a token to be nested44      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');45      46      // Nest47      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});48      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});49      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});5051      // Move bundle to different user52      await transferExpectSuccess(collection, targetToken, alice, {Substrate: bob.address});53      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: bob.address});54      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});5556      // Unnest57      await transferFromExpectSuccess(collection, newToken, bob, {Ethereum: tokenIdToAddress(collection, targetToken)}, {Substrate: bob.address});58      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});59    });60  });6162  // ---------- Non-Fungible ----------6364  it('NFT: allows an Owner to nest/unnest their token', async () => {65    await usingApi(async api => {66      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});67      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});68      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');6970      // Create a nested token71      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});72      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});73      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});7475      // Create a token to be nested and nest76      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');77      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});78      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});79      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});80    });81  });8283  it('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {84    await usingApi(async api => {85      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});86      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: {OwnerRestricted:[collection]}});87      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');8889      // Create a nested token90      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});91      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});92      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});9394      // Create a token to be nested and nest95      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');96      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});97      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});98      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});99    });100  });101102  // ---------- Fungible ----------103104  it('Fungible: allows an Owner to nest/unnest their token', async () => {105    await usingApi(async api => {106      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});107      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});108      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});109      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};110111      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});112113      // Create a nested token114      await expect(executeTransaction(api, alice, api.tx.unique.createItem(115        collectionFT, 116        targetAddress, 117        {Fungible: {Value: 10}},118      ))).to.not.be.rejected;119120      // Nest a new token121      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');122      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');123    });124  });125126  it('Fungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {127    await usingApi(async api => {128      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});129      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});130      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};131132      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});133134      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionFT]}});135136      // Create a nested token137      await expect(executeTransaction(api, alice, api.tx.unique.createItem(138        collectionFT, 139        targetAddress, 140        {Fungible: {Value: 10}},141      ))).to.not.be.rejected;142143      // Nest a new token144      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');145      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');146    });147  });148149  // ---------- Re-Fungible ----------150151  it('ReFungible: allows an Owner to nest/unnest their token', async () => {152    await usingApi(async api => {153      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});154      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});155      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});156      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};157158      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});159160      // Create a nested token161      await expect(executeTransaction(api, alice, api.tx.unique.createItem(162        collectionRFT, 163        targetAddress, 164        {ReFungible: {const_data: [], pieces: 100}},165      ))).to.not.be.rejected;166167      // Nest a new token168      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');169      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');170    });171  });172173  it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {174    await usingApi(async api => {175      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});176      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});177      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};178179      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});180181      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionRFT]}});182183      // Create a nested token184      await expect(executeTransaction(api, alice, api.tx.unique.createItem(185        collectionRFT, 186        targetAddress,187        {ReFungible: {const_data: [], pieces: 100}},188      ))).to.not.be.rejected;189190      // Nest a new token191      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');192      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');193    });194  });195});196197describe('Negative Test: Nesting', async() => {198  before(async () => {199    await usingApi(async api => {200      alice = privateKey('//Alice');201      bob = privateKey('//Bob');202    });203  });204205  it('Disallows excessive token nesting', async () => {206    await usingApi(async api => {207      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});208      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});209      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');210211      // Create a nested-token matryoshka212      const nestedToken1 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});213      const nestedToken2 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, nestedToken1)});214      // The nesting depth is limited by 2215      await expect(executeTransaction(216        api, alice, 217        api.tx.unique.createItem(218          collection, 219          {Ethereum: tokenIdToAddress(collection, nestedToken2)}, 220          {nft: {const_data: [], variable_data: []}} as any,221        ),222      ), 'while creating nested token').to.be.rejectedWith(/^structure\.DepthLimit$/); // OuroborosDetected?223224      expect(await getTopmostTokenOwner(api, collection, nestedToken2)).to.be.deep.equal({Substrate: alice.address});225    });226  });227228  // ---------- Non-Fungible ----------229230  it('NFT: disallows to nest token if nesting is disabled', async () => {231    await usingApi(async api => {232      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});233      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Disabled'});234      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');235236      // Try to create a nested token237      await expect(executeTransaction(238        api, alice, 239        api.tx.unique.createItem(240          collection, 241          {Ethereum: tokenIdToAddress(collection, targetToken)}, 242          {nft: {const_data: [], variable_data: []}} as any,243        ),244      ), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);245246      // Create a token to be nested247      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');248      // Try to nest249      await expect(executeTransaction(250        api, alice, 251        api.tx.unique.transfer(252          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,253        ),254      ), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/); // todo to.be.rejected for all255      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});256      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});257    });258  });259260  it('NFT: disallows a non-Owner to nest someone else\'s token', async () => {261    await usingApi(async api => {262      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});263      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});264265      await addToAllowListExpectSuccess(alice, collection, bob.address);266      await enableAllowListExpectSuccess(alice, collection);267      await enablePublicMintingExpectSuccess(alice, collection);268269      // Create a token to attempt to be nested into270      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');271272      // Try to create a nested token in the wrong collection273      await expect(executeTransaction(274        api, alice, 275        api.tx.unique.createItem(276          collection, 277          {Ethereum: tokenIdToAddress(collection, targetToken)}, 278          {nft: {const_data: [], variable_data: []}} as any,279        ),280      ), 'while creating nested token').to.be.rejectedWith(/structure\.DepthLimit/); // todo NestingIsDisabled?281282      // Try to create and nest a token in the wrong collection283      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');284      await expect(executeTransaction(285        api, alice, 286        api.tx.unique.transfer(287          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,288        ),289      ), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);290      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});291    });292  });293294  it('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {295    await usingApi(async api => {296      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});297      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: {OwnerRestricted:[collection]}});298299      await addToAllowListExpectSuccess(alice, collection, bob.address);300      await enableAllowListExpectSuccess(alice, collection);301      await enablePublicMintingExpectSuccess(alice, collection);302303      // Create a token to attempt to be nested into304      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');305306      // Try to create a nested token in the wrong collection307      await expect(executeTransaction(308        api, alice, 309        api.tx.unique.createItem(310          collection, 311          {Ethereum: tokenIdToAddress(collection, targetToken)}, 312          {nft: {const_data: [], variable_data: []}} as any,313        ),314      ), 'while creating nested token').to.be.rejectedWith(/structure\.DepthLimit/);315316      // Try to create and nest a token in the wrong collection317      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');318      await expect(executeTransaction(319        api, alice, 320        api.tx.unique.transfer(321          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,322        ),323      ), 'while nesting new token').to.be.rejectedWith(/common\.AddressNotInAllowlist/);324      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});325    });326  });327328  it('NFT: disallows to nest token in an unlisted collection', async () => {329    await usingApi(async api => {330      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});331      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: {OwnerRestricted:[]}});332333      // Create a token to attempt to be nested into334      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');335336      // Try to create a nested token in the wrong collection337      await expect(executeTransaction(338        api, alice, 339        api.tx.unique.createItem(340          collection, 341          {Ethereum: tokenIdToAddress(collection, targetToken)}, 342          {nft: {const_data: [], variable_data: []}} as any,343        ),344      ), 'while creating nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);345346      // Try to create and nest a token in the wrong collection347      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');348      await expect(executeTransaction(349        api, alice, 350        api.tx.unique.transfer(351          normalizeAccountId({Ethereum: tokenIdToAddress(collection, targetToken)}), collection, newToken, 1,352        ),353      ), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);354      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});355    });356  });357358  // ---------- Fungible ----------359360  it('Fungible: disallows to nest token if nesting is disabled', async () => {361    await usingApi(async api => {362      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});363      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Disabled'});364      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');365      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};366367      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});368369      // Try to create a nested token370      await expect(executeTransaction(371        api, alice, 372        api.tx.unique.createItem(373          collectionFT, 374          targetAddress, 375          {Fungible: {Value: 10}},376        )377      ), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);378379      // Create a token to be nested380      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');381      // Try to nest382      await expect(executeTransaction(383        api, alice, 384        api.tx.unique.transfer(385          normalizeAccountId({Ethereum: tokenIdToAddress(collectionFT, targetToken)}), collectionFT, newToken, 1,386        ),387      ), 'while nesting new token').to.be.rejectedWith(/fungible\.FungibleDisallowsNesting/);388    });389  });390391  it('Fungible: disallows a non-Owner to nest someone else\'s token', async () => {392    await usingApi(async api => {393      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});394      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});395396      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);397      await enableAllowListExpectSuccess(alice, collectionNFT);398      await enablePublicMintingExpectSuccess(alice, collectionNFT);399400      // Create a token to attempt to be nested into401      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');402      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};403404      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});405406      // Try to create a nested token in the wrong collection407      await expect(executeTransaction(408        api, alice, 409        api.tx.unique.createItem(410          collectionFT, 411          targetAddress, 412          {Fungible: {Value: 10}},413        )414      ), 'while creating nested token').to.be.rejectedWith(/structure\.DepthLimit/);415416      // Try to create and nest a token in the wrong collection417      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');418      await expect(executeTransaction(419        api, alice, 420        api.tx.unique.transfer(421          normalizeAccountId({Ethereum: tokenIdToAddress(collectionFT, targetToken)}), collectionFT, newToken, 1,422        ),423      ), 'while nesting new token').to.be.rejectedWith(/fungible\.FungibleDisallowsNesting/);424    });425  });426427  it('Fungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {428    await usingApi(async api => {429      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});430      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionNFT]}}); // todo clear redundant restrictions?431432      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);433      await enableAllowListExpectSuccess(alice, collectionNFT);434      await enablePublicMintingExpectSuccess(alice, collectionNFT);435436      // Create a token to attempt to be nested into437      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');438      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};439440      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});441442      // Try to create a nested token in the wrong collection443      await expect(executeTransaction(api, alice, api.tx.unique.createItem(444        collectionFT, 445        targetAddress, 446        {Fungible: {Value: 10}},447      ))).to.be.rejected;448449      // Try to create and nest a token in the wrong collection450      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');451      await transferExpectFailure(collectionFT, newToken, alice, targetAddress, 1);452    });453  });454455  it('Fungible: disallows to nest token in an unlisted collection', async () => {456    await usingApi(async api => {457      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});458      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[]}});459460      // Create a token to attempt to be nested into461      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');462      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};463464      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});465466      // Try to create a nested token in the wrong collection467      await expect(executeTransaction(api, alice, api.tx.unique.createItem(468        collectionFT, 469        targetAddress, 470        {Fungible: {Value: 10}},471      ))).to.be.rejected;472473      // Try to create and nest a token in the wrong collection474      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');475      await transferExpectFailure(collectionFT, newToken, alice, targetAddress, 1);476    });477  });478479  // ---------- Re-Fungible ----------480481  it('ReFungible: disallows to nest token if nesting is disabled', async () => {482    await usingApi(async api => {483      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});484      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Disabled'});485      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');486      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};487488      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});489490      // Create a nested token491      await expect(executeTransaction(api, alice, api.tx.unique.createItem(492        collectionRFT, 493        targetAddress, 494        {ReFungible: {const_data: [], pieces: 100}},495      ))).to.be.rejectedWith(/^common\.NestingIsDisabled$/);496497      // Create a token to be nested498      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');499      // Try to nest500      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);501    });502  });503504  it('ReFungible: disallows a non-Owner to nest someone else\'s token', async () => {505    await usingApi(async api => {506      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});507      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});508509      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);510      await enableAllowListExpectSuccess(alice, collectionNFT);511      await enablePublicMintingExpectSuccess(alice, collectionNFT);512513      // Create a token to attempt to be nested into514      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');515      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};516517      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});518519      // Try to create a nested token in the wrong collection520      await expect(executeTransaction(api, alice, api.tx.unique.createItem(521        collectionRFT, 522        targetAddress, 523        {ReFungible: {const_data: [], pieces: 100}},524      ))).to.be.rejected;525526      // Try to create and nest a token in the wrong collection527      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');528      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);529    });530  });531532  it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {533    await usingApi(async api => {534      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});535      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionNFT]}});536537      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);538      await enableAllowListExpectSuccess(alice, collectionNFT);539      await enablePublicMintingExpectSuccess(alice, collectionNFT);540541      // Create a token to attempt to be nested into542      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');543      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};544545      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});546547      // Try to create a nested token in the wrong collection548      await expect(executeTransaction(api, alice, api.tx.unique.createItem(549        collectionRFT, 550        targetAddress, 551        {ReFungible: {const_data: [], pieces: 100}},552      ))).to.be.rejected;553554      // Try to create and nest a token in the wrong collection555      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');556      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);557    });558  });559560  it('ReFungible: disallows to nest token to an unlisted collection', async () => {561    await usingApi(async api => {562      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});563      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[]}});564565      // Create a token to attempt to be nested into566      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');567      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};568569      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});570571      // Try to create a nested token in the wrong collection572      await expect(executeTransaction(api, alice, api.tx.unique.createItem(573        collectionRFT, 574        targetAddress, 575        {ReFungible: {const_data: [], pieces: 100}},576      ))).to.be.rejected;577578      // Try to create and nest a token in the wrong collection579      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');580      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);581    });582  });583});
after · tests/src/nesting/nest.test.ts
1import {expect} from 'chai';2import {tokenIdToAddress} from '../eth/util/helpers';3import privateKey from '../substrate/privateKey';4import usingApi, {executeTransaction} from '../substrate/substrate-api';5import {6  addToAllowListExpectSuccess,7  createCollectionExpectSuccess,8  createItemExpectSuccess,9  enableAllowListExpectSuccess,10  enablePublicMintingExpectSuccess,11  getTokenOwner, 12  getTopmostTokenOwner,13  setCollectionLimitsExpectSuccess, 14  transferExpectFailure, 15  transferExpectSuccess, 16  transferFromExpectSuccess,17} from '../util/helpers';18import {IKeyringPair} from '@polkadot/types/types';1920let alice: IKeyringPair;21let bob: IKeyringPair;2223describe('Integration Test: Nesting', () => {24  before(async () => {25    await usingApi(async () => {26      alice = privateKey('//Alice');27      bob = privateKey('//Bob');28    });29  });3031  it('Performs the full suite: bundles a token, transfers, and allows to unnest', async () => {32    await usingApi(async api => {33      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});34      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});35      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');3637      // Create a nested token38      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});39      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});40      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});4142      // Create a token to be nested43      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');44      45      // Nest46      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});47      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});48      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});4950      // Move bundle to different user51      await transferExpectSuccess(collection, targetToken, alice, {Substrate: bob.address});52      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: bob.address});53      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});5455      // Unnest56      await transferFromExpectSuccess(collection, newToken, bob, {Ethereum: tokenIdToAddress(collection, targetToken)}, {Substrate: bob.address});57      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: bob.address});58    });59  });6061  // ---------- Non-Fungible ----------6263  it('NFT: allows an Owner to nest/unnest their token', async () => {64    await usingApi(async api => {65      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});66      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});67      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');6869      // Create a nested token70      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});71      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});72      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});7374      // Create a token to be nested and nest75      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');76      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});77      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});78      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});79    });80  });8182  it('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {83    await usingApi(async api => {84      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});85      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: {OwnerRestricted:[collection]}});86      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');8788      // Create a nested token89      const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});90      expect(await getTopmostTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});91      expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});9293      // Create a token to be nested and nest94      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');95      await transferExpectSuccess(collection, newToken, alice, {Ethereum: tokenIdToAddress(collection, targetToken)});96      expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});97      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});98    });99  });100101  // ---------- Fungible ----------102103  it('Fungible: allows an Owner to nest/unnest their token', async () => {104    await usingApi(async api => {105      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});106      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});107      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});108      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};109110      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});111112      // Create a nested token113      await expect(executeTransaction(api, alice, api.tx.unique.createItem(114        collectionFT, 115        targetAddress, 116        {Fungible: {Value: 10}},117      ))).to.not.be.rejected;118119      // Nest a new token120      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');121      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');122    });123  });124125  it('Fungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {126    await usingApi(async api => {127      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});128      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});129      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};130131      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});132133      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionFT]}});134135      // Create a nested token136      await expect(executeTransaction(api, alice, api.tx.unique.createItem(137        collectionFT, 138        targetAddress, 139        {Fungible: {Value: 10}},140      ))).to.not.be.rejected;141142      // Nest a new token143      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');144      await transferExpectSuccess(collectionFT, newToken, alice, targetAddress, 1, 'Fungible');145    });146  });147148  // ---------- Re-Fungible ----------149150  it('ReFungible: allows an Owner to nest/unnest their token', async () => {151    await usingApi(async api => {152      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});153      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});154      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});155      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};156157      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});158159      // Create a nested token160      await expect(executeTransaction(api, alice, api.tx.unique.createItem(161        collectionRFT, 162        targetAddress, 163        {ReFungible: {const_data: [], pieces: 100}},164      ))).to.not.be.rejected;165166      // Nest a new token167      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');168      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');169    });170  });171172  it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {173    await usingApi(async api => {174      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});175      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});176      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};177178      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});179180      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionRFT]}});181182      // Create a nested token183      await expect(executeTransaction(api, alice, api.tx.unique.createItem(184        collectionRFT, 185        targetAddress,186        {ReFungible: {const_data: [], pieces: 100}},187      ))).to.not.be.rejected;188189      // Nest a new token190      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');191      await transferExpectSuccess(collectionRFT, newToken, alice, targetAddress, 100, 'ReFungible');192    });193  });194});195196describe('Negative Test: Nesting', async() => {197  before(async () => {198    await usingApi(async () => {199      alice = privateKey('//Alice');200      bob = privateKey('//Bob');201    });202  });203204  it('Disallows excessive token nesting', async () => {205    await usingApi(async api => {206      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});207      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});208      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');209210      // Create a nested-token matryoshka211      const nestedToken1 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});212      const nestedToken2 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, nestedToken1)});213      // The nesting depth is limited by 2214      await expect(executeTransaction(api, alice, api.tx.unique.createItem(215        collection, 216        {Ethereum: tokenIdToAddress(collection, nestedToken2)}, 217          {nft: {const_data: [], variable_data: []}} as any,218      )), 'while creating nested token').to.be.rejectedWith(/^structure\.DepthLimit$/);219220      expect(await getTopmostTokenOwner(api, collection, nestedToken2)).to.be.deep.equal({Substrate: alice.address});221    });222  });223224  // ---------- Non-Fungible ----------225226  it('NFT: disallows to nest token if nesting is disabled', async () => {227    await usingApi(async api => {228      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});229      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Disabled'});230      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');231232      // Try to create a nested token233      await expect(executeTransaction(api, alice, api.tx.unique.createItem(234        collection, 235        {Ethereum: tokenIdToAddress(collection, targetToken)}, 236          {nft: {const_data: [], variable_data: []}} as any,237      )), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);238239      // Create a token to be nested240      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');241      // Try to nest242      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/);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({Substrate: alice.address});245    });246  });247248  it('NFT: disallows a non-Owner to nest someone else\'s token', async () => {249    await usingApi(async api => {250      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});251      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});252253      await addToAllowListExpectSuccess(alice, collection, bob.address);254      await enableAllowListExpectSuccess(alice, collection);255      await enablePublicMintingExpectSuccess(alice, collection);256257      // Create a token to attempt to be nested into258      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');259260      // Try to create a nested token in the wrong collection261      await expect(executeTransaction(api, alice, api.tx.unique.createItem(262        collection, 263        {Ethereum: tokenIdToAddress(collection, targetToken)}, 264          {nft: {const_data: [], variable_data: []}} as any,265      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);266267      // Try to create and nest a token in the wrong collection268      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');269      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/);270      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});271    });272  });273274  it('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {275    await usingApi(async api => {276      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});277      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: {OwnerRestricted:[collection]}});278279      await addToAllowListExpectSuccess(alice, collection, bob.address);280      await enableAllowListExpectSuccess(alice, collection);281      await enablePublicMintingExpectSuccess(alice, collection);282283      // Create a token to attempt to be nested into284      const targetToken = await createItemExpectSuccess(bob, collection, 'NFT');285286      // Try to create a nested token in the wrong collection287      await expect(executeTransaction(api, alice, api.tx.unique.createItem(288        collection, 289        {Ethereum: tokenIdToAddress(collection, targetToken)}, 290          {nft: {const_data: [], variable_data: []}} as any,291      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);292293      // Try to create and nest a token in the wrong collection294      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');295      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/);296      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});297    });298  });299300  it('NFT: disallows to nest token in an unlisted collection', async () => {301    await usingApi(async api => {302      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});303      await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: {OwnerRestricted:[]}});304305      // Create a token to attempt to be nested into306      const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');307308      // Try to create a nested token in the wrong collection309      await expect(executeTransaction(api, alice, api.tx.unique.createItem(310        collection, 311        {Ethereum: tokenIdToAddress(collection, targetToken)}, 312          {nft: {const_data: [], variable_data: []}} as any,313      )), 'while creating nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);314315      // Try to create and nest a token in the wrong collection316      const newToken = await createItemExpectSuccess(alice, collection, 'NFT');317      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/);318      expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});319    });320  });321322  // ---------- Fungible ----------323324  it('Fungible: disallows to nest token if nesting is disabled', async () => {325    await usingApi(async api => {326      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});327      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Disabled'});328      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');329      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};330331      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});332333      // Try to create a nested token334      await expect(executeTransaction(api, alice, api.tx.unique.createItem(335        collectionFT, 336        targetAddress, 337        {Fungible: {Value: 10}},338      )), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);339      340      // Create a token to be nested341      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');342      // Try to nest343      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);344345      // Create another token to be nested346      const newToken2 = await createItemExpectSuccess(alice, collectionFT, 'Fungible');347      // Try to nest inside a fungible token348      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/);349    });350  });351352  it('Fungible: disallows a non-Owner to nest someone else\'s token', async () => {353    await usingApi(async api => {354      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});355      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});356357      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);358      await enableAllowListExpectSuccess(alice, collectionNFT);359      await enablePublicMintingExpectSuccess(alice, collectionNFT);360361      // Create a token to attempt to be nested into362      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');363      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};364365      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});366367      // Try to create a nested token in the wrong collection368      await expect(executeTransaction(api, alice, api.tx.unique.createItem(369        collectionFT, 370        targetAddress, 371        {Fungible: {Value: 10}},372      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);373374      // Try to create and nest a token in the wrong collection375      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');376      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);377    });378  });379380  it('Fungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {381    await usingApi(async api => {382      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});383      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);384      await enableAllowListExpectSuccess(alice, collectionNFT);385      await enablePublicMintingExpectSuccess(alice, collectionNFT);386387      // Create a token to attempt to be nested into388      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');389      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};390391      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});392      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionFT]}});393394      // Try to create a nested token in the wrong collection395      await expect(executeTransaction(api, alice, api.tx.unique.createItem(396        collectionFT, 397        targetAddress, 398        {Fungible: {Value: 10}},399      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);400401      // Try to create and nest a token in the wrong collection402      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');403      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);404    });405  });406407  it('Fungible: disallows to nest token in an unlisted collection', async () => {408    await usingApi(async api => {409      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});410      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[]}});411412      // Create a token to attempt to be nested into413      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');414      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};415416      const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});417418      // Try to create a nested token in the wrong collection419      await expect(executeTransaction(api, alice, api.tx.unique.createItem(420        collectionFT, 421        targetAddress, 422        {Fungible: {Value: 10}},423      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);424425      // Try to create and nest a token in the wrong collection426      const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');427      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);428    });429  });430431  // ---------- Re-Fungible ----------432433  it('ReFungible: disallows to nest token if nesting is disabled', async () => {434    await usingApi(async api => {435      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});436      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Disabled'});437      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');438      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};439440      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});441442      // Create a nested token443      await expect(executeTransaction(api, alice, api.tx.unique.createItem(444        collectionRFT, 445        targetAddress, 446        {ReFungible: {const_data: [], pieces: 100}},447      )), 'while creating a nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);448449      // Create a token to be nested450      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');451      // Try to nest452      await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);453      // Try to nest454      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);455456      // Create another token to be nested457      const newToken2 = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');458      // Try to nest inside a fungible token459      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/);460    });461  });462463  it('ReFungible: disallows a non-Owner to nest someone else\'s token', async () => {464    await usingApi(async api => {465      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});466      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: 'Owner'});467468      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);469      await enableAllowListExpectSuccess(alice, collectionNFT);470      await enablePublicMintingExpectSuccess(alice, collectionNFT);471472      // Create a token to attempt to be nested into473      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');474      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};475476      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});477478      // Try to create a nested token in the wrong collection479      await expect(executeTransaction(api, alice, api.tx.unique.createItem(480        collectionRFT, 481        targetAddress, 482        {ReFungible: {const_data: [], pieces: 100}},483      )), 'while creating a nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);484485      // Try to create and nest a token in the wrong collection486      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');487      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);488    });489  });490491  it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {492    await usingApi(async api => {493      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});494      await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);495      await enableAllowListExpectSuccess(alice, collectionNFT);496      await enablePublicMintingExpectSuccess(alice, collectionNFT);497498      // Create a token to attempt to be nested into499      const targetToken = await createItemExpectSuccess(bob, collectionNFT, 'NFT');500      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};501502      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});503      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[collectionRFT]}});504505      // Try to create a nested token in the wrong collection506      await expect(executeTransaction(api, alice, api.tx.unique.createItem(507        collectionRFT, 508        targetAddress, 509        {ReFungible: {const_data: [], pieces: 100}},510      )), 'while creating a nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);511512      // Try to create and nest a token in the wrong collection513      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');514      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);515    });516  });517518  it('ReFungible: disallows to nest token to an unlisted collection', async () => {519    await usingApi(async api => {520      const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});521      await setCollectionLimitsExpectSuccess(alice, collectionNFT, {nestingRule: {OwnerRestricted:[]}});522523      // Create a token to attempt to be nested into524      const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');525      const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};526527      const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});528529      // Try to create a nested token in the wrong collection530      await expect(executeTransaction(api, alice, api.tx.unique.createItem(531        collectionRFT, 532        targetAddress, 533        {ReFungible: {const_data: [], pieces: 100}},534      )), 'while creating a nested token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);535536      // Try to create and nest a token in the wrong collection537      const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');538      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);539    });540  });541});
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);