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

difftreelog

tests(nesting): refactor naming conventions for token addresses

Fahrrader2022-09-23parent: #378c38c.patch.diff
in: master

7 files changed

modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -240,7 +240,7 @@
   }
 
   fromTokenId(collectionId: number, tokenId: number): string  {
-    return this.helper.util.getNestingTokenAddressRaw({collectionId, tokenId});
+    return this.helper.util.getTokenAddress({collectionId, tokenId});
   }
 
   normalizeAddress(address: string): string {
modifiedtests/src/nesting/graphs.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/graphs.test.ts
+++ b/tests/src/nesting/graphs.test.ts
@@ -64,7 +64,7 @@
       'second transaction',
     ).to.be.rejectedWith(/structure\.OuroborosDetected/);
     await expect(
-      tokens[1].transferFrom(alice, tokens[0].nestingAddress(), tokens[7].nestingAddress()),
+      tokens[1].transferFrom(alice, tokens[0].nestingAccount(), tokens[7].nestingAccount()),
       'third transaction',
     ).to.be.rejectedWith(/structure\.OuroborosDetected/);
   });
modifiedtests/src/nesting/nest.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/nest.test.ts
+++ b/tests/src/nesting/nest.test.ts
@@ -33,9 +33,9 @@
     const targetToken = await collection.mintToken(alice);
 
     // Create an immediately nested token
-    const nestedToken = await collection.mintToken(alice, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
     
     // Create a token to be nested
     const newToken = await collection.mintToken(alice);
@@ -43,14 +43,14 @@
     // Nest
     await newToken.nest(alice, targetToken);
     expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
-    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Move bundle to different user
     await targetToken.transfer(alice, {Substrate: bob.address});
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
     expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});
-    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Unnest
     await newToken.unnest(bob, targetToken, {Substrate: bob.address});
@@ -64,13 +64,13 @@
     const tokenB = await collection.mintToken(alice);
 
     // Create a nested token
-    const tokenC = await collection.mintToken(alice, tokenA.nestingAddress());
-    expect(await tokenC.getOwner()).to.be.deep.equal(tokenA.nestingAddress());
+    const tokenC = await collection.mintToken(alice, tokenA.nestingAccount());
+    expect(await tokenC.getOwner()).to.be.deep.equal(tokenA.nestingAccount());
     
     // Transfer the nested token to another token
-    await expect(tokenC.transferFrom(alice, tokenA.nestingAddress(), tokenB.nestingAddress())).to.be.fulfilled;
+    await expect(tokenC.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount())).to.be.fulfilled;
     expect(await tokenC.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
-    expect(await tokenC.getOwner()).to.be.deep.equal(tokenB.nestingAddress());
+    expect(await tokenC.getOwner()).to.be.deep.equal(tokenB.nestingAccount());
   });
 
   itSub('Checks token children', async ({helper}) => {
@@ -81,7 +81,7 @@
     expect((await targetToken.getChildren()).length).to.be.equal(0, 'Children length check at creation');
 
     // Create a nested NFT token
-    const tokenA = await collectionA.mintToken(alice, targetToken.nestingAddress());
+    const tokenA = await collectionA.mintToken(alice, targetToken.nestingAccount());
     expect(await targetToken.getChildren()).to.have.deep.members([
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
     ], 'Children contents check at nesting #1').and.be.length(1, 'Children length check at nesting #1');
@@ -102,7 +102,7 @@
 
     // Create a fungible token in another collection and then nest
     await collectionB.mint(alice, 10n);
-    await collectionB.transfer(alice, targetToken.nestingAddress(), 2n);
+    await collectionB.transfer(alice, targetToken.nestingAccount(), 2n);
     expect(await targetToken.getChildren()).to.be.have.deep.members([
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
       {tokenId: 0, collectionId: collectionB.collectionId},
@@ -110,7 +110,7 @@
       .and.be.length(2, 'Children length check at nesting #4 (from another collection)');
     
     // Move part of the fungible token inside token A deeper in the nesting tree
-    await collectionB.transferFrom(alice, targetToken.nestingAddress(), tokenA.nestingAddress(), 1n);
+    await collectionB.transferFrom(alice, targetToken.nestingAccount(), tokenA.nestingAccount(), 1n);
     expect(await targetToken.getChildren()).to.be.have.deep.members([
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
       {tokenId: 0, collectionId: collectionB.collectionId},
@@ -120,7 +120,7 @@
     ], 'Children contents check at nesting #5.5 (deeper)').and.be.length(1, 'Children length check at nesting #5.5 (deeper)');
 
     // Move the remaining part of the fungible token inside token A deeper in the nesting tree
-    await collectionB.transferFrom(alice, targetToken.nestingAddress(), tokenA.nestingAddress(), 1n);
+    await collectionB.transferFrom(alice, targetToken.nestingAccount(), tokenA.nestingAccount(), 1n);
     expect(await targetToken.getChildren()).to.be.have.deep.members([
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
     ], 'Children contents check at nesting #6 (deeper)').and.be.length(1, 'Children length check at nesting #6 (deeper)');
@@ -148,15 +148,15 @@
     const targetToken = await collection.mintToken(alice, {Substrate: charlie.address});
 
     // Create an immediately nested token
-    const nestedToken = await collection.mintToken(bob, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Create a token to be nested and nest
     const newToken = await collection.mintToken(bob);
     await newToken.nest(bob, targetToken);
     expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
   });
 
   itSub('Admin (NFT): Admin and Token Owner can operate together', async ({helper}) => {
@@ -165,15 +165,15 @@
     const targetToken = await collection.mintToken(alice, {Substrate: charlie.address});
 
     // Create an immediately nested token by an administrator
-    const nestedToken = await collection.mintToken(bob, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Create a token to be nested and nest
     const newToken = await collection.mintToken(alice, {Substrate: charlie.address});
     await newToken.nest(charlie, targetToken);
     expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
   });
 
   itSub('Admin (NFT): allows an Admin to nest a token (Restricted nesting)', async ({helper}) => {
@@ -185,15 +185,15 @@
     const targetToken = await collectionA.mintToken(alice, {Substrate: charlie.address});
 
     // Create an immediately nested token
-    const nestedToken = await collectionB.mintToken(bob, targetToken.nestingAddress());
+    const nestedToken = await collectionB.mintToken(bob, targetToken.nestingAccount());
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Create a token to be nested and nest
     const newToken = await collectionB.mintToken(bob);
     await newToken.nest(bob, targetToken);
     expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
   });
 
   // ---------- Non-Fungible ----------
@@ -202,18 +202,18 @@
     const collection = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}}});
     await collection.addToAllowList(alice, {Substrate: charlie.address});
     const targetToken = await collection.mintToken(charlie);
-    await collection.addToAllowList(alice, targetToken.nestingAddress());
+    await collection.addToAllowList(alice, targetToken.nestingAccount());
 
     // Create an immediately nested token
-    const nestedToken = await collection.mintToken(charlie, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(charlie, targetToken.nestingAccount());
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Create a token to be nested and nest
     const newToken = await collection.mintToken(charlie);
     await newToken.nest(charlie, targetToken);
     expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
   });
 
   itSub('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {
@@ -224,22 +224,22 @@
 
     await collectionA.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true, restricted:[collectionB.collectionId]}});
     await collectionA.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionA.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionA.addToAllowList(alice, targetToken.nestingAccount());
 
     await collectionB.setPermissions(alice, {access: 'AllowList', mintMode: true});
     await collectionB.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionB.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionB.addToAllowList(alice, targetToken.nestingAccount());
 
     // Create an immediately nested token
-    const nestedToken = await collectionB.mintToken(charlie, targetToken.nestingAddress());
+    const nestedToken = await collectionB.mintToken(charlie, targetToken.nestingAccount());
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Create a token to be nested and nest
     const newToken = await collectionB.mintToken(charlie);
     await newToken.nest(charlie, targetToken);
     expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
-    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
   });
 
   // ---------- Fungible ----------
@@ -250,20 +250,20 @@
     const targetToken = await collectionNFT.mintToken(alice, {Substrate: charlie.address});
 
     await collectionNFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionNFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
 
     await collectionFT.setPermissions(alice, {access: 'AllowList', mintMode: true});
     await collectionFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionFT.addToAllowList(alice, targetToken.nestingAccount());
 
     // Create an immediately nested token
-    await collectionFT.mint(charlie, 5n, targetToken.nestingAddress());
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(5n);
+    await collectionFT.mint(charlie, 5n, targetToken.nestingAccount());
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
 
     // Create a token to be nested and nest
     await collectionFT.mint(charlie, 5n);
-    await collectionFT.transfer(charlie, targetToken.nestingAddress(), 2n);
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(7n);
+    await collectionFT.transfer(charlie, targetToken.nestingAccount(), 2n);
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(7n);
   });
 
   itSub('Fungible: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {
@@ -273,20 +273,20 @@
 
     await collectionNFT.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true, restricted:[collectionFT.collectionId]}});
     await collectionNFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionNFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
 
     await collectionFT.setPermissions(alice, {access: 'AllowList', mintMode: true});
     await collectionFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionFT.addToAllowList(alice, targetToken.nestingAccount());
 
     // Create an immediately nested token
-    await collectionFT.mint(charlie, 5n, targetToken.nestingAddress());
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(5n);
+    await collectionFT.mint(charlie, 5n, targetToken.nestingAccount());
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
 
     // Create a token to be nested and nest
     await collectionFT.mint(charlie, 5n);
-    await collectionFT.transfer(charlie, targetToken.nestingAddress(), 2n);
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(7n);
+    await collectionFT.transfer(charlie, targetToken.nestingAccount(), 2n);
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(7n);
   });
 
   // ---------- Re-Fungible ----------
@@ -297,20 +297,20 @@
     const targetToken = await collectionNFT.mintToken(alice, {Substrate: charlie.address});
 
     await collectionNFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionNFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
 
     await collectionRFT.setPermissions(alice, {access: 'AllowList', mintMode: true});
     await collectionRFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionRFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionRFT.addToAllowList(alice, targetToken.nestingAccount());
 
     // Create an immediately nested token
-    const nestedToken = await collectionRFT.mintToken(charlie, 5n, targetToken.nestingAddress());
-    expect(await nestedToken.getBalance(targetToken.nestingAddress())).to.be.equal(5n);
+    const nestedToken = await collectionRFT.mintToken(charlie, 5n, targetToken.nestingAccount());
+    expect(await nestedToken.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
 
     // Create a token to be nested and nest
     const newToken = await collectionRFT.mintToken(charlie, 5n);
-    await newToken.transfer(charlie, targetToken.nestingAddress(), 2n);
-    expect(await newToken.getBalance(targetToken.nestingAddress())).to.be.equal(2n);
+    await newToken.transfer(charlie, targetToken.nestingAccount(), 2n);
+    expect(await newToken.getBalance(targetToken.nestingAccount())).to.be.equal(2n);
   });
 
   itSub.ifWithPallets('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', [Pallets.ReFungible], async ({helper}) => {
@@ -320,20 +320,20 @@
 
     await collectionNFT.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true, restricted:[collectionRFT.collectionId]}});
     await collectionNFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionNFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
 
     await collectionRFT.setPermissions(alice, {access: 'AllowList', mintMode: true});
     await collectionRFT.addToAllowList(alice, {Substrate: charlie.address});
-    await collectionRFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionRFT.addToAllowList(alice, targetToken.nestingAccount());
 
     // Create an immediately nested token
-    const nestedToken = await collectionRFT.mintToken(charlie, 5n, targetToken.nestingAddress());
-    expect(await nestedToken.getBalance(targetToken.nestingAddress())).to.be.equal(5n);
+    const nestedToken = await collectionRFT.mintToken(charlie, 5n, targetToken.nestingAccount());
+    expect(await nestedToken.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
 
     // Create a token to be nested and nest
     const newToken = await collectionRFT.mintToken(charlie, 5n);
-    await newToken.transfer(charlie, targetToken.nestingAddress(), 2n);
-    expect(await newToken.getBalance(targetToken.nestingAddress())).to.be.equal(2n);
+    await newToken.transfer(charlie, targetToken.nestingAccount(), 2n);
+    expect(await newToken.getBalance(targetToken.nestingAccount())).to.be.equal(2n);
   });
 });
 
@@ -356,11 +356,11 @@
 
     // Create a nested-token matryoshka
     for (let i = 0; i < maxNestingLevel; i++) {
-      token = await collection.mintToken(alice, token.nestingAddress());
+      token = await collection.mintToken(alice, token.nestingAccount());
     }
 
     // The nesting depth is limited by `maxNestingLevel`
-    await expect(collection.mintToken(alice, token.nestingAddress()))
+    await expect(collection.mintToken(alice, token.nestingAccount()))
       .to.be.rejectedWith(/structure\.DepthLimit/);
     expect(await token.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
     expect(await token.getChildren()).to.be.length(0);
@@ -374,7 +374,7 @@
     const targetToken = await collection.mintToken(alice);
 
     // Try to create an immediately nested token as collection admin when it's disallowed
-    await expect(collection.mintToken(bob, targetToken.nestingAddress()))
+    await expect(collection.mintToken(bob, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
     // Try to create a token to be nested and nest
@@ -390,10 +390,10 @@
     const collection = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true, nesting: {collectionAdmin: true}}});
     const targetToken = await collection.mintToken(alice, {Substrate: bob.address});
     await collection.addToAllowList(alice, {Substrate: bob.address});
-    await collection.addToAllowList(alice, targetToken.nestingAddress());
+    await collection.addToAllowList(alice, targetToken.nestingAccount());
 
     // Try to create a nested token as token owner when it's disallowed
-    await expect(collection.mintToken(bob, targetToken.nestingAddress()))
+    await expect(collection.mintToken(bob, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
     // Try to create a token to be nested and nest
@@ -410,7 +410,7 @@
     //await collection.addAdmin(alice, {Substrate: bob.address});
     const targetToken = await collection.mintToken(alice, {Substrate: bob.address});
     await collection.addToAllowList(alice, {Substrate: bob.address});
-    await collection.addToAllowList(alice, targetToken.nestingAddress());
+    await collection.addToAllowList(alice, targetToken.nestingAccount());
 
     // Try to nest somebody else's token
     const newToken = await collection.mintToken(bob);
@@ -418,13 +418,13 @@
       .to.be.rejectedWith(/common\.NoPermission/);
 
     // Try to unnest a token belonging to someone else as collection admin
-    const nestedToken = await collection.mintToken(alice, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());
     await expect(nestedToken.unnest(alice, targetToken, {Substrate: bob.address}))
       .to.be.rejectedWith(/common\.AddressNotInAllowlist/);
 
     expect(await targetToken.getChildren()).to.be.length(1);
     expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
   });
 
   itSub('Admin (NFT): disallows an Admin to nest a token from an unlisted collection (Restricted nesting)', async ({helper}) => {
@@ -434,7 +434,7 @@
     const targetToken = await collectionA.mintToken(alice);
 
     // Try to create a nested token from another collection
-    await expect(collectionB.mintToken(alice, targetToken.nestingAddress()))
+    await expect(collectionB.mintToken(alice, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
 
     // Create a token in another collection yet to be nested and try to nest
@@ -454,7 +454,7 @@
     const targetToken = await collection.mintToken(alice);
 
     // Try to create a nested token as token owner when it's disallowed
-    await expect(collection.mintToken(alice, targetToken.nestingAddress()))
+    await expect(collection.mintToken(alice, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
     // Try to create a token to be nested and nest
@@ -472,7 +472,7 @@
 
     await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}});
     await collection.addToAllowList(alice, {Substrate: bob.address});
-    await collection.addToAllowList(alice, targetToken.nestingAddress());
+    await collection.addToAllowList(alice, targetToken.nestingAccount());
 
     // Try to create a token to be nested and nest
     const newToken = await collection.mintToken(alice);
@@ -488,11 +488,11 @@
 
     await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}});
     await collection.addToAllowList(alice, {Substrate: bob.address});
-    await collection.addToAllowList(alice, targetToken.nestingAddress());
+    await collection.addToAllowList(alice, targetToken.nestingAccount());
 
     const collectionB = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true}});
     await collectionB.addToAllowList(alice, {Substrate: bob.address});
-    await collectionB.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionB.addToAllowList(alice, targetToken.nestingAccount());
 
     // Try to create a token to be nested and nest
     const newToken = await collectionB.mintToken(alice);
@@ -508,10 +508,10 @@
     const targetToken = await collection.mintToken(alice, {Substrate: bob.address});
 
     await collection.addToAllowList(alice, {Substrate: bob.address});
-    await collection.addToAllowList(alice, targetToken.nestingAddress());
+    await collection.addToAllowList(alice, targetToken.nestingAccount());
 
     // Try to mint in own collection after allowlisting the accounts
-    await expect(collection.mintToken(bob, targetToken.nestingAddress()))
+    await expect(collection.mintToken(bob, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
   });
 
@@ -523,12 +523,12 @@
     const targetToken = await collectionNFT.mintToken(alice);
 
     // Try to create an immediately nested token
-    await expect(collectionFT.mint(alice, 5n, targetToken.nestingAddress()))
+    await expect(collectionFT.mint(alice, 5n, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
     // Try to create a token to be nested and nest
     await collectionFT.mint(alice, 5n);
-    await expect(collectionFT.transfer(alice, targetToken.nestingAddress(), 2n))
+    await expect(collectionFT.transfer(alice, targetToken.nestingAccount(), 2n))
       .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
     expect(await collectionFT.getBalance({Substrate: alice.address})).to.be.equal(5n);
   });
@@ -539,12 +539,12 @@
     const targetToken = await collectionNFT.mintToken(alice, {Substrate: bob.address});
 
     // Nest some tokens as Alice into Bob's token
-    await collectionFT.mint(alice, 5n, targetToken.nestingAddress());
+    await collectionFT.mint(alice, 5n, targetToken.nestingAccount());
 
     // Try to pull it out
-    await expect(collectionFT.transferFrom(alice, targetToken.nestingAddress(), {Substrate: bob.address}, 1n))
+    await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: bob.address}, 1n))
       .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(5n);
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
   });
 
   itSub('Fungible: disallows a non-Owner to unnest someone else\'s token (Restricted nesting)', async ({helper}) => {
@@ -555,12 +555,12 @@
     await collectionNFT.setPermissions(alice, {nesting: {collectionAdmin: true, tokenOwner: true, restricted: [collectionFT.collectionId]}});
 
     // Nest some tokens as Alice into Bob's token
-    await collectionFT.mint(alice, 5n, targetToken.nestingAddress());
+    await collectionFT.mint(alice, 5n, targetToken.nestingAccount());
 
     // Try to pull it out as Alice still
-    await expect(collectionFT.transferFrom(alice, targetToken.nestingAddress(), {Substrate: bob.address}, 1n))
+    await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: bob.address}, 1n))
       .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(5n);
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
   });
 
   itSub('Fungible: disallows to nest token in an unlisted collection', async ({helper}) => {
@@ -569,15 +569,15 @@
     const targetToken = await collectionNFT.mintToken(alice);
 
     // Try to mint an immediately nested token
-    await expect(collectionFT.mint(alice, 5n, targetToken.nestingAddress()))
+    await expect(collectionFT.mint(alice, 5n, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
 
     // Mint a token and try to nest it
     await collectionFT.mint(alice, 5n);
-    await expect(collectionFT.transfer(alice, targetToken.nestingAddress(), 1n))
+    await expect(collectionFT.transfer(alice, targetToken.nestingAccount(), 1n))
       .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
 
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(0n);
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(0n);
     expect(await collectionFT.getBalance({Substrate: alice.address})).to.be.equal(5n);
   });
 
@@ -589,12 +589,12 @@
     const targetToken = await collectionNFT.mintToken(alice);
 
     // Try to create an immediately nested token
-    await expect(collectionRFT.mintToken(alice, 5n, targetToken.nestingAddress()))
+    await expect(collectionRFT.mintToken(alice, 5n, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
     // Try to create a token to be nested and nest
     const token = await collectionRFT.mintToken(alice, 5n);
-    await expect(token.transfer(alice, targetToken.nestingAddress(), 2n))
+    await expect(token.transfer(alice, targetToken.nestingAccount(), 2n))
       .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
     expect(await token.getBalance({Substrate: alice.address})).to.be.equal(5n);
   });
@@ -606,22 +606,22 @@
 
     await collectionNFT.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}});
     await collectionNFT.addToAllowList(alice, {Substrate: bob.address});
-    await collectionNFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
 
     // Try to create a token to be nested and nest
     const newToken = await collectionRFT.mintToken(alice);
-    await expect(newToken.transfer(bob, targetToken.nestingAddress())).to.be.rejectedWith(/common\.TokenValueTooLow/);
+    await expect(newToken.transfer(bob, targetToken.nestingAccount())).to.be.rejectedWith(/common\.TokenValueTooLow/);
 
     expect(await targetToken.getChildren()).to.be.length(0);
     expect(await newToken.getBalance({Substrate: alice.address})).to.be.equal(1n);
 
     // Nest some tokens as Alice into Bob's token
-    await newToken.transfer(alice, targetToken.nestingAddress());
+    await newToken.transfer(alice, targetToken.nestingAccount());
 
     // Try to pull it out
-    await expect(newToken.transferFrom(bob, targetToken.nestingAddress(), {Substrate: alice.address}, 1n))
+    await expect(newToken.transferFrom(bob, targetToken.nestingAccount(), {Substrate: alice.address}, 1n))
       .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
-    expect(await newToken.getBalance(targetToken.nestingAddress())).to.be.equal(1n);
+    expect(await newToken.getBalance(targetToken.nestingAccount())).to.be.equal(1n);
   });
 
   itSub.ifWithPallets('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', [Pallets.ReFungible], async ({helper}) => {
@@ -631,22 +631,22 @@
 
     await collectionNFT.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true, restricted: [collectionRFT.collectionId]}});
     await collectionNFT.addToAllowList(alice, {Substrate: bob.address});
-    await collectionNFT.addToAllowList(alice, targetToken.nestingAddress());
+    await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
 
     // Try to create a token to be nested and nest
     const newToken = await collectionRFT.mintToken(alice);
-    await expect(newToken.transfer(bob, targetToken.nestingAddress())).to.be.rejectedWith(/common\.TokenValueTooLow/);
+    await expect(newToken.transfer(bob, targetToken.nestingAccount())).to.be.rejectedWith(/common\.TokenValueTooLow/);
 
     expect(await targetToken.getChildren()).to.be.length(0);
     expect(await newToken.getBalance({Substrate: alice.address})).to.be.equal(1n);
 
     // Nest some tokens as Alice into Bob's token
-    await newToken.transfer(alice, targetToken.nestingAddress());
+    await newToken.transfer(alice, targetToken.nestingAccount());
 
     // Try to pull it out
-    await expect(newToken.transferFrom(bob, targetToken.nestingAddress(), {Substrate: alice.address}, 1n))
+    await expect(newToken.transferFrom(bob, targetToken.nestingAccount(), {Substrate: alice.address}, 1n))
       .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
-    expect(await newToken.getBalance(targetToken.nestingAddress())).to.be.equal(1n);
+    expect(await newToken.getBalance(targetToken.nestingAccount())).to.be.equal(1n);
   });
 
   itSub.ifWithPallets('ReFungible: disallows to nest token to an unlisted collection', [Pallets.ReFungible], async ({helper}) => {
@@ -655,12 +655,12 @@
     const targetToken = await collectionNFT.mintToken(alice);
 
     // Try to create an immediately nested token
-    await expect(collectionRFT.mintToken(alice, 5n, targetToken.nestingAddress()))
+    await expect(collectionRFT.mintToken(alice, 5n, targetToken.nestingAccount()))
       .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
 
     // Try to create a token to be nested and nest
     const token = await collectionRFT.mintToken(alice, 5n);
-    await expect(token.transfer(alice, targetToken.nestingAddress(), 2n))
+    await expect(token.transfer(alice, targetToken.nestingAccount(), 2n))
       .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
     expect(await token.getBalance({Substrate: alice.address})).to.be.equal(5n);
   });
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
before · tests/src/nesting/properties.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/>.1617/*import usingApi, {executeTransaction} from '../substrate/substrate-api';18import {19  addCollectionAdminExpectSuccess,20  CollectionMode,21  createCollectionExpectSuccess,22  setCollectionPermissionsExpectSuccess,23  createItemExpectSuccess,24  getCreateCollectionResult,25  transferExpectSuccess,26} from '../util/helpers';*/27import {IKeyringPair} from '@polkadot/types/types';28import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds, expect} from '../util/playgrounds';29import {UniqueCollectionBase, UniqueHelper, UniqueNFTCollection, UniqueNFTToken, UniqueRFTCollection, UniqueRFTToken} from '../util/playgrounds/unique';3031// ---------- COLLECTION PROPERTIES3233describe('Integration Test: Collection Properties', () => {34  let alice: IKeyringPair;35  let bob: IKeyringPair;3637  before(async () => {38    await usingPlaygrounds(async (helper, privateKey) => {39      const donor = privateKey('//Alice');40      [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);41    });42  });4344  itSub('Properties are initially empty', async ({helper}) => {45    const collection = await helper.nft.mintCollection(alice);46    expect(await collection.getProperties()).to.be.empty;47  });4849  async function testSetsPropertiesForCollection(collection: UniqueCollectionBase) {50    // As owner51    await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;5253    await collection.addAdmin(alice, {Substrate: bob.address});5455    // As administrator56    await expect(collection.setProperties(bob, [{key: 'black_hole'}])).to.be.fulfilled;5758    const properties = await collection.getProperties();59    expect(properties).to.include.deep.members([60      {key: 'electron', value: 'come bond'},61      {key: 'black_hole', value: ''},62    ]);63  }6465  itSub('Sets properties for a NFT collection', async ({helper}) =>  {66    await testSetsPropertiesForCollection(await helper.nft.mintCollection(alice));67  });6869  itSub.ifWithPallets('Sets properties for a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {70    await testSetsPropertiesForCollection(await helper.rft.mintCollection(alice));71  });7273  async function testCheckValidNames(collection: UniqueCollectionBase) {74    // alpha symbols75    await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;7677    // numeric symbols78    await expect(collection.setProperties(alice, [{key: '451'}])).to.be.fulfilled;7980    // underscore symbol81    await expect(collection.setProperties(alice, [{key: 'black_hole'}])).to.be.fulfilled;8283    // dash symbol84    await expect(collection.setProperties(alice, [{key: '-'}])).to.be.fulfilled;8586    // dot symbol87    await expect(collection.setProperties(alice, [{key: 'once.in.a.long.long.while...', value: 'you get a little lost'}])).to.be.fulfilled;8889    const properties = await collection.getProperties();90    expect(properties).to.include.deep.members([91      {key: 'answer', value: ''},92      {key: '451', value: ''},93      {key: 'black_hole', value: ''},94      {key: '-', value: ''},95      {key: 'once.in.a.long.long.while...', value: 'you get a little lost'},96    ]);97  }9899  itSub('Check valid names for NFT collection properties keys', async ({helper}) =>  {100    await testCheckValidNames(await helper.nft.mintCollection(alice));101  });102103  itSub.ifWithPallets('Check valid names for ReFungible collection properties keys', [Pallets.ReFungible], async ({helper}) => {104    await testCheckValidNames(await helper.rft.mintCollection(alice));105  });106107  async function testChangesProperties(collection: UniqueCollectionBase) {108    await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;109110    // Mutate the properties111    await expect(collection.setProperties(alice, [{key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;112113    const properties = await collection.getProperties();114    expect(properties).to.include.deep.members([115      {key: 'electron', value: 'come bond'},116      {key: 'black_hole', value: 'LIGO'},117    ]);118  }119120  itSub('Changes properties of a NFT collection', async ({helper}) =>  {121    await testChangesProperties(await helper.nft.mintCollection(alice));122  });123124  itSub.ifWithPallets('Changes properties of a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {125    await testChangesProperties(await helper.rft.mintCollection(alice));126  });127128  async function testDeleteProperties(collection: UniqueCollectionBase) {129    await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;130131    await expect(collection.deleteProperties(alice, ['electron'])).to.be.fulfilled;132133    const properties = await collection.getProperties(['black_hole', 'electron']);134    expect(properties).to.be.deep.equal([135      {key: 'black_hole', value: 'LIGO'},136    ]);137  }138139  itSub('Deletes properties of a NFT collection', async ({helper}) =>  {140    await testDeleteProperties(await helper.nft.mintCollection(alice));141  });142143  itSub.ifWithPallets('Deletes properties of a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {144    await testDeleteProperties(await helper.rft.mintCollection(alice));145  });146});147148describe('Negative Integration Test: Collection Properties', () => {149  let alice: IKeyringPair;150  let bob: IKeyringPair;151152  before(async () => {153    await usingPlaygrounds(async (helper, privateKey) => {154      const donor = privateKey('//Alice');155      [alice, bob] = await helper.arrange.createAccounts([100n, 10n], donor);156    });157  });158  159  async function testFailsSetPropertiesIfNotOwnerOrAdmin(collection: UniqueCollectionBase) {  160    await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))161      .to.be.rejectedWith(/common\.NoPermission/);162163    expect(await collection.getProperties()).to.be.empty;164  }165166  itSub('Fails to set properties in a NFT collection if not its onwer/administrator', async ({helper}) =>  {167    await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.nft.mintCollection(alice));168  });169170  itSub.ifWithPallets('Fails to set properties in a ReFungible collection if not its onwer/administrator', [Pallets.ReFungible], async ({helper}) => {171    await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.rft.mintCollection(alice));172  });173  174  async function testFailsSetPropertiesThatExeedLimits(collection: UniqueCollectionBase) {175    const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();176  177    // Mute the general tx parsing error, too many bytes to process178    {179      console.error = () => {};180      await expect(collection.setProperties(alice, [181        {key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 9))},182      ])).to.be.rejected;183    }184185    expect(await collection.getProperties(['electron'])).to.be.empty;186187    await expect(collection.setProperties(alice, [188      {key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 18))}, 189      {key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))}, 190    ])).to.be.rejectedWith(/common\.NoSpaceForProperty/);191192    expect(await collection.getProperties(['electron', 'black_hole'])).to.be.empty;193  }194195  itSub('Fails to set properties that exceed the limits (NFT)', async ({helper}) =>  {196    await testFailsSetPropertiesThatExeedLimits(await helper.nft.mintCollection(alice));197  });198199  itSub.ifWithPallets('Fails to set properties that exceed the limits (ReFungible)', [Pallets.ReFungible], async ({helper}) => {200    await testFailsSetPropertiesThatExeedLimits(await helper.rft.mintCollection(alice));201  });202  203  async function testFailsSetMorePropertiesThanAllowed(collection: UniqueCollectionBase) {204    const propertiesToBeSet = [];205    for (let i = 0; i < 65; i++) {206      propertiesToBeSet.push({207        key: 'electron_' + i,208        value: Math.random() > 0.5 ? 'high' : 'low',209      });210    }211212    await expect(collection.setProperties(alice, propertiesToBeSet)).213      to.be.rejectedWith(/common\.PropertyLimitReached/);214215    expect(await collection.getProperties()).to.be.empty;216  }217218  itSub('Fails to set more properties than it is allowed (NFT)', async ({helper}) =>  {219    await testFailsSetMorePropertiesThanAllowed(await helper.nft.mintCollection(alice));220  });221222  itSub.ifWithPallets('Fails to set more properties than it is allowed (ReFungible)', [Pallets.ReFungible], async ({helper}) => {223    await testFailsSetMorePropertiesThanAllowed(await helper.rft.mintCollection(alice));224  });225  226  async function testFailsSetPropertiesWithInvalidNames(collection: UniqueCollectionBase) {227    const invalidProperties = [228      [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],229      [{key: 'Mr/Sandman', value: 'Bring me a gene'}],230      [{key: 'déjà vu', value: 'hmm...'}],231    ];232233    for (let i = 0; i < invalidProperties.length; i++) {234      await expect(235        collection.setProperties(alice, invalidProperties[i]), 236        `on rejecting the new badly-named property #${i}`,237      ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);238    }239240    await expect(241      collection.setProperties(alice, [{key: '', value: 'nothing must not exist'}]), 242      'on rejecting an unnamed property',243    ).to.be.rejectedWith(/common\.EmptyPropertyKey/);244245    await expect(246      collection.setProperties(alice, [{key: 'CRISPR-Cas9', value: 'rewriting nature!'}]), 247      'on setting the correctly-but-still-badly-named property',248    ).to.be.fulfilled;249250    const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat('CRISPR-Cas9').concat('');251252    const properties = await collection.getProperties(keys);253    expect(properties).to.be.deep.equal([254      {key: 'CRISPR-Cas9', value: 'rewriting nature!'},255    ]);256257    for (let i = 0; i < invalidProperties.length; i++) {258      await expect(259        collection.deleteProperties(alice, invalidProperties[i].map(propertySet => propertySet.key)), 260        `on trying to delete the non-existent badly-named property #${i}`,261      ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);262    }263  }264265  itSub('Fails to set properties with invalid names (NFT)', async ({helper}) =>  {266    await testFailsSetPropertiesWithInvalidNames(await helper.nft.mintCollection(alice));267  });268269  itSub.ifWithPallets('Fails to set properties with invalid names (ReFungible)', [Pallets.ReFungible], async ({helper}) => {270    await testFailsSetPropertiesWithInvalidNames(await helper.rft.mintCollection(alice));271  });272});273274// ---------- ACCESS RIGHTS275276describe('Integration Test: Access Rights to Token Properties', () => {277  let alice: IKeyringPair;278  let bob: IKeyringPair;279280  before(async () => {281    await usingPlaygrounds(async (helper, privateKey) => {282      const donor = privateKey('//Alice');283      [alice, bob] = await helper.arrange.createAccounts([100n, 10n], donor);284    });285  });286  287  itSub('Reads access rights to properties of a collection', async ({helper}) =>  {288    const collection = await helper.nft.mintCollection(alice);289    const propertyRights = (await helper.api!.query.common.collectionPropertyPermissions(collection.collectionId)).toJSON();290    expect(propertyRights).to.be.empty;291  });292  293  async function testSetsAccessRightsToProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {  294    await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true}}]))295      .to.be.fulfilled;296297    await collection.addAdmin(alice, {Substrate: bob.address});298299    await expect(collection.setTokenPropertyPermissions(bob, [{key: 'mindgame', permission: {collectionAdmin: true, tokenOwner: false}}]))300      .to.be.fulfilled;301302    const propertyRights = await collection.getPropertyPermissions(['skullduggery', 'mindgame']);303    expect(propertyRights).to.include.deep.members([304      {key: 'skullduggery', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}},305      {key: 'mindgame', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},306    ]);307  }308309  itSub('Sets access rights to properties of a collection (NFT)', async ({helper}) =>  {310    await testSetsAccessRightsToProperties(await helper.nft.mintCollection(alice));311  });312313  itSub.ifWithPallets('Sets access rights to properties of a collection (ReFungible)', [Pallets.ReFungible], async ({helper}) => {314    await testSetsAccessRightsToProperties(await helper.rft.mintCollection(alice));315  });316  317  async function testChangesAccessRightsToProperty(collection: UniqueNFTCollection | UniqueRFTCollection) {318    await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]))319      .to.be.fulfilled;320321    await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))322      .to.be.fulfilled;323324    const propertyRights = await collection.getPropertyPermissions();325    expect(propertyRights).to.be.deep.equal([326      {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},327    ]);328  }329330  itSub('Changes access rights to properties of a NFT collection', async ({helper}) =>  {331    await testChangesAccessRightsToProperty(await helper.nft.mintCollection(alice));332  });333334  itSub.ifWithPallets('Changes access rights to properties of a ReFungible collection', [Pallets.ReFungible], async ({helper}) => {335    await testChangesAccessRightsToProperty(await helper.rft.mintCollection(alice));336  });337});338339describe('Negative Integration Test: Access Rights to Token Properties', () => {340  let alice: IKeyringPair;341  let bob: IKeyringPair;342343  before(async () => {344    await usingPlaygrounds(async (helper, privateKey) => {345      const donor = privateKey('//Alice');346      [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);347    });348  });349350  async function testPreventsFromSettingAccessRightsNotAdminOrOwner(collection: UniqueNFTCollection | UniqueRFTCollection) {351    await expect(collection.setTokenPropertyPermissions(bob, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]))352      .to.be.rejectedWith(/common\.NoPermission/);353354    const propertyRights = await collection.getPropertyPermissions(['skullduggery']);355    expect(propertyRights).to.be.empty;356  }357358  itSub('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async ({helper}) =>  {359    await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.nft.mintCollection(alice));360  });361362  itSub.ifWithPallets('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', [Pallets.ReFungible], async ({helper}) => {363    await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.rft.mintCollection(alice));364  });365366  async function testPreventFromAddingTooManyPossibleProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {  367    const constitution = [];368    for (let i = 0; i < 65; i++) {369      constitution.push({370        key: 'property_' + i,371        permission: Math.random() > 0.5 ? {mutable: true, collectionAdmin: true, tokenOwner: true} : {},372      });373    }374375    await expect(collection.setTokenPropertyPermissions(alice, constitution))376      .to.be.rejectedWith(/common\.PropertyLimitReached/);377378    const propertyRights = await collection.getPropertyPermissions();379    expect(propertyRights).to.be.empty;380  }381382  itSub('Prevents from adding too many possible properties (NFT)', async ({helper}) =>  {383    await testPreventFromAddingTooManyPossibleProperties(await helper.nft.mintCollection(alice));384  });385386  itSub.ifWithPallets('Prevents from adding too many possible properties (ReFungible)', [Pallets.ReFungible], async ({helper}) => {387    await testPreventFromAddingTooManyPossibleProperties(await helper.rft.mintCollection(alice));388  });389390  async function testPreventAccessRightsModifiedIfConstant(collection: UniqueNFTCollection | UniqueRFTCollection) {391    await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))392      .to.be.fulfilled;393394    await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {collectionAdmin: true}}]))395      .to.be.rejectedWith(/common\.NoPermission/);396397    const propertyRights = await collection.getPropertyPermissions(['skullduggery']);398    expect(propertyRights).to.deep.equal([399      {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},400    ]);401  }402403  itSub('Prevents access rights to be modified if constant (NFT)', async ({helper}) =>  {404    await testPreventAccessRightsModifiedIfConstant(await helper.nft.mintCollection(alice));405  });406407  itSub.ifWithPallets('Prevents access rights to be modified if constant (ReFungible)', [Pallets.ReFungible], async ({helper}) => {408    await testPreventAccessRightsModifiedIfConstant(await helper.rft.mintCollection(alice));409  });410411  async function testPreventsAddingPropertiesWithInvalidNames(collection: UniqueNFTCollection | UniqueRFTCollection) {412    const invalidProperties = [413      [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],414      [{key: 'G#4', permission: {tokenOwner: true}}],415      [{key: 'HÆMILTON', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}],416    ];417418    for (let i = 0; i < invalidProperties.length; i++) {419      await expect(420        collection.setTokenPropertyPermissions(alice, invalidProperties[i]), 421        `on setting the new badly-named property #${i}`,422      ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);423    }424425    await expect(426      collection.setTokenPropertyPermissions(alice, [{key: '', permission: {}}]), 427      'on rejecting an unnamed property',428    ).to.be.rejectedWith(/common\.EmptyPropertyKey/);429430    const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string431    await expect(432      collection.setTokenPropertyPermissions(alice, [433        {key: correctKey, permission: {collectionAdmin: true}},434      ]), 435      'on setting the correctly-but-still-badly-named property',436    ).to.be.fulfilled;437438    const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat(correctKey).concat('');439440    const propertyRights = await collection.getPropertyPermissions(keys);441    expect(propertyRights).to.be.deep.equal([442      {key: correctKey, permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},443    ]);444  }445446  itSub('Prevents adding properties with invalid names (NFT)', async ({helper}) =>  {447    await testPreventsAddingPropertiesWithInvalidNames(await helper.nft.mintCollection(alice));448  });449450  itSub.ifWithPallets('Prevents adding properties with invalid names (ReFungible)', [Pallets.ReFungible], async ({helper}) => {451    await testPreventsAddingPropertiesWithInvalidNames(await helper.rft.mintCollection(alice));452  });453});454455// ---------- TOKEN PROPERTIES456457describe('Integration Test: Token Properties', () => {458  let alice: IKeyringPair; // collection owner459  let bob: IKeyringPair; // collection admin460  let charlie: IKeyringPair; // token owner461462  let permissions: {permission: any, signers: IKeyringPair[]}[];463464  before(async () => {465    await usingPlaygrounds(async (helper, privateKey) => {466      const donor = privateKey('//Alice');467      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);468    });469470    // todo:playgrounds probably separate these tests later471    permissions = [472      {permission: {mutable: true, collectionAdmin: true}, signers: [alice, bob]},473      {permission: {mutable: false, collectionAdmin: true}, signers: [alice, bob]},474      {permission: {mutable: true, tokenOwner: true}, signers: [charlie]},475      {permission: {mutable: false, tokenOwner: true}, signers: [charlie]},476      {permission: {mutable: true, collectionAdmin: true, tokenOwner: true}, signers: [alice, bob, charlie]},477      {permission: {mutable: false, collectionAdmin: true, tokenOwner: true}, signers: [alice, bob, charlie]},478    ];479  });480  481  async function testReadsYetEmptyProperties(token: UniqueNFTToken | UniqueRFTToken) {482    const properties = await token.getProperties();483    expect(properties).to.be.empty;484485    const tokenData = await token.getData();486    expect(tokenData!.properties).to.be.empty;487  }488489  itSub('Reads yet empty properties of a token (NFT)', async ({helper}) => {490    const collection = await helper.nft.mintCollection(alice);491    const token = await collection.mintToken(alice);492    await testReadsYetEmptyProperties(token);493  });494495  itSub.ifWithPallets('Reads yet empty properties of a token (ReFungible)', [Pallets.ReFungible], async ({helper}) => {496    const collection = await helper.rft.mintCollection(alice);497    const token = await collection.mintToken(alice);498    await testReadsYetEmptyProperties(token);499  });500501  async function testAssignPropertiesAccordingToPermissions(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {502    await token.collection.addAdmin(alice, {Substrate: bob.address});503    await token.transfer(alice, {Substrate: charlie.address}, pieces);504505    const propertyKeys: string[] = [];506    let i = 0;507    for (const permission of permissions) {508      i++;509      let j = 0;510      for (const signer of permission.signers) {511        j++;512        const key = i + '_' + signer.address;513        propertyKeys.push(key);514515        await expect(516          token.collection.setTokenPropertyPermissions(alice, [{key: key, permission: permission.permission}]), 517          `on setting permission #${i} by alice`,518        ).to.be.fulfilled;519520        await expect(521          token.setProperties(signer, [{key: key, value: 'Serotonin increase'}]), 522          `on adding property #${i} by signer #${j}`,523        ).to.be.fulfilled;524      }525    }526527    const properties = await token.getProperties(propertyKeys);528    const tokenData = await token.getData();529    for (let i = 0; i < properties.length; i++) {530      expect(properties[i].value).to.be.equal('Serotonin increase');531      expect(tokenData!.properties[i].value).to.be.equal('Serotonin increase');532    }533  }534535  itSub('Assigns properties to a token according to permissions (NFT)', async ({helper}) =>  {536    const collection = await helper.nft.mintCollection(alice);537    const token = await collection.mintToken(alice);538    await testAssignPropertiesAccordingToPermissions(token, 1n);539  });540541  itSub.ifWithPallets('Assigns properties to a token according to permissions (ReFungible)', [Pallets.ReFungible], async ({helper}) => {542    const collection = await helper.rft.mintCollection(alice);543    const token = await collection.mintToken(alice, 100n);544    await testAssignPropertiesAccordingToPermissions(token, 100n);545  });546547  async function testChangesPropertiesAccordingPermission(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {548    await token.collection.addAdmin(alice, {Substrate: bob.address});549    await token.transfer(alice, {Substrate: charlie.address}, pieces);550551    const propertyKeys: string[] = [];552    let i = 0;553    for (const permission of permissions) {554      i++;555      if (!permission.permission.mutable) continue;556      557      let j = 0;558      for (const signer of permission.signers) {559        j++;560        const key = i + '_' + signer.address;561        propertyKeys.push(key);562563        await expect(564          token.collection.setTokenPropertyPermissions(alice, [{key: key, permission: permission.permission}]), 565          `on setting permission #${i} by alice`,566        ).to.be.fulfilled;567568        await expect(569          token.setProperties(signer, [{key, value: 'Serotonin increase'}]), 570          `on adding property #${i} by signer #${j}`,571        ).to.be.fulfilled;572573        await expect(574          token.setProperties(signer, [{key, value: 'Serotonin stable'}]), 575          `on changing property #${i} by signer #${j}`,576        ).to.be.fulfilled;577      }578    }579580    const properties = await token.getProperties(propertyKeys);581    const tokenData = await token.getData();582    for (let i = 0; i < properties.length; i++) {583      expect(properties[i].value).to.be.equal('Serotonin stable');584      expect(tokenData!.properties[i].value).to.be.equal('Serotonin stable');585    }586  }587588  itSub('Changes properties of a token according to permissions (NFT)', async ({helper}) =>  {589    const collection = await helper.nft.mintCollection(alice);590    const token = await collection.mintToken(alice);591    await testChangesPropertiesAccordingPermission(token, 1n);592  });593594  itSub.ifWithPallets('Changes properties of a token according to permissions (ReFungible)', [Pallets.ReFungible], async ({helper}) => {595    const collection = await helper.rft.mintCollection(alice);596    const token = await collection.mintToken(alice, 100n);597    await testChangesPropertiesAccordingPermission(token, 100n);598  });599600  async function testDeletePropertiesAccordingPermission(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {601    await token.collection.addAdmin(alice, {Substrate: bob.address});602    await token.transfer(alice, {Substrate: charlie.address}, pieces);603604    const propertyKeys: string[] = [];605    let i = 0;606607    for (const permission of permissions) {608      i++;609      if (!permission.permission.mutable) continue;610      611      let j = 0;612      for (const signer of permission.signers) {613        j++;614        const key = i + '_' + signer.address;615        propertyKeys.push(key);616617        await expect(618          token.collection.setTokenPropertyPermissions(alice, [{key: key, permission: permission.permission}]), 619          `on setting permission #${i} by alice`,620        ).to.be.fulfilled;621622        await expect(623          token.setProperties(signer, [{key, value: 'Serotonin increase'}]), 624          `on adding property #${i} by signer #${j}`,625        ).to.be.fulfilled;626627        await expect(628          token.deleteProperties(signer, [key]), 629          `on deleting property #${i} by signer #${j}`,630        ).to.be.fulfilled;631      }632    }633634    expect(await token.getProperties(propertyKeys)).to.be.empty;635    expect((await token.getData())!.properties).to.be.empty;636  }637  638  itSub('Deletes properties of a token according to permissions (NFT)', async ({helper}) =>  {639    const collection = await helper.nft.mintCollection(alice);640    const token = await collection.mintToken(alice);641    await testDeletePropertiesAccordingPermission(token, 1n);642  });643644  itSub.ifWithPallets('Deletes properties of a token according to permissions (ReFungible)', [Pallets.ReFungible], async ({helper}) => {645    const collection = await helper.rft.mintCollection(alice);646    const token = await collection.mintToken(alice, 100n);647    await testDeletePropertiesAccordingPermission(token, 100n);648  });649650  itSub('Assigns properties to a nested token according to permissions', async ({helper}) =>  {651    const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});652    const collectionB = await helper.nft.mintCollection(alice);653    const targetToken = await collectionA.mintToken(alice);654    const nestedToken = await collectionB.mintToken(alice, targetToken.nestingAddress());655656    await collectionB.addAdmin(alice, {Substrate: bob.address});657    await targetToken.transfer(alice, {Substrate: charlie.address});658659    const propertyKeys: string[] = [];660    let i = 0;661    for (const permission of permissions) {662      i++;663      let j = 0;664      for (const signer of permission.signers) {665        j++;666        const key = i + '_' + signer.address;667        propertyKeys.push(key);668        669        await expect(670          nestedToken.collection.setTokenPropertyPermissions(alice, [{key: key, permission: permission.permission}]), 671          `on setting permission #${i} by alice`,672        ).to.be.fulfilled;673674        await expect(675          nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), 676          `on adding property #${i} by signer #${j}`,677        ).to.be.fulfilled;678      }679680    }681682    const properties = await nestedToken.getProperties(propertyKeys);683    const tokenData = await nestedToken.getData();684    for (let i = 0; i < properties.length; i++) {685      expect(properties[i].value).to.be.equal('Serotonin increase');686      expect(tokenData!.properties[i].value).to.be.equal('Serotonin increase');687    }688    expect(await targetToken.getProperties()).to.be.empty;689  });690691  itSub('Changes properties of a nested token according to permissions', async ({helper}) =>  {692    const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});693    const collectionB = await helper.nft.mintCollection(alice);694    const targetToken = await collectionA.mintToken(alice);695    const nestedToken = await collectionB.mintToken(alice, targetToken.nestingAddress());696697    await collectionB.addAdmin(alice, {Substrate: bob.address});698    await targetToken.transfer(alice, {Substrate: charlie.address});699700    const propertyKeys: string[] = [];701    let i = 0;702    for (const permission of permissions) {703      i++;704      if (!permission.permission.mutable) continue;705      706      let j = 0;707      for (const signer of permission.signers) {708        j++;709        const key = i + '_' + signer.address;710        propertyKeys.push(key);711712        await expect(713          nestedToken.collection.setTokenPropertyPermissions(alice, [{key: key, permission: permission.permission}]), 714          `on setting permission #${i} by alice`,715        ).to.be.fulfilled;716717        await expect(718          nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), 719          `on adding property #${i} by signer #${j}`,720        ).to.be.fulfilled;721722        await expect(723          nestedToken.setProperties(signer, [{key, value: 'Serotonin stable'}]), 724          `on changing property #${i} by signer #${j}`,725        ).to.be.fulfilled;726      }727    }728729    const properties = await nestedToken.getProperties(propertyKeys);730    const tokenData = await nestedToken.getData();731    for (let i = 0; i < properties.length; i++) {732      expect(properties[i].value).to.be.equal('Serotonin stable');733      expect(tokenData!.properties[i].value).to.be.equal('Serotonin stable');734    }735    expect(await targetToken.getProperties()).to.be.empty;736  });737738  itSub('Deletes properties of a nested token according to permissions', async ({helper}) =>  {739    const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});740    const collectionB = await helper.nft.mintCollection(alice);741    const targetToken = await collectionA.mintToken(alice);742    const nestedToken = await collectionB.mintToken(alice, targetToken.nestingAddress());743744    await collectionB.addAdmin(alice, {Substrate: bob.address});745    await targetToken.transfer(alice, {Substrate: charlie.address});746747    const propertyKeys: string[] = [];748    let i = 0;749    for (const permission of permissions) {750      i++;751      if (!permission.permission.mutable) continue;752      753      let j = 0;754      for (const signer of permission.signers) {755        j++;756        const key = i + '_' + signer.address;757        propertyKeys.push(key);758759        await expect(760          nestedToken.collection.setTokenPropertyPermissions(alice, [{key: key, permission: permission.permission}]), 761          `on setting permission #${i} by alice`,762        ).to.be.fulfilled;763764        await expect(765          nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), 766          `on adding property #${i} by signer #${j}`,767        ).to.be.fulfilled;768769        await expect(770          nestedToken.deleteProperties(signer, [key]), 771          `on deleting property #${i} by signer #${j}`,772        ).to.be.fulfilled;773      }774    }775776    expect(await nestedToken.getProperties(propertyKeys)).to.be.empty;777    expect((await nestedToken.getData())!.properties).to.be.empty;778    expect(await targetToken.getProperties()).to.be.empty;779  });780});781782describe('Negative Integration Test: Token Properties', () => {783  let alice: IKeyringPair; // collection owner784  let bob: IKeyringPair; // collection admin785  let charlie: IKeyringPair; // token owner786787  let constitution: {permission: any, signers: IKeyringPair[], sinner: IKeyringPair}[];788789  before(async () => {790    await usingPlaygrounds(async (helper, privateKey) => {791      const donor = privateKey('//Alice');792      let dave: IKeyringPair;793      [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);794795      // todo:playgrounds probably separate these tests later796      constitution = [797        {permission: {mutable: true, collectionAdmin: true}, signers: [alice, bob], sinner: charlie},798        {permission: {mutable: false, collectionAdmin: true}, signers: [alice, bob], sinner: charlie},799        {permission: {mutable: true, tokenOwner: true}, signers: [charlie], sinner: alice},800        {permission: {mutable: false, tokenOwner: true}, signers: [charlie], sinner: alice},801        {permission: {mutable: true, collectionAdmin: true, tokenOwner: true}, signers: [alice, bob, charlie], sinner: dave},802        {permission: {mutable: false, collectionAdmin: true, tokenOwner: true}, signers: [alice, bob, charlie], sinner: dave},803      ];804    });805  });806807  async function getConsumedSpace(api: any, collectionId: number, tokenId: number, mode: 'NFT' | 'RFT'): Promise<number> {808    return (await (mode == 'NFT' ? api.query.nonfungible : api.query.refungible).tokenProperties(collectionId, tokenId)).toJSON().consumedSpace;809  }810811  async function prepare(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint): Promise<number> {812    await token.collection.addAdmin(alice, {Substrate: bob.address});813    await token.transfer(alice, {Substrate: charlie.address}, pieces);814815    let i = 0;816    for (const passage of constitution) {817      i++;818      const signer = passage.signers[0];819      820      await expect(821        token.collection.setTokenPropertyPermissions(alice, [{key: `${i}`, permission: passage.permission}]), 822        `on setting permission ${i} by alice`,823      ).to.be.fulfilled;824825      await expect(826        token.setProperties(signer, [{key: `${i}`, value: 'Serotonin increase'}]), 827        `on adding property ${i} by ${signer.address}`,828      ).to.be.fulfilled;829    }830831    const originalSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 832    return originalSpace;833  }834835  async function testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {836    const originalSpace = await prepare(token, pieces);837838    let i = 0;839    for (const forbiddance of constitution) {840      i++;841      if (!forbiddance.permission.mutable) continue;842843      await expect(844        token.setProperties(forbiddance.sinner, [{key: `${i}`, value: 'Serotonin down'}]), 845        `on failing to change property ${i} by the malefactor`,846      ).to.be.rejectedWith(/common\.NoPermission/);847848      await expect(849        token.deleteProperties(forbiddance.sinner, [`${i}`]), 850        `on failing to delete property ${i} by the malefactor`,851      ).to.be.rejectedWith(/common\.NoPermission/);852    }853854    const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 855    expect(consumedSpace).to.be.equal(originalSpace);856  }857858  itSub('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async ({helper}) =>  {859    const collection = await helper.nft.mintCollection(alice);860    const token = await collection.mintToken(alice);861    await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token, 1n);862  });863864  itSub.ifWithPallets('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', [Pallets.ReFungible], async ({helper}) => {865    const collection = await helper.rft.mintCollection(alice);866    const token = await collection.mintToken(alice, 100n);867    await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token, 100n);868  });869870  async function testForbidsChangingDeletingPropertiesIfPropertyImmutable(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {871    const originalSpace = await prepare(token, pieces);872873    let i = 0;874    for (const permission of constitution) {875      i++;876      if (permission.permission.mutable) continue;877878      await expect(879        token.setProperties(permission.signers[0], [{key: `${i}`, value: 'Serotonin down'}]), 880        `on failing to change property ${i} by signer #0`,881      ).to.be.rejectedWith(/common\.NoPermission/);882883      await expect(884        token.deleteProperties(permission.signers[0], [i.toString()]), 885        `on failing to delete property ${i} by signer #0`,886      ).to.be.rejectedWith(/common\.NoPermission/);887    }888  889    const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 890    expect(consumedSpace).to.be.equal(originalSpace);891  }892893  itSub('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async ({helper}) =>  {894    const collection = await helper.nft.mintCollection(alice);895    const token = await collection.mintToken(alice);896    await testForbidsChangingDeletingPropertiesIfPropertyImmutable(token, 1n);897  });898899  itSub.ifWithPallets('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', [Pallets.ReFungible], async ({helper}) => {900    const collection = await helper.rft.mintCollection(alice);901    const token = await collection.mintToken(alice, 100n);902    await testForbidsChangingDeletingPropertiesIfPropertyImmutable(token, 100n);903  });904905  async function testForbidsAddingPropertiesIfPropertyNotDeclared(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {906    const originalSpace = await prepare(token, pieces);907908    await expect(909      token.setProperties(alice, [{key: 'non-existent', value: 'I exist!'}]), 910      'on failing to add a previously non-existent property',911    ).to.be.rejectedWith(/common\.NoPermission/);912      913    await expect(914      token.collection.setTokenPropertyPermissions(alice, [{key: 'now-existent', permission: {}}]), 915      'on setting a new non-permitted property',916    ).to.be.fulfilled;917918    await expect(919      token.setProperties(alice, [{key: 'now-existent', value: 'I exist!'}]), 920      'on failing to add a property forbidden by the \'None\' permission',921    ).to.be.rejectedWith(/common\.NoPermission/);922923    expect(await token.getProperties(['non-existent', 'now-existent'])).to.be.empty;924      925    const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 926    expect(consumedSpace).to.be.equal(originalSpace);927  }928929  itSub('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async ({helper}) =>  {930    const collection = await helper.nft.mintCollection(alice);931    const token = await collection.mintToken(alice);932    await testForbidsAddingPropertiesIfPropertyNotDeclared(token, 1n);933  });934935  itSub.ifWithPallets('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', [Pallets.ReFungible], async ({helper}) => {936    const collection = await helper.rft.mintCollection(alice);937    const token = await collection.mintToken(alice, 100n);938    await testForbidsAddingPropertiesIfPropertyNotDeclared(token, 100n);939  });940941  async function testForbidsAddingTooManyProperties(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {942    const originalSpace = await prepare(token, pieces);943944    await expect(945      token.collection.setTokenPropertyPermissions(alice, [946        {key: 'a_holy_book', permission: {collectionAdmin: true, tokenOwner: true}}, 947        {key: 'young_years', permission: {collectionAdmin: true, tokenOwner: true}},948      ]), 949      'on setting new permissions for properties',950    ).to.be.fulfilled;951952    // Mute the general tx parsing error953    {954      console.error = () => {};955      await expect(token.setProperties(alice, [{key: 'a_holy_book', value: 'word '.repeat(6554)}]))956        .to.be.rejected;957    }958959    await expect(token.setProperties(alice, [960      {key: 'a_holy_book', value: 'word '.repeat(3277)}, 961      {key: 'young_years', value: 'neverending'.repeat(1490)},962    ])).to.be.rejectedWith(/common\.NoSpaceForProperty/);963  964    expect(await token.getProperties(['a_holy_book', 'young_years'])).to.be.empty;965    const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 966    expect(consumedSpace).to.be.equal(originalSpace);967  }968969  itSub('Forbids adding too many properties to a token (NFT)', async ({helper}) =>  {970    const collection = await helper.nft.mintCollection(alice);971    const token = await collection.mintToken(alice);972    await testForbidsAddingTooManyProperties(token, 1n);973  });974975  itSub.ifWithPallets('Forbids adding too many properties to a token (ReFungible)', [Pallets.ReFungible], async ({helper}) => {976    const collection = await helper.rft.mintCollection(alice);977    const token = await collection.mintToken(alice, 100n);978    await testForbidsAddingTooManyProperties(token, 100n);979  });980});981982describe('ReFungible token properties permissions tests', () => {983  let alice: IKeyringPair;984  let bob: IKeyringPair;985  let charlie: IKeyringPair;986987  before(async function() {988    await usingPlaygrounds(async (helper, privateKey) => {989      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);990991      const donor = privateKey('//Alice');992      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);993    });994  });995996  async function prepare(helper: UniqueHelper): Promise<UniqueRFTToken> {997    const collection = await helper.rft.mintCollection(alice);998    const token = await collection.mintToken(alice, 100n);999    1000    await collection.addAdmin(alice, {Substrate: bob.address});1001    await collection.setTokenPropertyPermissions(alice, [{key: 'fractals', permission: {mutable: true, tokenOwner: true}}]);1002    1003    return token;1004  }10051006  itSub('Forbids adding token property with tokenOwner==true when signer doesn\'t have all pieces', async ({helper}) =>  {1007    const token = await prepare(helper);10081009    await token.transfer(alice, {Substrate: charlie.address}, 33n);10101011    await expect(token.setProperties(alice, [1012      {key: 'fractals', value: 'multiverse'}, 1013    ])).to.be.rejectedWith(/common\.NoPermission/);1014  });10151016  itSub('Forbids mutating token property with tokenOwher==true when signer doesn\'t have all pieces', async ({helper}) =>  {1017    const token = await prepare(helper);10181019    await expect(token.collection.setTokenPropertyPermissions(alice, [{key: 'fractals', permission: {mutable:true, tokenOwner: true}}]))1020      .to.be.fulfilled;10211022    await expect(token.setProperties(alice, [1023      {key: 'fractals', value: 'multiverse'}, 1024    ])).to.be.fulfilled;10251026    await token.transfer(alice, {Substrate: charlie.address}, 33n);10271028    await expect(token.setProperties(alice, [1029      {key: 'fractals', value: 'want to rule the world'}, 1030    ])).to.be.rejectedWith(/common\.NoPermission/);1031  });10321033  itSub('Forbids deleting token property with tokenOwner==true when signer doesn\'t have all pieces', async ({helper}) =>  {1034    const token = await prepare(helper);10351036    await expect(token.setProperties(alice, [1037      {key: 'fractals', value: 'one headline - why believe it'}, 1038    ])).to.be.fulfilled;10391040    await token.transfer(alice, {Substrate: charlie.address}, 33n);10411042    await expect(token.deleteProperties(alice, ['fractals'])).1043      to.be.rejectedWith(/common\.NoPermission/);1044  });10451046  itSub('Allows token property mutation with collectionOwner==true when admin doesn\'t have all pieces', async ({helper}) =>  {1047    const token = await prepare(helper);10481049    await token.transfer(alice, {Substrate: charlie.address}, 33n);10501051    await expect(token.collection.setTokenPropertyPermissions(alice, [{key: 'fractals', permission: {mutable:true, collectionAdmin: true}}]))1052      .to.be.fulfilled;10531054    await expect(token.setProperties(alice, [1055      {key: 'fractals', value: 'multiverse'}, 1056    ])).to.be.fulfilled;1057  });1058});
modifiedtests/src/nesting/unnest.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/unnest.test.ts
+++ b/tests/src/nesting/unnest.test.ts
@@ -32,15 +32,15 @@
     const targetToken = await collection.mintToken(alice);
     
     // Create a nested token
-    const nestedToken = await collection.mintToken(alice, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());
 
     // Unnest
-    await expect(nestedToken.transferFrom(alice, targetToken.nestingAddress(), {Substrate: alice.address}), 'while unnesting').to.be.fulfilled;
+    await expect(nestedToken.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}), 'while unnesting').to.be.fulfilled;
     expect(await nestedToken.getOwner()).to.be.deep.equal({Substrate: alice.address});
 
     // Nest and burn
     await nestedToken.nest(alice, targetToken);
-    await expect(nestedToken.burnFrom(alice, targetToken.nestingAddress()), 'while burning').to.be.fulfilled;
+    await expect(nestedToken.burnFrom(alice, targetToken.nestingAccount()), 'while burning').to.be.fulfilled;
     await expect(nestedToken.getOwner()).to.be.rejected;
   });
 
@@ -51,16 +51,16 @@
     const collectionFT = await helper.ft.mintCollection(alice);
     
     // Nest and unnest
-    await collectionFT.mint(alice, 10n, targetToken.nestingAddress());
-    await expect(collectionFT.transferFrom(alice, targetToken.nestingAddress(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;
+    await collectionFT.mint(alice, 10n, targetToken.nestingAccount());
+    await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;
     expect(await collectionFT.getBalance({Substrate: alice.address})).to.be.equal(9n);
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(1n);
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(1n);
 
     // Nest and burn
-    await collectionFT.transfer(alice, targetToken.nestingAddress(), 5n);
-    await expect(collectionFT.burnTokensFrom(alice, targetToken.nestingAddress(), 6n), 'while burning').to.be.fulfilled;
+    await collectionFT.transfer(alice, targetToken.nestingAccount(), 5n);
+    await expect(collectionFT.burnTokensFrom(alice, targetToken.nestingAccount(), 6n), 'while burning').to.be.fulfilled;
     expect(await collectionFT.getBalance({Substrate: alice.address})).to.be.equal(4n);
-    expect(await collectionFT.getBalance(targetToken.nestingAddress())).to.be.equal(0n);
+    expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(0n);
     expect(await targetToken.getChildren()).to.be.length(0);
   });
 
@@ -71,16 +71,16 @@
     const collectionRFT = await helper.rft.mintCollection(alice);
     
     // Nest and unnest
-    const token = await collectionRFT.mintToken(alice, 10n, targetToken.nestingAddress());
-    await expect(token.transferFrom(alice, targetToken.nestingAddress(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;
+    const token = await collectionRFT.mintToken(alice, 10n, targetToken.nestingAccount());
+    await expect(token.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled;
     expect(await token.getBalance({Substrate: alice.address})).to.be.equal(9n);
-    expect(await token.getBalance(targetToken.nestingAddress())).to.be.equal(1n);
+    expect(await token.getBalance(targetToken.nestingAccount())).to.be.equal(1n);
 
     // Nest and burn
-    await token.transfer(alice, targetToken.nestingAddress(), 5n);
-    await expect(token.burnFrom(alice, targetToken.nestingAddress(), 6n), 'while burning').to.be.fulfilled;
+    await token.transfer(alice, targetToken.nestingAccount(), 5n);
+    await expect(token.burnFrom(alice, targetToken.nestingAccount(), 6n), 'while burning').to.be.fulfilled;
     expect(await token.getBalance({Substrate: alice.address})).to.be.equal(4n);
-    expect(await token.getBalance(targetToken.nestingAddress())).to.be.equal(0n);
+    expect(await token.getBalance(targetToken.nestingAccount())).to.be.equal(0n);
     expect(await targetToken.getChildren()).to.be.length(0);
   });
 });
@@ -101,15 +101,15 @@
     const targetToken = await collection.mintToken(alice);
 
     // Create a nested token
-    const nestedToken = await collection.mintToken(alice, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());
 
     // Try to unnest
     await expect(nestedToken.unnest(bob, targetToken, {Substrate: alice.address})).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
 
     // Try to burn
-    await expect(nestedToken.burnFrom(bob, targetToken.nestingAddress())).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
-    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAddress());
+    await expect(nestedToken.burnFrom(bob, targetToken.nestingAccount())).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+    expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());
   });
 
   // todo another test for creating excessive depth matryoshka with Ethereum?
@@ -120,7 +120,7 @@
     const targetToken = await collection.mintToken(alice);
 
     // Fail to create a nested token ouroboros
-    const nestedToken = await collection.mintToken(alice, targetToken.nestingAddress());
+    const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());
     await expect(targetToken.nest(alice, nestedToken)).to.be.rejectedWith(/^structure\.OuroborosDetected$/);
   });
 });
modifiedtests/src/util/playgrounds/types.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/types.ts
+++ b/tests/src/util/playgrounds/types.ts
@@ -109,7 +109,6 @@
 export interface IToken {
   collectionId: number;
   tokenId: number;
-  //nestingAddress: () => {Ethereum: string};
 }
 
 export interface IBlock {
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -55,11 +55,11 @@
     RPC: 'rpc',
   };
 
-  static getNestingTokenAddress(token: IToken) {
-    return {Ethereum: this.getNestingTokenAddressRaw(token).toLowerCase()};
+  static getTokenAccount(token: IToken) {
+    return {Ethereum: this.getTokenAddress(token).toLowerCase()};
   }
 
-  static getNestingTokenAddressRaw(token: IToken) {
+  static getTokenAddress(token: IToken) {
     return nesting.tokenIdToAddress(token.collectionId, token.tokenId);
   }
 
@@ -1370,7 +1370,7 @@
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
   async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken): Promise<boolean> {
-    const rootTokenAddress = this.helper.util.getNestingTokenAddress(rootTokenObj);
+    const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);
     const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);
     if(!result) {
       throw Error('Unable to nest token!');
@@ -1388,7 +1388,7 @@
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
   async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {
-    const rootTokenAddress = this.helper.util.getNestingTokenAddress(rootTokenObj);
+    const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);
     const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);
     if(!result) {
       throw Error('Unable to unnest token!');
@@ -2566,8 +2566,8 @@
     return await this.collection.deleteTokenProperties(signer, this.tokenId, propertyKeys);
   }
 
-  nestingAddress() {
-    return this.collection.helper.util.getNestingTokenAddress(this);
+  nestingAccount() {
+    return this.collection.helper.util.getTokenAccount(this);
   }
 }