git.delta.rocks / unique-network / refs/commits / 340447083f1b

difftreelog

source

tests/src/createMultipleItems.test.ts22.1 KiBsourcehistory
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 {ApiPromise} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';19import chai from 'chai';20import chaiAsPromised from 'chai-as-promised';21import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync, executeTransaction} from './substrate/substrate-api';22import {23  createCollectionExpectSuccess,24  destroyCollectionExpectSuccess,25  getGenericResult,26  normalizeAccountId,27  setCollectionLimitsExpectSuccess,28  addCollectionAdminExpectSuccess,29  getBalance,30  getTokenOwner,31  getLastTokenId,32  getCreatedCollectionCount,33  createCollectionWithPropsExpectSuccess,34  createMultipleItemsWithPropsExpectSuccess,35  getTokenProperties,36  requirePallets,37  Pallets,38  checkPalletsPresence,39} from './util/helpers';40import {usingPlaygrounds} from './util/playgrounds';4142chai.use(chaiAsPromised);43const expect = chai.expect;4445let donor: IKeyringPair;4647before(async () => {48  await usingPlaygrounds(async (_, privateKey) => {49    donor = privateKey('//Alice');50  });51});5253let alice: IKeyringPair;54let bob: IKeyringPair;5556describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {57  before(async () => {58    await usingPlaygrounds(async (helper) => {59      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);60    });61  });6263  it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {64    await usingPlaygrounds(async (helper) => {65      const collection = await helper.nft.mintCollection(alice, {66        name: 'name',67        description: 'descr',68        tokenPrefix: 'COL',69        tokenPropertyPermissions: [70          {key: 'data', permission: {tokenOwner: true, mutable: false, collectionAdmin: false}},71        ],72      });73      const args = [74        {properties: [{key: 'data', value: '1'}]},75        {properties: [{key: 'data', value: '2'}]},76        {properties: [{key: 'data', value: '3'}]},77      ];78      const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);79      for (const [i, token] of tokens.entries()) {80        const tokenData = await token.getData();81        expect(tokenData?.normalizedOwner).to.be.deep.equal({Substrate: alice.address});82        expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);83      }84    });85  });8687  it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {88    await usingPlaygrounds(async (helper) => {89      const collection = await helper.ft.mintCollection(alice, {90        name: 'name',91        description: 'descr',92        tokenPrefix: 'COL',93      });94      const args = [95        {value: 1n},96        {value: 2n},97        {value: 3n},98      ];99      await helper.ft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);100      expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(6n);101    });102  });103104  it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {105    await usingPlaygrounds(async (helper) => {106      const collection = await helper.rft.mintCollection(alice, {107        name: 'name',108        description: 'descr',109        tokenPrefix: 'COL',110      });111      const args = [112        {pieces: 1n},113        {pieces: 2n},114        {pieces: 3n},115      ];116      const tokens = await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);117118      for (const [i, token] of tokens.entries()) {119        expect(await token.getBalance({Substrate: alice.address})).to.be.equal(BigInt(i + 1));120      }121    });122  });123124  it('Can mint amount of items equals to collection limits', async () => {125    await usingPlaygrounds(async (helper) => {126      const collection = await helper.nft.mintCollection(alice, {127        name: 'name',128        description: 'descr',129        tokenPrefix: 'COL',130        limits: {131          tokenLimit: 2,132        },133      });134      const args = [{}, {}];135      await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);136    });137  });138139  it('Create 0x31, 0x32, 0x33 items in active NFT with property Admin', async () => {140    await usingPlaygrounds(async (helper) => {141      const collection = await helper.nft.mintCollection(alice, {142        name: 'name',143        description: 'descr',144        tokenPrefix: 'COL',145        tokenPropertyPermissions: [146          {key: 'data', permission: {tokenOwner: false, mutable: true, collectionAdmin: true}},147        ],148      });149      const args = [150        {properties: [{key: 'data', value: '1'}]},151        {properties: [{key: 'data', value: '2'}]},152        {properties: [{key: 'data', value: '3'}]},153      ];154      const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);155      for (const [i, token] of tokens.entries()) {156        const tokenData = await token.getData();157        expect(tokenData?.normalizedOwner).to.be.deep.equal({Substrate: alice.address});158        expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);159      }160    });161  });162163  it('Create 0x31, 0x32, 0x33 items in active NFT with property AdminConst', async () => {164    await usingPlaygrounds(async (helper) => {165      const collection = await helper.nft.mintCollection(alice, {166        name: 'name',167        description: 'descr',168        tokenPrefix: 'COL',169        tokenPropertyPermissions: [170          {key: 'data', permission: {tokenOwner: false, mutable: false, collectionAdmin: true}},171        ],172      });173      const args = [174        {properties: [{key: 'data', value: '1'}]},175        {properties: [{key: 'data', value: '2'}]},176        {properties: [{key: 'data', value: '3'}]},177      ];178      const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);179      for (const [i, token] of tokens.entries()) {180        const tokenData = await token.getData();181        expect(tokenData?.normalizedOwner).to.be.deep.equal({Substrate: alice.address});182        expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);183      }184    });185  });186187  it('Create 0x31, 0x32, 0x33 items in active NFT with property itemOwnerOrAdmin', async () => {188    await usingPlaygrounds(async (helper) => {189      const collection = await helper.nft.mintCollection(alice, {190        name: 'name',191        description: 'descr',192        tokenPrefix: 'COL',193        tokenPropertyPermissions: [194          {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},195        ],196      });197      const args = [198        {properties: [{key: 'data', value: '1'}]},199        {properties: [{key: 'data', value: '2'}]},200        {properties: [{key: 'data', value: '3'}]},201      ];202      const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);203      for (const [i, token] of tokens.entries()) {204        const tokenData = await token.getData();205        expect(tokenData?.normalizedOwner).to.be.deep.equal({Substrate: alice.address});206        expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);207      }208    });209  });210});211212describe('Integration Test createMultipleItems(collection_id, owner, items_data) with collection admin permissions:', () => {213  let alice: IKeyringPair;214  let bob: IKeyringPair;215216  before(async () => {217    await usingApi(async (api, privateKeyWrapper) => {218      alice = privateKeyWrapper('//Alice');219      bob = privateKeyWrapper('//Bob');220    });221  });222223  it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {224    await usingApi(async (api: ApiPromise) => {225      const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'data', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});226      const itemsListIndexBefore = await getLastTokenId(api, collectionId);227      expect(itemsListIndexBefore).to.be.equal(0);228      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);229      const args = [230        {NFT: {properties: [{key: 'data', value: 'v1'}]}},231        {NFT: {properties: [{key: 'data', value: 'v2'}]}},232        {NFT: {properties: [{key: 'data', value: 'v3'}]}},233      ];234      const createMultipleItemsTx = api.tx.unique235        .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);236      await submitTransactionAsync(bob, createMultipleItemsTx);237      const itemsListIndexAfter = await getLastTokenId(api, collectionId);238      expect(itemsListIndexAfter).to.be.equal(3);239240      expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(bob.address));241      expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(bob.address));242      expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(bob.address));243244      expect((await getTokenProperties(api, collectionId, 1, ['data']))[0].value).to.be.equal('v1');245      expect((await getTokenProperties(api, collectionId, 2, ['data']))[0].value).to.be.equal('v2');246      expect((await getTokenProperties(api, collectionId, 3, ['data']))[0].value).to.be.equal('v3');247    });248  });249250  it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {251    await usingApi(async (api: ApiPromise) => {252      const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});253      const itemsListIndexBefore = await getLastTokenId(api, collectionId);254      expect(itemsListIndexBefore).to.be.equal(0);255      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);256      const args = [257        {Fungible: {value: 1}},258        {Fungible: {value: 2}},259        {Fungible: {value: 3}},260      ];261      const createMultipleItemsTx = api.tx.unique262        .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);263      await submitTransactionAsync(bob, createMultipleItemsTx);264      const token1Data = await getBalance(api, collectionId, bob.address, 0);265266      expect(token1Data).to.be.equal(6n); // 1 + 2 + 3267    });268  });269270  it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {271    await requirePallets(this, [Pallets.ReFungible]);272273    await usingApi(async (api: ApiPromise) => {274      const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});275      const itemsListIndexBefore = await getLastTokenId(api, collectionId);276      expect(itemsListIndexBefore).to.be.equal(0);277      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);278      const args = [279        {ReFungible: {pieces: 1}},280        {ReFungible: {pieces: 2}},281        {ReFungible: {pieces: 3}},282      ];283      const createMultipleItemsTx = api.tx.unique284        .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);285      await submitTransactionAsync(bob, createMultipleItemsTx);286      const itemsListIndexAfter = await getLastTokenId(api, collectionId);287      expect(itemsListIndexAfter).to.be.equal(3);288289      expect(await getBalance(api, collectionId, bob.address, 1)).to.be.equal(1n);290      expect(await getBalance(api, collectionId, bob.address, 2)).to.be.equal(2n);291      expect(await getBalance(api, collectionId, bob.address, 3)).to.be.equal(3n);292    });293  });294});295296describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {297  let alice: IKeyringPair;298  let bob: IKeyringPair;299300  before(async () => {301    await usingPlaygrounds(async (helper) => {302      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);303    });304  });305306  it('Regular user cannot create items in active NFT collection', async () => {307    await usingPlaygrounds(async (helper) => {308      const collection = await helper.nft.mintCollection(alice, {309        name: 'name',310        description: 'descr',311        tokenPrefix: 'COL',312      });313      const args = [314        {},315        {},316      ];317      const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(bob, collection.collectionId, {Substrate: alice.address}, args);318      await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);319    });320  });321322  it('Regular user cannot create items in active Fungible collection', async () => {323    await usingPlaygrounds(async (helper) => {324      const collection = await helper.ft.mintCollection(alice, {325        name: 'name',326        description: 'descr',327        tokenPrefix: 'COL',328      });329      const args = [330        {value: 1n},331        {value: 2n},332        {value: 3n},333      ];334      const mintTx = async () => helper.ft.mintMultipleTokensWithOneOwner(bob, collection.collectionId, {Substrate: alice.address}, args);335      await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);336    });337  });338339  it('Regular user cannot create items in active ReFungible collection', async function() {340    await usingPlaygrounds(async (helper) => {341      const collection = await helper.rft.mintCollection(alice, {342        name: 'name',343        description: 'descr',344        tokenPrefix: 'COL',345      });346      const args = [347        {pieces: 1n},348        {pieces: 1n},349        {pieces: 1n},350      ];351      const mintTx = async () => helper.rft.mintMultipleTokensWithOneOwner(bob, collection.collectionId, {Substrate: alice.address}, args);352      await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);353    });354  });355356  it('Create token in not existing collection', async () => {357    await usingPlaygrounds(async (helper) => {358      const collectionId = 1_000_000;359      const args = [360        {},361        {},362      ];363      const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(bob, collectionId, {Substrate: alice.address}, args);364      await expect(mintTx()).to.be.rejectedWith(/common\.CollectionNotFound/);365    });366  });367368  it('Create NFTs that has reached the maximum data limit', async function() {369    await usingPlaygrounds(async (helper) => {370      const collection = await helper.nft.mintCollection(alice, {371        name: 'name',372        description: 'descr',373        tokenPrefix: 'COL',374        tokenPropertyPermissions: [375          {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},376        ],377      });378      const args = [379        {properties: [{key: 'data', value: 'A'.repeat(32769)}]},380        {properties: [{key: 'data', value: 'B'.repeat(32769)}]},381        {properties: [{key: 'data', value: 'C'.repeat(32769)}]},382      ];383      const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);384      await expect(mintTx()).to.be.rejected;385    });386  });387388  it('Create Refungible tokens that has reached the maximum data limit', async function() {389    await usingPlaygrounds(async (helper) => {390      const collection = await helper.rft.mintCollection(alice, {391        name: 'name',392        description: 'descr',393        tokenPrefix: 'COL',394        tokenPropertyPermissions: [395          {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},396        ],397      });398      const args = [399        {pieces: 10n, properties: [{key: 'data', value: 'A'.repeat(32769)}]},400        {pieces: 10n, properties: [{key: 'data', value: 'B'.repeat(32769)}]},401        {pieces: 10n, properties: [{key: 'data', value: 'C'.repeat(32769)}]},402      ];403      const mintTx = async () => helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);404      await expect(mintTx()).to.be.rejected;405    });406  });407408  it('Create tokens with different types', async () => {409    await usingPlaygrounds(async (helper) => {410      const {collectionId} = await helper.nft.mintCollection(alice, {411        name: 'name',412        description: 'descr',413        tokenPrefix: 'COL',414      });415416      //FIXME:417      const types = ['NFT', 'Fungible', 'ReFungible'];418      const mintTx = helper.api?.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), types);419      await expect(helper.signTransaction(alice, mintTx)).to.be.rejected;420    });421  });422423  it('Create tokens with different data limits <> maximum data limit', async () => {424    await usingApi(async (api: ApiPromise) => {425      const collectionId = await createCollectionWithPropsExpectSuccess({426        propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],427      });428      const args = [429        {NFT: {properties: [{key: 'key', value: 'A'}]}},430        {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},431      ];432      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);433      await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;434    });435  });436437  it('Fails when minting tokens exceeds collectionLimits amount', async () => {438    await usingApi(async (api) => {439      const collectionId = await createCollectionExpectSuccess();440      await setCollectionLimitsExpectSuccess(alice, collectionId, {441        tokenLimit: 1,442      });443      const args = [444        {NFT: {}},445        {NFT: {}},446      ];447      const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);448      await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);449    });450  });451452  it('User doesnt have editing rights', async () => {453    await usingApi(async (api: ApiPromise) => {454      const collectionId = await createCollectionWithPropsExpectSuccess({455        propPerm: [{key: 'key1', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}],456      });457      const itemsListIndexBefore = await getLastTokenId(api, collectionId);458      expect(itemsListIndexBefore).to.be.equal(0);459      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);460      const args = [461        {NFT: {properties: [{key: 'key1', value: 'v2'}]}},462        {NFT: {}},463        {NFT: {}},464      ];465466      const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);467      await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);468    });469  });470471  it('Adding property without access rights', async () => {472    await usingApi(async (api: ApiPromise) => {473      const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'k', value: 'v1'}]});474      const itemsListIndexBefore = await getLastTokenId(api, collectionId);475      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);476      expect(itemsListIndexBefore).to.be.equal(0);477      const args = [{NFT: {properties: [{key: 'k', value: 'v'}]}},478        {NFT: {}},479        {NFT: {}}];480481      const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);482      await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);483    });484  });485486  it('Adding more than 64 prps', async () => {487    await usingApi(async (api: ApiPromise) => {488      const propPerms = [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}];489      for (let i = 0; i < 65; i++) {490        propPerms.push({key: `key${i}`, permission: {mutable: true, collectionAdmin: true, tokenOwner: true}});491      }492493      const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});494495      const tx1 = api.tx.unique.setTokenPropertyPermissions(collectionId, propPerms);496      await expect(executeTransaction(api, alice, tx1)).to.be.rejectedWith(/common\.PropertyLimitReached/);497498      const itemsListIndexBefore = await getLastTokenId(api, collectionId);499      expect(itemsListIndexBefore).to.be.equal(0);500      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);501502      const prps = [];503504      for (let i = 0; i < 65; i++) {505        prps.push({key: `key${i}`, value: `value${i}`});506      }507508      const args = [509        {NFT: {properties: prps}},510        {NFT: {properties: prps}},511        {NFT: {properties: prps}},512      ];513514      // there are no permissions, but will fail anyway because of too much weight for a block515      const tx2 = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);516      await expect(submitTransactionExpectFailAsync(alice, tx2)).to.be.rejected;517    });518  });519520  it('Trying to add bigger property than allowed', async () => {521    await usingApi(async (api: ApiPromise) => {522      const collectionId = await createCollectionWithPropsExpectSuccess({523        propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],524      });525      const itemsListIndexBefore = await getLastTokenId(api, collectionId);526      expect(itemsListIndexBefore).to.be.equal(0);527      const args = [{NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},528        {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},529        {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}}];530531      const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);532      await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);533    });534  });535});