difftreelog
Merge pull request #596 from UniqueNetwork/test/playground-migration
in: master
Test/playground migration
15 files changed
tests/package.jsondiffbeforeafterboth44 "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",44 "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",45 "testSetSchemaVersion": "mocha --timeout 9999999 -r ts-node/register ./**/setSchemaVersion.test.ts",45 "testSetSchemaVersion": "mocha --timeout 9999999 -r ts-node/register ./**/setSchemaVersion.test.ts",46 "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",46 "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",47 "testChangeCollectionOwner": "mocha --timeout 9999999 -r ts-node/register ./**/change-collection-owner.test.ts",47 "testSetCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionSponsor.test.ts",48 "testSetCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionSponsor.test.ts",48 "testConfirmSponsorship": "mocha --timeout 9999999 -r ts-node/register ./**/confirmSponsorship.test.ts",49 "testConfirmSponsorship": "mocha --timeout 9999999 -r ts-node/register ./**/confirmSponsorship.test.ts",49 "testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",50 "testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",tests/src/adminTransferAndBurn.test.tsdiffbeforeafterboth15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import chai from 'chai';19import chaiAsPromised from 'chai-as-promised';20import {usingPlaygrounds} from './util/playgrounds';18import {usingPlaygrounds, expect, itSub} from './util/playgrounds';2122chai.use(chaiAsPromised);23const expect = chai.expect;2425let donor: IKeyringPair;261927describe('Integration Test: ownerCanTransfer allows admins to use only transferFrom/burnFrom:', () => {20describe('Integration Test: ownerCanTransfer allows admins to use only transferFrom/burnFrom:', () => {28 let alice: IKeyringPair;21 let alice: IKeyringPair;312432 before(async () => {25 before(async () => {33 await usingPlaygrounds(async (helper, privateKey) => {26 await usingPlaygrounds(async (helper, privateKey) => {34 donor = privateKey('//Alice');27 const donor = privateKey('//Alice');35 [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);28 [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);36 });29 });37 });30 });383139 it('admin transfers other user\'s token', async () => {32 itSub('admin transfers other user\'s token', async ({helper}) => {40 await usingPlaygrounds(async (helper) => {41 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'});33 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'});42 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});34 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});43 const limits = await helper.collection.getEffectiveLimits(collectionId);35 const limits = await helper.collection.getEffectiveLimits(collectionId);50 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address});42 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address});51 const newTokenOwner = await helper.nft.getTokenOwner(collectionId, tokenId);43 const newTokenOwner = await helper.nft.getTokenOwner(collectionId, tokenId);52 expect(newTokenOwner.Substrate).to.be.equal(charlie.address);44 expect(newTokenOwner.Substrate).to.be.equal(charlie.address);53 });54 });45 });554656 it('admin burns other user\'s token', async () => {47 itSub('admin burns other user\'s token', async ({helper}) => {57 await usingPlaygrounds(async (helper) => {58 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'});48 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'});594960 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});50 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});69 await helper.nft.burnToken(bob, collectionId, tokenId);59 await helper.nft.burnToken(bob, collectionId, tokenId);70 const token = await helper.nft.getToken(collectionId, tokenId);60 const token = await helper.nft.getToken(collectionId, tokenId);71 expect(token).to.be.null;61 expect(token).to.be.null;72 });73 });62 });74});63});7564tests/src/allowLists.test.tsdiffbeforeafterboth18import {usingPlaygrounds, expect, itSub} from './util/playgrounds';18import {usingPlaygrounds, expect, itSub} from './util/playgrounds';19import {ICollectionPermissions} from './util/playgrounds/types';19import {ICollectionPermissions} from './util/playgrounds/types';202021describe('Integration Test ext. Add to Allow List', () => { 21describe('Integration Test ext. Allow list tests', () => {22 let alice: IKeyringPair;22 let alice: IKeyringPair;23 let bob: IKeyringPair;23 let bob: IKeyringPair;24 let charlie: IKeyringPair;24 let charlie: IKeyringPair;tests/src/change-collection-owner.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import chai from 'chai';18import chaiAsPromised from 'chai-as-promised';19import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';17import {IKeyringPair} from '@polkadot/types/types';20import {createCollectionExpectSuccess,18import {usingPlaygrounds, expect, itSub} from './util/playgrounds';21 addCollectionAdminExpectSuccess,22 setCollectionSponsorExpectSuccess,23 confirmSponsorshipExpectSuccess,24 removeCollectionSponsorExpectSuccess,25 enableAllowListExpectSuccess,26 setMintPermissionExpectSuccess,27 destroyCollectionExpectSuccess,28 setCollectionSponsorExpectFailure,29 confirmSponsorshipExpectFailure,30 removeCollectionSponsorExpectFailure,31 enableAllowListExpectFail,32 setMintPermissionExpectFailure,33 destroyCollectionExpectFailure,34 setPublicAccessModeExpectSuccess,35 queryCollectionExpectSuccess,36} from './util/helpers';3738chai.use(chaiAsPromised);39const expect = chai.expect;401941describe('Integration Test changeCollectionOwner(collection_id, new_owner):', () => {20describe('Integration Test changeCollectionOwner(collection_id, new_owner):', () => {21 let alice: IKeyringPair;22 let bob: IKeyringPair;2324 before(async () => {25 await usingPlaygrounds(async (helper, privateKey) => {26 const donor = privateKey('//Alice');27 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);28 });29 });3042 it('Changing owner changes owner address', async () => {31 itSub('Changing owner changes owner address', async ({helper}) => {43 await usingApi(async (api, privateKeyWrapper) => {32 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});33 const beforeChanging = await helper.collection.getData(collection.collectionId);44 const collectionId = await createCollectionExpectSuccess();34 expect(beforeChanging?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(alice.address));45 const alice = privateKeyWrapper('//Alice');46 const bob = privateKeyWrapper('//Bob');4748 const collection =await queryCollectionExpectSuccess(api, collectionId);49 expect(collection.owner.toString()).to.be.deep.eq(alice.address);503551 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);36 await collection.changeOwner(alice, bob.address);52 await submitTransactionAsync(alice, changeOwnerTx);5354 const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);37 const afterChanging = await helper.collection.getData(collection.collectionId);55 expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(bob.address);38 expect(afterChanging?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(bob.address));56 });57 });39 });58});40});594160describe('Integration Test changeCollectionOwner(collection_id, new_owner) special checks for exOwner:', () => {42describe('Integration Test changeCollectionOwner(collection_id, new_owner) special checks for exOwner:', () => {43 let alice: IKeyringPair;44 let bob: IKeyringPair;45 let charlie: IKeyringPair;4647 before(async () => {48 await usingPlaygrounds(async (helper, privateKey) => {49 const donor = privateKey('//Alice');50 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);51 });52 });5361 it('Changing the owner of the collection is not allowed for the former owner', async () => {54 itSub('Changing the owner of the collection is not allowed for the former owner', async ({helper}) => {62 await usingApi(async (api, privateKeyWrapper) => {55 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});5663 const collectionId = await createCollectionExpectSuccess();57 await collection.changeOwner(alice, bob.address);64 const alice = privateKeyWrapper('//Alice');65 const bob = privateKeyWrapper('//Bob');6667 const collection = await queryCollectionExpectSuccess(api, collectionId);68 expect(collection.owner.toString()).to.be.deep.eq(alice.address);6970 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);71 await submitTransactionAsync(alice, changeOwnerTx);725873 const badChangeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, alice.address);59 const changeOwnerTx = async () => collection.changeOwner(alice, alice.address);74 await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected;60 await expect(changeOwnerTx()).to.be.rejectedWith(/common\.NoPermission/);756176 const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);62 const afterChanging = await helper.collection.getData(collection.collectionId);77 expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(bob.address);63 expect(afterChanging?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(bob.address));78 });79 });64 });806581 it('New collectionOwner has access to sponsorship management operations in the collection', async () => {66 itSub('New collectionOwner has access to sponsorship management operations in the collection', async ({helper}) => {82 await usingApi(async (api, privateKeyWrapper) => {67 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});83 const collectionId = await createCollectionExpectSuccess();68 await collection.changeOwner(alice, bob.address);84 const alice = privateKeyWrapper('//Alice');85 const bob = privateKeyWrapper('//Bob');86 const charlie = privateKeyWrapper('//Charlie');8788 const collection = await queryCollectionExpectSuccess(api, collectionId);89 expect(collection.owner.toString()).to.be.deep.eq(alice.address);906991 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);70 const afterChanging = await helper.collection.getData(collection.collectionId);92 await submitTransactionAsync(alice, changeOwnerTx);9394 const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);95 expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(bob.address);71 expect(afterChanging?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(bob.address));967297 // After changing the owner of the collection, all privileged methods are available to the new owner98 // The new owner of the collection has access to sponsorship management operations in the collection99 await setCollectionSponsorExpectSuccess(collectionId, charlie.address, '//Bob');73 await collection.setSponsor(bob, charlie.address);100 await confirmSponsorshipExpectSuccess(collectionId, '//Charlie');74 await collection.confirmSponsorship(charlie);101 await removeCollectionSponsorExpectSuccess(collectionId, '//Bob');75 await collection.removeSponsor(bob);102103 // The new owner of the collection has access to operations for managing the collection parameters104 const collectionLimits = {76 const limits = {105 accountTokenOwnershipLimit: 1,77 accountTokenOwnershipLimit: 1,106 sponsoredMintSize: 1,107 tokenLimit: 1,78 tokenLimit: 1,108 sponsorTransferTimeout: 1,79 sponsorTransferTimeout: 1,109 ownerCanTransfer: true,80 ownerCanDestroy: true,110 ownerCanDestroy: true,81 ownerCanTransfer: true,111 };82 };83112 const tx1 = api.tx.unique.setCollectionLimits(84 await collection.setLimits(bob, limits);113 collectionId,114 collectionLimits,115 );116 await submitTransactionAsync(bob, tx1);85 const gotLimits = await collection.getEffectiveLimits();86 expect(gotLimits).to.be.deep.contains(limits);11787118 await setPublicAccessModeExpectSuccess(bob, collectionId, 'AllowList');88 await collection.setPermissions(bob, {access: 'AllowList', mintMode: true});89119 await enableAllowListExpectSuccess(bob, collectionId);90 await collection.burn(bob);120 await setMintPermissionExpectSuccess(bob, collectionId, true);91 const collectionData = await helper.collection.getData(collection.collectionId);121 await destroyCollectionExpectSuccess(collectionId, '//Bob');92 expect(collectionData).to.be.null;122 });123 });93 });12494125 it('New collectionOwner has access to changeCollectionOwner', async () => {95 itSub('New collectionOwner has access to changeCollectionOwner', async ({helper}) => {126 await usingApi(async (api, privateKeyWrapper) => {96 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});127 const collectionId = await createCollectionExpectSuccess();97 await collection.changeOwner(alice, bob.address);128 const alice = privateKeyWrapper('//Alice');129 const bob = privateKeyWrapper('//Bob');130 const charlie = privateKeyWrapper('//Charlie');131132 const collection = await queryCollectionExpectSuccess(api, collectionId);133 expect(collection.owner.toString()).to.be.deep.eq(alice.address);134135 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);136 await submitTransactionAsync(alice, changeOwnerTx);137138 const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);139 expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(bob.address);140141 const changeOwnerTx2 = api.tx.unique.changeCollectionOwner(collectionId, charlie.address);98 await collection.changeOwner(bob, charlie.address);142 await submitTransactionAsync(bob, changeOwnerTx2);143144 // ownership lost145 const collectionAfterOwnerChange2 = await queryCollectionExpectSuccess(api, collectionId);99 const collectionData = await collection.getData();146 expect(collectionAfterOwnerChange2.owner.toString()).to.be.deep.eq(charlie.address);100 expect(collectionData?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(charlie.address));147 });148 });101 });149});102});150103151describe('Negative Integration Test changeCollectionOwner(collection_id, new_owner):', () => {104describe('Negative Integration Test changeCollectionOwner(collection_id, new_owner):', () => {105 let alice: IKeyringPair;106 let bob: IKeyringPair;107 let charlie: IKeyringPair;108152 it('Not owner can\'t change owner.', async () => {109 before(async () => {153 await usingApi(async (api, privateKeyWrapper) => {110 await usingPlaygrounds(async (helper, privateKey) => {154 const collectionId = await createCollectionExpectSuccess();155 const alice = privateKeyWrapper('//Alice');111 const donor = privateKey('//Alice');156 const bob = privateKeyWrapper('//Bob');157158 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);112 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);159 await expect(submitTransactionExpectFailAsync(bob, changeOwnerTx)).to.be.rejected;160161 const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);162 expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(alice.address);163164 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)165 await createCollectionExpectSuccess();166 });113 });167 });114 });115116 itSub('Not owner can\'t change owner.', async ({helper}) => {117 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});118 const changeOwnerTx = async () => collection.changeOwner(bob, bob.address);119 await expect(changeOwnerTx()).to.be.rejectedWith(/common\.NoPermission/);120 });168121169 it('Collection admin can\'t change owner.', async () => {122 itSub('Collection admin can\'t change owner.', async ({helper}) => {170 await usingApi(async (api, privateKeyWrapper) => {123 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});171 const collectionId = await createCollectionExpectSuccess();124 await collection.addAdmin(alice, {Substrate: bob.address});172 const alice = privateKeyWrapper('//Alice');173 const bob = privateKeyWrapper('//Bob');174175 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);176177 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);125 const changeOwnerTx = async () => collection.changeOwner(bob, bob.address);178 await expect(submitTransactionExpectFailAsync(bob, changeOwnerTx)).to.be.rejected;126 await expect(changeOwnerTx()).to.be.rejectedWith(/common\.NoPermission/);179180 const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);181 expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(alice.address);182183 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)184 await createCollectionExpectSuccess();185 });186 });127 });187128188 it('Can\'t change owner of a non-existing collection.', async () => {129 itSub('Can\'t change owner of a non-existing collection.', async ({helper}) => {189 await usingApi(async (api, privateKeyWrapper) => {190 const collectionId = (1<<32) - 1;130 const collectionId = (1 << 32) - 1;191 const alice = privateKeyWrapper('//Alice');192 const bob = privateKeyWrapper('//Bob');193194 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);131 const changeOwnerTx = async () => helper.collection.changeOwner(bob, collectionId, bob.address);195 await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;132 await expect(changeOwnerTx()).to.be.rejectedWith(/common\.CollectionNotFound/);196197 // Verifying that nothing bad happened (network is live, new collections can be created, etc.)198 await createCollectionExpectSuccess();199 });200 });133 });201134202 it('Former collectionOwner not allowed to sponsorship management operations in the collection', async () => {135 itSub('Former collectionOwner not allowed to sponsorship management operations in the collection', async ({helper}) => {203 await usingApi(async (api, privateKeyWrapper) => {136 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});204 const collectionId = await createCollectionExpectSuccess();137 await collection.changeOwner(alice, bob.address);138205 const alice = privateKeyWrapper('//Alice');139 const changeOwnerTx = async () => collection.changeOwner(alice, alice.address);206 const bob = privateKeyWrapper('//Bob');140 await expect(changeOwnerTx()).to.be.rejectedWith(/common\.NoPermission/);207 const charlie = privateKeyWrapper('//Charlie');208141209 const collection = await queryCollectionExpectSuccess(api, collectionId);142 const afterChanging = await helper.collection.getData(collection.collectionId);210 expect(collection.owner.toString()).to.be.deep.eq(alice.address);143 expect(afterChanging?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(bob.address));211144212 const changeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, bob.address);145 const setSponsorTx = async () => collection.setSponsor(alice, charlie.address);213 await submitTransactionAsync(alice, changeOwnerTx);146 const confirmSponsorshipTx = async () => collection.confirmSponsorship(alice);214215 const badChangeOwnerTx = api.tx.unique.changeCollectionOwner(collectionId, alice.address);147 const removeSponsorTx = async () => collection.removeSponsor(alice);216 await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected;148 await expect(setSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);217218 const collectionAfterOwnerChange = await queryCollectionExpectSuccess(api, collectionId);219 expect(collectionAfterOwnerChange.owner.toString()).to.be.deep.eq(bob.address);149 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);220221 await setCollectionSponsorExpectFailure(collectionId, charlie.address, '//Alice');150 await expect(removeSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);222 await confirmSponsorshipExpectFailure(collectionId, '//Alice');223 await removeCollectionSponsorExpectFailure(collectionId, '//Alice');224151225 const collectionLimits = {152 const limits = {226 accountTokenOwnershipLimit: 1,153 accountTokenOwnershipLimit: 1,227 sponsoredMintSize: 1,228 tokenLimit: 1,154 tokenLimit: 1,229 sponsorTransferTimeout: 1,155 sponsorTransferTimeout: 1,230 ownerCanTransfer: true,156 ownerCanDestroy: true,231 ownerCanDestroy: true,157 ownerCanTransfer: true,232 };158 };159233 const tx1 = api.tx.unique.setCollectionLimits(160 const setLimitsTx = async () => collection.setLimits(alice, limits);234 collectionId,235 collectionLimits,236 );237 await expect(submitTransactionExpectFailAsync(alice, tx1)).to.be.rejected;161 await expect(setLimitsTx()).to.be.rejectedWith(/common\.NoPermission/);238162239 await enableAllowListExpectFail(alice, collectionId);163 const setPermissionTx = async () => collection.setPermissions(alice, {access: 'AllowList', mintMode: true});240 await setMintPermissionExpectFailure(alice, collectionId, true);164 await expect(setPermissionTx()).to.be.rejectedWith(/common\.NoPermission/);165166 const burnTx = async () => collection.burn(alice);241 await destroyCollectionExpectFailure(collectionId, '//Alice');167 await expect(burnTx()).to.be.rejectedWith(/common\.NoPermission/);242 });243 });168 });244});169});245170tests/src/confirmSponsorship.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import chai from 'chai';18import chaiAsPromised from 'chai-as-promised';19import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';20import {21 createCollectionExpectSuccess,22 setCollectionSponsorExpectSuccess,23 destroyCollectionExpectSuccess,24 confirmSponsorshipExpectSuccess,25 confirmSponsorshipExpectFailure,26 createItemExpectSuccess,27 findUnusedAddress,28 getGenericResult,29 enableAllowListExpectSuccess,30 enablePublicMintingExpectSuccess,31 addToAllowListExpectSuccess,32 normalizeAccountId,33 addCollectionAdminExpectSuccess,34 getCreatedCollectionCount,35 UNIQUE,36 requirePallets,37 Pallets,38} from './util/helpers';39import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {usingPlaygrounds, expect, itSub, Pallets} from './util/playgrounds';401920async function setSponsorHelper(collection: any, signer: IKeyringPair, sponsorAddress: string) {41chai.use(chaiAsPromised);21 await collection.setSponsor(signer, sponsorAddress);42const expect = chai.expect;22 const raw = (await collection.getData())?.raw;23 expect(raw.sponsorship.Unconfirmed).to.be.equal(sponsorAddress);24}432544let alice: IKeyringPair;26async function confirmSponsorHelper(collection: any, signer: IKeyringPair) {27 await collection.confirmSponsorship(signer);45let bob: IKeyringPair;28 const raw = (await collection.getData())?.raw;46let charlie: IKeyringPair;29 expect(raw.sponsorship.Confirmed).to.be.equal(signer.address);30}473148describe('integration test: ext. confirmSponsorship():', () => {32describe('integration test: ext. confirmSponsorship():', () => {33 let alice: IKeyringPair;34 let bob: IKeyringPair;35 let charlie: IKeyringPair;36 let zeroBalance: IKeyringPair;493750 before(async () => {38 before(async () => {51 await usingApi(async (api, privateKeyWrapper) => {39 await usingPlaygrounds(async (helper, privateKey) => {52 alice = privateKeyWrapper('//Alice');40 const donor = privateKey('//Alice');53 bob = privateKeyWrapper('//Bob');41 [alice, bob, charlie, zeroBalance] = await helper.arrange.createAccounts([100n, 100n, 100n, 0n], donor);54 charlie = privateKeyWrapper('//Charlie');55 });42 });56 });43 });574458 it('Confirm collection sponsorship', async () => {45 itSub('Confirm collection sponsorship', async ({helper}) => {59 const collectionId = await createCollectionExpectSuccess();46 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});60 await setCollectionSponsorExpectSuccess(collectionId, bob.address);47 await setSponsorHelper(collection, alice, bob.address);61 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');48 await confirmSponsorHelper(collection, bob);62 });49 });5063 it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {51 itSub('Add sponsor to a collection after the same sponsor was already added and confirmed', async ({helper}) => {64 const collectionId = await createCollectionExpectSuccess();52 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});65 await setCollectionSponsorExpectSuccess(collectionId, bob.address);53 await setSponsorHelper(collection, alice, bob.address);66 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');54 await confirmSponsorHelper(collection, bob);67 await setCollectionSponsorExpectSuccess(collectionId, bob.address);55 await setSponsorHelper(collection, alice, bob.address);68 });56 });69 it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {57 itSub('Add new sponsor to a collection after another sponsor was already added and confirmed', async ({helper}) => {70 const collectionId = await createCollectionExpectSuccess();58 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});71 await setCollectionSponsorExpectSuccess(collectionId, bob.address);59 await setSponsorHelper(collection, alice, bob.address);72 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');60 await confirmSponsorHelper(collection, bob);73 await setCollectionSponsorExpectSuccess(collectionId, charlie.address);61 await setSponsorHelper(collection, alice, charlie.address);74 });62 });756376 it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {64 itSub('NFT: Transfer fees are paid by the sponsor after confirmation', async ({helper}) => {77 const collectionId = await createCollectionExpectSuccess();65 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});78 await setCollectionSponsorExpectSuccess(collectionId, bob.address);79 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');66 await collection.setSponsor(alice, bob.address);8081 await usingApi(async (api, privateKeyWrapper) => {67 await collection.confirmSponsorship(bob);82 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();68 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);8384 // Find unused address69 const token = await collection.mintToken(alice, {Substrate: zeroBalance.address});85 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);8687 // Mint token for unused address88 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);8990 // Transfer this tokens from unused address to Alice70 await token.transfer(zeroBalance, {Substrate: alice.address});91 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);92 const events = await submitTransactionAsync(zeroBalance, zeroToAlice);93 const result = getGenericResult(events);94 expect(result.success).to.be.true;9596 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();71 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);9798 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;72 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;99 });100101 });73 });10274103 it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {75 itSub('Fungible: Transfer fees are paid by the sponsor after confirmation', async ({helper}) => {104 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});76 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);105 await setCollectionSponsorExpectSuccess(collectionId, bob.address);77 await collection.setSponsor(alice, bob.address);106 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');78 await collection.confirmSponsorship(bob);107108 await usingApi(async (api, privateKeyWrapper) => {79 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);109 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();110111 // Find unused address80 await collection.mint(alice, 100n, {Substrate: zeroBalance.address});112 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);113114 // Mint token for unused address115 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);116117 // Transfer this tokens from unused address to Alice81 await collection.transfer(zeroBalance, {Substrate: alice.address}, 1n);118 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);119 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);82 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);120 const result1 = getGenericResult(events1);121 expect(result1.success).to.be.true;122123 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();124125 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;83 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;126 });127 });84 });12885129 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async function() {86 itSub.ifWithPallets('ReFungible: Transfer fees are paid by the sponsor after confirmation', [Pallets.ReFungible], async ({helper}) => {130 await requirePallets(this, [Pallets.ReFungible]);87 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});131132 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});133 await setCollectionSponsorExpectSuccess(collectionId, bob.address);88 await collection.setSponsor(alice, bob.address);134 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');89 await collection.confirmSponsorship(bob);135136 await usingApi(async (api, privateKeyWrapper) => {90 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);137 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();138139 // Find unused address91 const token = await collection.mintToken(alice, 100n, {Substrate: zeroBalance.address});140 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);141142 // Mint token for unused address143 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);144145 // Transfer this tokens from unused address to Alice92 await token.transfer(zeroBalance, {Substrate: alice.address}, 1n);146 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);147 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);93 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);148 const result1 = getGenericResult(events1);149150 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();151152 expect(result1.success).to.be.true;94 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;153 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;154 });155 });95 });15696157 it('CreateItem fees are paid by the sponsor after confirmation', async () => {97 itSub('CreateItem fees are paid by the sponsor after confirmation', async ({helper}) => {158 const collectionId = await createCollectionExpectSuccess();98 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});159 await setCollectionSponsorExpectSuccess(collectionId, bob.address);99 await collection.setSponsor(alice, bob.address);160 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');100 await collection.confirmSponsorship(bob);101 await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});102 await collection.addToAllowList(alice, {Substrate: zeroBalance.address});161103162 // Enable collection allow list104 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);163 await enableAllowListExpectSuccess(alice, collectionId);105 await collection.mintToken(zeroBalance, {Substrate: zeroBalance.address});106 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);164107165 // Enable public minting108 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;166 await enablePublicMintingExpectSuccess(alice, collectionId);167168 // Create Item169 await usingApi(async (api, privateKeyWrapper) => {170 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();171172 // Find unused address173 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);174175 // Add zeroBalance address to allow list176 await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);177178 // Mint token using unused address as signer179 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);180181 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();182183 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;184 });185 });109 });186110187 it('NFT: Sponsoring of transfers is rate limited', async () => {111 itSub('NFT: Sponsoring of transfers is rate limited', async ({helper}) => {188 const collectionId = await createCollectionExpectSuccess();112 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});189 await setCollectionSponsorExpectSuccess(collectionId, bob.address);113 await collection.setSponsor(alice, bob.address);190 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');114 await collection.confirmSponsorship(bob);191115192 await usingApi(async (api, privateKeyWrapper) => {116 const token = await collection.mintToken(alice, {Substrate: alice.address});193 // Find unused address117 await token.transfer(alice, {Substrate: zeroBalance.address});194 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);118 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);195119196 // Mint token for alice120 const transferTx = async () => token.transfer(zeroBalance, {Substrate: alice.address});197 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);121 await expect(transferTx()).to.be.rejectedWith('Inability to pay some fees');122 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);198123199 // Transfer this token from Alice to unused address and back124 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;200 // Alice to Zero gets sponsored201 const aliceToZero = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);202 const events1 = await submitTransactionAsync(alice, aliceToZero);203 const result1 = getGenericResult(events1);204205 // Second transfer should fail206 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();207 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);208 const badTransaction = async function () {209 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);210 };211 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');212 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();213214 // Try again after Zero gets some balance - now it should succeed215 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);216 await submitTransactionAsync(alice, balancetx);217 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);218 const result2 = getGenericResult(events2);219220 expect(result1.success).to.be.true;221 expect(result2.success).to.be.true;222 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);223 });224 });125 });225126226 it('Fungible: Sponsoring is rate limited', async () => {127 itSub('Fungible: Sponsoring is rate limited', async ({helper}) => {227 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});128 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});228 await setCollectionSponsorExpectSuccess(collectionId, bob.address);129 await collection.setSponsor(alice, bob.address);229 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');130 await collection.confirmSponsorship(bob);230131231 await usingApi(async (api, privateKeyWrapper) => {132 await collection.mint(alice, 100n, {Substrate: zeroBalance.address});232 // Find unused address133 await collection.transfer(zeroBalance, {Substrate: zeroBalance.address}, 1n);233 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);134 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);234135235 // Mint token for unused address136 const transferTx = async () => collection.transfer(zeroBalance, {Substrate: zeroBalance.address});236 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);137 await expect(transferTx()).to.be.rejected;138 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);237139238 // Transfer this tokens in parts from unused address to Alice140 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;239 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);240 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);241 const result1 = getGenericResult(events1);242 expect(result1.success).to.be.true;243244 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();245 await expect(submitTransactionExpectFailAsync(zeroBalance, zeroToAlice)).to.be.rejected;246 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();247248 // Try again after Zero gets some balance - now it should succeed249 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);250 await submitTransactionAsync(alice, balancetx);251 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);252 const result2 = getGenericResult(events2);253 expect(result2.success).to.be.true;254255 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);256 });257 });141 });258142259 it('ReFungible: Sponsoring is rate limited', async function() {143 itSub.ifWithPallets('ReFungible: Sponsoring is rate limited', [Pallets.ReFungible], async ({helper}) => {260 await requirePallets(this, [Pallets.ReFungible]);144 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});145 await collection.setSponsor(alice, bob.address);146 await collection.confirmSponsorship(bob);261147262 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});148 const token = await collection.mintToken(alice, 100n, {Substrate: zeroBalance.address});263 await setCollectionSponsorExpectSuccess(collectionId, bob.address);149 await token.transfer(zeroBalance, {Substrate: alice.address});264 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');265150266 await usingApi(async (api, privateKeyWrapper) => {151 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);152 const transferTx = async () => token.transfer(zeroBalance, {Substrate: alice.address});267 // Find unused address153 await expect(transferTx()).to.be.rejectedWith('Inability to pay some fees');268 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);154 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);269155270 // Mint token for alice156 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;271 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);272273 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 1);274275 // Zero to alice gets sponsored276 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);277 const result1 = getGenericResult(events1);278 expect(result1.success).to.be.true;279280 // Second transfer should fail281 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();282 await expect(submitTransactionExpectFailAsync(zeroBalance, zeroToAlice)).to.be.rejectedWith('Inability to pay some fees');283 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();284 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);285286 // Try again after Zero gets some balance - now it should succeed287 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);288 await submitTransactionAsync(alice, balancetx);289 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);290 const result2 = getGenericResult(events2);291 expect(result2.success).to.be.true;292 });293 });157 });294158295 it('NFT: Sponsoring of createItem is rate limited', async () => {159 itSub('NFT: Sponsoring of createItem is rate limited', async ({helper}) => {296 const collectionId = await createCollectionExpectSuccess();160 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});297 await setCollectionSponsorExpectSuccess(collectionId, bob.address);161 await collection.setSponsor(alice, bob.address);298 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');162 await collection.confirmSponsorship(bob);163 await collection.setPermissions(alice, {mintMode: true, access: 'AllowList'});164 await collection.addToAllowList(alice, {Substrate: zeroBalance.address});299165300 // Enable collection allow list166 await collection.mintToken(zeroBalance, {Substrate: zeroBalance.address});301 await enableAllowListExpectSuccess(alice, collectionId);302167303 // Enable public minting168 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);304 await enablePublicMintingExpectSuccess(alice, collectionId);169 const mintTx = async () => collection.mintToken(zeroBalance, {Substrate: zeroBalance.address});170 await expect(mintTx()).to.be.rejectedWith('Inability to pay some fees');171 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);305172306 await usingApi(async (api, privateKeyWrapper) => {173 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;307 // Find unused address308 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);309310 // Add zeroBalance address to allow list311 await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);312313 // Mint token using unused address as signer - gets sponsored314 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);315316 // Second mint should fail317 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();318319 const badTransaction = async function () {320 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);321 };322 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');323 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();324325 // Try again after Zero gets some balance - now it should succeed326 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);327 await submitTransactionAsync(alice, balancetx);328 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);329330 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);331 });332 });174 });333334});175});335176336describe('(!negative test!) integration test: ext. confirmSponsorship():', () => {177describe('(!negative test!) integration test: ext. confirmSponsorship():', () => {178 let alice: IKeyringPair;179 let bob: IKeyringPair;180 let charlie: IKeyringPair;181 let ownerZeroBalance: IKeyringPair;182 let senderZeroBalance: IKeyringPair;183337 before(async () => {184 before(async () => {338 await usingApi(async (api, privateKeyWrapper) => {185 await usingPlaygrounds(async (helper, privateKey) => {339 alice = privateKeyWrapper('//Alice');186 const donor = privateKey('//Alice');340 bob = privateKeyWrapper('//Bob');187 [alice, bob, charlie, ownerZeroBalance, senderZeroBalance] = await helper.arrange.createAccounts([100n, 100n, 100n, 0n, 0n], donor);341 charlie = privateKeyWrapper('//Charlie');342 });188 });343 });189 });344190345 it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {191 itSub('(!negative test!) Confirm sponsorship for a collection that never existed', async ({helper}) => {346 // Find the collection that never existed192 const collectionId = 1_000_000;347 let collectionId = 0;348 await usingApi(async (api) => {193 const confirmSponsorshipTx = async () => helper.collection.confirmSponsorship(bob, collectionId);349 collectionId = await getCreatedCollectionCount(api) + 1;350 });194 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.CollectionNotFound/);351352 await confirmSponsorshipExpectFailure(collectionId, '//Bob');353 });195 });354196355 it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {197 itSub('(!negative test!) Confirm sponsorship using a non-sponsor address', async ({helper}) => {356 const collectionId = await createCollectionExpectSuccess();198 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});357 await setCollectionSponsorExpectSuccess(collectionId, bob.address);199 await collection.setSponsor(alice, bob.address);358359 await usingApi(async (api) => {200 const confirmSponsorshipTx = async () => collection.confirmSponsorship(charlie);360 const transfer = api.tx.balances.transfer(charlie.address, 1e15);361 await submitTransactionAsync(alice, transfer);201 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);362 });363364 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');365 });202 });366203367 it('(!negative test!) Confirm sponsorship using owner address', async () => {204 itSub('(!negative test!) Confirm sponsorship using owner address', async ({helper}) => {368 const collectionId = await createCollectionExpectSuccess();205 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});369 await setCollectionSponsorExpectSuccess(collectionId, bob.address);206 await collection.setSponsor(alice, bob.address);370 await confirmSponsorshipExpectFailure(collectionId, '//Alice');207 const confirmSponsorshipTx = async () => collection.confirmSponsorship(alice);208 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);371 });209 });372210373 it('(!negative test!) Confirm sponsorship by collection admin', async () => {211 itSub('(!negative test!) Confirm sponsorship by collection admin', async ({helper}) => {374 const collectionId = await createCollectionExpectSuccess();212 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});375 await setCollectionSponsorExpectSuccess(collectionId, bob.address);213 await collection.setSponsor(alice, bob.address);376 await addCollectionAdminExpectSuccess(alice, collectionId, charlie.address);214 await collection.addAdmin(alice, {Substrate: charlie.address});377 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');215 const confirmSponsorshipTx = async () => collection.confirmSponsorship(charlie);216 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);378 });217 });379218380 it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {219 itSub('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async ({helper}) => {381 const collectionId = await createCollectionExpectSuccess();220 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});382 await confirmSponsorshipExpectFailure(collectionId, '//Bob');221 const confirmSponsorshipTx = async () => collection.confirmSponsorship(charlie);222 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);383 });223 });384224385 it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {225 itSub('(!negative test!) Confirm sponsorship in a collection that was destroyed', async ({helper}) => {386 const collectionId = await createCollectionExpectSuccess();226 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});387 await destroyCollectionExpectSuccess(collectionId);227 await collection.burn(alice);388 await confirmSponsorshipExpectFailure(collectionId, '//Bob');228 const confirmSponsorshipTx = async () => collection.confirmSponsorship(charlie);229 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.CollectionNotFound/);389 });230 });390231391 it('(!negative test!) Transfer fees are not paid by the sponsor if the transfer failed', async () => {232 itSub('(!negative test!) Transfer fees are not paid by the sponsor if the transfer failed', async ({helper}) => {392 const collectionId = await createCollectionExpectSuccess();233 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});393 await setCollectionSponsorExpectSuccess(collectionId, bob.address);394 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');395396 await usingApi(async (api, privateKeyWrapper) => {234 await collection.setSponsor(alice, bob.address);397 // Find unused address398 const ownerZeroBalance = await findUnusedAddress(api, privateKeyWrapper);399400 // Find another unused address235 await collection.confirmSponsorship(bob);401 const senderZeroBalance = await findUnusedAddress(api, privateKeyWrapper);402403 // Mint token for an unused address236 const token = await collection.mintToken(alice, {Substrate: ownerZeroBalance.address});404 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', ownerZeroBalance.address);405406 const sponsorBalanceBeforeTx = (await api.query.system.account(bob.address)).data.free.toBigInt();237 const sponsorBalanceBefore = await helper.balance.getSubstrate(bob.address);407408 // Try to transfer this token from an unsponsored unused adress to Alice238 const transferTx = async () => token.transfer(senderZeroBalance, {Substrate: alice.address});409 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);410 await expect(submitTransactionExpectFailAsync(senderZeroBalance, zeroToAlice)).to.be.rejected;239 await expect(transferTx()).to.be.rejectedWith('Inability to pay some fees');411412 const sponsorBalanceAfterTx = (await api.query.system.account(bob.address)).data.free.toBigInt();240 const sponsorBalanceAfter = await helper.balance.getSubstrate(bob.address);413414 expect(sponsorBalanceAfterTx).to.equal(sponsorBalanceBeforeTx);241 expect(sponsorBalanceAfter).to.equal(sponsorBalanceBefore);415 });416 });242 });417});243});418244tests/src/createCollection.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {IKeyringPair} from '@polkadot/types/types';17import {expect} from 'chai';18import {usingPlaygrounds, expect, itSub, Pallets} from './util/playgrounds';18import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';19import {ICollectionCreationOptions, IProperty} from './util/playgrounds/types';19import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess, requirePallets, Pallets} from './util/helpers';20import {UniqueHelper} from './util/playgrounds/unique';2122async function mintCollectionHelper(helper: UniqueHelper, signer: IKeyringPair, options: ICollectionCreationOptions, type?: 'nft' | 'fungible' | 'refungible') {23 let collection;24 if (type === 'nft') {25 collection = await helper.nft.mintCollection(signer, options);26 } else if (type === 'fungible') {27 collection = await helper.ft.mintCollection(signer, options, 0);28 } else {29 collection = await helper.rft.mintCollection(signer, options);30 }31 const data = await collection.getData();32 expect(data?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(signer.address));33 expect(data?.name).to.be.equal(options.name);34 expect(data?.description).to.be.equal(options.description);35 expect(data?.raw.tokenPrefix).to.be.equal(options.tokenPrefix);36 if (options.properties) {37 expect(data?.raw.properties).to.be.deep.equal(options.properties);38 }3940 if (options.tokenPropertyPermissions) {41 expect(data?.raw.tokenPropertyPermissions).to.be.deep.equal(options.tokenPropertyPermissions);42 }4344 return collection;45}204621describe('integration test: ext. createCollection():', () => {47describe('integration test: ext. createCollection():', () => {48 let alice: IKeyringPair;4950 before(async () => {51 await usingPlaygrounds(async (helper, privateKey) => {52 const donor = privateKey('//Alice');53 [alice] = await helper.arrange.createAccounts([100n], donor);54 });55 });22 it('Create new NFT collection', async () => {56 itSub('Create new NFT collection', async ({helper}) => {23 await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});57 await mintCollectionHelper(helper, alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 'nft');24 });58 });25 it('Create new NFT collection whith collection_name of maximum length (64 bytes)', async () => {59 itSub('Create new NFT collection whith collection_name of maximum length (64 bytes)', async ({helper}) => {26 await createCollectionExpectSuccess({name: 'A'.repeat(64)});60 await mintCollectionHelper(helper, alice, {name: 'A'.repeat(64), description: 'descr', tokenPrefix: 'COL'}, 'nft');27 });61 });28 it('Create new NFT collection whith collection_description of maximum length (256 bytes)', async () => {62 itSub('Create new NFT collection whith collection_description of maximum length (256 bytes)', async ({helper}) => {29 await createCollectionExpectSuccess({description: 'A'.repeat(256)});63 await mintCollectionHelper(helper, alice, {name: 'name', description: 'A'.repeat(256), tokenPrefix: 'COL'}, 'nft');30 });64 });31 it('Create new NFT collection whith token_prefix of maximum length (16 bytes)', async () => {65 itSub('Create new NFT collection whith token_prefix of maximum length (16 bytes)', async ({helper}) => {32 await createCollectionExpectSuccess({tokenPrefix: 'A'.repeat(16)});66 await mintCollectionHelper(helper, alice, {name: 'name', description: 'descr', tokenPrefix: 'A'.repeat(16)}, 'nft');33 });67 });34 it('Create new Fungible collection', async () => {35 await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});36 });37 it('Create new ReFungible collection', async function() {38 await requirePallets(this, [Pallets.ReFungible]);3940 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});41 });426843 it('create new collection with properties #1', async () => {69 itSub('Create new Fungible collection', async ({helper}) => {44 await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'},70 await mintCollectionHelper(helper, alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'}, 'fungible');45 properties: [{key: 'key1', value: 'val1'}],46 propPerm: [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}]});47 });71 });487249 it('create new collection with properties #2', async () => {73 itSub.ifWithPallets('Create new ReFungible collection', [Pallets.ReFungible], async ({helper}) => {50 await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'},74 await mintCollectionHelper(helper, alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'}, 'refungible');51 properties: [{key: 'key1', value: 'val1'}],52 propPerm: [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}]});53 });75 });547655 it('create new collection with properties #3', async () => {77 itSub('create new collection with properties', async ({helper}) => {56 await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'},78 await mintCollectionHelper(helper, alice, {79 name: 'name', description: 'descr', tokenPrefix: 'COL',57 properties: [{key: 'key1', value: 'val1'}],80 properties: [{key: 'key1', value: 'val1'}],58 propPerm: [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}]});81 tokenPropertyPermissions: [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}],82 }, 'nft');59 });83 });608461 it('Create new collection with extra fields', async () => {85 itSub('Create new collection with extra fields', async ({helper}) => {62 await usingApi(async (api, privateKeyWrapper) => {86 const collection = await mintCollectionHelper(helper, alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'}, 'fungible');63 const alice = privateKeyWrapper('//Alice');87 await collection.setPermissions(alice, {access: 'AllowList'});64 const bob = privateKeyWrapper('//Bob');88 await collection.setLimits(alice, {accountTokenOwnershipLimit: 3});65 const tx = api.tx.unique.createCollectionEx({89 const data = await collection.getData();66 mode: {Fungible: 8},67 permissions: {68 access: 'AllowList',69 },70 name: [1],71 description: [2],72 tokenPrefix: '0x000000',73 pendingSponsor: bob.address,74 limits: {75 accountTokenOwnershipLimit: 3,76 },77 });78 const events = await submitTransactionAsync(alice, tx);90 const limits = await collection.getEffectiveLimits();79 const result = getCreateCollectionResult(events);91 const raw = data?.raw;809281 const collection = (await getDetailedCollectionInfo(api, result.collectionId))!;82 expect(collection.owner.toString()).to.equal(alice.address);93 expect(data?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(alice.address));83 expect(collection.mode.asFungible.toNumber()).to.equal(8);84 expect(collection.permissions.access.toHuman()).to.equal('AllowList');85 expect(collection.name.map(v => v.toNumber())).to.deep.equal([1]);94 expect(data?.name).to.be.equal('name');86 expect(collection.description.map(v => v.toNumber())).to.deep.equal([2]);95 expect(data?.description).to.be.equal('descr');87 expect(collection.tokenPrefix.toString()).to.equal('0x000000');96 expect(raw.permissions.access).to.be.equal('AllowList');88 expect(collection.sponsorship.asUnconfirmed.toString()).to.equal(bob.address);97 expect(raw.mode).to.be.deep.equal({Fungible: '0'});89 expect(collection.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.equal(3);98 expect(limits.accountTokenOwnershipLimit).to.be.equal(3);90 });91 });99 });9210093 it('New collection is not external', async () => {101 itSub('New collection is not external', async ({helper}) => {94 await usingApi(async (api, privateKeyWrapper) => {95 const alice = privateKeyWrapper('//Alice');102 const collection = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'});96 const tx = api.tx.unique.createCollectionEx({ });97 const events = await submitTransactionAsync(alice, tx);98 const result = getCreateCollectionResult(events);99100 const collection = (await getDetailedCollectionInfo(api, result.collectionId))!;101 expect(collection.readOnly.toHuman()).to.be.false;102 });103 const data = await collection.getData();104 expect(data?.raw.readOnly).to.be.false;103 });105 });104});106});105107106describe('(!negative test!) integration test: ext. createCollection():', () => {108describe('(!negative test!) integration test: ext. createCollection():', () => {109 let alice: IKeyringPair;110111 before(async () => {112 await usingPlaygrounds(async (helper, privateKey) => {113 const donor = privateKey('//Alice');114 [alice] = await helper.arrange.createAccounts([100n], donor);115 });116 });117107 it('(!negative test!) create new NFT collection whith incorrect data (collection_name)', async () => {118 itSub('(!negative test!) create new NFT collection whith incorrect data (collection_name)', async ({helper}) => {108 await createCollectionExpectFailure({name: 'A'.repeat(65), mode: {type: 'NFT'}});119 const mintCollectionTx = async () => helper.nft.mintCollection(alice, {name: 'A'.repeat(65), description: 'descr', tokenPrefix: 'COL'});120 await expect(mintCollectionTx()).to.be.rejectedWith('Verification Error');109 });121 });110 it('(!negative test!) create new NFT collection whith incorrect data (collection_description)', async () => {122 itSub('(!negative test!) create new NFT collection whith incorrect data (collection_description)', async ({helper}) => {111 await createCollectionExpectFailure({description: 'A'.repeat(257), mode: {type: 'NFT'}});123 const mintCollectionTx = async () => helper.nft.mintCollection(alice, {name: 'name', description: 'A'.repeat(257), tokenPrefix: 'COL'});124 await expect(mintCollectionTx()).to.be.rejectedWith('Verification Error');112 });125 });113 it('(!negative test!) create new NFT collection whith incorrect data (token_prefix)', async () => {126 itSub('(!negative test!) create new NFT collection whith incorrect data (token_prefix)', async ({helper}) => {114 await createCollectionExpectFailure({tokenPrefix: 'A'.repeat(17), mode: {type: 'NFT'}});127 const mintCollectionTx = async () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'A'.repeat(17)});128 await expect(mintCollectionTx()).to.be.rejectedWith('Verification Error');115 });129 });130 116 it('fails when bad limits are set', async () => {131 itSub('(!negative test!) fails when bad limits are set', async ({helper}) => {117 await usingApi(async (api, privateKeyWrapper) => {132 const mintCollectionTx = async () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL', limits: {tokenLimit: 0}});118 const alice = privateKeyWrapper('//Alice');133 await expect(mintCollectionTx()).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);119 const tx = api.tx.unique.createCollectionEx({mode: 'NFT', limits: {tokenLimit: 0}});120 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/^common.CollectionTokenLimitExceeded$/);121 });122 });134 });123135124 it('(!negative test!) create collection with incorrect property limit (64 elements)', async () => {136 itSub('(!negative test!) create collection with incorrect property limit (64 elements)', async ({helper}) => {125 const props = [];137 const props: IProperty[] = [];126138127 for (let i = 0; i < 65; i++) {139 for (let i = 0; i < 65; i++) {128 props.push({key: `key${i}`, value: `value${i}`});140 props.push({key: `key${i}`, value: `value${i}`});129 }141 }130131 await createCollectionWithPropsExpectFailure({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}, properties: props});142 const mintCollectionTx = async () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL', properties: props});143 await expect(mintCollectionTx()).to.be.rejectedWith('Verification Error');132 });144 });133145134 it('(!negative test!) create collection with incorrect property limit (40 kb)', async () => {146 itSub('(!negative test!) create collection with incorrect property limit (40 kb)', async ({helper}) => {135 const props = [];147 const props: IProperty[] = [];136148137 for (let i = 0; i < 32; i++) {149 for (let i = 0; i < 32; i++) {138 props.push({key: `key${i}`.repeat(80), value: `value${i}`.repeat(80)});150 props.push({key: `key${i}`.repeat(80), value: `value${i}`.repeat(80)});139 }151 }140152141 await createCollectionWithPropsExpectFailure({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}, properties: props});153 const mintCollectionTx = async () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL', properties: props});154 await expect(mintCollectionTx()).to.be.rejectedWith('Verification Error');142 });155 });143});156});144157tests/src/createItem.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {default as usingApi, executeTransaction} from './substrate/substrate-api';18import chai from 'chai';19import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';20import {18import {usingPlaygrounds, expect, itSub, Pallets} from './util/playgrounds';21 createCollectionExpectSuccess,22 createItemExpectSuccess,23 addCollectionAdminExpectSuccess,24 createCollectionWithPropsExpectSuccess,25 createItemWithPropsExpectSuccess,26 createItemWithPropsExpectFailure,19import {IProperty, ICrossAccountId} from './util/playgrounds/types';27 createCollection,28 transferExpectSuccess,29 itApi,20import {UniqueHelper} from './util/playgrounds/unique';30 normalizeAccountId,31 getCreateItemResult,32 requirePallets,33 Pallets,34} from './util/helpers';352122async function mintTokenHelper(helper: UniqueHelper, collection: any, signer: IKeyringPair, owner: ICrossAccountId, type: 'nft' | 'fungible' | 'refungible'='nft', properties?: IProperty[]) {23 let token;36const expect = chai.expect;24 const itemCountBefore = await helper.collection.getLastTokenId(collection.collectionId);37let alice: IKeyringPair;25 const itemBalanceBefore = (await helper.callRpc('api.rpc.unique.balance', [collection.collectionId, owner, 0])).toBigInt();38let bob: IKeyringPair;26 if (type === 'nft') {27 token = await collection.mintToken(signer, owner, properties);28 } else if (type === 'fungible') {29 await collection.mint(signer, 10n, owner);30 } else {31 token = await collection.mintToken(signer, 100n, owner, properties);32 }393334 const itemCountAfter = await helper.collection.getLastTokenId(collection.collectionId);35 const itemBalanceAfter = (await helper.callRpc('api.rpc.unique.balance', [collection.collectionId, owner, 0])).toBigInt();3637 if (type === 'fungible') {38 expect(itemBalanceAfter - itemBalanceBefore).to.be.equal(10n);39 } else {40 expect(itemCountAfter).to.be.equal(itemCountBefore + 1);41 }4243 return token;44}454640describe('integration test: ext. ():', () => {47describe('integration test: ext. ():', () => {48 let alice: IKeyringPair;49 let bob: IKeyringPair;5041 before(async () => {51 before(async () => {42 await usingApi(async (api, privateKeyWrapper) => {52 await usingPlaygrounds(async (helper, privateKey) => {43 alice = privateKeyWrapper('//Alice');53 const donor = privateKey('//Alice');44 bob = privateKeyWrapper('//Bob');54 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);45 });55 });46 });56 });475748 it('Create new item in NFT collection', async () => {58 itSub('Create new item in NFT collection', async ({helper}) => {49 const createMode = 'NFT';59 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});50 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});51 await createItemExpectSuccess(alice, newCollectionID, createMode);60 await mintTokenHelper(helper, collection, alice, {Substrate: alice.address});52 });61 });53 it('Create new item in Fungible collection', async () => {62 itSub('Create new item in Fungible collection', async ({helper}) => {54 const createMode = 'Fungible';63 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);55 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});56 await createItemExpectSuccess(alice, newCollectionID, createMode);64 await mintTokenHelper(helper, collection, alice, {Substrate: alice.address}, 'fungible');57 });65 });58 itApi('Check events on create new item in Fungible collection', async ({api}) => {66 itSub('Check events on create new item in Fungible collection', async ({helper}) => {59 const createMode = 'Fungible';67 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}, 0);60 61 const newCollectionID = (await createCollection(api, alice, {mode: {type: createMode, decimalPoints: 0}})).collectionId;62 68 const to = {Substrate: alice.address};63 const to = normalizeAccountId(alice);64 {69 {65 const createData = {fungible: {value: 100}};70 const createData = {fungible: {value: 100}};66 const tx = api.tx.unique.createItem(newCollectionID, to, createData as any);71 const events = await helper.executeExtrinsic(alice, 'api.tx.unique.createItem', [collectionId, to, createData as any]);67 const events = await executeTransaction(api, alice, tx);72 const result = helper.util.extractTokensFromCreationResult(events);68 const result = getCreateItemResult(events);69 expect(result.amount).to.be.equal(100);73 expect(result.tokens[0].amount).to.be.equal(100n);70 expect(result.collectionId).to.be.equal(newCollectionID);74 expect(result.tokens[0].collectionId).to.be.equal(collectionId);71 expect(result.recipient).to.be.deep.equal(to);75 expect(result.tokens[0].owner).to.be.deep.equal(to);72 }76 }73 {77 {74 const createData = {fungible: {value: 50}};78 const createData = {fungible: {value: 50}};75 const tx = api.tx.unique.createItem(newCollectionID, to, createData as any);79 const events = await helper.executeExtrinsic(alice, 'api.tx.unique.createItem', [collectionId, to, createData as any]);76 const events = await executeTransaction(api, alice, tx);80 const result = helper.util.extractTokensFromCreationResult(events);77 const result = getCreateItemResult(events);78 expect(result.amount).to.be.equal(50);81 expect(result.tokens[0].amount).to.be.equal(50n);79 expect(result.collectionId).to.be.equal(newCollectionID);82 expect(result.tokens[0].collectionId).to.be.equal(collectionId);80 expect(result.recipient).to.be.deep.equal(to);83 expect(result.tokens[0].owner).to.be.deep.equal(to);81 }84 }8283 });85 });84 it('Create new item in ReFungible collection', async function() {86 itSub.ifWithPallets('Create new item in ReFungible collection', [Pallets.ReFungible], async ({helper}) => {85 await requirePallets(this, [Pallets.ReFungible]);8687 const createMode = 'ReFungible';88 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});87 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});89 await createItemExpectSuccess(alice, newCollectionID, createMode);88 await mintTokenHelper(helper, collection, alice, {Substrate: alice.address}, 'refungible');90 });89 });91 it('Create new item in NFT collection with collection admin permissions', async () => {90 itSub('Create new item in NFT collection with collection admin permissions', async ({helper}) => {92 const createMode = 'NFT';91 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});93 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});94 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);92 await collection.addAdmin(alice, {Substrate: bob.address});95 await createItemExpectSuccess(bob, newCollectionID, createMode);93 await mintTokenHelper(helper, collection, bob, {Substrate: alice.address});96 });94 });97 it('Create new item in Fungible collection with collection admin permissions', async () => {95 itSub('Create new item in Fungible collection with collection admin permissions', async ({helper}) => {98 const createMode = 'Fungible';96 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);99 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});100 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);97 await collection.addAdmin(alice, {Substrate: bob.address});101 await createItemExpectSuccess(bob, newCollectionID, createMode);98 await mintTokenHelper(helper, collection, bob, {Substrate: alice.address}, 'fungible');102 });99 });103 it('Create new item in ReFungible collection with collection admin permissions', async function() {100 itSub.ifWithPallets('Create new item in ReFungible collection with collection admin permissions', [Pallets.ReFungible], async ({helper}) => {104 await requirePallets(this, [Pallets.ReFungible]);105106 const createMode = 'ReFungible';107 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});101 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});108 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);102 await collection.addAdmin(alice, {Substrate: bob.address});109 await createItemExpectSuccess(bob, newCollectionID, createMode);103 await mintTokenHelper(helper, collection, bob, {Substrate: alice.address}, 'refungible');110 });104 });111105112 it('Set property Admin', async () => {106 itSub('Set property Admin', async ({helper}) => {113 const createMode = 'NFT';107 const collection = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL',114 const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 108 properties: [{key: 'k', value: 'v'}],115 propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]});109 tokenPropertyPermissions: [{key: 'k', permission: {tokenOwner: false, mutable: true, collectionAdmin: true}}],116 110 });117 await createItemWithPropsExpectSuccess(alice, newCollectionID, createMode, [{key: 'k', value: 't2'}]);111 await mintTokenHelper(helper, collection, alice, {Substrate: bob.address}, 'nft', [{key: 'k', value: 'v'}]);118 });112 });119113120 it('Set property AdminConst', async () => {114 itSub('Set property AdminConst', async ({helper}) => {121 const createMode = 'NFT';115 const collection = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL',122 const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 116 properties: [{key: 'k', value: 'v'}],123 propPerm: [{key: 'key1', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]});117 tokenPropertyPermissions: [{key: 'k', permission: {tokenOwner: false, mutable: false, collectionAdmin: true}}],124 118 });125 await createItemWithPropsExpectSuccess(alice, newCollectionID, createMode, [{key: 'key1', value: 'val1'}]);119 await mintTokenHelper(helper, collection, alice, {Substrate: bob.address}, 'nft', [{key: 'k', value: 'v'}]);126 });120 });127121128 it('Set property itemOwnerOrAdmin', async () => {122 itSub('Set property itemOwnerOrAdmin', async ({helper}) => {129 const createMode = 'NFT';123 const collection = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL',130 const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode},124 properties: [{key: 'k', value: 'v'}],131 propPerm: [{key: 'key1', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});125 tokenPropertyPermissions: [{key: 'k', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}}],132 126 });133 await createItemWithPropsExpectSuccess(alice, newCollectionID, createMode, [{key: 'key1', value: 'val1'}]);127 await mintTokenHelper(helper, collection, alice, {Substrate: bob.address}, 'nft', [{key: 'k', value: 'v'}]);134 });128 });135129136 it('Check total pieces of Fungible token', async () => {130 itSub('Check total pieces of Fungible token', async ({helper}) => {137 await usingApi(async api => {131 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);138 const createMode = 'Fungible';139 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});140 const amountPieces = 10n;132 const amount = 10n;141 const tokenId = await createItemExpectSuccess(alice, collectionId, createMode, bob.address);133 await mintTokenHelper(helper, collection, alice, {Substrate: bob.address}, 'fungible');142 {134 {143 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);135 const totalPieces = await collection.getTotalPieces();144 expect(totalPieces.isSome).to.be.true;136 expect(totalPieces).to.be.equal(amount);145 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);146 }137 }147148 await transferExpectSuccess(collectionId, tokenId, bob, alice, 1, createMode);138 await collection.transfer(bob, {Substrate: alice.address}, 1n);149 {150 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);151 expect(totalPieces.isSome).to.be.true;139 {152 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);140 const totalPieces = await collection.getTotalPieces();153 }154155 const totalPieces = (await api.rpc.unique.tokenData(collectionId, tokenId, [])).pieces;156 expect(totalPieces.toBigInt()).to.be.eq(amountPieces);141 expect(totalPieces).to.be.equal(amount);157 });142 }158 });143 });159144160 it('Check total pieces of NFT token', async () => {145 itSub('Check total pieces of NFT token', async ({helper}) => {161 await usingApi(async api => {146 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});162 const createMode = 'NFT';163 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});164 const amountPieces = 1n;147 const amount = 1n;165 const tokenId = await createItemExpectSuccess(alice, collectionId, createMode, bob.address);148 const token = await mintTokenHelper(helper, collection, alice, {Substrate: bob.address});166 {149 {167 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);150 const totalPieces = await helper.callRpc('api.rpc.unique.totalPieces', [collection.collectionId, token.tokenId]);168 expect(totalPieces.isSome).to.be.true;151 expect(totalPieces?.unwrap().toBigInt()).to.be.equal(amount);169 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);170 }152 }171172 await transferExpectSuccess(collectionId, tokenId, bob, alice, 1, createMode);153 await token.transfer(bob, {Substrate: alice.address});173 {154 {174 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);155 const totalPieces = await helper.callRpc('api.rpc.unique.totalPieces', [collection.collectionId, token.tokenId]);175 expect(totalPieces.isSome).to.be.true;156 expect(totalPieces?.unwrap().toBigInt()).to.be.equal(amount);176 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);177 }157 }178179 const totalPieces = (await api.rpc.unique.tokenData(collectionId, tokenId, [])).pieces;180 expect(totalPieces.toBigInt()).to.be.eq(amountPieces);181 });182 });158 });183159184 it('Check total pieces of ReFungible token', async function() {160 itSub.ifWithPallets('Check total pieces of ReFungible token', [Pallets.ReFungible], async ({helper}) => {185 await requirePallets(this, [Pallets.ReFungible]);186187 await usingApi(async api => {188 const createMode = 'ReFungible';161 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});189 const createCollectionResult = await createCollection(api, alice, {mode: {type: createMode}});190 const collectionId = createCollectionResult.collectionId;162 const amount = 100n;191 const amountPieces = 100n;192 const tokenId = await createItemExpectSuccess(alice, collectionId, createMode, bob.address);163 const token = await mintTokenHelper(helper, collection, alice, {Substrate: bob.address}, 'refungible');193 {164 {194 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);165 const totalPieces = await token.getTotalPieces();195 expect(totalPieces.isSome).to.be.true;166 expect(totalPieces).to.be.equal(amount);196 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);197 }167 }198199 await transferExpectSuccess(collectionId, tokenId, bob, alice, 60n, createMode);168 await token.transfer(bob, {Substrate: alice.address}, 60n);200 {169 {201 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);170 const totalPieces = await token.getTotalPieces();202 expect(totalPieces.isSome).to.be.true;171 expect(totalPieces).to.be.equal(amount);203 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);204 }172 }205206 const totalPieces = (await api.rpc.unique.tokenData(collectionId, tokenId, [])).pieces;207 expect(totalPieces.toBigInt()).to.be.eq(amountPieces);208 });209 });173 });210});174});211175212describe('Negative integration test: ext. createItem():', () => {176describe('Negative integration test: ext. createItem():', () => {177 let alice: IKeyringPair;178 let bob: IKeyringPair;179213 before(async () => {180 before(async () => {214 await usingApi(async (api, privateKeyWrapper) => {181 await usingPlaygrounds(async (helper, privateKey) => {215 alice = privateKeyWrapper('//Alice');182 const donor = privateKey('//Alice');216 bob = privateKeyWrapper('//Bob');183 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);217 });184 });218 });185 });219186220 it('Regular user cannot create new item in NFT collection', async () => {187 itSub('Regular user cannot create new item in NFT collection', async ({helper}) => {221 const createMode = 'NFT';188 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});222 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});189 const mintTx = async () => collection.mintToken(bob, {Substrate: bob.address});223 await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;190 await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);224 });191 });225 it('Regular user cannot create new item in Fungible collection', async () => {192 itSub('Regular user cannot create new item in Fungible collection', async ({helper}) => {226 const createMode = 'Fungible';193 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);227 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});194 const mintTx = async () => collection.mint(bob, 10n, {Substrate: bob.address});228 await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;195 await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);229 });196 });230 it('Regular user cannot create new item in ReFungible collection', async function() {197 itSub.ifWithPallets('Regular user cannot create new item in ReFungible collection', [Pallets.ReFungible], async ({helper}) => {231 await requirePallets(this, [Pallets.ReFungible]);198 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});232233 const createMode = 'ReFungible';234 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});199 const mintTx = async () => collection.mintToken(bob, 100n, {Substrate: bob.address});235 await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;200 await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);236 });201 });237202238 it('No editing rights', async () => {203 itSub('No editing rights', async ({helper}) => {239 await usingApi(async () => {240 const createMode = 'NFT';204 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL',241 const newCollectionID = await createCollectionWithPropsExpectSuccess({mode: {type: createMode}, 242 propPerm: [{key: 'key1', permission: {mutable: false, collectionAdmin: false, tokenOwner: false}}]});205 tokenPropertyPermissions: [{key: 'k', permission: {mutable: false, collectionAdmin: false, tokenOwner: false}}],243 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);244245 await createItemWithPropsExpectFailure(bob, newCollectionID, 'NFT', [{key: 'key1', value: 'v'}]);246 });206 });207 const mintTx = async () => collection.mintToken(alice, {Substrate: bob.address}, [{key: 'k', value: 'v'}]);208 await expect(mintTx()).to.be.rejectedWith(/common\.NoPermission/);247 });209 });248210249 it('User doesnt have editing rights', async () => {211 itSub('User doesnt have editing rights', async ({helper}) => {250 await usingApi(async () => {212 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL',251 const newCollectionID = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'key1', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}]});213 tokenPropertyPermissions: [{key: 'k', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}],252 await createItemWithPropsExpectFailure(bob, newCollectionID, 'NFT', [{key: 'key1', value: 'v'}]);253 });214 });215 const mintTx = async () => collection.mintToken(alice, {Substrate: bob.address}, [{key: 'k', value: 'v'}]);216 await expect(mintTx()).to.be.rejectedWith(/common\.NoPermission/);254 });217 });255218256 it('Adding property without access rights', async () => {219 itSub('Adding property without access rights', async ({helper}) => {257 await usingApi(async () => {220 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});258 const newCollectionID = await createCollectionWithPropsExpectSuccess();221 const mintTx = async () => collection.mintToken(alice, {Substrate: bob.address}, [{key: 'k', value: 'v'}]);259 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);260261 await createItemWithPropsExpectFailure(bob, newCollectionID, 'NFT', [{key: 'k', value: 'v'}]);262 });222 await expect(mintTx()).to.be.rejectedWith(/common\.NoPermission/);263 });223 });264224265 it('Adding more than 64 prps', async () => {225 itSub('Adding more than 64 prps', async ({helper}) => {266 await usingApi(async () => {267 const prps = [];226 const props: IProperty[] = [];268227269 for (let i = 0; i < 65; i++) {228 for (let i = 0; i < 65; i++) {270 prps.push({key: `key${i}`, value: `value${i}`});229 props.push({key: `key${i}`, value: `value${i}`});271 }230 }272231232273 const newCollectionID = await createCollectionWithPropsExpectSuccess();233 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});274 275 await createItemWithPropsExpectFailure(alice, newCollectionID, 'NFT', prps);234 const mintTx = async () => collection.mintToken(alice, {Substrate: bob.address}, props);276 });235 await expect(mintTx()).to.be.rejectedWith('Verification Error');277 });236 });278237279 it('Trying to add bigger property than allowed', async () => {238 itSub('Trying to add bigger property than allowed', async ({helper}) => {280 await usingApi(async () => {239 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL',281 const newCollectionID = await createCollectionWithPropsExpectSuccess();240 tokenPropertyPermissions: [282 283 await createItemWithPropsExpectFailure(alice, newCollectionID, 'NFT', [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]);241 {key: 'k1', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}},242 {key: 'k2', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}},243 ],284 });244 });245 const mintTx = async () => collection.mintToken(alice, {Substrate: bob.address}, [246 {key: 'k1', value: 'vvvvvv'.repeat(5000)},247 {key: 'k2', value: 'vvv'.repeat(5000)},248 ]);249 await expect(mintTx()).to.be.rejectedWith(/common\.NoSpaceForProperty/);285 });250 });286251287 it('Check total pieces for invalid Fungible token', async () => {252 itSub('Check total pieces for invalid Fungible token', async ({helper}) => {288 await usingApi(async api => {253 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);289 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}});290 const collectionId = createCollectionResult.collectionId;254 const invalidTokenId = 1_000_000;291 const invalidTokenId = 1000_000;292 255 expect((await helper.callRpc('api.rpc.unique.totalPieces', [collection.collectionId, invalidTokenId]))?.isNone).to.be.true;293 expect((await api.rpc.unique.totalPieces(collectionId, invalidTokenId)).isNone).to.be.true;294 expect((await api.rpc.unique.tokenData(collectionId, invalidTokenId, [])).pieces.toBigInt()).to.be.eq(0n);256 expect((await helper.callRpc('api.rpc.unique.tokenData', [collection.collectionId, invalidTokenId]))?.pieces.toBigInt()).to.be.equal(0n);295 });296 });257 });297258298 it('Check total pieces for invalid NFT token', async () => {259 itSub('Check total pieces for invalid NFT token', async ({helper}) => {299 await usingApi(async api => {260 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});300 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'NFT'}});301 const collectionId = createCollectionResult.collectionId;261 const invalidTokenId = 1_000_000;302 const invalidTokenId = 1000_000;303 262 expect((await helper.callRpc('api.rpc.unique.totalPieces', [collection.collectionId, invalidTokenId]))?.isNone).to.be.true;304 expect((await api.rpc.unique.totalPieces(collectionId, invalidTokenId)).isNone).to.be.true;305 expect((await api.rpc.unique.tokenData(collectionId, invalidTokenId, [])).pieces.toBigInt()).to.be.eq(0n);263 expect((await helper.callRpc('api.rpc.unique.tokenData', [collection.collectionId, invalidTokenId]))?.pieces.toBigInt()).to.be.equal(0n);306 });307 });264 });308265309 it('Check total pieces for invalid Refungible token', async function() {266 itSub.ifWithPallets('Check total pieces for invalid Refungible token', [Pallets.ReFungible], async ({helper}) => {310 await requirePallets(this, [Pallets.ReFungible]);311312 await usingApi(async api => {313 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});267 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});314 const collectionId = createCollectionResult.collectionId;268 const invalidTokenId = 1_000_000;315 const invalidTokenId = 1000_000;316 269 expect((await helper.callRpc('api.rpc.unique.totalPieces', [collection.collectionId, invalidTokenId]))?.isNone).to.be.true;317 expect((await api.rpc.unique.totalPieces(collectionId, invalidTokenId)).isNone).to.be.true;318 expect((await api.rpc.unique.tokenData(collectionId, invalidTokenId, [])).pieces.toBigInt()).to.be.eq(0n);270 expect((await helper.callRpc('api.rpc.unique.tokenData', [collection.collectionId, invalidTokenId]))?.pieces.toBigInt()).to.be.equal(0n);319 });320 });271 });321});272});322273tests/src/createMultipleItems.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {ApiPromise} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';19import chai from 'chai';18import {usingPlaygrounds, expect, Pallets, itSub} from './util/playgrounds';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';401941chai.use(chaiAsPromised);42const expect = chai.expect;4344describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {20describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {45 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {21 let alice: IKeyringPair;46 await usingApi(async (api, privateKeyWrapper) => {47 const collectionId = await createCollectionExpectSuccess();48 const itemsListIndexBefore = await getLastTokenId(api, collectionId);49 expect(itemsListIndexBefore).to.be.equal(0);502251 const alice = privateKeyWrapper('//Alice');23 before(async () => {52 await submitTransactionAsync(24 await usingPlaygrounds(async (helper, privateKey) => {53 alice, 54 api.tx.unique.setTokenPropertyPermissions(collectionId, [{key: 'data', permission: {tokenOwner: true}}]),55 );56 57 const args = [58 {NFT: {properties: [{key: 'data', value: '1'}]}},59 {NFT: {properties: [{key: 'data', value: '2'}]}},25 const donor = privateKey('//Alice');60 {NFT: {properties: [{key: 'data', value: '3'}]}},61 ];62 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);63 await submitTransactionAsync(alice, createMultipleItemsTx);26 [alice] = await helper.arrange.createAccounts([100n], donor);64 const itemsListIndexAfter = await getLastTokenId(api, collectionId);65 expect(itemsListIndexAfter).to.be.equal(3);6667 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));68 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));69 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));7071 expect((await getTokenProperties(api, collectionId, 1, ['data']))[0].value).to.be.equal('1');72 expect((await getTokenProperties(api, collectionId, 2, ['data']))[0].value).to.be.equal('2');73 expect((await getTokenProperties(api, collectionId, 3, ['data']))[0].value).to.be.equal('3');74 });27 });75 });28 });762977 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {30 itSub('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async ({helper}) => {78 await usingApi(async (api, privateKeyWrapper) => {31 const collection = await helper.nft.mintCollection(alice, {79 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});32 name: 'name',80 const itemsListIndexBefore = await getLastTokenId(api, collectionId);33 description: 'descr',81 expect(itemsListIndexBefore).to.be.equal(0);34 tokenPrefix: 'COL',82 const alice = privateKeyWrapper('//Alice');83 const args = [35 tokenPropertyPermissions: [84 {Fungible: {value: 1}},36 {key: 'data', permission: {tokenOwner: true, mutable: false, collectionAdmin: false}},85 {Fungible: {value: 2}},86 {Fungible: {value: 3}},87 ];37 ],88 const createMultipleItemsTx = api.tx.unique89 .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);90 await submitTransactionAsync(alice, createMultipleItemsTx);91 const token1Data = await getBalance(api, collectionId, alice.address, 0);9293 expect(token1Data).to.be.equal(6n); // 1 + 2 + 394 });38 });39 const args = [40 {properties: [{key: 'data', value: '1'}]},41 {properties: [{key: 'data', value: '2'}]},42 {properties: [{key: 'data', value: '3'}]},43 ];44 const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);45 for (const [i, token] of tokens.entries()) {46 const tokenData = await token.getData();47 expect(tokenData?.normalizedOwner.Substrate).to.be.deep.equal(helper.address.normalizeSubstrate(alice.address));48 expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);49 }95 });50 });965197 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {52 itSub('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async ({helper}) => {98 await requirePallets(this, [Pallets.ReFungible]);99100 await usingApi(async (api, privateKeyWrapper) => {101 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});53 const collection = await helper.ft.mintCollection(alice, {102 const itemsListIndexBefore = await getLastTokenId(api, collectionId);103 expect(itemsListIndexBefore).to.be.equal(0);104 const alice = privateKeyWrapper('//Alice');105 const args = [54 name: 'name',106 {ReFungible: {pieces: 1}},107 {ReFungible: {pieces: 2}},55 description: 'descr',108 {ReFungible: {pieces: 3}},56 tokenPrefix: 'COL',109 ];110 const createMultipleItemsTx = api.tx.unique111 .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);112 await submitTransactionAsync(alice, createMultipleItemsTx);113 const itemsListIndexAfter = await getLastTokenId(api, collectionId);114 expect(itemsListIndexAfter).to.be.equal(3);115116 expect(await getBalance(api, collectionId, alice.address, 1)).to.be.equal(1n);117 expect(await getBalance(api, collectionId, alice.address, 2)).to.be.equal(2n);118 expect(await getBalance(api, collectionId, alice.address, 3)).to.be.equal(3n);119 });57 });58 const args = [59 {value: 1n},60 {value: 2n},61 {value: 3n},62 ];63 await helper.ft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, args, {Substrate: alice.address});64 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(6n);120 });65 });12166122 it('Can mint amount of items equals to collection limits', async () => {67 itSub.ifWithPallets('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', [Pallets.ReFungible], async ({helper}) => {123 await usingApi(async (api, privateKeyWrapper) => {124 const alice = privateKeyWrapper('//Alice');68 const collection = await helper.rft.mintCollection(alice, {125126 const collectionId = await createCollectionExpectSuccess();127 await setCollectionLimitsExpectSuccess(alice, collectionId, {128 tokenLimit: 2,69 name: 'name',129 });70 description: 'descr',130 const args = [131 {NFT: {}},132 {NFT: {}},71 tokenPrefix: 'COL',133 ];134 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);135 const events = await submitTransactionAsync(alice, createMultipleItemsTx);136 const result = getGenericResult(events);137 expect(result.success).to.be.true;138 });72 });139 });73 const args = [74 {pieces: 1n},75 {pieces: 2n},76 {pieces: 3n},77 ];78 const tokens = await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);14079141 it('Create 0x31, 0x32, 0x33 items in active NFT with property Admin', async () => {80 for (const [i, token] of tokens.entries()) {142 await usingApi(async (api, privateKeyWrapper) => {143 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]});144 const itemsListIndexBefore = await getLastTokenId(api, collectionId);145 expect(itemsListIndexBefore).to.be.equal(0);146 const alice = privateKeyWrapper('//Alice');147 const args = [148 {NFT: {properties: [{key: 'k', value: 'v1'}]}},149 {NFT: {properties: [{key: 'k', value: 'v2'}]}},81 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(BigInt(i + 1));150 {NFT: {properties: [{key: 'k', value: 'v3'}]}},151 ];152153 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);154 const itemsListIndexAfter = await getLastTokenId(api, collectionId);155 expect(itemsListIndexAfter).to.be.equal(3);156157 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));158 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));159 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));160161 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');162 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');82 }163 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');164 });165 });83 });16684167 it('Create 0x31, 0x32, 0x33 items in active NFT with property AdminConst', async () => {85 itSub('Can mint amount of items equals to collection limits', async ({helper}) => {168 await usingApi(async (api, privateKeyWrapper) => {169 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]});86 const collection = await helper.nft.mintCollection(alice, {170 const itemsListIndexBefore = await getLastTokenId(api, collectionId);171 expect(itemsListIndexBefore).to.be.equal(0);172 const alice = privateKeyWrapper('//Alice');173 const bob = privateKeyWrapper('//Bob');87 name: 'name',174 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);175 const args = [88 description: 'descr',176 {NFT: {properties: [{key: 'k', value: 'v1'}]}},177 {NFT: {properties: [{key: 'k', value: 'v2'}]}},89 tokenPrefix: 'COL',178 {NFT: {properties: [{key: 'k', value: 'v3'}]}},90 limits: {179 ];91 tokenLimit: 2,180181 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);182 const itemsListIndexAfter = await getLastTokenId(api, collectionId);183 expect(itemsListIndexAfter).to.be.equal(3);184185 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));186 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));187 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));188189 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');92 },190 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');191 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');192 });93 });94 const args = [{}, {}];95 await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);193 });96 });19497195 it('Create 0x31, 0x32, 0x33 items in active NFT with property itemOwnerOrAdmin', async () => {98 itSub('Create 0x31, 0x32, 0x33 items in active NFT with property Admin', async ({helper}) => {196 await usingApi(async (api, privateKeyWrapper) => {197 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});99 const collection = await helper.nft.mintCollection(alice, {198 const itemsListIndexBefore = await getLastTokenId(api, collectionId);100 name: 'name',199 expect(itemsListIndexBefore).to.be.equal(0);101 description: 'descr',200 const alice = privateKeyWrapper('//Alice');201 const args = [102 tokenPrefix: 'COL',202 {NFT: {properties: [{key: 'k', value: 'v1'}]}},103 tokenPropertyPermissions: [203 {NFT: {properties: [{key: 'k', value: 'v2'}]}},104 {key: 'data', permission: {tokenOwner: false, mutable: true, collectionAdmin: true}},204 {NFT: {properties: [{key: 'k', value: 'v3'}]}},205 ];105 ],206207 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);208 const itemsListIndexAfter = await getLastTokenId(api, collectionId);209 expect(itemsListIndexAfter).to.be.equal(3);210211 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));212 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));213 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));214215 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');216 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');217 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');218 });106 });107 const args = [108 {properties: [{key: 'data', value: '1'}]},109 {properties: [{key: 'data', value: '2'}]},110 {properties: [{key: 'data', value: '3'}]},111 ];112 const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);113 for (const [i, token] of tokens.entries()) {114 const tokenData = await token.getData();115 expect(tokenData?.normalizedOwner.Substrate).to.be.deep.equal(helper.address.normalizeSubstrate(alice.address));116 expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);117 }219 });118 });220});221119222describe('Integration Test createMultipleItems(collection_id, owner, items_data) with collection admin permissions:', () => {120 itSub('Create 0x31, 0x32, 0x33 items in active NFT with property AdminConst', async ({helper}) => {223 let alice: IKeyringPair;121 const collection = await helper.nft.mintCollection(alice, {224 let bob: IKeyringPair;122 name: 'name',225226 before(async () => {123 description: 'descr',227 await usingApi(async (api, privateKeyWrapper) => {124 tokenPrefix: 'COL',125 tokenPropertyPermissions: [228 alice = privateKeyWrapper('//Alice');126 {key: 'data', permission: {tokenOwner: false, mutable: false, collectionAdmin: true}},229 bob = privateKeyWrapper('//Bob');127 ],230 });128 });129 const args = [130 {properties: [{key: 'data', value: '1'}]},131 {properties: [{key: 'data', value: '2'}]},132 {properties: [{key: 'data', value: '3'}]},133 ];134 const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);135 for (const [i, token] of tokens.entries()) {136 const tokenData = await token.getData();137 expect(tokenData?.normalizedOwner.Substrate).to.be.deep.equal(helper.address.normalizeSubstrate(alice.address));138 expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);139 }231 });140 });232141233 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {142 itSub('Create 0x31, 0x32, 0x33 items in active NFT with property itemOwnerOrAdmin', async ({helper}) => {234 await usingApi(async (api: ApiPromise) => {235 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'data', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});143 const collection = await helper.nft.mintCollection(alice, {236 const itemsListIndexBefore = await getLastTokenId(api, collectionId);144 name: 'name',237 expect(itemsListIndexBefore).to.be.equal(0);145 description: 'descr',238 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);239 const args = [146 tokenPrefix: 'COL',240 {NFT: {properties: [{key: 'data', value: 'v1'}]}},147 tokenPropertyPermissions: [241 {NFT: {properties: [{key: 'data', value: 'v2'}]}},148 {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},242 {NFT: {properties: [{key: 'data', value: 'v3'}]}},243 ];149 ],244 const createMultipleItemsTx = api.tx.unique245 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);246 await submitTransactionAsync(bob, createMultipleItemsTx);247 const itemsListIndexAfter = await getLastTokenId(api, collectionId);248 expect(itemsListIndexAfter).to.be.equal(3);249250 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(bob.address));251 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(bob.address));252 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(bob.address));253254 expect((await getTokenProperties(api, collectionId, 1, ['data']))[0].value).to.be.equal('v1');255 expect((await getTokenProperties(api, collectionId, 2, ['data']))[0].value).to.be.equal('v2');256 expect((await getTokenProperties(api, collectionId, 3, ['data']))[0].value).to.be.equal('v3');257 });150 });151 const args = [152 {properties: [{key: 'data', value: '1'}]},153 {properties: [{key: 'data', value: '2'}]},154 {properties: [{key: 'data', value: '3'}]},155 ];156 const tokens = await helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);157 for (const [i, token] of tokens.entries()) {158 const tokenData = await token.getData();159 expect(tokenData?.normalizedOwner.Substrate).to.be.equal(helper.address.normalizeSubstrate(alice.address));160 expect(tokenData?.properties[0].value).to.be.equal(args[i].properties[0].value);161 }258 });162 });259260 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {261 await usingApi(async (api: ApiPromise) => {262 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});263 const itemsListIndexBefore = await getLastTokenId(api, collectionId);264 expect(itemsListIndexBefore).to.be.equal(0);265 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);266 const args = [267 {Fungible: {value: 1}},268 {Fungible: {value: 2}},269 {Fungible: {value: 3}},270 ];271 const createMultipleItemsTx = api.tx.unique272 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);273 await submitTransactionAsync(bob, createMultipleItemsTx);274 const token1Data = await getBalance(api, collectionId, bob.address, 0);275276 expect(token1Data).to.be.equal(6n); // 1 + 2 + 3277 });278 });279280 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {281 await requirePallets(this, [Pallets.ReFungible]);282283 await usingApi(async (api: ApiPromise) => {284 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});285 const itemsListIndexBefore = await getLastTokenId(api, collectionId);286 expect(itemsListIndexBefore).to.be.equal(0);287 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);288 const args = [289 {ReFungible: {pieces: 1}},290 {ReFungible: {pieces: 2}},291 {ReFungible: {pieces: 3}},292 ];293 const createMultipleItemsTx = api.tx.unique294 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);295 await submitTransactionAsync(bob, createMultipleItemsTx);296 const itemsListIndexAfter = await getLastTokenId(api, collectionId);297 expect(itemsListIndexAfter).to.be.equal(3);298299 expect(await getBalance(api, collectionId, bob.address, 1)).to.be.equal(1n);300 expect(await getBalance(api, collectionId, bob.address, 2)).to.be.equal(2n);301 expect(await getBalance(api, collectionId, bob.address, 3)).to.be.equal(3n);302 });303 });304});163});305164306describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {165describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {307 let alice: IKeyringPair;166 let alice: IKeyringPair;308 let bob: IKeyringPair;167 let bob: IKeyringPair;309168310 before(async () => {169 before(async () => {311 await usingApi(async (api, privateKeyWrapper) => {170 await usingPlaygrounds(async (helper, privateKey) => {312 alice = privateKeyWrapper('//Alice');171 const donor = privateKey('//Alice');313 bob = privateKeyWrapper('//Bob');172 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);314 });173 });315 });174 });316175317 it('Regular user cannot create items in active NFT collection', async () => {176 itSub('Regular user cannot create items in active NFT collection', async ({helper}) => {318 await usingApi(async (api: ApiPromise) => {319 const collectionId = await createCollectionExpectSuccess();177 const collection = await helper.nft.mintCollection(alice, {320 const itemsListIndexBefore = await getLastTokenId(api, collectionId);321 expect(itemsListIndexBefore).to.be.equal(0);322 const args = [{NFT: {}},323 {NFT: {}},178 name: 'name',324 {NFT: {}}];179 description: 'descr',325 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);326 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);180 tokenPrefix: 'COL',327 });181 });182 const args = [183 {},184 {},185 ];186 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(bob, collection.collectionId, {Substrate: alice.address}, args);187 await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);328 });188 });329189330 it('Regular user cannot create items in active Fungible collection', async () => {190 itSub('Regular user cannot create items in active Fungible collection', async ({helper}) => {331 await usingApi(async (api: ApiPromise) => {332 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});191 const collection = await helper.ft.mintCollection(alice, {333 const itemsListIndexBefore = await getLastTokenId(api, collectionId);334 expect(itemsListIndexBefore).to.be.equal(0);335 const args = [336 {Fungible: {value: 1}},192 name: 'name',337 {Fungible: {value: 2}},193 description: 'descr',338 {Fungible: {value: 3}},194 tokenPrefix: 'COL',339 ];340 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);341 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);342 });195 });196 const args = [197 {value: 1n},198 {value: 2n},199 {value: 3n},200 ];201 const mintTx = async () => helper.ft.mintMultipleTokensWithOneOwner(bob, collection.collectionId, args, {Substrate: alice.address});202 await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);343 });203 });344204345 it('Regular user cannot create items in active ReFungible collection', async function() {205 itSub.ifWithPallets('Regular user cannot create items in active ReFungible collection', [Pallets.ReFungible], async ({helper}) => {346 await requirePallets(this, [Pallets.ReFungible]);347348 await usingApi(async (api: ApiPromise) => {349 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});206 const collection = await helper.rft.mintCollection(alice, {350 const itemsListIndexBefore = await getLastTokenId(api, collectionId);351 expect(itemsListIndexBefore).to.be.equal(0);352 const args = [353 {ReFungible: {pieces: 1}},207 name: 'name',354 {ReFungible: {pieces: 1}},208 description: 'descr',355 {ReFungible: {pieces: 1}},209 tokenPrefix: 'COL',356 ];357 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);358 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);359 });210 });211 const args = [212 {pieces: 1n},213 {pieces: 1n},214 {pieces: 1n},215 ];216 const mintTx = async () => helper.rft.mintMultipleTokensWithOneOwner(bob, collection.collectionId, {Substrate: alice.address}, args);217 await expect(mintTx()).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);360 });218 });361219362 it('Create token in not existing collection', async () => {220 itSub('Create token in not existing collection', async ({helper}) => {363 await usingApi(async (api: ApiPromise) => {221 const collectionId = 1_000_000;222 const args = [364 const collectionId = await getCreatedCollectionCount(api) + 1;223 {},224 {},365 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'NFT', 'NFT']);225 ];226 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(bob, collectionId, {Substrate: alice.address}, args);366 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/common\.CollectionNotFound/);227 await expect(mintTx()).to.be.rejectedWith(/common\.CollectionNotFound/);367 });368 });228 });369229370 it('Create NFTs that has reached the maximum data limit', async function() {230 itSub('Create NFTs that has reached the maximum data limit', async ({helper}) => {371 await usingApi(async (api, privateKeyWrapper) => {372 const collectionId = await createCollectionWithPropsExpectSuccess({231 const collection = await helper.nft.mintCollection(alice, {373 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],232 name: 'name',233 description: 'descr',374 });234 tokenPrefix: 'COL',375 const alice = privateKeyWrapper('//Alice');376 const args = [235 tokenPropertyPermissions: [377 {NFT: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},236 {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},378 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},379 {NFT: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},380 ];237 ],381 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);382 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;383 });238 });239 const args = [240 {properties: [{key: 'data', value: 'A'.repeat(32769)}]},241 {properties: [{key: 'data', value: 'B'.repeat(32769)}]},242 {properties: [{key: 'data', value: 'C'.repeat(32769)}]},243 ];244 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);245 await expect(mintTx()).to.be.rejectedWith('Verification Error');384 });246 });385247386 it('Create Refungible tokens that has reached the maximum data limit', async function() {248 itSub.ifWithPallets('Create Refungible tokens that has reached the maximum data limit', [Pallets.ReFungible], async ({helper}) => {387 await requirePallets(this, [Pallets.ReFungible]);388389 await usingApi(async api => {390 const collectionIdReFungible =249 const collection = await helper.rft.mintCollection(alice, {391 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});392 {250 name: 'name',393 const argsReFungible = [394 {ReFungible: [10, [['key', 'A'.repeat(32769)]]]},395 {ReFungible: [10, [['key', 'B'.repeat(32769)]]]},251 description: 'descr',396 {ReFungible: [10, [['key', 'C'.repeat(32769)]]]},252 tokenPrefix: 'COL',397 ];253 tokenPropertyPermissions: [398 const createMultipleItemsTxFungible = api.tx.unique399 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);400 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;401 }402 {403 const argsReFungible = [404 {ReFungible: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},254 {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},405 {ReFungible: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},406 {ReFungible: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},407 ];255 ],408 const createMultipleItemsTxFungible = api.tx.unique409 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);410 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;411 }412 });256 });257 const args = [258 {pieces: 10n, properties: [{key: 'data', value: 'A'.repeat(32769)}]},259 {pieces: 10n, properties: [{key: 'data', value: 'B'.repeat(32769)}]},260 {pieces: 10n, properties: [{key: 'data', value: 'C'.repeat(32769)}]},261 ];262 const mintTx = async () => helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);263 await expect(mintTx()).to.be.rejectedWith('Verification Error');413 });264 });414265415 it('Create tokens with different types', async () => {266 itSub.ifWithPallets('Create tokens with different types', [Pallets.ReFungible], async ({helper}) => {416 await usingApi(async (api: ApiPromise) => {417 const collectionId = await createCollectionExpectSuccess();267 const {collectionId} = await helper.nft.mintCollection(alice, {418419 const types = ['NFT', 'Fungible'];420421 if (await checkPalletsPresence([Pallets.ReFungible])) {422 types.push('ReFungible');268 name: 'name',423 }424425 const createMultipleItemsTx = api.tx.unique426 .createMultipleItems(collectionId, normalizeAccountId(alice.address), types);427 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);269 description: 'descr',428 // garbage collection :-D // lol270 tokenPrefix: 'COL',429 await destroyCollectionExpectSuccess(collectionId);430 });271 });272273 const types = ['NFT', 'Fungible', 'ReFungible'];274 await expect(helper.executeExtrinsic(275 alice, 276 'api.tx.unique.createMultipleItems', 277 [collectionId, {Substrate: alice.address}, types],278 )).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);431 });279 });432280433 it('Create tokens with different data limits <> maximum data limit', async () => {281 itSub('Create tokens with different data limits <> maximum data limit', async ({helper}) => {434 await usingApi(async (api: ApiPromise) => {435 const collectionId = await createCollectionWithPropsExpectSuccess({282 const collection = await helper.nft.mintCollection(alice, {436 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],283 name: 'name',284 description: 'descr',437 });285 tokenPrefix: 'COL',438 const args = [286 tokenPropertyPermissions: [439 {NFT: {properties: [{key: 'key', value: 'A'}]}},287 {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},440 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},441 ];288 ],442 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);443 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;444 });289 });290 const args = [291 {properties: [{key: 'data', value: 'A'}]},292 {properties: [{key: 'data', value: 'B'.repeat(32769)}]},293 ];294 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);295 await expect(mintTx()).to.be.rejectedWith('Verification Error');445 });296 });446297447 it('Fails when minting tokens exceeds collectionLimits amount', async () => {298 itSub('Fails when minting tokens exceeds collectionLimits amount', async ({helper}) => {448 await usingApi(async (api) => {299 const collection = await helper.nft.mintCollection(alice, {300 name: 'name',449 const collectionId = await createCollectionExpectSuccess();301 description: 'descr',302 tokenPrefix: 'COL',450 await setCollectionLimitsExpectSuccess(alice, collectionId, {303 tokenPropertyPermissions: [304 {key: 'data', permission: {tokenOwner: true, mutable: true, collectionAdmin: true}},305 ],306 limits: {451 tokenLimit: 1,307 tokenLimit: 1,452 });308 },453 const args = [454 {NFT: {}},455 {NFT: {}},456 ];457 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);458 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);459 });309 });310 const args = [311 {},312 {},313 ];314 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);315 await expect(mintTx()).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);460 });316 });461317462 it('User doesnt have editing rights', async () => {318 itSub('User doesnt have editing rights', async ({helper}) => {463 await usingApi(async (api: ApiPromise) => {464 const collectionId = await createCollectionWithPropsExpectSuccess({319 const collection = await helper.nft.mintCollection(alice, {465 propPerm: [{key: 'key1', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}],320 name: 'name',321 description: 'descr',466 });322 tokenPrefix: 'COL',467 const itemsListIndexBefore = await getLastTokenId(api, collectionId);468 expect(itemsListIndexBefore).to.be.equal(0);323 tokenPropertyPermissions: [469 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);470 const args = [471 {NFT: {properties: [{key: 'key1', value: 'v2'}]}},324 {key: 'data', permission: {tokenOwner: false, mutable: true, collectionAdmin: false}},472 {NFT: {}},473 {NFT: {}},474 ];325 ],475476 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);477 await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);478 });326 });327 const args = [328 {properties: [{key: 'data', value: 'A'}]},329 ];330 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);331 await expect(mintTx()).to.be.rejectedWith(/common\.NoPermission/);479 });332 });480333481 it('Adding property without access rights', async () => {334 itSub('Adding property without access rights', async ({helper}) => {482 await usingApi(async (api: ApiPromise) => {335 const collection = await helper.nft.mintCollection(alice, {483 const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'k', value: 'v1'}]});336 name: 'name',337 description: 'descr',484 const itemsListIndexBefore = await getLastTokenId(api, collectionId);338 tokenPrefix: 'COL',485 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);339 properties: [486 expect(itemsListIndexBefore).to.be.equal(0);340 {487 const args = [{NFT: {properties: [{key: 'k', value: 'v'}]}},341 key: 'data',488 {NFT: {}},342 value: 'v',489 {NFT: {}}];343 },490491 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);492 await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);344 ],493 });345 });346 const args = [347 {properties: [{key: 'data', value: 'A'}]},348 ];349 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);350 await expect(mintTx()).to.be.rejectedWith(/common\.NoPermission/);494 });351 });495352496 it('Adding more than 64 prps', async () => {353 itSub('Adding more than 64 prps', async ({helper}) => {497 await usingApi(async (api: ApiPromise) => {498 const propPerms = [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}];354 const collection = await helper.nft.mintCollection(alice, {499 for (let i = 0; i < 65; i++) {500 propPerms.push({key: `key${i}`, permission: {mutable: true, collectionAdmin: true, tokenOwner: true}});501 }502503 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});504505 const tx1 = api.tx.unique.setTokenPropertyPermissions(collectionId, propPerms);506 await expect(executeTransaction(api, alice, tx1)).to.be.rejectedWith(/common\.PropertyLimitReached/);507508 const itemsListIndexBefore = await getLastTokenId(api, collectionId);509 expect(itemsListIndexBefore).to.be.equal(0);510 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);511512 const prps = [];513514 for (let i = 0; i < 65; i++) {515 prps.push({key: `key${i}`, value: `value${i}`});355 name: 'name',516 }356 description: 'descr',517518 const args = [519 {NFT: {properties: prps}},520 {NFT: {properties: prps}},357 tokenPrefix: 'COL',521 {NFT: {properties: prps}},522 ];523524 // there are no permissions, but will fail anyway because of too much weight for a block525 const tx2 = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);526 await expect(submitTransactionExpectFailAsync(alice, tx2)).to.be.rejected;527 });358 });528 });359 const prps = [];529360530 it('Trying to add bigger property than allowed', async () => {361 for (let i = 0; i < 65; i++) {531 await usingApi(async (api: ApiPromise) => {532 const collectionId = await createCollectionWithPropsExpectSuccess({362 prps.push({key: `key${i}`, value: `value${i}`});533 propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],534 });535 const itemsListIndexBefore = await getLastTokenId(api, collectionId);536 expect(itemsListIndexBefore).to.be.equal(0);537 const args = [{NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},538 {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},539 {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}}];363 }540364541 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);365 const args = [366 {properties: prps},367 {properties: prps},368 {properties: prps},369 ];370371 const mintTx = async () => helper.nft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, args);542 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);372 await expect(mintTx()).to.be.rejectedWith('Verification Error');543 });544 });373 });545});374});546375tests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {expect} from 'chai';17import {IKeyringPair} from '@polkadot/types/types';18import usingApi, {executeTransaction} from './substrate/substrate-api';18import {usingPlaygrounds, expect, Pallets, itSub} from './util/playgrounds';19import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties, requirePallets, Pallets} from './util/helpers';19import {IProperty} from './util/playgrounds/types';202021describe('Integration Test: createMultipleItemsEx', () => {21describe('Integration Test: createMultipleItemsEx', () => {22 it('can initialize multiple NFT with different owners', async () => {22 let alice: IKeyringPair;23 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});24 await usingApi(async (api, privateKeyWrapper) => {23 let bob: IKeyringPair;25 const alice = privateKeyWrapper('//Alice');26 const bob = privateKeyWrapper('//Bob');27 const charlie = privateKeyWrapper('//Charlie');24 let charlie: IKeyringPair;28 const data = [29 {30 owner: {substrate: alice.address},31 }, {32 owner: {substrate: bob.address},33 }, {34 owner: {substrate: charlie.address},35 },36 ];372538 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {26 before(async () => {39 NFT: data,27 await usingPlaygrounds(async (helper, privateKey) => {40 }));41 const tokens = await api.query.nonfungible.tokenData.entries(collection);28 const donor = privateKey('//Alice');42 const json = tokens.map(([, token]) => token.toJSON());29 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);43 expect(json).to.be.deep.equal(data);44 });30 });45 });31 });463247 it('createMultipleItemsEx with property Admin', async () => {33 itSub('can initialize multiple NFT with different owners', async ({helper}) => {48 const collection = await createCollectionWithPropsExpectSuccess({mode: {type: 'NFT'}, propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]});34 const collection = await helper.nft.mintCollection(alice, {35 name: 'name',36 description: 'descr',37 tokenPrefix: 'COL',38 });39 const args = [40 {41 owner: {Substrate: alice.address},42 },43 {44 owner: {Substrate: bob.address},45 },46 {47 owner: {Substrate: charlie.address},48 },49 ];5049 await usingApi(async (api, privateKeyWrapper) => {51 const tokens = await collection.mintMultipleTokens(alice, args);52 for (const [i, token] of tokens.entries()) {50 const alice = privateKeyWrapper('//Alice');53 expect(await token.getOwner()).to.be.deep.equal(args[i].owner);54 }55 });5651 const bob = privateKeyWrapper('//Bob');57 itSub('createMultipleItemsEx with property Admin', async ({helper}) => {58 const collection = await helper.nft.mintCollection(alice, {59 name: 'name',52 const charlie = privateKeyWrapper('//Charlie');60 description: 'descr',61 tokenPrefix: 'COL',53 const data = [62 tokenPropertyPermissions: [54 {63 {55 owner: {substrate: alice.address},64 key: 'k',56 properties: [{key: 'k', value: 'v1'}],65 permission: {57 }, {58 owner: {substrate: bob.address},66 mutable: true,59 properties: [{key: 'k', value: 'v2'}],67 collectionAdmin: true,60 }, {68 tokenOwner: false,61 owner: {substrate: charlie.address},62 properties: [{key: 'k', value: 'v3'}],69 },63 },70 },64 ];71 ],72 });657366 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {74 const args = [75 {76 owner: {Substrate: alice.address},77 properties: [{key: 'k', value: 'v1'}],78 },79 {80 owner: {Substrate: bob.address},81 properties: [{key: 'k', value: 'v2'}],67 NFT: data,82 },83 {84 owner: {Substrate: charlie.address},68 }));85 properties: [{key: 'k', value: 'v3'}],69 for (let i = 1; i < 4; i++) {86 },87 ];8889 const tokens = await collection.mintMultipleTokens(alice, args);90 for (const [i, token] of tokens.entries()) {70 expect(await api.rpc.unique.tokenProperties(collection, i)).not.to.be.empty;91 expect(await token.getOwner()).to.be.deep.equal(args[i].owner);71 }92 expect(await token.getData()).to.not.be.empty;72 });93 }73 });94 });749575 it('createMultipleItemsEx with property AdminConst', async () => {96 itSub('createMultipleItemsEx with property AdminConst', async ({helper}) => {76 const collection = await createCollectionWithPropsExpectSuccess({mode: {type: 'NFT'}, propPerm: [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]});97 const collection = await helper.nft.mintCollection(alice, {77 await usingApi(async (api, privateKeyWrapper) => {78 const alice = privateKeyWrapper('//Alice');98 name: 'name',79 const bob = privateKeyWrapper('//Bob');99 description: 'descr',80 const charlie = privateKeyWrapper('//Charlie');100 tokenPrefix: 'COL',81 const data = [101 tokenPropertyPermissions: [82 {102 {83 owner: {substrate: alice.address},103 key: 'k',84 properties: [{key: 'k', value: 'v1'}],104 permission: {85 }, {86 owner: {substrate: bob.address},105 mutable: false,87 properties: [{key: 'k', value: 'v2'}],106 collectionAdmin: true,88 }, {107 tokenOwner: false,89 owner: {substrate: charlie.address},90 properties: [{key: 'k', value: 'v3'}],108 },91 },109 },92 ];110 ],111 });9311294 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {113 const args = [114 {115 owner: {Substrate: alice.address},116 properties: [{key: 'k', value: 'v1'}],117 },118 {119 owner: {Substrate: bob.address},120 properties: [{key: 'k', value: 'v2'}],95 NFT: data,121 },122 {123 owner: {Substrate: charlie.address},96 }));124 properties: [{key: 'k', value: 'v3'}],97 for (let i = 1; i < 4; i++) {125 },126 ];127128 const tokens = await collection.mintMultipleTokens(alice, args);129 for (const [i, token] of tokens.entries()) {98 expect(await api.rpc.unique.tokenProperties(collection, i)).not.to.be.empty;130 expect(await token.getOwner()).to.be.deep.equal(args[i].owner);99 }131 expect(await token.getData()).to.not.be.empty;100 });132 }101 });133 });102134103 it('createMultipleItemsEx with property itemOwnerOrAdmin', async () => {135 itSub('createMultipleItemsEx with property itemOwnerOrAdmin', async ({helper}) => {104 const collection = await createCollectionWithPropsExpectSuccess({mode: {type: 'NFT'}, propPerm: [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}]});136 const collection = await helper.nft.mintCollection(alice, {105 await usingApi(async (api, privateKeyWrapper) => {106 const alice = privateKeyWrapper('//Alice');137 name: 'name',107 const bob = privateKeyWrapper('//Bob');138 description: 'descr',108 const charlie = privateKeyWrapper('//Charlie');139 tokenPrefix: 'COL',109 const data = [140 tokenPropertyPermissions: [110 {141 {111 owner: {substrate: alice.address},142 key: 'k',112 properties: [{key: 'k', value: 'v1'}],143 permission: {113 }, {114 owner: {substrate: bob.address},144 mutable: false,115 properties: [{key: 'k', value: 'v2'}],145 collectionAdmin: true,116 }, {146 tokenOwner: true,117 owner: {substrate: charlie.address},118 properties: [{key: 'k', value: 'v3'}],147 },119 },148 },120 ];149 ],150 });121151122 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {152 const args = [153 {154 owner: {Substrate: alice.address},155 properties: [{key: 'k', value: 'v1'}],156 },157 {158 owner: {Substrate: bob.address},159 properties: [{key: 'k', value: 'v2'}],123 NFT: data,160 },161 {162 owner: {Substrate: charlie.address},124 }));163 properties: [{key: 'k', value: 'v3'}],125 for (let i = 1; i < 4; i++) {164 },165 ];166167 const tokens = await collection.mintMultipleTokens(alice, args);168 for (const [i, token] of tokens.entries()) {126 expect(await api.rpc.unique.tokenProperties(collection, i)).not.to.be.empty;169 expect(await token.getOwner()).to.be.deep.equal(args[i].owner);127 }170 expect(await token.getData()).to.not.be.empty;128 });171 }129 });172 });130173131 it('can initialize fungible with multiple owners', async () => {174 itSub('can initialize fungible with multiple owners', async ({helper}) => {132 const collection = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});175 const collection = await helper.ft.mintCollection(alice, {176 name: 'name',133 await usingApi(async (api, privateKeyWrapper) => {177 description: 'descr',134 const alice = privateKeyWrapper('//Alice');178 tokenPrefix: 'COL',135 const bob = privateKeyWrapper('//Bob');179 }, 0);136180137 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {181 const api = helper.api;182 await helper.signTransaction(alice, api?.tx.unique.createMultipleItemsEx(collection.collectionId, {138 Fungible: new Map([183 Fungible: new Map([139 [JSON.stringify({Substrate: alice.address}), 50],184 [JSON.stringify({Substrate: alice.address}), 50],140 [JSON.stringify({Substrate: bob.address}), 100],185 [JSON.stringify({Substrate: bob.address}), 100],141 ]),186 ]),142 }));187 }));143188144 expect(await getBalance(api, collection, alice.address, 0)).to.equal(50n);189 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(50n);145 expect(await getBalance(api, collection, bob.address, 0)).to.equal(100n);190 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(100n);191 });192193 itSub.ifWithPallets('can initialize an RFT with multiple owners', [Pallets.ReFungible], async ({helper}) => {194 const collection = await helper.rft.mintCollection(alice, {195 name: 'name',196 description: 'descr',197 tokenPrefix: 'COL',198 tokenPropertyPermissions: [199 {key: 'k', permission: {tokenOwner: true, mutable: false, collectionAdmin: false}},200 ],146 });201 });202203 const api = helper.api;204 await helper.signTransaction(alice, api?.tx.unique.createMultipleItemsEx(collection.collectionId, {205 RefungibleMultipleOwners: {206 users: new Map([207 [JSON.stringify({Substrate: alice.address}), 1],208 [JSON.stringify({Substrate: bob.address}), 2],209 ]),210 properties: [211 {key: 'k', value: 'v'},212 ],213 },214 }));215 const tokenId = await collection.getLastTokenId();216 expect(tokenId).to.be.equal(1);217 expect(await collection.getTokenBalance(1, {Substrate: alice.address})).to.be.equal(1n);218 expect(await collection.getTokenBalance(1, {Substrate: bob.address})).to.be.equal(2n);147 });219 });148220149 it('can initialize an RFT with multiple owners', async function() {221 itSub.ifWithPallets('can initialize multiple RFTs with the same owner', [Pallets.ReFungible], async ({helper}) => {150 await requirePallets(this, [Pallets.ReFungible]);222 const collection = await helper.rft.mintCollection(alice, {223 name: 'name',224 description: 'descr',225 tokenPrefix: 'COL',226 tokenPropertyPermissions: [227 {key: 'k', permission: {tokenOwner: true, mutable: false, collectionAdmin: false}},228 ],229 });151230152 await usingApi(async (api, privateKeyWrapper) => {231 const api = helper.api;153 const alice = privateKeyWrapper('//Alice');154 const bob = privateKeyWrapper('//Bob');155 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});156 await executeTransaction(157 api,158 alice,159 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'data', permission: {tokenOwner: true}}]),160 );161232162 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {233 await helper.signTransaction(alice, api?.tx.unique.createMultipleItemsEx(collection.collectionId, {163 RefungibleMultipleOwners: {234 RefungibleMultipleItems: [164 users: new Map([235 {165 [JSON.stringify({Substrate: alice.address}), 1],236 user: {Substrate: alice.address}, pieces: 1,166 [JSON.stringify({Substrate: bob.address}), 2],167 ]),168 properties: [237 properties: [169 {key: 'data', value: 'testValue'},238 {key: 'k', value: 'v1'},170 ],239 ],171 },240 },172 }));241 {242 user: {Substrate: alice.address}, pieces: 3,243 properties: [244 {key: 'k', value: 'v2'},245 ],246 },247 ],248 }));173249174 const itemsListIndexAfter = await getLastTokenId(api, collection);250 expect(await collection.getLastTokenId()).to.be.equal(2);251 expect(await collection.getTokenBalance(1, {Substrate: alice.address})).to.be.equal(1n);175 expect(itemsListIndexAfter).to.be.equal(1);252 expect(await collection.getTokenBalance(2, {Substrate: alice.address})).to.be.equal(3n);176253177 expect(await getBalance(api, collection, alice.address, 1)).to.be.equal(1n);254 const tokenData1 = await helper.rft.getToken(collection.collectionId, 1);178 expect(await getBalance(api, collection, bob.address, 1)).to.be.equal(2n);255 expect(tokenData1).to.not.be.null;179 expect((await getTokenProperties(api, collection, 1, ['data']))[0].value).to.be.equal('testValue');256 expect(tokenData1?.properties[0]).to.be.deep.equal({key: 'k', value: 'v1'});180 });181 });182257183 it('can initialize multiple RFTs with the same owner', async function() {258 const tokenData2 = await helper.rft.getToken(collection.collectionId, 2);184 await requirePallets(this, [Pallets.ReFungible]);185186 await usingApi(async (api, privateKeyWrapper) => {187 const alice = privateKeyWrapper('//Alice');188 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});189 await executeTransaction(190 api,191 alice,192 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'data', permission: {tokenOwner: true}}]),193 );194195 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {196 RefungibleMultipleItems: [197 {198 user: {Substrate: alice.address}, pieces: 1,199 properties: [200 {key: 'data', value: 'testValue1'},201 ],202 },203 {204 user: {Substrate: alice.address}, pieces: 3,205 properties: [206 {key: 'data', value: 'testValue2'},207 ],208 },209 ],210 }));211212 const itemsListIndexAfter = await getLastTokenId(api, collection);213 expect(itemsListIndexAfter).to.be.equal(2);214215 expect(await getBalance(api, collection, alice.address, 1)).to.be.equal(1n);259 expect(tokenData2).to.not.be.null;216 expect(await getBalance(api, collection, alice.address, 2)).to.be.equal(3n);217 expect((await getTokenProperties(api, collection, 1, ['data']))[0].value).to.be.equal('testValue1');260 expect(tokenData2?.properties[0]).to.be.deep.equal({key: 'k', value: 'v2'});218 expect((await getTokenProperties(api, collection, 2, ['data']))[0].value).to.be.equal('testValue2');219 });220 });261 });221});262});222263223describe('Negative test: createMultipleItemsEx', () => {264describe('Negative test: createMultipleItemsEx', () => {224 it('No editing rights', async () => {265 let alice: IKeyringPair;225 const collection = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],226 propPerm: [{key: 'key1', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}]});227 await usingApi(async (api, privateKeyWrapper) => {266 let bob: IKeyringPair;228 const alice = privateKeyWrapper('//Alice');229 const bob = privateKeyWrapper('//Bob');230 const charlie = privateKeyWrapper('//Charlie');267 let charlie: IKeyringPair;231 await addCollectionAdminExpectSuccess(alice, collection, bob.address);232 const data = [233 {234 owner: {substrate: alice.address},235 properties: [{key: 'key1', value: 'v2'}],236 }, {237 owner: {substrate: bob.address},238 properties: [{key: 'key1', value: 'v2'}],239 }, {240 owner: {substrate: charlie.address},241 properties: [{key: 'key1', value: 'v2'}],242 },243 ];244268245 const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});269 before(async () => {246 // await executeTransaction(api, alice, tx);270 await usingPlaygrounds(async (helper, privateKey) => {247271 const donor = privateKey('//Alice');248 //await submitTransactionExpectFailAsync(alice, tx);272 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);249 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);250 });273 });251 });274 });252275253 it('User doesnt have editing rights', async () => {276 itSub('No editing rights', async ({helper}) => {254 const collection = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}],277 const collection = await helper.nft.mintCollection(alice, {255 propPerm: [{key: 'key1', permission: {mutable: false, collectionAdmin: false, tokenOwner: false}}]});278 name: 'name',256 await usingApi(async (api, privateKeyWrapper) => {257 const alice = privateKeyWrapper('//Alice');279 description: 'descr',258 const bob = privateKeyWrapper('//Bob');280 tokenPrefix: 'COL',259 await addCollectionAdminExpectSuccess(alice, collection, bob.address);260 const data = [281 tokenPropertyPermissions: [261 {282 {262 owner: {substrate: alice.address},283 key: 'k',263 properties: [{key: 'key1', value: 'v2'}],284 permission: {264 }, {285 mutable: true,265 owner: {substrate: alice.address},266 properties: [{key: 'key1', value: 'v2'}],286 collectionAdmin: false,267 }, {287 tokenOwner: false,268 owner: {substrate: alice.address},269 properties: [{key: 'key1', value: 'v2'}],288 },270 },289 },271 ];290 ],291 });272292273 const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});293 const args = [294 {295 owner: {Substrate: alice.address},296 properties: [{key: 'k', value: 'v1'}],297 },298 {299 owner: {Substrate: bob.address},300 properties: [{key: 'k', value: 'v2'}],274 // await executeTransaction(api, alice, tx);301 },302 {303 owner: {Substrate: charlie.address},304 properties: [{key: 'k', value: 'v3'}],305 },306 ];275307276 //await submitTransactionExpectFailAsync(alice, tx);308 await expect(collection.mintMultipleTokens(alice, args)).to.be.rejectedWith(/common\.NoPermission/);277 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);278 });279 });309 });280310281 it('Adding property without access rights', async () => {311 itSub('User doesnt have editing rights', async ({helper}) => {282 const collection = await createCollectionWithPropsExpectSuccess({properties: [{key: 'key1', value: 'v'}]});312 const collection = await helper.nft.mintCollection(alice, {283 await usingApi(async (api, privateKeyWrapper) => {284 const alice = privateKeyWrapper('//Alice');313 name: 'name',285 const bob = privateKeyWrapper('//Bob');314 description: 'descr',286 const charlie = privateKeyWrapper('//Charlie');315 tokenPrefix: 'COL',287 await addCollectionAdminExpectSuccess(alice, collection, bob.address);288 const data = [316 tokenPropertyPermissions: [289 {317 {290 owner: {substrate: alice.address},318 key: 'k',291 properties: [{key: 'key1', value: 'v2'}],319 permission: {292 }, {320 mutable: false,293 owner: {substrate: bob.address},294 properties: [{key: 'key1', value: 'v2'}],321 collectionAdmin: false,295 }, {322 tokenOwner: false,296 owner: {substrate: charlie.address},297 properties: [{key: 'key1', value: 'v2'}],323 },298 },324 },299 ];325 ],326 });300327301 const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});328 const args = [329 {330 owner: {Substrate: alice.address},331 properties: [{key: 'k', value: 'v1'}],332 },333 {334 owner: {Substrate: bob.address},335 properties: [{key: 'k', value: 'v2'}],336 },337 {338 owner: {Substrate: charlie.address},339 properties: [{key: 'k', value: 'v3'}],340 },341 ];302342303 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);343 await expect(collection.mintMultipleTokens(alice, args)).to.be.rejectedWith(/common\.NoPermission/);304 //await submitTransactionExpectFailAsync(alice, tx);305 });306 });344 });307345308 it('Adding more than 64 properties', async () => {346 itSub('Adding property without access rights', async ({helper}) => {309 const propPerms = [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}];347 const collection = await helper.nft.mintCollection(alice, {348 name: 'name',349 description: 'descr',350 tokenPrefix: 'COL',351 });310352311 for (let i = 0; i < 65; i++) {353 const args = [354 {312 propPerms.push({key: `key${i}`, permission: {mutable: true, collectionAdmin: true, tokenOwner: true}});355 owner: {Substrate: alice.address},356 properties: [{key: 'k', value: 'v1'}],357 },358 {359 owner: {Substrate: bob.address},360 properties: [{key: 'k', value: 'v2'}],361 },362 {363 owner: {Substrate: charlie.address},364 properties: [{key: 'k', value: 'v3'}],313 }365 },366 ];314367315 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});368 await expect(collection.mintMultipleTokens(alice, args)).to.be.rejectedWith(/common\.NoPermission/);316 await usingApi(async (api, privateKeyWrapper) => {317 const alice = privateKeyWrapper('//Alice');318 await expect(executeTransaction(api, alice, api.tx.unique.setTokenPropertyPermissions(collection, propPerms))).to.be.rejectedWith(/common\.PropertyLimitReached/);319 });320 });369 });321370322 it('Trying to add bigger property than allowed', async () => {371 itSub('Adding more than 64 properties', async ({helper}) => {323 const collection = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});372 const collection = await helper.nft.mintCollection(alice, {324 await usingApi(async (api, privateKeyWrapper) => {373 name: 'name',325 const alice = privateKeyWrapper('//Alice');326 const bob = privateKeyWrapper('//Bob');374 description: 'descr',327 const charlie = privateKeyWrapper('//Charlie');375 tokenPrefix: 'COL',328 await addCollectionAdminExpectSuccess(alice, collection, bob.address);329 const data = [376 tokenPropertyPermissions: [330 {377 {331 owner: {substrate: alice.address}, properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}],378 key: 'k',332 }, {379 permission: {333 owner: {substrate: bob.address}, properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}],380 mutable: true,334 }, {381 collectionAdmin: true,335 owner: {substrate: charlie.address}, properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}],382 tokenOwner: true,383 },336 },384 },337 ];385 ],386 });338387339 const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});388 const properties: IProperty[] = [];340389341 //await submitTransactionExpectFailAsync(alice, tx);390 for (let i = 0; i < 65; i++) {342 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);391 properties.push({key: `k${i}`, value: `v${i}`});343 });344 });392 }345393346 it('can initialize multiple NFT with different owners', async () => {394 const args = [395 {347 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});396 owner: {Substrate: alice.address},348 await usingApi(async (api, privateKeyWrapper) => {349 const alice = privateKeyWrapper('//Alice');397 properties: properties,350 const bob = privateKeyWrapper('//Bob');398 },351 const charlie = privateKeyWrapper('//Charlie');399 {352 const data = [353 {354 owner: {substrate: alice.address},400 owner: {Substrate: bob.address},355 }, {401 properties: properties,356 owner: {substrate: bob.address},402 },357 }, {403 {358 owner: {substrate: charlie.address},404 owner: {Substrate: charlie.address},359 },405 properties: properties,360 ];406 },407 ];361408362 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {409 await expect(collection.mintMultipleTokens(alice, args)).to.be.rejectedWith('Verification Error');363 NFT: data,364 }));365 const tokens = await api.query.nonfungible.tokenData.entries(collection);366 const json = tokens.map(([, token]) => token.toJSON());367 expect(json).to.be.deep.equal(data);368 });369 });410 });370411371 it('can initialize multiple NFT with different owners', async () => {412 itSub('Trying to add bigger property than allowed', async ({helper}) => {372 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});413 const collection = await helper.nft.mintCollection(alice, {373 await usingApi(async (api, privateKeyWrapper) => {374 const alice = privateKeyWrapper('//Alice');414 name: 'name',375 const bob = privateKeyWrapper('//Bob');415 description: 'descr',376 const charlie = privateKeyWrapper('//Charlie');416 tokenPrefix: 'COL',377 const data = [417 tokenPropertyPermissions: [378 {418 {379 owner: {substrate: alice.address},419 key: 'k',380 }, {420 permission: {381 owner: {substrate: bob.address},421 mutable: true,382 }, {422 collectionAdmin: true,383 owner: {substrate: charlie.address},423 tokenOwner: true,424 },384 },425 },385 ];426 ],427 });386428387 await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {429 const args = [430 {431 owner: {Substrate: alice.address},432 properties: [{key: 'k', value: 'A'.repeat(32769)}],433 },434 {388 NFT: data,435 owner: {Substrate: bob.address},389 }));436 properties: [{key: 'k', value: 'A'.repeat(32769)}],390 const tokens = await api.query.nonfungible.tokenData.entries(collection);437 },438 {439 owner: {Substrate: charlie.address},391 const json = tokens.map(([, token]) => token.toJSON());440 properties: [{key: 'k', value: 'A'.repeat(32769)}],441 },442 ];443392 expect(json).to.be.deep.equal(data);444 await expect(collection.mintMultipleTokens(alice, args)).to.be.rejectedWith('Verification Error');393 });394 });445 });395});446});396447tests/src/creditFeesToTreasury.test.tsdiffbeforeafterboth15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import './interfaces/augment-api-consts';17import './interfaces/augment-api-consts';18import chai from 'chai';19import chaiAsPromised from 'chai-as-promised';20import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';21import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';22import {23 createCollectionExpectSuccess,24 createItemExpectSuccess,25 getGenericResult,26 transferExpectSuccess,27 UNIQUE,28} from './util/helpers';2930import {default as waitNewBlocks} from './substrate/wait-new-blocks';31import {ApiPromise} from '@polkadot/api';19import {ApiPromise} from '@polkadot/api';3233chai.use(chaiAsPromised);34const expect = chai.expect;20import {usingPlaygrounds, expect, itSub} from './util/playgrounds';352136const TREASURY = '5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z';22const TREASURY = '5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z';37const saneMinimumFee = 0.05;23const saneMinimumFee = 0.05;38const saneMaximumFee = 0.5;24const saneMaximumFee = 0.5;39const createCollectionDeposit = 100;25const createCollectionDeposit = 100;4041let alice: IKeyringPair;42let bob: IKeyringPair;432644// Skip the inflation block pauses if the block is close to inflation block27// Skip the inflation block pauses if the block is close to inflation block45// until the inflation happens28// until the inflation happens62}45}634664describe('integration test: Fees must be credited to Treasury:', () => {47describe('integration test: Fees must be credited to Treasury:', () => {48 let alice: IKeyringPair;49 let bob: IKeyringPair;5065 before(async () => {51 before(async () => {66 await usingApi(async (api, privateKeyWrapper) => {52 await usingPlaygrounds(async (helper, privateKey) => {67 alice = privateKeyWrapper('//Alice');53 const donor = privateKey('//Alice');68 bob = privateKeyWrapper('//Bob');54 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);69 });55 });70 });56 });715772 it('Total issuance does not change', async () => {58 itSub('Total issuance does not change', async ({helper}) => {73 await usingApi(async (api) => {59 const api = helper.api!;74 await skipInflationBlock(api);60 await skipInflationBlock(api);75 await waitNewBlocks(api, 1);61 await helper.wait.newBlocks(1);766277 const totalBefore = (await api.query.balances.totalIssuance()).toBigInt();63 const totalBefore = (await api.query.balances.totalIssuance()).toBigInt();786479 const amount = 1n;80 const transfer = api.tx.balances.transfer(bob.address, amount);65 await helper.balance.transferToSubstrate(alice, bob.address, 1n);8182 const result = getGenericResult(await submitTransactionAsync(alice, transfer));836684 const totalAfter = (await api.query.balances.totalIssuance()).toBigInt();67 const totalAfter = (await api.query.balances.totalIssuance()).toBigInt();856886 expect(result.success).to.be.true;87 expect(totalAfter).to.be.equal(totalBefore);69 expect(totalAfter).to.be.equal(totalBefore);88 });89 });70 });907191 it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {72 itSub('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async ({helper}) => {92 await usingApi(async (api) => {93 await skipInflationBlock(api);73 await skipInflationBlock(helper.api!);94 await waitNewBlocks(api, 1);74 await helper.wait.newBlocks(1);957596 const treasuryBalanceBefore: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();76 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);97 const aliceBalanceBefore: bigint = (await api.query.system.account(alice.address)).data.free.toBigInt();77 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);987899 const amount = 1n;79 const amount = 1n;100 const transfer = api.tx.balances.transfer(bob.address, amount);80 await helper.balance.transferToSubstrate(alice, bob.address, amount);101 const result = getGenericResult(await submitTransactionAsync(alice, transfer));10281103 const treasuryBalanceAfter: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();82 const treasuryBalanceAfter = await helper.balance.getSubstrate(TREASURY);104 const aliceBalanceAfter: bigint = (await api.query.system.account(alice.address)).data.free.toBigInt();83 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);84105 const fee = aliceBalanceBefore - aliceBalanceAfter - amount;85 const fee = aliceBalanceBefore - aliceBalanceAfter - amount;106 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;86 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;10787108 expect(result.success).to.be.true;109 expect(treasuryIncrease).to.be.equal(fee);88 expect(treasuryIncrease).to.be.equal(fee);110 });111 });89 });11290113 it('Treasury balance increased by failed tx fee', async () => {91 itSub('Treasury balance increased by failed tx fee', async ({helper}) => {114 await usingApi(async (api) => {92 const api = helper.api!;115 //await skipInflationBlock(api);116 await waitNewBlocks(api, 1);93 await helper.wait.newBlocks(1);11794118 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();95 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);119 const bobBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();96 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);12097121 const badTx = api.tx.balances.setBalance(alice.address, 0, 0);98 await expect(helper.signTransaction(bob, api.tx.balances.setBalance(alice.address, 0, 0))).to.be.rejected;122 await expect(submitTransactionExpectFailAsync(bob, badTx)).to.be.rejected;12399124 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();100 const treasuryBalanceAfter = await helper.balance.getSubstrate(TREASURY);125 const bobBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();101 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);102126 const fee = bobBalanceBefore - bobBalanceAfter;103 const fee = bobBalanceBefore - bobBalanceAfter;127 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;104 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;128105129 expect(treasuryIncrease).to.be.equal(fee);106 expect(treasuryIncrease).to.be.equal(fee);130 });131 });107 });132108133 it('NFT Transactions also send fees to Treasury', async () => {109 itSub('NFT Transactions also send fees to Treasury', async ({helper}) => {134 await usingApi(async (api) => {135 await skipInflationBlock(api);110 await skipInflationBlock(helper.api!);136 await waitNewBlocks(api, 1);111 await helper.wait.newBlocks(1);137112138 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();113 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);139 const aliceBalanceBefore = (await api.query.system.account(alice.address)).data.free.toBigInt();114 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);140115141 await createCollectionExpectSuccess();116 await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});142117143 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();118 const treasuryBalanceAfter = await helper.balance.getSubstrate(TREASURY);144 const aliceBalanceAfter = (await api.query.system.account(alice.address)).data.free.toBigInt();119 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);145 const fee = aliceBalanceBefore - aliceBalanceAfter;120 const fee = aliceBalanceBefore - aliceBalanceAfter;146 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;121 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;147122148 expect(treasuryIncrease).to.be.equal(fee);123 expect(treasuryIncrease).to.be.equal(fee);149 });150 });124 });151125152 it('Fees are sane', async () => {126 itSub('Fees are sane', async ({helper}) => {153 await usingApi(async (api) => {154 await skipInflationBlock(api);127 const unique = helper.balance.getOneTokenNominal();155 await waitNewBlocks(api, 1);128 await skipInflationBlock(helper.api!);129 await helper.wait.newBlocks(1);156130157 const aliceBalanceBefore: bigint = (await api.query.system.account(alice.address)).data.free.toBigInt();131 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);158132159 await createCollectionExpectSuccess();133 await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});160134161 const aliceBalanceAfter: bigint = (await api.query.system.account(alice.address)).data.free.toBigInt();135 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);162 const fee = aliceBalanceBefore - aliceBalanceAfter;136 const fee = aliceBalanceBefore - aliceBalanceAfter;163137164 expect(fee / UNIQUE < BigInt(Math.ceil(saneMaximumFee + createCollectionDeposit))).to.be.true;138 expect(fee / unique < BigInt(Math.ceil(saneMaximumFee + createCollectionDeposit))).to.be.true;165 expect(fee / UNIQUE < BigInt(Math.ceil(saneMinimumFee + createCollectionDeposit))).to.be.true;139 expect(fee / unique < BigInt(Math.ceil(saneMinimumFee + createCollectionDeposit))).to.be.true;166 });167 });140 });168141169 it('NFT Transfer fee is close to 0.1 Unique', async () => {142 itSub('NFT Transfer fee is close to 0.1 Unique', async ({helper}) => {170 await usingApi(async (api) => {171 await skipInflationBlock(api);143 await skipInflationBlock(helper.api!);172 await waitNewBlocks(api, 1);144 await helper.wait.newBlocks(1);173145174 const collectionId = await createCollectionExpectSuccess();146 const collection = await helper.nft.mintCollection(alice, {147 name: 'test',148 description: 'test',149 tokenPrefix: 'test',150 });151 // const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');175 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');152 const token = await collection.mintToken(alice, {Substrate: alice.address});176153177 const aliceBalanceBefore: bigint = (await api.query.system.account(alice.address)).data.free.toBigInt();154 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);178 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');155 await token.transfer(alice, {Substrate: bob.address});179 const aliceBalanceAfter: bigint = (await api.query.system.account(alice.address)).data.free.toBigInt();156 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);180157181 const fee = Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE);158 const fee = Number(aliceBalanceBefore - aliceBalanceAfter) / Number(helper.balance.getOneTokenNominal());182 const expectedTransferFee = 0.1;159 const expectedTransferFee = 0.1;183 // fee drifts because of NextFeeMultiplier160 // fee drifts because of NextFeeMultiplier184 const tolerance = 0.001;161 const tolerance = 0.001;185162186 expect(Math.abs(fee - expectedTransferFee)).to.be.lessThan(tolerance);163 expect(Math.abs(fee - expectedTransferFee)).to.be.lessThan(tolerance);187 });188 });164 });189190});165});tests/src/destroyCollection.test.tsdiffbeforeafterboth15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import chai from 'chai';19import chaiAsPromised from 'chai-as-promised';20import {default as usingApi} from './substrate/substrate-api';21import {createCollectionExpectSuccess,18import {itSub, expect, usingPlaygrounds, Pallets} from './util/playgrounds';22 destroyCollectionExpectSuccess,23 destroyCollectionExpectFailure,24 setCollectionLimitsExpectSuccess,25 addCollectionAdminExpectSuccess,26 getCreatedCollectionCount,27 createItemExpectSuccess,28 requirePallets,29 Pallets,30} from './util/helpers';3132chai.use(chaiAsPromised);331934describe('integration test: ext. destroyCollection():', () => {20describe('integration test: ext. destroyCollection():', () => {21 let alice: IKeyringPair;2223 before(async () => {24 await usingPlaygrounds(async (helper, privateKey) => {25 const donor = privateKey('//Alice');26 [alice] = await helper.arrange.createAccounts([100n], donor);27 });28 });2935 it('NFT collection can be destroyed', async () => {30 itSub('NFT collection can be destroyed', async ({helper}) => {36 const collectionId = await createCollectionExpectSuccess();31 const collection = await helper.nft.mintCollection(alice, {32 name: 'test',33 description: 'test',34 tokenPrefix: 'test',35 });37 await destroyCollectionExpectSuccess(collectionId);36 await collection.burn(alice);37 expect(await collection.getData()).to.be.null;38 });38 });39 it('Fungible collection can be destroyed', async () => {39 itSub('Fungible collection can be destroyed', async ({helper}) => {40 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});40 const collection = await helper.ft.mintCollection(alice, {41 name: 'test',42 description: 'test',43 tokenPrefix: 'test',44 }, 0);41 await destroyCollectionExpectSuccess(collectionId);45 await collection.burn(alice);46 expect(await collection.getData()).to.be.null;42 });47 });43 it('ReFungible collection can be destroyed', async function() {48 itSub.ifWithPallets('ReFungible collection can be destroyed', [Pallets.ReFungible], async ({helper}) => {44 await requirePallets(this, [Pallets.ReFungible]);4546 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});49 const collection = await helper.rft.mintCollection(alice, {50 name: 'test',51 description: 'test',52 tokenPrefix: 'test',53 });47 await destroyCollectionExpectSuccess(collectionId);54 await collection.burn(alice);55 expect(await collection.getData()).to.be.null;48 });56 });49});57});505851describe('(!negative test!) integration test: ext. destroyCollection():', () => {59describe('(!negative test!) integration test: ext. destroyCollection():', () => {52 let alice: IKeyringPair;60 let alice: IKeyringPair;53 let bob: IKeyringPair;61 let bob: IKeyringPair;546255 before(async () => {63 before(async () => {56 await usingApi(async (api, privateKeyWrapper) => {64 await usingPlaygrounds(async (helper, privateKey) => {57 alice = privateKeyWrapper('//Alice');65 const donor = privateKey('//Alice');58 bob = privateKeyWrapper('//Bob');66 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);59 });67 });60 });68 });616962 it('(!negative test!) Destroy a collection that never existed', async () => {70 itSub('(!negative test!) Destroy a collection that never existed', async ({helper}) => {71 const collectionId = 1_000_000;63 await usingApi(async (api) => {72 await expect(helper.collection.burn(alice, collectionId)).to.be.rejectedWith(/common\.CollectionNotFound/);64 // Find the collection that never existed65 const collectionId = await getCreatedCollectionCount(api) + 1;66 await destroyCollectionExpectFailure(collectionId);67 });68 });73 });69 it('(!negative test!) Destroy a collection that has already been destroyed', async () => {74 itSub('(!negative test!) Destroy a collection that has already been destroyed', async ({helper}) => {70 const collectionId = await createCollectionExpectSuccess();75 const collection = await helper.nft.mintCollection(alice, {76 name: 'test',77 description: 'test',78 tokenPrefix: 'test',79 });71 await destroyCollectionExpectSuccess(collectionId);80 await collection.burn(alice);72 await destroyCollectionExpectFailure(collectionId);81 await expect(collection.burn(alice)).to.be.rejectedWith(/common\.CollectionNotFound/);73 });82 });74 it('(!negative test!) Destroy a collection using non-owner account', async () => {83 itSub('(!negative test!) Destroy a collection using non-owner account', async ({helper}) => {75 const collectionId = await createCollectionExpectSuccess();84 const collection = await helper.nft.mintCollection(alice, {85 name: 'test',86 description: 'test',87 tokenPrefix: 'test',88 });76 await destroyCollectionExpectFailure(collectionId, '//Bob');89 await expect(collection.burn(bob)).to.be.rejectedWith(/common\.NoPermission/);77 await destroyCollectionExpectSuccess(collectionId, '//Alice');78 });90 });79 it('(!negative test!) Destroy a collection using collection admin account', async () => {91 itSub('(!negative test!) Destroy a collection using collection admin account', async ({helper}) => {80 const collectionId = await createCollectionExpectSuccess();92 const collection = await helper.nft.mintCollection(alice, {93 name: 'test',94 description: 'test',95 tokenPrefix: 'test',96 });81 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);97 await collection.addAdmin(alice, {Substrate: bob.address});82 await destroyCollectionExpectFailure(collectionId, '//Bob');98 await expect(collection.burn(bob)).to.be.rejectedWith(/common\.NoPermission/);83 });99 });84 it('fails when OwnerCanDestroy == false', async () => {100 itSub('fails when OwnerCanDestroy == false', async ({helper}) => {85 const collectionId = await createCollectionExpectSuccess();101 const collection = await helper.nft.mintCollection(alice, {86 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanDestroy: false});102 name: 'test',87103 description: 'test',104 tokenPrefix: 'test',105 limits: {106 ownerCanDestroy: false,107 },108 });88 await destroyCollectionExpectFailure(collectionId, '//Alice');109 await expect(collection.burn(alice)).to.be.rejectedWith(/common\.NoPermission/);89 });110 });90 it('fails when a collection still has a token', async () => {111 itSub('fails when a collection still has a token', async ({helper}) => {91 const collectionId = await createCollectionExpectSuccess();112 const collection = await helper.nft.mintCollection(alice, {113 name: 'test',114 description: 'test',115 tokenPrefix: 'test',116 });92 await createItemExpectSuccess(alice, collectionId, 'NFT');117 await collection.mintToken(alice, {Substrate: alice.address});9394 await destroyCollectionExpectFailure(collectionId, '//Alice');118 await expect(collection.burn(alice)).to.be.rejectedWith(/common\.CantDestroyNotEmptyCollection/);95 });119 });96});120});97121tests/src/enableDisableTransfer.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import chai from 'chai';18import chaiAsPromised from 'chai-as-promised';17import {IKeyringPair} from '@polkadot/types/types';19import usingApi from './substrate/substrate-api';20import {18import {itSub, usingPlaygrounds, expect} from './util/playgrounds';21 createItemExpectSuccess,22 createCollectionExpectSuccess,23 transferExpectSuccess,24 transferExpectFailure,25 setTransferFlagExpectSuccess,26 setTransferFlagExpectFailure,27} from './util/helpers';2829chai.use(chaiAsPromised);301931describe('Enable/Disable Transfers', () => {20describe('Enable/Disable Transfers', () => {21 let alice: IKeyringPair;22 let bob: IKeyringPair;2332 it('User can transfer token with enabled transfer flag', async () => {24 before(async () => {33 await usingApi(async (api, privateKeyWrapper) => {25 await usingPlaygrounds(async (helper, privateKey) => {34 const alice = privateKeyWrapper('//Alice');26 const donor = privateKey('//Alice');35 const bob = privateKeyWrapper('//Bob');36 // nft37 const nftCollectionId = await createCollectionExpectSuccess();38 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');27 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);3940 // explicitely set transfer flag41 await setTransferFlagExpectSuccess(alice, nftCollectionId, true);4243 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1);44 });28 });45 });29 });463047 it('User can\'n transfer token with disabled transfer flag', async () => {31 itSub('User can transfer token with enabled transfer flag', async ({helper}) => {48 await usingApi(async (api, privateKeyWrapper) => {32 const collection = await helper.nft.mintCollection(alice, {33 name: 'test',34 description: 'test',35 tokenPrefix: 'test',36 limits: {37 transfersEnabled: true,38 },49 const alice = privateKeyWrapper('//Alice');39 });50 const bob = privateKeyWrapper('//Bob');51 // nft52 const nftCollectionId = await createCollectionExpectSuccess();40 const token = await collection.mintToken(alice, {Substrate: alice.address});53 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');41 await token.transfer(alice, {Substrate: bob.address});5455 // explicitely set transfer flag56 await setTransferFlagExpectSuccess(alice, nftCollectionId, false);42 expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});5758 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);59 });60 });43 });4445 itSub('User can\'n transfer token with disabled transfer flag', async ({helper}) => {46 const collection = await helper.nft.mintCollection(alice, {47 name: 'test',48 description: 'test',49 tokenPrefix: 'test',50 limits: {51 transfersEnabled: false,52 },53 });54 const token = await collection.mintToken(alice, {Substrate: alice.address});55 await expect(token.transfer(alice, {Substrate: bob.address})).to.be.rejectedWith(/common\.TransferNotAllowed/);56 });61});57});625863describe('Negative Enable/Disable Transfers', () => {59describe('Negative Enable/Disable Transfers', () => {60 let alice: IKeyringPair;61 let bob: IKeyringPair;6264 it('Non-owner cannot change transfer flag', async () => {63 before(async () => {65 await usingApi(async (api, privateKeyWrapper) => {64 await usingPlaygrounds(async (helper, privateKey) => {66 const bob = privateKeyWrapper('//Bob');65 const donor = privateKey('//Alice');67 // nft68 const nftCollectionId = await createCollectionExpectSuccess();66 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);6970 // Change transfer flag71 await setTransferFlagExpectFailure(bob, nftCollectionId, false);72 });67 });73 });68 });6970 itSub('Non-owner cannot change transfer flag', async ({helper}) => {71 const collection = await helper.nft.mintCollection(alice, {72 name: 'test',73 description: 'test',74 tokenPrefix: 'test',75 limits: {76 transfersEnabled: true,77 },78 });7980 await expect(collection.setLimits(bob, {transfersEnabled: false})).to.be.rejectedWith(/common\.NoPermission/);81 });74});82});7583tests/src/nesting/properties.test.tsdiffbeforeafterbothno syntactic changes
tests/src/refungible.test.tsdiffbeforeafterboth124 const token = await collection.mintToken(alice, 100n);124 const token = await collection.mintToken(alice, 100n);125 expect(await collection.isTokenExists(token.tokenId)).to.be.true;125 expect(await collection.isTokenExists(token.tokenId)).to.be.true;126 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);126 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);127 expect((await token.burn(alice, 99n)).success).to.be.true;127 expect(await token.burn(alice, 99n)).to.be.true;128 expect(await collection.isTokenExists(token.tokenId)).to.be.true;128 expect(await collection.isTokenExists(token.tokenId)).to.be.true;129 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(1n);129 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(1n);130 });130 });136 expect(await collection.isTokenExists(token.tokenId)).to.be.true;136 expect(await collection.isTokenExists(token.tokenId)).to.be.true;137 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);137 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);138138139 expect((await token.burn(alice, 100n)).success).to.be.true;139 expect(await token.burn(alice, 100n)).to.be.true;140 expect(await collection.isTokenExists(token.tokenId)).to.be.false;140 expect(await collection.isTokenExists(token.tokenId)).to.be.false;141 });141 });142142152 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);152 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);153 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);153 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);154154155 expect((await token.burn(alice, 40n)).success).to.be.true;155 expect(await token.burn(alice, 40n)).to.be.true;156156157 expect(await collection.isTokenExists(token.tokenId)).to.be.true;157 expect(await collection.isTokenExists(token.tokenId)).to.be.true;158 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);158 expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);159159160 expect((await token.burn(bob, 59n)).success).to.be.true;160 expect(await token.burn(bob, 59n)).to.be.true;161161162 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(1n);162 expect(await token.getBalance({Substrate: bob.address})).to.be.equal(1n);163 expect(await collection.isTokenExists(token.tokenId)).to.be.true;163 expect(await collection.isTokenExists(token.tokenId)).to.be.true;164164165 expect((await token.burn(bob, 1n)).success).to.be.true;165 expect(await token.burn(bob, 1n)).to.be.true;166166167 expect(await collection.isTokenExists(token.tokenId)).to.be.false;167 expect(await collection.isTokenExists(token.tokenId)).to.be.false;168 });168 });tests/src/util/playgrounds/unique.tsdiffbeforeafterboth141 return keyring.addFromUri(seed);141 return keyring.addFromUri(seed);142 }142 }143143144 static extractCollectionIdFromCreationResult(creationResult: ITransactionResult) {144 static extractCollectionIdFromCreationResult(creationResult: ITransactionResult): number {145 if (creationResult.status !== this.transactionStatus.SUCCESS) {145 if (creationResult.status !== this.transactionStatus.SUCCESS) {146 throw Error('Unable to create collection!');146 throw Error('Unable to create collection!');147 }147 }160 return collectionId;160 return collectionId;161 }161 }162162163 static extractTokensFromCreationResult(creationResult: ITransactionResult) {163 static extractTokensFromCreationResult(creationResult: ITransactionResult): {164 success: boolean, 165 tokens: {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[],166 } {164 if (creationResult.status !== this.transactionStatus.SUCCESS) {167 if (creationResult.status !== this.transactionStatus.SUCCESS) {165 throw Error('Unable to create tokens!');168 throw Error('Unable to create tokens!');166 }169 }167 let success = false;170 let success = false;168 const tokens = [] as any;171 const tokens = [] as {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[];169 creationResult.result.events.forEach(({event: {data, method, section}}) => {172 creationResult.result.events.forEach(({event: {data, method, section}}) => {170 if (method === 'ExtrinsicSuccess') {173 if (method === 'ExtrinsicSuccess') {171 success = true;174 success = true;172 } else if ((section === 'common') && (method === 'ItemCreated')) {175 } else if ((section === 'common') && (method === 'ItemCreated')) {173 tokens.push({176 tokens.push({174 collectionId: parseInt(data[0].toString(), 10),177 collectionId: parseInt(data[0].toString(), 10),175 tokenId: parseInt(data[1].toString(), 10),178 tokenId: parseInt(data[1].toString(), 10),176 owner: data[2].toJSON(),179 owner: data[2].toHuman(),180 amount: data[3].toBigInt(),177 });181 });178 }182 }179 });183 });180 return {success, tokens};184 return {success, tokens};181 }185 }182186183 static extractTokensFromBurnResult(burnResult: ITransactionResult) {187 static extractTokensFromBurnResult(burnResult: ITransactionResult): {188 success: boolean, 189 tokens: {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[],190 } {184 if (burnResult.status !== this.transactionStatus.SUCCESS) {191 if (burnResult.status !== this.transactionStatus.SUCCESS) {185 throw Error('Unable to burn tokens!');192 throw Error('Unable to burn tokens!');186 }193 }187 let success = false;194 let success = false;188 const tokens = [] as any;195 const tokens = [] as {collectionId: number, tokenId: number, owner: CrossAccountId, amount: bigint}[];189 burnResult.result.events.forEach(({event: {data, method, section}}) => {196 burnResult.result.events.forEach(({event: {data, method, section}}) => {190 if (method === 'ExtrinsicSuccess') {197 if (method === 'ExtrinsicSuccess') {191 success = true;198 success = true;192 } else if ((section === 'common') && (method === 'ItemDestroyed')) {199 } else if ((section === 'common') && (method === 'ItemDestroyed')) {193 tokens.push({200 tokens.push({194 collectionId: parseInt(data[0].toString(), 10),201 collectionId: parseInt(data[0].toString(), 10),195 tokenId: parseInt(data[1].toString(), 10),202 tokenId: parseInt(data[1].toString(), 10),196 owner: data[2].toJSON(),203 owner: data[2].toHuman(),204 amount: data[3].toBigInt(),197 });205 });198 }206 }199 });207 });200 return {success, tokens};208 return {success, tokens};201 }209 }202210203 static findCollectionInEvents(events: {event: IEvent}[], collectionId: number, expectedSection: string, expectedMethod: string) {211 static findCollectionInEvents(events: {event: IEvent}[], collectionId: number, expectedSection: string, expectedMethod: string): boolean {204 let eventId = null;212 let eventId = null;205 events.forEach(({event: {data, method, section}}) => {213 events.forEach(({event: {data, method, section}}) => {206 if ((section === expectedSection) && (method === expectedMethod)) {214 if ((section === expectedSection) && (method === expectedMethod)) {1013 return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1021 return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1014 }1022 }101510231016 /**1024 /**1017 *1025 *1018 * Destroys a concrete instance of NFT/RFT or burns a specified amount of fungible tokens.1026 * Destroys a concrete instance of NFT/RFT or burns a specified amount of fungible tokens.1019 *1027 *1020 * @param signer keyring of signer1028 * @param signer keyring of signer1021 * @param collectionId ID of collection1029 * @param collectionId ID of collection1022 * @param tokenId ID of token1030 * @param tokenId ID of token1023 * @param amount amount of tokens to be burned. For NFT must be set to 1n1031 * @param amount amount of tokens to be burned. For NFT must be set to 1n1024 * @example burnToken(aliceKeyring, 10, 5);1032 * @example burnToken(aliceKeyring, 10, 5);1025 * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```1033 * @returns ```true``` if the extrinsic is successful, otherwise ```false```1026 */1034 */1027 async burnToken(signer: TSigner, collectionId: number, tokenId: number, amount=1n): Promise<{1035 async burnToken(signer: TSigner, collectionId: number, tokenId: number, amount=1n): Promise<boolean> {1028 success: boolean,1029 token: number | null1030 }> {1031 const burnResult = await this.helper.executeExtrinsic(1036 const burnResult = await this.helper.executeExtrinsic(1032 signer,1037 signer,1033 'api.tx.unique.burnItem', [collectionId, tokenId, amount],1038 'api.tx.unique.burnItem', [collectionId, tokenId, amount],1034 true, // `Unable to burn token for ${label}`,1039 true, // `Unable to burn token for ${label}`,1035 );1040 );1036 const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);1041 const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);1037 if (burnedTokens.tokens.length > 1) throw Error('Burned multiple tokens');1042 if (burnedTokens.tokens.length > 1) throw Error('Burned multiple tokens');1038 return {success: burnedTokens.success, token: burnedTokens.tokens.length > 0 ? burnedTokens.tokens[0] : null};1043 return burnedTokens.success;1039 }1044 }104010451041 /**1046 /**1161 if (tokenData === null || tokenData.owner === null) return null;1166 if (tokenData === null || tokenData.owner === null) return null;1162 const owner = {} as any;1167 const owner = {} as any;1163 for (const key of Object.keys(tokenData.owner)) {1168 for (const key of Object.keys(tokenData.owner)) {1164 owner[key.toLocaleLowerCase()] = new CrossAccountId(tokenData.owner[key]).withNormalizedSubstrate();1169 owner[key.toLocaleLowerCase()] = key.toLocaleLowerCase() == 'substrate' 1170 ? CrossAccountId.normalizeSubstrateAddress(tokenData.owner[key]) 1171 : tokenData.owner[key];1165 }1172 }1166 tokenData.normalizedOwner = CrossAccountId.fromLowerCaseKeys(owner);1173 tokenData.normalizedOwner = CrossAccountId.fromLowerCaseKeys(owner);1167 return tokenData;1174 return tokenData;1704 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1711 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1705 }1712 }170617131707 /**1714 /**1708 * Destroys a concrete instance of RFT.1715 * Destroys a concrete instance of RFT.1709 * @param signer keyring of signer1716 * @param signer keyring of signer1710 * @param collectionId ID of collection1717 * @param collectionId ID of collection1711 * @param tokenId ID of token1718 * @param tokenId ID of token1712 * @param amount number of pieces to be burnt1719 * @param amount number of pieces to be burnt1713 * @example burnToken(aliceKeyring, 10, 5);1720 * @example burnToken(aliceKeyring, 10, 5);1714 * @returns ```true``` and burnt token number, if extrinsic is successful. Otherwise ```false``` and ```null```1721 * @returns ```true``` if the extrinsic is successful, otherwise ```false```1715 */1722 */1716 async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, amount=1n): Promise<{ success: boolean; token: number | null; }> {1723 async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, amount=1n): Promise<boolean> {1717 return await super.burnToken(signer, collectionId, tokenId, amount);1724 return await super.burnToken(signer, collectionId, tokenId, amount);1718 }1725 }171917261919 * @returns ```true``` if extrinsic success, otherwise ```false```1926 * @returns ```true``` if extrinsic success, otherwise ```false```1920 */1927 */1921 async burnTokens(signer: IKeyringPair, collectionId: number, amount=1n): Promise<boolean> {1928 async burnTokens(signer: IKeyringPair, collectionId: number, amount=1n): Promise<boolean> {1922 return (await super.burnToken(signer, collectionId, 0, amount)).success;1929 return await super.burnToken(signer, collectionId, 0, amount);1923 }1930 }192419311925 /**1932 /**