1import {executeTransaction} from '../substrate/substrate-api';2import {IKeyringPair} from '@polkadot/types/types';3import {itSub, expect, usingPlaygrounds, Pallets, requirePalletsOrSkip} from '../util';4import {UniqueHelper} from '../util/playgrounds/unique';56let alice: IKeyringPair;7let bob: IKeyringPair;89async function createRmrkCollection(helper: UniqueHelper, sender: IKeyringPair): Promise<{uniqueId: number, rmrkId: number}> {10 const result = await helper.executeExtrinsic(sender, 'api.tx.rmrkCore.createCollection', ['metadata', null, 'symbol'], true);1112 const uniqueId = helper.util.extractCollectionIdFromCreationResult(result);1314 let rmrkId = null;15 result.result.events.forEach(({event: {data, method, section}}) => {16 if ((section === 'rmrkCore') && (method === 'CollectionCreated')) {17 rmrkId = parseInt(data[1].toString(), 10);18 }19 });2021 if (rmrkId === null) {22 throw Error('No rmrkCore.CollectionCreated event was found!');23 }2425 return {26 uniqueId,27 rmrkId,28 };29}3031async function createRmrkNft(helper: UniqueHelper, sender: IKeyringPair, collectionId: number): Promise<number> {32 const result = await helper.executeExtrinsic(33 sender,34 'api.tx.rmrkCore.mintNft',35 [36 sender.address,37 collectionId,38 sender.address,39 null,40 'nft-metadata',41 true,42 null,43 ],44 true,45 );4647 let rmrkNftId = null;48 result.result.events.forEach(({event: {data, method, section}}) => {49 if ((section === 'rmrkCore') && (method === 'NftMinted')) {50 rmrkNftId = parseInt(data[2].toString(), 10);51 }52 });5354 if (rmrkNftId === null) {55 throw Error('No rmrkCore.NftMinted event was found!');56 }5758 return rmrkNftId;59}6061describe('RMRK External Integration Test', () => {62 before(async function() {63 await usingPlaygrounds(async (_helper, privateKey) => {64 alice = await privateKey('//Alice');65 });66 });6768 itSub.ifWithPallets('Creates a new RMRK collection that is mapped to a different ID and is tagged as external', [Pallets.RmrkCore], async ({helper}) => {69 70 await helper.nft.mintCollection(alice, {tokenPrefix: 'unqt'});7172 const collectionIds = await createRmrkCollection(helper, alice);7374 expect(collectionIds.rmrkId).to.be.lessThan(collectionIds.uniqueId, 'collection ID mapping');7576 const collection = (await helper.nft.getCollectionObject(collectionIds.uniqueId).getData())!; 77 expect(collection.raw.readOnly, 'tagged external').to.be.true;78 });79});8081describe('Negative Integration Test: External Collections, Internal Ops', () => {82 let uniqueCollectionId: number;83 let rmrkCollectionId: number;84 let rmrkNftId: number;85 let normalizedAlice: {Substrate: string};8687 before(async function() {88 await usingPlaygrounds(async (helper, privateKey) => {89 alice = await privateKey('//Alice');90 bob = await privateKey('//Bob');91 normalizedAlice = {Substrate: helper.address.normalizeSubstrateToChainFormat(alice.address)};9293 requirePalletsOrSkip(this, helper, [Pallets.RmrkCore]);9495 const collectionIds = await createRmrkCollection(helper, alice);96 uniqueCollectionId = collectionIds.uniqueId;97 rmrkCollectionId = collectionIds.rmrkId;9899 rmrkNftId = await createRmrkNft(helper, alice, rmrkCollectionId);100 });101 });102103 itSub.ifWithPallets('[Negative] Forbids Unique operations with an external collection, handled by dispatch_call', [Pallets.RmrkCore], async ({helper}) => {104 105106 await expect(helper.nft.mintToken(alice, {collectionId: uniqueCollectionId, owner: {Substrate: alice.address}}), 'creating item')107 .to.be.rejectedWith(/common\.CollectionIsExternal/);108109 const txCreateMultipleItems = helper.getApi().tx.unique.createMultipleItems(uniqueCollectionId, normalizedAlice, [{NFT: {}}, {NFT: {}}]);110 await expect(executeTransaction(helper.getApi(), alice, txCreateMultipleItems), 'creating multiple')111 .to.be.rejectedWith(/common\.CollectionIsExternal/);112 113 await expect(helper.nft.mintMultipleTokens(alice, uniqueCollectionId, [{owner: {Substrate: alice.address}}]), 'creating multiple ex')114 .to.be.rejectedWith(/common\.CollectionIsExternal/);115116 117118 await expect(helper.nft.setProperties(alice, uniqueCollectionId, [{key: 'a', value: '1'}, {key: 'b'}]), 'setting collection properties')119 .to.be.rejectedWith(/common\.CollectionIsExternal/);120121 await expect(helper.nft.deleteProperties(alice, uniqueCollectionId, ['a']), 'deleting collection properties')122 .to.be.rejectedWith(/common\.CollectionIsExternal/);123124 await expect(helper.nft.setTokenPropertyPermissions(alice, uniqueCollectionId, [{key: 'a', permission: {mutable: true}}]), 'setting property permissions')125 .to.be.rejectedWith(/common\.CollectionIsExternal/);126127 128129 await expect(helper.nft.burnToken(alice, uniqueCollectionId, rmrkNftId, 1n), 'burning')130 .to.be.rejectedWith(/common\.CollectionIsExternal/);131132 await expect(helper.nft.burnTokenFrom(alice, uniqueCollectionId, rmrkNftId, {Substrate: alice.address}, 1n), 'burning-from')133 .to.be.rejectedWith(/common\.CollectionIsExternal/);134135 await expect(helper.nft.transferToken(alice, uniqueCollectionId, rmrkNftId, {Substrate: bob.address}), 'transferring')136 .to.be.rejectedWith(/common\.CollectionIsExternal/);137138 await expect(helper.nft.approveToken(alice, uniqueCollectionId, rmrkNftId, {Substrate: bob.address}), 'approving')139 .to.be.rejectedWith(/common\.CollectionIsExternal/);140141 await expect(helper.nft.transferTokenFrom(alice, uniqueCollectionId, rmrkNftId, {Substrate: alice.address}, {Substrate: bob.address}), 'transferring-from')142 .to.be.rejectedWith(/common\.CollectionIsExternal/);143144 145146 await expect(helper.nft.setTokenProperties(alice, uniqueCollectionId, rmrkNftId, [{key: 'a', value: '2'}]), 'setting token properties')147 .to.be.rejectedWith(/common\.CollectionIsExternal/);148149 await expect(helper.nft.deleteTokenProperties(alice, uniqueCollectionId, rmrkNftId, ['a']))150 .to.be.rejectedWith(/common\.CollectionIsExternal/);151 });152153 itSub.ifWithPallets('[Negative] Forbids Unique collection operations with an external collection', [Pallets.RmrkCore], async ({helper}) => {154 await expect(helper.nft.burn(alice, uniqueCollectionId), 'destroying collection')155 .to.be.rejectedWith(/common\.CollectionIsExternal/);156157 158159 await expect(helper.nft.addToAllowList(alice, uniqueCollectionId, {Substrate: bob.address}), 'adding to allow list')160 .to.be.rejectedWith(/common\.CollectionIsExternal/);161162 await expect(helper.nft.removeFromAllowList(alice, uniqueCollectionId, {Substrate: bob.address}), 'removing from allowlist')163 .to.be.rejectedWith(/common\.CollectionIsExternal/);164165 166167 await expect(helper.nft.changeOwner(alice, uniqueCollectionId, bob.address), 'changing owner')168 .to.be.rejectedWith(/common\.CollectionIsExternal/);169170 await expect(helper.nft.addAdmin(alice, uniqueCollectionId, {Substrate: bob.address}), 'adding admin')171 .to.be.rejectedWith(/common\.CollectionIsExternal/);172173 await expect(helper.nft.removeAdmin(alice, uniqueCollectionId, {Substrate: bob.address}), 'removing admin')174 .to.be.rejectedWith(/common\.CollectionIsExternal/);175176 await expect(helper.nft.setSponsor(alice, uniqueCollectionId, bob.address), 'setting sponsor')177 .to.be.rejectedWith(/common\.CollectionIsExternal/);178179 await expect(helper.nft.confirmSponsorship(alice, uniqueCollectionId), 'confirming sponsor')180 .to.be.rejectedWith(/common\.CollectionIsExternal/);181182 await expect(helper.nft.removeSponsor(alice, uniqueCollectionId), 'removing sponsor')183 .to.be.rejectedWith(/common\.CollectionIsExternal/);184 185 186187 const txSetTransfers = helper.getApi().tx.unique.setTransfersEnabledFlag(uniqueCollectionId, true);188 await expect(executeTransaction(helper.getApi(), alice, txSetTransfers), 'setting transfers enabled flag')189 .to.be.rejectedWith(/common\.CollectionIsExternal/);190191 await expect(helper.nft.setLimits(alice, uniqueCollectionId, {transfersEnabled: false}), 'setting collection limits')192 .to.be.rejectedWith(/common\.CollectionIsExternal/);193194 await expect(helper.nft.setPermissions(alice, uniqueCollectionId, {access: 'AllowList'}), 'setting collection permissions')195 .to.be.rejectedWith(/common\.CollectionIsExternal/);196 });197});198199describe('Negative Integration Test: Internal Collections, External Ops', () => {200 let collectionId: number;201 let nftId: number;202203 before(async () => {204 await usingPlaygrounds(async (helper, privateKey) => {205 alice = await privateKey('//Alice');206 bob = await privateKey('//Bob');207208 const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'iceo'});209 collectionId = collection.collectionId;210 nftId = (await collection.mintToken(alice)).tokenId;211 });212 });213214 itSub.ifWithPallets('[Negative] Forbids RMRK operations with the internal collection and NFT (due to the lack of mapping)', [Pallets.RmrkCore], async ({helper}) => {215 const api = helper.getApi();216217 const txChangeOwner = api.tx.rmrkCore.changeCollectionIssuer(collectionId, bob.address);218 await expect(executeTransaction(api, alice, txChangeOwner), 'changing collection issuer')219 .to.be.rejectedWith(/rmrkCore\.CollectionUnknown/);220221 const maxBurns = 10;222 const txBurnItem = api.tx.rmrkCore.burnNft(collectionId, nftId, maxBurns);223 await expect(executeTransaction(api, alice, txBurnItem), 'burning NFT').to.be.rejectedWith(/rmrkCore\.CollectionUnknown/);224 });225});