git.delta.rocks / unique-network / refs/commits / 36ef0466a311

difftreelog

Add tests for properties

kryadinskii2022-05-10parent: #2976d69.patch.diff
in: master

6 files changed

modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -50,6 +50,7 @@
     "testContracts": "mocha --timeout 9999999 -r ts-node/register ./**/contracts.test.ts",
     "testCreateItem": "mocha --timeout 9999999 -r ts-node/register ./**/createItem.test.ts",
     "testCreateMultipleItems": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItems.test.ts",
+    "testCreateMultipleItemsEx": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItemsEx.test.ts",
     "testApprove": "mocha --timeout 9999999 -r ts-node/register ./**/approve.test.ts",
     "testTransferFrom": "mocha --timeout 9999999 -r ts-node/register ./**/transferFrom.test.ts",
     "testCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts",
modifiedtests/src/createCollection.test.tsdiffbeforeafterboth
--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -17,7 +17,7 @@
 import {expect} from 'chai';
 import privateKey from './substrate/privateKey';
 import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';
-import {createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo} from './util/helpers';
+import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess} from './util/helpers';
 
 describe('integration test: ext. createCollection():', () => {
   it('Create new NFT collection', async () => {
@@ -38,6 +38,25 @@
   it('Create new ReFungible collection', async () => {
     await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
   });
+
+  it('create new collection with properties #1', async () => {
+    await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}, 
+      properties: [{key: 'key1', value: 'val1'}], 
+      propPerm:   [{key: 'key1', tokenOwner: true, mutable: false, collectionAdmin: true}]});
+  });
+
+  it('create new collection with properties #2', async () => {
+    await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}, 
+      properties: [{key: 'key1', value: 'val1'}], 
+      propPerm:   [{key: 'key1', tokenOwner: false, mutable: true, collectionAdmin: false}]});
+  });
+
+  it('create new collection with properties #3', async () => {
+    await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}, 
+      properties: [{key: 'key1', value: 'val1'}], 
+      propPerm:   [{key: 'key1', tokenOwner: true, mutable: false, collectionAdmin: false}]});
+  });
+
   it('Create new collection with extra fields', async () => {
     await usingApi(async api => {
       const alice = privateKey('//Alice');
@@ -96,4 +115,24 @@
       await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/^common.CollectionTokenLimitExceeded$/);
     });
   });
+
+  it('(!negative test!) create collection with incorrect property limit (64 elements)', async () => {
+    const props = [];
+
+    for (let i = 0; i < 65; i++) {
+      props.push({key: `key${i}`, value: `value${i}`});
+    }
+
+    await createCollectionWithPropsExpectFailure({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}, properties: props});
+  });
+
+  it('(!negative test!) create collection with incorrect property limit (40 kb)', async () => {
+    const props = [];
+
+    for (let i = 0; i < 32; i++) {
+      props.push({key: `key${i}`.repeat(80), value: `value${i}`.repeat(80)});
+    }
+
+    await createCollectionWithPropsExpectFailure({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}, properties: props});
+  });
 });
modifiedtests/src/createItem.test.tsdiffbeforeafterboth
--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU General Public License
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
-import {default as usingApi} from './substrate/substrate-api';
+import {default as usingApi, executeTransaction} from './substrate/substrate-api';
 import chai from 'chai';
 import {Keyring} from '@polkadot/api';
 import {IKeyringPair} from '@polkadot/types/types';
@@ -22,6 +22,7 @@
   createCollectionExpectSuccess,
   createItemExpectSuccess,
   addCollectionAdminExpectSuccess,
+  createCollectionWithPropsExpectSuccess,
 } from './util/helpers';
 
 const expect = chai.expect;
@@ -70,6 +71,33 @@
     await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
     await createItemExpectSuccess(bob, newCollectionID, createMode);
   });
+
+  it('Set property Admin', async () => {
+    const createMode = 'NFT';
+    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 
+      properties: [{key: 'key1', value: 'val1'}], 
+      propPerm:   [{key: 'key1', mutable: true, collectionAdmin: true, tokenOwner: false}]});
+    
+    await createItemExpectSuccess(alice, newCollectionID, createMode);
+  });
+
+  it('Set property AdminConst', async () => {
+    const createMode = 'NFT';
+    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 
+      properties: [{key: 'key1', value: 'val1'}], 
+      propPerm:   [{key: 'key1', mutable: false, collectionAdmin: true, tokenOwner: false}]});
+    
+    await createItemExpectSuccess(alice, newCollectionID, createMode);
+  });
+
+  it('Set property itemOwnerOrAdmin', async () => {
+    const createMode = 'NFT';
+    const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 
+      properties: [{key: 'key1', value: 'val1'}], 
+      propPerm:   [{key: 'key1', mutable: true, collectionAdmin: true, tokenOwner: true}]});
+    
+    await createItemExpectSuccess(alice, newCollectionID, createMode);
+  });
 });
 
 describe('Negative integration test: ext. createItem():', () => {
@@ -96,4 +124,76 @@
     const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
     await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
   });
+
+  it('No editing rights', async () => {
+    await usingApi(async api => {
+      const createMode = 'NFT';
+      const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 
+        propPerm:   [{key: 'key1', mutable: false, collectionAdmin: false, tokenOwner: false}]});
+
+      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');
+      await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
+
+      await expect(executeTransaction(
+        api, 
+        alice, 
+        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 
+      )).to.be.rejected;
+    });
+  });
+
+  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');
+
+      await expect(executeTransaction(
+        api, 
+        bob, 
+        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 
+      )).to.be.rejected;
+    });
+  });
+
+  it('Adding property without access rights', async () => {
+    await usingApi(async api => {
+      const createMode = 'NFT';
+      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
+
+      const token = await createItemExpectSuccess(alice, newCollectionID, 'NFT');
+      await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
+      
+      await expect(executeTransaction(
+        api, 
+        bob, 
+        api.tx.unique.setTokenProperties(newCollectionID, token, [{key: 'key1', value: 'v2'}]), 
+      )).to.be.rejected;
+    });
+  });
+
+  it('Adding more than 64 prps', async () => {
+    await usingApi(async api => {
+      const createMode = 'NFT';
+
+      const prps = [];
+
+      for (let i = 0; i < 65; i++) {
+        prps.push({key: `key${i}`, value: `value${i}`});
+      }
+
+      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
+      
+      await expect(executeTransaction(api, alice, api.tx.unique.setCollectionProperties(newCollectionID, prps))).to.be.rejectedWith(/common\.PropertyLimitReached/);
+    });
+  });
+
+  it('Trying to add bigger property than allowed', async () => {
+    await usingApi(async api => {
+      const createMode = 'NFT';
+      const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
+      
+      await expect(executeTransaction(api, alice, api.tx.unique.setCollectionProperties(newCollectionID, [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]))).to.be.rejectedWith(/common\.NoSpaceForProperty/);
+    });
+  });
 });
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -19,7 +19,7 @@
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
 import privateKey from './substrate/privateKey';
-import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';
+import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync, executeTransaction} from './substrate/substrate-api';
 import {
   createCollectionExpectSuccess,
   destroyCollectionExpectSuccess,
@@ -33,6 +33,8 @@
   getVariableMetadata,
   getConstMetadata,
   getCreatedCollectionCount,
+  createCollectionWithPropsExpectSuccess,
+  getCreateItemsResult,
 } from './util/helpers';
 
 chai.use(chaiAsPromised);
@@ -45,7 +47,9 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const args = [{NFT: ['0x31', '0x31']}, {NFT: ['0x32', '0x32']}, {NFT: ['0x33', '0x33']}];
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -135,6 +139,114 @@
       expect(result.success).to.be.true;
     });
   });
+
+  it('Create  0x31, 0x32, 0x33 items in active NFT with property Admin', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      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'}}];
+      const createMultipleItemsTx = api.tx.unique
+        .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+      await submitTransactionAsync(alice, createMultipleItemsTx);
+      const itemsListIndexAfter = await getLastTokenId(api, collectionId);
+      expect(itemsListIndexAfter).to.be.equal(3);
+
+      await expect(executeTransaction(
+        api, 
+        alice, 
+        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]), 
+      )).to.not.be.rejected;
+
+      expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));
+      expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));
+      expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));
+
+      expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
+      expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
+      expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
+
+      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
+      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
+      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
+    });
+  });
+
+  it('Create  0x31, 0x32, 0x33 items in active NFT with property AdminConst', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      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'}}];
+      const createMultipleItemsTx = api.tx.unique
+        .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+      await submitTransactionAsync(alice, createMultipleItemsTx);
+      const itemsListIndexAfter = await getLastTokenId(api, collectionId);
+      expect(itemsListIndexAfter).to.be.equal(3);
+
+      await expect(executeTransaction(
+        api, 
+        alice, 
+        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]), 
+      )).to.not.be.rejected;
+
+      expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));
+      expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));
+      expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));
+
+      expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
+      expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
+      expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
+
+      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
+      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
+      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
+    });
+  });
+
+  it('Create  0x31, 0x32, 0x33 items in active NFT with property itemOwnerOrAdmin', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionExpectSuccess();
+      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'}}];
+      const createMultipleItemsTx = api.tx.unique
+        .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+      await submitTransactionAsync(alice, createMultipleItemsTx);
+      const itemsListIndexAfter = await getLastTokenId(api, collectionId);
+      expect(itemsListIndexAfter).to.be.equal(3);
+
+      await expect(executeTransaction(
+        api, 
+        alice, 
+        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]), 
+      )).to.not.be.rejected;
+
+      expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));
+      expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));
+      expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));
+
+      expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
+      expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
+      expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
+
+      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
+      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
+      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
+    });
+  });
 });
 
 describe('Integration Test createMultipleItems(collection_id, owner, items_data) with collection admin permissions:', () => {
@@ -155,7 +267,9 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const args = [{NFT: ['0x31', '0x31']}, {NFT: ['0x32', '0x32']}, {NFT: ['0x33', '0x33']}];
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);
       await submitTransactionAsync(bob, createMultipleItemsTx);
@@ -245,7 +359,9 @@
       const collectionId = await createCollectionExpectSuccess();
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
-      const args = [{NFT: ['0x31', '0x31']}, {NFT: ['0x32', '0x32']}, {NFT: ['0x33', '0x33']}];
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionAsync(bob, createMultipleItemsTx)).to.be.rejected;
@@ -361,4 +477,146 @@
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
     });
   });
+
+  it('No editing rights', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],
+        propPerm:   [{key: 'key1', mutable: true, collectionAdmin: false, tokenOwner: false}]});
+      const itemsListIndexBefore = await getLastTokenId(api, collectionId);
+      expect(itemsListIndexBefore).to.be.equal(0);
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      
+      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+
+      const events = await submitTransactionAsync(alice, createMultipleItemsTx);
+      const result = getCreateItemsResult(events);
+
+      for (const elem of result) {
+        await expect(executeTransaction(
+          api, 
+          bob, 
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+        )).to.be.rejected;
+      }
+
+      // await expect(submitTransactionAsync(bob, createMultipleItemsTx)).to.be.rejected;
+    });
+  });
+
+  it('User doesnt have editing rights', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],
+        propPerm:   [{key: 'key1', mutable: false, collectionAdmin: false, tokenOwner: false}]});
+      const itemsListIndexBefore = await getLastTokenId(api, collectionId);
+      expect(itemsListIndexBefore).to.be.equal(0);
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      
+      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+
+      const events = await submitTransactionAsync(alice, createMultipleItemsTx);
+      const result = getCreateItemsResult(events);
+
+      for (const elem of result) {
+        await expect(executeTransaction(
+          api, 
+          bob, 
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+        )).to.be.rejected;
+      }
+    });
+  });
+
+  it('Adding property without access rights', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}]});
+      const itemsListIndexBefore = await getLastTokenId(api, collectionId);
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
+      expect(itemsListIndexBefore).to.be.equal(0);
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      
+      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+
+      const events = await submitTransactionAsync(alice, createMultipleItemsTx);
+      const result = getCreateItemsResult(events);
+
+      for (const elem of result) {
+        await expect(executeTransaction(
+          api, 
+          bob, 
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+        )).to.be.rejected;
+      }
+    });
+  });
+
+  it('Adding more than 64 prps', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],
+        propPerm:   [{key: 'key1', mutable: true, collectionAdmin: true, tokenOwner: false}]});
+      const itemsListIndexBefore = await getLastTokenId(api, collectionId);
+      expect(itemsListIndexBefore).to.be.equal(0);
+      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
+
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      
+      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+      const events = await submitTransactionAsync(alice, createMultipleItemsTx);
+
+      const result = getCreateItemsResult(events);
+      
+      const prps = [];
+      
+      for (let i = 0; i < 65; i++) {
+        prps.push({key: `key${i}`, value: `value${i}`});
+      }
+
+      await expect(executeTransaction(api, bob, api.tx.unique.setCollectionProperties(collectionId, prps))).to.be.rejectedWith(/common\.PropertyLimitReached/);
+      
+      for (const elem of result) {
+        await expect(executeTransaction(
+          api, 
+          bob, 
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps), 
+        )).to.be.rejected;
+      }
+    });
+  });
+
+  it('Trying to add bigger property than allowed', async () => {
+    await usingApi(async (api: ApiPromise) => {
+      const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],
+        propPerm:   [{key: 'key1', mutable: true, collectionAdmin: false, tokenOwner: false}]});
+      const itemsListIndexBefore = await getLastTokenId(api, collectionId);
+      expect(itemsListIndexBefore).to.be.equal(0);
+      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
+        {Nft: {const_data: '0x32', variable_data: '0x32'}},
+        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      
+      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
+
+      const events = await submitTransactionAsync(alice, createMultipleItemsTx);
+      const result = getCreateItemsResult(events);
+
+
+      await expect(executeTransaction(api, alice, api.tx.unique.setCollectionProperties(collectionId, [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]))).to.be.rejectedWith(/common\.NoSpaceForProperty/);
+
+      for (const elem of result) {
+        await expect(executeTransaction(
+          api, 
+          bob, 
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]), 
+        )).to.be.rejected;
+      }
+    });
+  });
 });
modifiedtests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth
before · tests/src/createMultipleItemsEx.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {expect} from 'chai';18import privateKey from './substrate/privateKey';19import usingApi, {executeTransaction} from './substrate/substrate-api';20import {createCollectionExpectSuccess} from './util/helpers';2122describe('createMultipleItemsEx', () => {23  it('can initialize multiple NFT with different owners', async () => {24    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});25    const alice = privateKey('//Alice');26    const bob = privateKey('//Bob');27    const charlie = privateKey('//Charlie');28    await usingApi(async (api) => {29      const data = [30        {31          owner: {substrate: alice.address},32          constData: '0x0000',33          variableData: '0x1111',34        }, {35          owner: {substrate: bob.address},36          constData: '0x2222',37          variableData: '0x3333',38        }, {39          owner: {substrate: charlie.address},40          constData: '0x4444',41          variableData: '0x5555',42        },43      ];4445      await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {46        NFT: data,47      }));48      const tokens = await api.query.nonfungible.tokenData.entries(collection);49      const json = tokens.map(([, token]) => token.toJSON());50      expect(json).to.be.deep.equal(data);51    });52  });5354  it('fails when trying to set multiple owners when creating multiple refungibles', async () => {55    const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});56    const alice = privateKey('//Alice');57    const bob = privateKey('//Bob');5859    await usingApi(async (api) => {60      // Polkadot requires map, and yet requires keys to be JSON encoded61      const users = new Map();62      users.set(JSON.stringify({substrate: alice.address}), 1);63      users.set(JSON.stringify({substrate: bob.address}), 1);6465      // TODO: better error message?66      await expect(executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {67        RefungibleMultipleItems: [68          {users},69          {users},70        ],71      }))).to.be.rejectedWith(/^refungible\.NotRefungibleDataUsedToMintFungibleCollectionToken$/);72    });73  });74});
after · tests/src/createMultipleItemsEx.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {expect} from 'chai';18import privateKey from './substrate/privateKey';19import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';20import {createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, addCollectionAdminExpectSuccess, getCreateItemsResult} from './util/helpers';2122describe('createMultipleItemsEx', () => {23  it('can initialize multiple NFT with different owners', async () => {24    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});25    const alice = privateKey('//Alice');26    const bob = privateKey('//Bob');27    const charlie = privateKey('//Charlie');28    await usingApi(async (api) => {29      const data = [30        {31          owner: {substrate: alice.address},32          constData: '0x0000',33          variableData: '0x1111',34        }, {35          owner: {substrate: bob.address},36          constData: '0x2222',37          variableData: '0x3333',38        }, {39          owner: {substrate: charlie.address},40          constData: '0x4444',41          variableData: '0x5555',42        },43      ];4445      await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {46        NFT: data,47      }));48      const tokens = await api.query.nonfungible.tokenData.entries(collection);49      const json = tokens.map(([, token]) => token.toJSON());50      expect(json).to.be.deep.equal(data);51    });52  });5354  it('createMultipleItemsEx with property Admin', async () => {55    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});56    const alice = privateKey('//Alice');57    const bob = privateKey('//Bob');58    const charlie = privateKey('//Charlie');59    await usingApi(async (api) => {60      const data = [61        {62          owner: {substrate: alice.address},63          constData: '0x0000',64          variableData: '0x1111',65        }, {66          owner: {substrate: bob.address},67          constData: '0x2222',68          variableData: '0x3333',69        }, {70          owner: {substrate: charlie.address},71          constData: '0x4444',72          variableData: '0x5555',73        },74      ];7576      await expect(executeTransaction(77        api, 78        alice, 79        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]), 80      )).to.not.be.rejected;8182      await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {83        NFT: data,84      }));85      const tokens = await api.query.nonfungible.tokenData.entries(collection);86      const json = tokens.map(([, token]) => token.toJSON());87      expect(json).to.be.deep.equal(data);88    });89  });9091  it('createMultipleItemsEx with property AdminConst', async () => {92    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});93    const alice = privateKey('//Alice');94    const bob = privateKey('//Bob');95    const charlie = privateKey('//Charlie');96    await usingApi(async (api) => {97      const data = [98        {99          owner: {substrate: alice.address},100          constData: '0x0000',101          variableData: '0x1111',102        }, {103          owner: {substrate: bob.address},104          constData: '0x2222',105          variableData: '0x3333',106        }, {107          owner: {substrate: charlie.address},108          constData: '0x4444',109          variableData: '0x5555',110        },111      ];112      await expect(executeTransaction(113        api, 114        alice, 115        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]), 116      )).to.not.be.rejected;117118      await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {119        NFT: data,120      }));121      122123      const tokens = await api.query.nonfungible.tokenData.entries(collection);124      const json = tokens.map(([, token]) => token.toJSON());125      expect(json).to.be.deep.equal(data);126    });127  });128129  it('createMultipleItemsEx with property itemOwnerOrAdmin', async () => {130    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});131    const alice = privateKey('//Alice');132    const bob = privateKey('//Bob');133    const charlie = privateKey('//Charlie');134    await usingApi(async (api) => {135      const data = [136        {137          owner: {substrate: alice.address},138          constData: '0x0000',139          variableData: '0x1111',140        }, {141          owner: {substrate: bob.address},142          constData: '0x2222',143          variableData: '0x3333',144        }, {145          owner: {substrate: charlie.address},146          constData: '0x4444',147          variableData: '0x5555',148        },149      ];150      await expect(executeTransaction(151        api, 152        alice, 153        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]), 154      )).to.not.be.rejected;155156      await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {157        NFT: data,158      }));159      160161      const tokens = await api.query.nonfungible.tokenData.entries(collection);162      const json = tokens.map(([, token]) => token.toJSON());163      expect(json).to.be.deep.equal(data);164    });165  });166167  it('No editing rights', async () => {168    const collection = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],169      propPerm:   [{key: 'key1', mutable: true, collectionAdmin: false, tokenOwner: false}]});170    const alice = privateKey('//Alice');171    const bob = privateKey('//Bob');172    const charlie = privateKey('//Charlie');173    await addCollectionAdminExpectSuccess(alice, collection, bob.address);174    await usingApi(async (api) => {175      const data = [176        {177          owner: {substrate: alice.address},178        }, {179          owner: {substrate: bob.address},180        }, {181          owner: {substrate: charlie.address},182        },183      ];184185      const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});186      await executeTransaction(api, alice, tx);187      188      const events = await submitTransactionAsync(alice, tx);189      const result = getCreateItemsResult(events);190      191      for (const elem of result) {192        await expect(executeTransaction(193          api, 194          bob, 195          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 196        )).to.be.rejected;197      }198    });199  });200201  it('User doesnt have editing rights', async () => {202    const collection = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],203      propPerm:   [{key: 'key1', mutable: false, collectionAdmin: false, tokenOwner: false}]});204    const alice = privateKey('//Alice');205    const bob = privateKey('//Bob');206    const charlie = privateKey('//Charlie');207    await addCollectionAdminExpectSuccess(alice, collection, bob.address);208    await usingApi(async (api) => {209      const data = [210        {211          owner: {substrate: alice.address},212        }, {213          owner: {substrate: bob.address},214        }, {215          owner: {substrate: charlie.address},216        },217      ];218219      const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});220      await executeTransaction(api, alice, tx);221      222      const events = await submitTransactionAsync(alice, tx);223      const result = getCreateItemsResult(events);224      225      for (const elem of result) {226        await expect(executeTransaction(227          api, 228          bob, 229          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 230        )).to.be.rejected;231      }232    });233  });234235  it('Adding property without access rights', async () => {236    const collection = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}]});237    const alice = privateKey('//Alice');238    const bob = privateKey('//Bob');239    const charlie = privateKey('//Charlie');240    await addCollectionAdminExpectSuccess(alice, collection, bob.address);241    await usingApi(async (api) => {242      const data = [243        {244          owner: {substrate: alice.address},245        }, {246          owner: {substrate: bob.address},247        }, {248          owner: {substrate: charlie.address},249        },250      ];251252      const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});253      await executeTransaction(api, alice, tx);254      255      const events = await submitTransactionAsync(alice, tx);256      const result = getCreateItemsResult(events);257      258      for (const elem of result) {259        await expect(executeTransaction(260          api, 261          bob, 262          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 263        )).to.be.rejected;264      }265    });266  });267268  it('Adding more than 64 prps', async () => {269    const collection = await createCollectionWithPropsExpectSuccess();270    const alice = privateKey('//Alice');271    const bob = privateKey('//Bob');272    const charlie = privateKey('//Charlie');273    await addCollectionAdminExpectSuccess(alice, collection, bob.address);274    await usingApi(async (api) => {275      const data = [276        {277          owner: {substrate: alice.address},278        }, {279          owner: {substrate: bob.address},280        }, {281          owner: {substrate: charlie.address},282        },283      ];284285      const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});286      await executeTransaction(api, alice, tx);287      288      const events = await submitTransactionAsync(alice, tx);289      const result = getCreateItemsResult(events);290291      const prps = [];292      293      for (let i = 0; i < 65; i++) {294        prps.push({key: `key${i}`, value: `value${i}`});295      }296297      await expect(executeTransaction(api, bob, api.tx.unique.setCollectionProperties(collection, prps))).to.be.rejectedWith(/common\.PropertyLimitReached/);298299      300      for (const elem of result) {301        await expect(executeTransaction(302          api, 303          bob, 304          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps), 305        )).to.be.rejected;306      }307    });308  });309310  it('Trying to add bigger property than allowed', async () => {311    const collection = await createCollectionWithPropsExpectSuccess();312    const alice = privateKey('//Alice');313    const bob = privateKey('//Bob');314    const charlie = privateKey('//Charlie');315    await addCollectionAdminExpectSuccess(alice, collection, bob.address);316    await usingApi(async (api) => {317      const data = [318        {319          owner: {substrate: alice.address},320        }, {321          owner: {substrate: bob.address},322        }, {323          owner: {substrate: charlie.address},324        },325      ];326327      const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});328      await executeTransaction(api, alice, tx);329      330      const events = await submitTransactionAsync(alice, tx);331      const result = getCreateItemsResult(events);332333      const prps = [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}];334335      await expect(executeTransaction(api, bob, api.tx.unique.setCollectionProperties(collection, prps))).to.be.rejectedWith(/common\.NoSpaceForProperty/);336337      338      for (const elem of result) {339        await expect(executeTransaction(340          api, 341          bob, 342          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps), 343        )).to.be.rejected;344      }345    });346  });347348  it('can initialize multiple NFT with different owners', async () => {349    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});350    const alice = privateKey('//Alice');351    const bob = privateKey('//Bob');352    const charlie = privateKey('//Charlie');353    await usingApi(async (api) => {354      const data = [355        {356          owner: {substrate: alice.address},357          constData: '0x0000',358          variableData: '0x1111',359        }, {360          owner: {substrate: bob.address},361          constData: '0x2222',362          variableData: '0x3333',363        }, {364          owner: {substrate: charlie.address},365          constData: '0x4444',366          variableData: '0x5555',367        },368      ];369370      await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {371        NFT: data,372      }));373      const tokens = await api.query.nonfungible.tokenData.entries(collection);374      const json = tokens.map(([, token]) => token.toJSON());375      expect(json).to.be.deep.equal(data);376    });377  });378379  it('can initialize multiple NFT with different owners', async () => {380    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});381    const alice = privateKey('//Alice');382    const bob = privateKey('//Bob');383    const charlie = privateKey('//Charlie');384    await usingApi(async (api) => {385      const data = [386        {387          owner: {substrate: alice.address},388          constData: '0x0000',389          variableData: '0x1111',390        }, {391          owner: {substrate: bob.address},392          constData: '0x2222',393          variableData: '0x3333',394        }, {395          owner: {substrate: charlie.address},396          constData: '0x4444',397          variableData: '0x5555',398        },399      ];400401      await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {402        NFT: data,403      }));404      const tokens = await api.query.nonfungible.tokenData.entries(collection);405      const json = tokens.map(([, token]) => token.toJSON());406      expect(json).to.be.deep.equal(data);407    });408  });409410  it('fails when trying to set multiple owners when creating multiple refungibles', async () => {411    const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});412    const alice = privateKey('//Alice');413    const bob = privateKey('//Bob');414415    await usingApi(async (api) => {416      // Polkadot requires map, and yet requires keys to be JSON encoded417      const users = new Map();418      users.set(JSON.stringify({substrate: alice.address}), 1);419      users.set(JSON.stringify({substrate: bob.address}), 1);420421      // TODO: better error message?422      await expect(executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {423        RefungibleMultipleItems: [424          {users},425          {users},426        ],427      }))).to.be.rejectedWith(/^refungible\.NotRefungibleDataUsedToMintFungibleCollectionToken$/);428    });429  });430});431'';
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -201,6 +201,37 @@
   return result;
 }
 
+export function getCreateItemsResult(events: EventRecord[]): CreateItemResult[] {
+  let success = false;
+  let collectionId = 0;
+  let itemId = 0;
+  let recipient;
+
+  const results : CreateItemResult[]  = [];
+
+  events.forEach(({event: {data, method, section}}) => {
+    // console.log(`    ${phase}: ${section}.${method}:: ${data}`);
+    if (method == 'ExtrinsicSuccess') {
+      success = true;
+    } else if ((section == 'common') && (method == 'ItemCreated')) {
+      collectionId = parseInt(data[0].toString(), 10);
+      itemId = parseInt(data[1].toString(), 10);
+      recipient = normalizeAccountId(data[2].toJSON() as any);
+
+      const itemRes: CreateItemResult = {
+        success,
+        collectionId,
+        itemId,
+        recipient,
+      };
+
+      results.push(itemRes);
+    }
+  });
+
+  return results;
+}
+
 export function getCreateItemResult(events: EventRecord[]): CreateItemResult {
   let success = false;
   let collectionId = 0;
@@ -263,12 +294,26 @@
 
 type CollectionMode = Nft | Fungible | ReFungible;
 
+export type Property = {
+  key: any,
+  value: any,
+};
+
+type PropertyPermission = {
+  key: any,
+  mutable: boolean;
+  collectionAdmin: boolean;
+  tokenOwner: boolean;
+}
+
 export type CreateCollectionParams = {
   mode: CollectionMode,
   name: string,
   description: string,
   tokenPrefix: string,
   schemaVersion: string,
+  properties?: Array<Property>,
+  propPerm?: Array<PropertyPermission>
 };
 
 const defaultCreateCollectionParams: CreateCollectionParams = {
@@ -333,6 +378,86 @@
   return collectionId;
 }
 
+export async function createCollectionWithPropsExpectSuccess(params: Partial<CreateCollectionParams> = {}): Promise<number> {
+  const {name, description, mode, tokenPrefix} = {...defaultCreateCollectionParams, ...params};
+
+  let collectionId = 0;
+  await usingApi(async (api) => {
+    // Get number of collections before the transaction
+    const collectionCountBefore = await getCreatedCollectionCount(api);
+
+    // Run the CreateCollection transaction
+    const alicePrivateKey = privateKey('//Alice');
+
+    let modeprm = {};
+    if (mode.type === 'NFT') {
+      modeprm = {nft: null};
+    } else if (mode.type === 'Fungible') {
+      modeprm = {fungible: mode.decimalPoints};
+    } else if (mode.type === 'ReFungible') {
+      modeprm = {refungible: null};
+    }
+
+    const tx = api.tx.unique.createCollectionEx({name: strToUTF16(name), description: strToUTF16(description), tokenPrefix: strToUTF16(tokenPrefix), mode: modeprm as any, properties: params.properties, tokenPropertyPermissions: params.propPerm});
+    const events = await submitTransactionAsync(alicePrivateKey, tx);
+    const result = getCreateCollectionResult(events);
+
+    // Get number of collections after the transaction
+    const collectionCountAfter = await getCreatedCollectionCount(api);
+
+    // Get the collection
+    const collection = await queryCollectionExpectSuccess(api, result.collectionId);
+
+    // What to expect
+    // tslint:disable-next-line:no-unused-expression
+    expect(result.success).to.be.true;
+    expect(result.collectionId).to.be.equal(collectionCountAfter);
+    // tslint:disable-next-line:no-unused-expression
+    expect(collection).to.be.not.null;
+    expect(collectionCountAfter).to.be.equal(collectionCountBefore + 1, 'Error: NFT collection NOT created.');
+    expect(collection.owner.toString()).to.be.equal(toSubstrateAddress(alicesPublicKey));
+    expect(utf16ToStr(collection.name.toJSON() as any)).to.be.equal(name);
+    expect(utf16ToStr(collection.description.toJSON() as any)).to.be.equal(description);
+    expect(hexToStr(collection.tokenPrefix.toJSON())).to.be.equal(tokenPrefix);
+
+
+    collectionId = result.collectionId;
+  });
+
+  return collectionId;
+}
+
+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);
+
+    // Run the CreateCollection transaction
+    const alicePrivateKey = privateKey('//Alice');
+
+    let modeprm = {};
+    if (mode.type === 'NFT') {
+      modeprm = {nft: null};
+    } else if (mode.type === 'Fungible') {
+      modeprm = {fungible: mode.decimalPoints};
+    } else if (mode.type === 'ReFungible') {
+      modeprm = {refungible: null};
+    }
+
+    const tx = api.tx.unique.createCollectionEx({name: strToUTF16(name), description: strToUTF16(description), tokenPrefix: strToUTF16(tokenPrefix), mode: modeprm as any, properties: params.properties, tokenPropertyPermissions: params.propPerm});
+    await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;
+
+
+    // Get number of collections after the transaction
+    const collectionCountAfter = await getCreatedCollectionCount(api);
+
+    expect(collectionCountAfter).to.be.equal(collectionCountBefore, 'Error: Collection with incorrect data created.');
+  });
+}
+
 export async function createCollectionExpectFailure(params: Partial<CreateCollectionParams> = {}) {
   const {name, description, mode, tokenPrefix} = {...defaultCreateCollectionParams, ...params};