difftreelog
Merge pull request #567 from UniqueNetwork/test/playground-migration
in: master
Test/playground migration
5 files changed
tests/package.jsondiffbeforeafterboth49 "testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",49 "testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",50 "testRemoveCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionSponsor.test.ts",50 "testRemoveCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionSponsor.test.ts",51 "testRemoveFromAllowList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromAllowList.test.ts",51 "testRemoveFromAllowList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromAllowList.test.ts",52 "testAllowLists": "mocha --timeout 9999999 -r ts-node/register ./**/allowLists.test.ts",52 "testConnection": "mocha --timeout 9999999 -r ts-node/register ./**/connection.test.ts",53 "testConnection": "mocha --timeout 9999999 -r ts-node/register ./**/connection.test.ts",53 "testContracts": "mocha --timeout 9999999 -r ts-node/register ./**/contracts.test.ts",54 "testContracts": "mocha --timeout 9999999 -r ts-node/register ./**/contracts.test.ts",54 "testCreateItem": "mocha --timeout 9999999 -r ts-node/register ./**/createItem.test.ts",55 "testCreateItem": "mocha --timeout 9999999 -r ts-node/register ./**/createItem.test.ts",tests/src/adminTransferAndBurn.test.tsdiffbeforeafterboth17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import chai from 'chai';18import chai from 'chai';19import chaiAsPromised from 'chai-as-promised';19import chaiAsPromised from 'chai-as-promised';20import {default as usingApi} from './substrate/substrate-api';21import {20import {usingPlaygrounds} from './util/playgrounds';22 createCollectionExpectSuccess,23 createItemExpectSuccess,24 transferExpectFailure,25 transferFromExpectSuccess,26 burnItemExpectFailure,27 burnFromExpectSuccess,28 setCollectionLimitsExpectSuccess,29} from './util/helpers';302131chai.use(chaiAsPromised);22chai.use(chaiAsPromised);32const expect = chai.expect;23const expect = chai.expect;2425let donor: IKeyringPair;2627before(async () => {28 await usingPlaygrounds(async (_, privateKey) => {29 donor = privateKey('//Alice');30 });31});333234describe('Integration Test: ownerCanTransfer allows admins to use only transferFrom/burnFrom:', () => {33describe('Integration Test: ownerCanTransfer allows admins to use only transferFrom/burnFrom:', () => {35 let alice: IKeyringPair;34 let alice: IKeyringPair;36 let bob: IKeyringPair;35 let bob: IKeyringPair;37 let charlie: IKeyringPair;36 let charlie: IKeyringPair;383739 before(async () => {38 before(async () => {40 await usingApi(async (api, privateKeyWrapper) => {39 await usingPlaygrounds(async (helper) => {41 alice = privateKeyWrapper('//Alice');40 [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);42 bob = privateKeyWrapper('//Bob');43 charlie = privateKeyWrapper('//Charlie');44 });41 });45 });42 });464347 it('admin transfers other user\'s token', async () => {44 it('admin transfers other user\'s token', async () => {48 await usingApi(async () => {45 await usingPlaygrounds(async (helper) => {49 const collectionId = await createCollectionExpectSuccess();46 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'});50 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});47 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});48 const limits = await helper.collection.getEffectiveLimits(collectionId);49 expect(limits.ownerCanTransfer).to.be.true;515052 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Substrate: bob.address});51 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});5354 await transferExpectFailure(collectionId, tokenId, alice, charlie);52 const transferResult = async () => helper.nft.transferToken(alice, collectionId, tokenId, {Substrate: charlie.address});53 await expect(transferResult()).to.be.rejected;555456 await transferFromExpectSuccess(collectionId, tokenId, alice, bob, charlie, 1);55 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address});56 const newTokenOwner = await helper.nft.getTokenOwner(collectionId, tokenId);57 expect(newTokenOwner.Substrate).to.be.equal(charlie.address);57 });58 });58 });59 });596060 it('admin burns other user\'s token', async () => {61 it('admin burns other user\'s token', async () => {61 await usingApi(async () => {62 await usingPlaygrounds(async (helper) => {62 const collectionId = await createCollectionExpectSuccess();63 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL'});6463 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});65 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});66 const limits = await helper.collection.getEffectiveLimits(collectionId);67 expect(limits.ownerCanTransfer).to.be.true;646865 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Substrate: bob.address});69 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});6667 await burnItemExpectFailure(alice, collectionId, tokenId);70 const burnTxFailed = async () => helper.nft.burnToken(alice, collectionId, tokenId);7172 await expect(burnTxFailed()).to.be.rejected;687369 await burnFromExpectSuccess(alice, bob, collectionId, tokenId);74 await helper.nft.burnToken(bob, collectionId, tokenId);75 const token = await helper.nft.getToken(collectionId, tokenId);76 expect(token).to.be.null;70 });77 });71 });78 });72});79});tests/src/allowLists.test.tsdiffbeforeafterboth17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import chai from 'chai';18import chai from 'chai';19import chaiAsPromised from 'chai-as-promised';19import chaiAsPromised from 'chai-as-promised';20import usingApi, {submitTransactionExpectFailAsync} from './substrate/substrate-api';20import {usingPlaygrounds} from './util/playgrounds';21import {22 addToAllowListExpectSuccess,23 createCollectionExpectSuccess,24 createItemExpectSuccess,25 destroyCollectionExpectSuccess,26 enableAllowListExpectSuccess,27 normalizeAccountId,28 addCollectionAdminExpectSuccess,29 addToAllowListExpectFail,30 removeFromAllowListExpectSuccess,31 removeFromAllowListExpectFailure,32 addToAllowListAgainExpectSuccess,33 transferExpectFailure,34 approveExpectSuccess,35 approveExpectFail,36 transferExpectSuccess,37 transferFromExpectSuccess,38 setMintPermissionExpectSuccess,39 createItemExpectFailure,40} from './util/helpers';412142chai.use(chaiAsPromised);22chai.use(chaiAsPromised);43const expect = chai.expect;23const expect = chai.expect;442425let donor: IKeyringPair;2627before(async () => {28 await usingPlaygrounds(async (_, privateKey) => {29 donor = privateKey('//Alice');30 });31});3245let alice: IKeyringPair;33let alice: IKeyringPair;46let bob: IKeyringPair;34let bob: IKeyringPair;47let charlie: IKeyringPair;35let charlie: IKeyringPair;483649describe('Integration Test ext. Allow list tests', () => {37describe('Integration Test ext. Allow list tests', () => {503851 before(async () => {39 before(async () => {52 await usingApi(async (api, privateKeyWrapper) => {40 await usingPlaygrounds(async (helper) => {53 alice = privateKeyWrapper('//Alice');41 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);54 bob = privateKeyWrapper('//Bob');55 charlie = privateKeyWrapper('//Charlie');56 });42 });57 });43 });584459 it('Owner can add address to allow list', async () => {45 it('Owner can add address to allow list', async () => {60 const collectionId = await createCollectionExpectSuccess();46 await usingPlaygrounds(async (helper) => {47 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});61 await addToAllowListExpectSuccess(alice, collectionId, bob.address);48 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});49 const allowList = await helper.nft.getAllowList(collectionId);50 expect(allowList).to.be.deep.contains({Substrate: bob.address});51 });62 });52 });635364 it('Admin can add address to allow list', async () => {54 it('Admin can add address to allow list', async () => {65 const collectionId = await createCollectionExpectSuccess();55 await usingPlaygrounds(async (helper) => {56 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});66 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);57 await helper.nft.addAdmin(alice, collectionId, {Substrate: bob.address});5867 await addToAllowListExpectSuccess(bob, collectionId, charlie.address);59 await helper.nft.addToAllowList(bob, collectionId, {Substrate: charlie.address});60 const allowList = await helper.nft.getAllowList(collectionId);61 expect(allowList).to.be.deep.contains({Substrate: charlie.address});62 });68 });63 });696470 it('Non-privileged user cannot add address to allow list', async () => {65 it('Non-privileged user cannot add address to allow list', async () => {71 const collectionId = await createCollectionExpectSuccess();66 await usingPlaygrounds(async (helper) => {67 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});72 await addToAllowListExpectFail(bob, collectionId, charlie.address);68 const addToAllowListTx = async () => helper.nft.addToAllowList(bob, collectionId, {Substrate: charlie.address});69 await expect(addToAllowListTx()).to.be.rejected;70 });73 });71 });747275 it('Nobody can add address to allow list of non-existing collection', async () => {73 it('Nobody can add address to allow list of non-existing collection', async () => {76 const collectionId = (1<<32) - 1;74 const collectionId = (1<<32) - 1;77 await addToAllowListExpectFail(alice, collectionId, bob.address);75 await usingPlaygrounds(async (helper) => {76 const addToAllowListTx = async () => helper.nft.addToAllowList(bob, collectionId, {Substrate: charlie.address});77 await expect(addToAllowListTx()).to.be.rejected;78 });78 });79 });798080 it('Nobody can add address to allow list of destroyed collection', async () => {81 it('Nobody can add address to allow list of destroyed collection', async () => {81 const collectionId = await createCollectionExpectSuccess();82 await usingPlaygrounds(async (helper) => {83 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});82 await destroyCollectionExpectSuccess(collectionId, '//Alice');84 await helper.collection.burn(alice, collectionId);83 await addToAllowListExpectFail(alice, collectionId, bob.address);85 const addToAllowListTx = async () => helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});86 await expect(addToAllowListTx()).to.be.rejected;87 });84 });88 });858986 it('If address is already added to allow list, nothing happens', async () => {90 it('If address is already added to allow list, nothing happens', async () => {87 const collectionId = await createCollectionExpectSuccess();91 await usingPlaygrounds(async (helper) => {92 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});88 await addToAllowListExpectSuccess(alice, collectionId, bob.address);93 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});89 await addToAllowListAgainExpectSuccess(alice, collectionId, bob.address);94 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});95 const allowList = await helper.nft.getAllowList(collectionId);96 expect(allowList).to.be.deep.contains({Substrate: bob.address});97 });90 });98 });919992 it('Owner can remove address from allow list', async () => {100 it('Owner can remove address from allow list', async () => {93 const collectionId = await createCollectionExpectSuccess();101 await usingPlaygrounds(async (helper) => {102 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});94 await addToAllowListExpectSuccess(alice, collectionId, bob.address);103 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});10495 await removeFromAllowListExpectSuccess(alice, collectionId, normalizeAccountId(bob));105 await helper.collection.removeFromAllowList(alice, collectionId, {Substrate: bob.address});106107 const allowList = await helper.nft.getAllowList(collectionId);108109 expect(allowList).to.be.not.deep.contains({Substrate: bob.address});110 });96 });111 });9711298 it('Admin can remove address from allow list', async () => {113 it('Admin can remove address from allow list', async () => {99 const collectionId = await createCollectionExpectSuccess();114 await usingPlaygrounds(async (helper) => {115 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});100 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);116 await helper.nft.addAdmin(alice, collectionId, {Substrate: charlie.address});101 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);117 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});102 await removeFromAllowListExpectSuccess(bob, collectionId, normalizeAccountId(charlie));118 await helper.collection.removeFromAllowList(charlie, collectionId, {Substrate: bob.address});119120 const allowList = await helper.nft.getAllowList(collectionId);121122 expect(allowList).to.be.not.deep.contains({Substrate: bob.address});123 });103 });124 });104125105 it('Non-privileged user cannot remove address from allow list', async () => {126 it('Non-privileged user cannot remove address from allow list', async () => {106 const collectionId = await createCollectionExpectSuccess();127 await usingPlaygrounds(async (helper) => {128 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});107 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);129 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});108 await removeFromAllowListExpectFailure(bob, collectionId, normalizeAccountId(charlie));130 const removeTx = async () => helper.collection.removeFromAllowList(bob, collectionId, {Substrate: charlie.address});131 await expect(removeTx()).to.be.rejected;132 const allowList = await helper.nft.getAllowList(collectionId);133134 expect(allowList).to.be.deep.contains({Substrate: charlie.address});135 });109 });136 });110137111 it('Nobody can remove address from allow list of non-existing collection', async () => {138 it('Nobody can remove address from allow list of non-existing collection', async () => {112 const collectionId = (1<<32) - 1;139 const collectionId = (1<<32) - 1;113 await removeFromAllowListExpectFailure(alice, collectionId, normalizeAccountId(charlie));140 await usingPlaygrounds(async (helper) => {141 const removeTx = async () => helper.collection.removeFromAllowList(bob, collectionId, {Substrate: charlie.address});142 await expect(removeTx()).to.be.rejected;143 });114 });144 });115145116 it('Nobody can remove address from allow list of deleted collection', async () => {146 it('Nobody can remove address from allow list of deleted collection', async () => {117 const collectionId = await createCollectionExpectSuccess();147 await usingPlaygrounds(async (helper) => {148 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});118 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);149 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});119 await destroyCollectionExpectSuccess(collectionId, '//Alice');150 await helper.collection.burn(alice, collectionId);120 await removeFromAllowListExpectFailure(alice, collectionId, normalizeAccountId(charlie));151 const removeTx = async () => helper.collection.removeFromAllowList(alice, collectionId, {Substrate: bob.address});152153 await expect(removeTx()).to.be.rejected;154 });121 });155 });122156123 it('If address is already removed from allow list, nothing happens', async () => {157 it('If address is already removed from allow list, nothing happens', async () => {124 const collectionId = await createCollectionExpectSuccess();158 await usingPlaygrounds(async (helper) => {159 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});125 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);160 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});126 await removeFromAllowListExpectSuccess(alice, collectionId, normalizeAccountId(charlie));161 await helper.collection.removeFromAllowList(alice, collectionId, {Substrate: bob.address});162 const allowListBefore = await helper.nft.getAllowList(collectionId);163 expect(allowListBefore).to.be.not.deep.contains({Substrate: bob.address});164127 await removeFromAllowListExpectSuccess(alice, collectionId, normalizeAccountId(charlie));165 await helper.collection.removeFromAllowList(alice, collectionId, {Substrate: bob.address});166167 const allowListAfter = await helper.nft.getAllowList(collectionId);168 expect(allowListAfter).to.be.not.deep.contains({Substrate: bob.address});169 });128 });170 });129171130 it('If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom. Test1', async () => {172 it('If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom. Test1', async () => {131 const collectionId = await createCollectionExpectSuccess();173 await usingPlaygrounds(async (helper) => {174 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});132 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);175 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});133 await enableAllowListExpectSuccess(alice, collectionId);176 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});134 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);177 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});135178136 await transferExpectFailure(179 const transferResult = async () => helper.nft.transferToken(alice, collectionId, tokenId, {Substrate: charlie.address});137 collectionId,138 itemId,139 alice,140 charlie,141 1,180 await expect(transferResult()).to.be.rejected;142 );181 });143 });182 });144183145 it('If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom. Test2', async () => {184 it('If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom. Test2', async () => {146 const collectionId = await createCollectionExpectSuccess();185 await usingPlaygrounds(async (helper) => {186 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});147 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);187 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});148 await enableAllowListExpectSuccess(alice, collectionId);188 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});149 await addToAllowListExpectSuccess(alice, collectionId, alice.address);189 await helper.nft.addToAllowList(alice, collectionId, {Substrate: alice.address});150 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);190 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});151 await approveExpectSuccess(collectionId, itemId, alice, charlie.address);191 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});152 await removeFromAllowListExpectSuccess(alice, collectionId, normalizeAccountId(alice));192 await helper.collection.removeFromAllowList(alice, collectionId, {Substrate: alice.address});153193154 await transferExpectFailure(194 const transferResult = async () => helper.nft.transferToken(alice, collectionId, tokenId, {Substrate: charlie.address});155 collectionId,156 itemId,157 alice,158 charlie,159 1,195 await expect(transferResult()).to.be.rejected;160 );196 });161 });197 });162198163 it('If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom. Test1', async () => {199 it('If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom. Test1', async () => {164 const collectionId = await createCollectionExpectSuccess();200 await usingPlaygrounds(async (helper) => {201 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});165 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);202 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});166 await enableAllowListExpectSuccess(alice, collectionId);203 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});167 await addToAllowListExpectSuccess(alice, collectionId, alice.address);204 await helper.nft.addToAllowList(alice, collectionId, {Substrate: alice.address});168205169 await transferExpectFailure(206 const transferResult = async () => helper.nft.transferToken(alice, collectionId, tokenId, {Substrate: charlie.address});170 collectionId,171 itemId,172 alice,173 charlie,174 1,207 await expect(transferResult()).to.be.rejected;175 );208 });176 });209 });177210178 it('If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom. Test2', async () => {211 it('If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom. Test2', async () => {179 const collectionId = await createCollectionExpectSuccess();212 await usingPlaygrounds(async (helper) => {180 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);213 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});181 await enableAllowListExpectSuccess(alice, collectionId);214 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});182 await addToAllowListExpectSuccess(alice, collectionId, alice.address);183 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);215 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});184 await approveExpectSuccess(collectionId, itemId, alice, charlie.address);216 await helper.nft.addToAllowList(alice, collectionId, {Substrate: alice.address});185 await removeFromAllowListExpectSuccess(alice, collectionId, normalizeAccountId(alice));217 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});186218187 await transferExpectFailure(219 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});188 collectionId,220 await helper.collection.removeFromAllowList(alice, collectionId, {Substrate: alice.address});221189 itemId,222 const transferResult = async () => helper.nft.transferToken(alice, collectionId, tokenId, {Substrate: charlie.address});190 alice,191 charlie,192 1,223 await expect(transferResult()).to.be.rejected;193 );224 });194 });225 });195226196 it('If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)', async () => {227 it('If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)', async () => {197 const collectionId = await createCollectionExpectSuccess();228 await usingPlaygrounds(async (helper) => {198 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);229 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});199 await enableAllowListExpectSuccess(alice, collectionId);230 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});200201 await usingApi(async (api) => {202 const tx = api.tx.unique.burnItem(collectionId, itemId, /*normalizeAccountId(Alice.address),*/ 11);231 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});203 const badTransaction = async function () {232 const burnTx = async () => helper.nft.burnToken(bob, collectionId, tokenId);204 await submitTransactionExpectFailAsync(alice, tx);205 };206 await expect(badTransaction()).to.be.rejected;233 await expect(burnTx()).to.be.rejected;207 });234 });208 });235 });209236210 it('If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method)', async () => {237 it('If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method)', async () => {211 const collectionId = await createCollectionExpectSuccess();238 await usingPlaygrounds(async (helper) => {239 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});212 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);240 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});213 await enableAllowListExpectSuccess(alice, collectionId);241 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});214 await approveExpectFail(collectionId, itemId, alice, bob);242 const approveTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});243 await expect(approveTx()).to.be.rejected;244 });215 });245 });216246217 it('If Public Access mode is set to AllowList, tokens can be transferred to a allowlisted address with transfer.', async () => {247 it('If Public Access mode is set to AllowList, tokens can be transferred to a allowlisted address with transfer.', async () => {218 const collectionId = await createCollectionExpectSuccess();248 await usingPlaygrounds(async (helper) => {249 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});219 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);250 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});220 await enableAllowListExpectSuccess(alice, collectionId);251 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});221 await addToAllowListExpectSuccess(alice, collectionId, alice.address);252 await helper.nft.addToAllowList(alice, collectionId, {Substrate: alice.address});222 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);253 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});223 await transferExpectSuccess(collectionId, itemId, alice, charlie, 1, 'NFT');254 await helper.nft.transferToken(alice, collectionId, tokenId, {Substrate: charlie.address});255 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);256 expect(owner.Substrate).to.be.equal(charlie.address);257 });224 });258 });225259226 it('If Public Access mode is set to AllowList, tokens can be transferred to a alowlisted address with transferFrom.', async () => {260 it('If Public Access mode is set to AllowList, tokens can be transferred to a allowlisted address with transferFrom.', async () => {227 const collectionId = await createCollectionExpectSuccess();261 await usingPlaygrounds(async (helper) => {262 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});228 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);263 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});229 await enableAllowListExpectSuccess(alice, collectionId);264 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});230 await addToAllowListExpectSuccess(alice, collectionId, alice.address);265 await helper.nft.addToAllowList(alice, collectionId, {Substrate: alice.address});231 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);266 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});232 await approveExpectSuccess(collectionId, itemId, alice, charlie.address);267 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});268233 await transferFromExpectSuccess(collectionId, itemId, alice, alice, charlie, 1, 'NFT');269 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address});270 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);271 expect(owner.Substrate).to.be.equal(charlie.address);272 });234 });273 });235274236 it('If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer', async () => {275 it('If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer', async () => {237 const collectionId = await createCollectionExpectSuccess();276 await usingPlaygrounds(async (helper) => {277 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});238 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);278 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});239 await enableAllowListExpectSuccess(alice, collectionId);279 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});240 await addToAllowListExpectSuccess(alice, collectionId, alice.address);280 await helper.nft.addToAllowList(alice, collectionId, {Substrate: alice.address});241 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);281 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});282242 await transferExpectSuccess(collectionId, itemId, alice, charlie, 1, 'NFT');283 await helper.nft.transferToken(alice, collectionId, tokenId, {Substrate: charlie.address});284 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);285 expect(owner.Substrate).to.be.equal(charlie.address);286 });243 });287 });244288245 it('If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transferFrom', async () => {289 it('If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transferFrom', async () => {246 const collectionId = await createCollectionExpectSuccess();290 await usingPlaygrounds(async (helper) => {291 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});247 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);292 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});248 await enableAllowListExpectSuccess(alice, collectionId);293 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList'});249 await addToAllowListExpectSuccess(alice, collectionId, alice.address);294 await helper.nft.addToAllowList(alice, collectionId, {Substrate: alice.address});250 await addToAllowListExpectSuccess(alice, collectionId, charlie.address);295 await helper.nft.addToAllowList(alice, collectionId, {Substrate: charlie.address});251 await approveExpectSuccess(collectionId, itemId, alice, charlie.address);296 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});297252 await transferFromExpectSuccess(collectionId, itemId, alice, alice, charlie, 1, 'NFT');298 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address});299 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);300 expect(owner.Substrate).to.be.equal(charlie.address);301 });253 });302 });254303255 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner', async () => {304 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner', async () => {256 const collectionId = await createCollectionExpectSuccess();305 await usingPlaygrounds(async (helper) => {306 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});257 await enableAllowListExpectSuccess(alice, collectionId);307 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: false});258 await setMintPermissionExpectSuccess(alice, collectionId, false);308 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});259 await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);309 const token = await helper.nft.getToken(collectionId, tokenId);310 expect(token).to.be.not.null;311 });260 });312 });261313262 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin', async () => {314 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin', async () => {263 const collectionId = await createCollectionExpectSuccess();315 await usingPlaygrounds(async (helper) => {316 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});264 await enableAllowListExpectSuccess(alice, collectionId);317 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: false});265 await setMintPermissionExpectSuccess(alice, collectionId, false);318 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});266 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);319 const {tokenId} = await helper.nft.mintToken(bob, {collectionId: collectionId, owner: bob.address});267 await createItemExpectSuccess(bob, collectionId, 'NFT', bob.address);320 const token = await helper.nft.getToken(collectionId, tokenId);321 expect(token).to.be.not.null;322 });268 });323 });269324270 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow-listed address', async () => {325 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow-listed address', async () => {271 const collectionId = await createCollectionExpectSuccess();326 await usingPlaygrounds(async (helper) => {272 await enableAllowListExpectSuccess(alice, collectionId);327 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});273 await setMintPermissionExpectSuccess(alice, collectionId, false);328 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: false});274 await addToAllowListExpectSuccess(alice, collectionId, bob.address);329 await helper.collection.addToAllowList(alice, collectionId, {Substrate: bob.address});275 await createItemExpectFailure(bob, collectionId, 'NFT', bob.address);330 const mintTokenTx = async () => helper.nft.mintToken(bob, {collectionId: collectionId, owner: bob.address});331 await expect(mintTokenTx()).to.be.rejected;332 });276 });333 });277334278 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address', async () => {335 it('If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address', async () => {279 const collectionId = await createCollectionExpectSuccess();336 await usingPlaygrounds(async (helper) => {280 await enableAllowListExpectSuccess(alice, collectionId);337 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});281 await setMintPermissionExpectSuccess(alice, collectionId, false);338 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: false});282 await createItemExpectFailure(bob, collectionId, 'NFT', bob.address);339 const mintTokenTx = async () => helper.nft.mintToken(bob, {collectionId: collectionId, owner: bob.address});340 await expect(mintTokenTx()).to.be.rejected;341 });283 });342 });284343285 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner', async () => {344 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner', async () => {286 const collectionId = await createCollectionExpectSuccess();345 await usingPlaygrounds(async (helper) => {346 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});287 await enableAllowListExpectSuccess(alice, collectionId);347 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: true});288 await setMintPermissionExpectSuccess(alice, collectionId, true);348 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});289 await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);349 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);350 expect(owner.Substrate).to.be.equal(alice.address);351 });290 });352 });291353292 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin', async () => {354 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin', async () => {293 const collectionId = await createCollectionExpectSuccess();355 await usingPlaygrounds(async (helper) => {356 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});294 await enableAllowListExpectSuccess(alice, collectionId);357 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: true});295 await setMintPermissionExpectSuccess(alice, collectionId, true);358 await helper.nft.addAdmin(alice, collectionId, {Substrate: bob.address});296 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);359 const {tokenId} = await helper.nft.mintToken(bob, {collectionId: collectionId, owner: bob.address});297 await createItemExpectSuccess(bob, collectionId, 'NFT', bob.address);360 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);361 expect(owner.Substrate).to.be.equal(bob.address);362 });298 });363 });299364300 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address', async () => {365 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address', async () => {301 const collectionId = await createCollectionExpectSuccess();366 await usingPlaygrounds(async (helper) => {302 await enableAllowListExpectSuccess(alice, collectionId);367 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});303 await setMintPermissionExpectSuccess(alice, collectionId, true);368 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: true});304 await createItemExpectFailure(bob, collectionId, 'NFT', bob.address);369 const mintTokenTx = async () => helper.nft.mintToken(bob, {collectionId: collectionId, owner: bob.address});370 await expect(mintTokenTx()).to.be.rejected;371 });305 });372 });306373307 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address', async () => {374 it('If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address', async () => {308 const collectionId = await createCollectionExpectSuccess();375 await usingPlaygrounds(async (helper) => {376 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});309 await enableAllowListExpectSuccess(alice, collectionId);377 await helper.nft.setPermissions(alice, collectionId, {access: 'AllowList', mintMode: true});310 await setMintPermissionExpectSuccess(alice, collectionId, true);378 await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});311 await addToAllowListExpectSuccess(alice, collectionId, bob.address);379 const {tokenId} = await helper.nft.mintToken(bob, {collectionId: collectionId, owner: bob.address});312 await createItemExpectSuccess(bob, collectionId, 'NFT', bob.address);380 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);381 expect(owner.Substrate).to.be.equal(bob.address);382 });313 });383 });314});384});315385tests/src/approve.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 {ApiPromise} from '@polkadot/api';19import chai from 'chai';18import chai from 'chai';20import chaiAsPromised from 'chai-as-promised';19import chaiAsPromised from 'chai-as-promised';21import {default as usingApi} from './substrate/substrate-api';22import {20import {23 approveExpectFail,21 approveExpectFail,24 approveExpectSuccess,22 approveExpectSuccess,25 createCollectionExpectSuccess,23 createCollectionExpectSuccess,26 createItemExpectSuccess,24 createItemExpectSuccess,27 destroyCollectionExpectSuccess,28 setCollectionLimitsExpectSuccess,29 transferExpectSuccess,30 addCollectionAdminExpectSuccess,31 adminApproveFromExpectFail,32 getCreatedCollectionCount,33 transferFromExpectSuccess,34 transferFromExpectFail,35 requirePallets,36 Pallets,37} from './util/helpers';25} from './util/helpers';26import {usingPlaygrounds} from './util/playgrounds';382728let donor: IKeyringPair;2930before(async () => {31 await usingPlaygrounds(async (_, privateKey) => {32 donor = privateKey('//Alice');33 });34});3539chai.use(chaiAsPromised);36chai.use(chaiAsPromised);37const expect = chai.expect;403841describe('Integration Test approve(spender, collection_id, item_id, amount):', () => {39describe('Integration Test approve(spender, collection_id, item_id, amount):', () => {42 let alice: IKeyringPair;40 let alice: IKeyringPair;43 let bob: IKeyringPair;41 let bob: IKeyringPair;44 let charlie: IKeyringPair;42 let charlie: IKeyringPair;454346 before(async () => {44 before(async () => {47 await usingApi(async (api, privateKeyWrapper) => {45 await usingPlaygrounds(async (helper) => {48 alice = privateKeyWrapper('//Alice');46 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);49 bob = privateKeyWrapper('//Bob');50 charlie = privateKeyWrapper('//Charlie');51 });47 });52 });48 });534954 it('[nft] Execute the extrinsic and check approvedList', async () => {50 it('[nft] Execute the extrinsic and check approvedList', async () => {55 const nftCollectionId = await createCollectionExpectSuccess();51 await usingPlaygrounds(async (helper) => {52 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});56 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');53 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});57 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);54 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});55 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;56 });58 });57 });595860 it('[fungible] Execute the extrinsic and check approvedList', async () => {59 it('[fungible] Execute the extrinsic and check approvedList', async () => {61 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});60 await usingPlaygrounds(async (helper) => {61 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);62 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');62 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);63 const tokenId = await helper.ft.getLastTokenId(collectionId);64 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});63 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);65 const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});66 expect(amount).to.be.equal(BigInt(1));67 });64 });68 });656966 it('[refungible] Execute the extrinsic and check approvedList', async function() {70 it('[refungible] Execute the extrinsic and check approvedList', async function() {67 await requirePallets(this, [Pallets.ReFungible]);71 await usingPlaygrounds(async (helper) => {6869 const reFungibleCollectionId =72 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});70 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});71 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');73 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});72 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);74 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});75 const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});76 expect(amount).to.be.equal(BigInt(1));77 });73 });78 });747975 it('[nft] Remove approval by using 0 amount', async () => {80 it('[nft] Remove approval by using 0 amount', async () => {76 const nftCollectionId = await createCollectionExpectSuccess();81 await usingPlaygrounds(async (helper) => {82 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});77 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');83 const collectionId = collection.collectionId;84 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});78 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);85 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});79 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);86 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;87 await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));88 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;89 });80 });90 });819182 it('[fungible] Remove approval by using 0 amount', async () => {92 it('[fungible] Remove approval by using 0 amount', async () => {83 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});93 await usingPlaygrounds(async (helper) => {94 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);84 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');95 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);96 const tokenId = await helper.ft.getLastTokenId(collectionId);97 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});85 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);98 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});99 expect(amountBefore).to.be.equal(BigInt(1));10086 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);101 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);102 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});103 expect(amountAfter).to.be.equal(BigInt(0));104 });87 });105 });8810689 it('[refungible] Remove approval by using 0 amount', async function() {107 it('[refungible] Remove approval by using 0 amount', async function() {90 await requirePallets(this, [Pallets.ReFungible]);108 await usingPlaygrounds(async (helper) => {109 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});110 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});111 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});112 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});113 expect(amountBefore).to.be.equal(BigInt(1));9111492 const reFungibleCollectionId =115 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);93 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});94 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');116 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});95 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 1);96 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 0);117 expect(amountAfter).to.be.equal(BigInt(0));118 });97 });119 });9812099 it('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {121 it('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {100 const collectionId = await createCollectionExpectSuccess();122 await usingPlaygrounds(async (helper) => {123 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});101 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);124 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});102103 await adminApproveFromExpectFail(collectionId, itemId, alice, bob.address, charlie.address);125 const approveTokenTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});126 await expect(approveTokenTx()).to.be.rejected;127 });104 });128 });105});129});106130110 let charlie: IKeyringPair;134 let charlie: IKeyringPair;111135112 before(async () => {136 before(async () => {113 await usingApi(async (api, privateKeyWrapper) => {137 await usingPlaygrounds(async (helper) => {114 alice = privateKeyWrapper('//Alice');138 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);115 bob = privateKeyWrapper('//Bob');116 charlie = privateKeyWrapper('//Charlie');117 });139 });118 }); 140 });119141120 it('NFT', async () => {142 it('NFT', async () => {121 const collectionId = await createCollectionExpectSuccess();143 await usingPlaygrounds(async (helper) => {144 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});122 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);145 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});123 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);146 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});147 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;148 });124 });149 });125150126 it('Fungible up to an approved amount', async () => {151 it('Fungible up to an approved amount', async () => {127 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});152 await usingPlaygrounds(async (helper) => {153 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);128 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 154 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);155 const tokenId = await helper.ft.getLastTokenId(collectionId);156 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});129 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);157 const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});158 expect(amount).to.be.equal(BigInt(1));159 });130 });160 });131161132 it('ReFungible up to an approved amount', async function() {162 it('ReFungible up to an approved amount', async function() {133 await requirePallets(this, [Pallets.ReFungible]);163 await usingPlaygrounds(async (helper) => {134135 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});164 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});136 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);165 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});137 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);166 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);167 const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});168 expect(amount).to.be.equal(BigInt(100n));169 });138 });170 });139});171});140172144 let charlie: IKeyringPair;176 let charlie: IKeyringPair;145177146 before(async () => {178 before(async () => {147 await usingApi(async (api, privateKeyWrapper) => {179 await usingPlaygrounds(async (helper) => {148 alice = privateKeyWrapper('//Alice');180 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);149 bob = privateKeyWrapper('//Bob');150 charlie = privateKeyWrapper('//Charlie');151 });181 });152 }); 182 });153183154 it('NFT', async () => {184 it('NFT', async () => {155 const collectionId = await createCollectionExpectSuccess();185 await usingPlaygrounds(async (helper) => {186 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});156 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);187 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});157 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);188 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});158 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'NFT');189 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});190 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);191 expect(owner.Substrate).to.be.equal(alice.address);192 });159 });193 });160194161 it('Fungible up to an approved amount', async () => {195 it('Fungible up to an approved amount', async () => {162 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});196 await usingPlaygrounds(async (helper) => {197 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);163 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 198 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);199 const tokenId = await helper.ft.getLastTokenId(collectionId);164 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);200 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});165 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');201 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});202 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);203 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});204 expect(after - before).to.be.equal(BigInt(1));205 });166 });206 });167207168 it('ReFungible up to an approved amount', async function() {208 it('ReFungible up to an approved amount', async function() {169 await requirePallets(this, [Pallets.ReFungible]);209 await usingPlaygrounds(async (helper) => {170171 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});210 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});172 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);211 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});173 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);212 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});174 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'ReFungible');213 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});214 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);215 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});216 expect(after - before).to.be.equal(BigInt(1));217 });175 });218 });176});219});177220181 let charlie: IKeyringPair;224 let charlie: IKeyringPair;182225183 before(async () => {226 before(async () => {184 await usingApi(async (api, privateKeyWrapper) => {227 await usingPlaygrounds(async (helper) => {185 alice = privateKeyWrapper('//Alice');228 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);186 bob = privateKeyWrapper('//Bob');187 charlie = privateKeyWrapper('//Charlie');188 });229 });189 }); 230 });190231191 it('NFT', async () => {232 it('NFT', async () => {192 const collectionId = await createCollectionExpectSuccess();233 await usingPlaygrounds(async (helper) => {234 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});193 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);235 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});194 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);236 await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});195 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'NFT');237 await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});238 const owner = await helper.nft.getTokenOwner(collectionId, tokenId);196 await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);239 expect(owner.Substrate).to.be.equal(alice.address);240 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});241 await expect(transferTokenFromTx()).to.be.rejected;242 });197 });243 });198244199 it('Fungible up to an approved amount', async () => {245 it('Fungible up to an approved amount', async () => {200 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});246 await usingPlaygrounds(async (helper) => {247 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);201 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 248 await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);249 const tokenId = await helper.ft.getLastTokenId(collectionId);202 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);250 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});203 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');251 const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});252 await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);204 await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);253 const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});254 expect(after - before).to.be.equal(BigInt(1));255256 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);257 await expect(transferTokenFromTx()).to.be.rejected;258 });205 });259 });206260207 it('ReFungible up to an approved amount', async function() {261 it('ReFungible up to an approved amount', async function() {208 await requirePallets(this, [Pallets.ReFungible]);262 await usingPlaygrounds(async (helper) => {209210 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});263 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});211 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);264 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});212 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);265 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);213 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'ReFungible');266 const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});267 await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);214 await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);268 const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});269 expect(after - before).to.be.equal(BigInt(100));270 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);271 await expect(transferTokenFromTx()).to.be.rejected;272 });215 });273 });216});274});217275222 let dave: IKeyringPair;280 let dave: IKeyringPair;223281224 before(async () => {282 before(async () => {225 await usingApi(async (api, privateKeyWrapper) => {283 await usingPlaygrounds(async (helper) => {226 alice = privateKeyWrapper('//Alice');284 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);227 bob = privateKeyWrapper('//Bob');228 charlie = privateKeyWrapper('//Charlie');229 dave = privateKeyWrapper('//Dave');230 });285 });231 }); 286 });232287233 it('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async () => {288 it('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async () => {234 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});289 await usingPlaygrounds(async (helper) => {290 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);235 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address); 291 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);292 const tokenId = await helper.ft.getLastTokenId(collectionId);236 await approveExpectSuccess(collectionId, itemId, alice, bob.address, 10);293 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);294237 await transferFromExpectSuccess(collectionId, itemId, bob, alice, charlie, 2, 'Fungible');295 const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});296 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);297 const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});238 await transferFromExpectSuccess(collectionId, itemId, bob, alice, dave, 8, 'Fungible');298 expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));299300 const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});301 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: dave.address}, 8n);302 const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});303 expect(daveAfter - daveBefore).to.be.equal(BigInt(8));304 });239 });305 });240});306});241307245 let charlie: IKeyringPair;311 let charlie: IKeyringPair;246312247 before(async () => {313 before(async () => {248 await usingApi(async (api, privateKeyWrapper) => {314 await usingPlaygrounds(async (helper) => {249 alice = privateKeyWrapper('//Alice');315 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);250 bob = privateKeyWrapper('//Bob');251 charlie = privateKeyWrapper('//Charlie');252 });316 });253 });317 });254318255 it('NFT', async () => {319 it('NFT', async () => {256 const collectionId = await createCollectionExpectSuccess();320 await usingPlaygrounds(async (helper) => {321 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});257 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT');322 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});258 await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);323 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});259 await approveExpectSuccess(collectionId, itemId, alice, bob.address, 0);324 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;325 await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));260 await transferFromExpectFail(collectionId, itemId, bob, bob, charlie, 1);326 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;327 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});328 await expect(transferTokenFromTx()).to.be.rejected;329 });261 });330 });262331263 it('Fungible', async () => {332 it('Fungible', async () => {264 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});333 await usingPlaygrounds(async (helper) => {334 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);265 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');335 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);336 const tokenId = await helper.ft.getLastTokenId(collectionId);337 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});266 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);338 const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});339 expect(amountBefore).to.be.equal(BigInt(1));340267 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);341 await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);268 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);342 const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});343 expect(amountAfter).to.be.equal(BigInt(0));344345 const transferTokenFromTx = async () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);346 await expect(transferTokenFromTx()).to.be.rejected;347 });269 });348 });270349271 it('ReFungible', async function() {350 it('ReFungible', async function() {272 await requirePallets(this, [Pallets.ReFungible]);351 await usingPlaygrounds(async (helper) => {352 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});353 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});354 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});355 const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});356 expect(amountBefore).to.be.equal(BigInt(1));273357274 const reFungibleCollectionId =358 await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);275 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});276 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');359 const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});277 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 1);360 expect(amountAfter).to.be.equal(BigInt(0));361278 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 0);362 const transferTokenFromTx = async () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);279 await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, bob, charlie, 1);363 await expect(transferTokenFromTx()).to.be.rejected;364 });280 });365 });281});366});282367286 let charlie: IKeyringPair;371 let charlie: IKeyringPair;287372288 before(async () => {373 before(async () => {289 await usingApi(async (api, privateKeyWrapper) => {374 await usingPlaygrounds(async (helper) => {290 alice = privateKeyWrapper('//Alice');375 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);291 bob = privateKeyWrapper('//Bob');292 charlie = privateKeyWrapper('//Charlie');293 });376 });294 });377 });295378296 it('1 for NFT', async () => {379 it('1 for NFT', async () => {297 const collectionId = await createCollectionExpectSuccess();380 await usingPlaygrounds(async (helper) => {381 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});298 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);382 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});299 await approveExpectFail(collectionId, itemId, bob, charlie, 2);383 const approveTx = async () => helper.signTransaction(bob, helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2));384 await expect(approveTx()).to.be.rejected;385 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;386 });300 });387 });301388302 it('Fungible', async () => {389 it('Fungible', async () => {303 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});390 await usingPlaygrounds(async (helper) => {391 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);304 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');392 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);305 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);393 const tokenId = await helper.ft.getLastTokenId(collectionId);394 const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 11n);395 await expect(approveTx()).to.be.rejected;396 });306 });397 });307398308 it('ReFungible', async function() {399 it('ReFungible', async function() {309 await requirePallets(this, [Pallets.ReFungible]);400 await usingPlaygrounds(async (helper) => {310311 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});401 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});312 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');402 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});313 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, charlie, 101);403 const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 101n);404 await expect(approveTx()).to.be.rejected;405 });314 });406 });315});407});316408321 let dave: IKeyringPair;413 let dave: IKeyringPair;322414323 before(async () => {415 before(async () => {324 await usingApi(async (api, privateKeyWrapper) => {416 await usingPlaygrounds(async (helper) => {325 alice = privateKeyWrapper('//Alice');417 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);326 bob = privateKeyWrapper('//Bob');327 charlie = privateKeyWrapper('//Charlie');328 dave = privateKeyWrapper('//Dave');329 });418 });330 }); 419 });331420332 it('NFT', async () => {421 it('NFT', async () => {333 const collectionId = await createCollectionExpectSuccess();422 await usingPlaygrounds(async (helper) => {423 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});334 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});424 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});335 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', charlie.address);425 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: charlie.address});426336 await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'NFT');427 await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address});428 const owner1 = await helper.nft.getTokenOwner(collectionId, tokenId);337 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);429 expect(owner1.Substrate).to.be.equal(dave.address);430431 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});338 await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'NFT');432 await helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address});433 const owner2 = await helper.nft.getTokenOwner(collectionId, tokenId);434 expect(owner2.Substrate).to.be.equal(alice.address);435 });339 });436 });340437341 it('Fungible up to an approved amount', async () => {438 it('Fungible up to an approved amount', async () => {342 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});439 await usingPlaygrounds(async (helper) => {440 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);343 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});441 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});344 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', charlie.address); 442 await helper.ft.mintTokens(alice, collectionId, charlie.address, 10n);443 const tokenId = await helper.ft.getLastTokenId(collectionId);444345 await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'Fungible');445 const daveBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});446 await helper.ft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);447 const daveBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});346 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);448 expect(daveBalanceAfter - daveBalanceBefore).to.be.equal(BigInt(1));449450 await helper.collection.addAdmin(alice ,collectionId, {Substrate: bob.address});451347 await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');452 const aliceBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: alice.address});453 await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);454 const aliceBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: alice.address});455 expect(aliceBalanceAfter - aliceBalanceBefore).to.be.equal(BigInt(1));456 });348 });457 });349458350 it('ReFungible up to an approved amount', async function() {459 it('ReFungible up to an approved amount', async function() {351 await requirePallets(this, [Pallets.ReFungible]);460 await usingPlaygrounds(async (helper) => {461 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});462 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});463 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: charlie.address, pieces: 100n});352464353 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});465 const daveBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});354 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});466 await helper.rft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);355 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', charlie.address);467 const daveAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});468 expect(daveAfter - daveBefore).to.be.equal(BigInt(1));469470 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});471356 await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'ReFungible');472 const aliceBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});473 await helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);357 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);474 const aliceAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});358 await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'ReFungible');475 expect(aliceAfter - aliceBefore).to.be.equal(BigInt(1));476 });359 });477 });360});478});361479366 let dave: IKeyringPair;484 let dave: IKeyringPair;367485368 before(async () => {486 before(async () => {369 await usingApi(async (api, privateKeyWrapper) => {487 await usingPlaygrounds(async (helper) => {370 alice = privateKeyWrapper('//Alice');488 [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);371 bob = privateKeyWrapper('//Bob');372 charlie = privateKeyWrapper('//Charlie');373 dave = privateKeyWrapper('//Dave');374 });489 });375 }); 490 });376491377 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {492 it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {378 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});493 const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});417 let charlie: IKeyringPair;532 let charlie: IKeyringPair;418533419 before(async () => {534 before(async () => {420 await usingApi(async (api, privateKeyWrapper) => {535 await usingPlaygrounds(async (helper) => {421 alice = privateKeyWrapper('//Alice');536 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);422 bob = privateKeyWrapper('//Bob');423 charlie = privateKeyWrapper('//Charlie');424 });537 });425 });538 });426539427 it('can be called by collection admin on non-owned item', async () => {540 it('can be called by collection admin on non-owned item', async () => {428 const collectionId = await createCollectionExpectSuccess();541 await usingPlaygrounds(async (helper) => {542 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});429 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);543 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});430431 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);544 await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});432 await adminApproveFromExpectFail(collectionId, itemId, bob, alice.address, charlie.address);545 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});546 await expect(approveTx()).to.be.rejected;547 });433 });548 });434});549});435550439 let charlie: IKeyringPair;554 let charlie: IKeyringPair;440555441 before(async () => {556 before(async () => {442 await usingApi(async (api, privateKeyWrapper) => {557 await usingPlaygrounds(async (helper) => {443 alice = privateKeyWrapper('//Alice');558 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);444 bob = privateKeyWrapper('//Bob');445 charlie = privateKeyWrapper('//Charlie');446 });559 });447 });560 });448561449 it('[nft] Approve for a collection that does not exist', async () => {562 it('[nft] Approve for a collection that does not exist', async () => {450 await usingApi(async (api: ApiPromise) => {563 await usingPlaygrounds(async (helper) => {451 const nftCollectionCount = await getCreatedCollectionCount(api);564 const collectionId = 1 << 32 - 1;452 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);565 const approveTx = async () => helper.nft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});566 await expect(approveTx()).to.be.rejected;453 });567 });454 });568 });455569456 it('[fungible] Approve for a collection that does not exist', async () => {570 it('[fungible] Approve for a collection that does not exist', async () => {457 await usingApi(async (api: ApiPromise) => {571 await usingPlaygrounds(async (helper) => {458 const fungibleCollectionCount = await getCreatedCollectionCount(api);572 const collectionId = 1 << 32 - 1;459 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);573 const approveTx = async () => helper.ft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});574 await expect(approveTx()).to.be.rejected;460 });575 });461 });576 });462577463 it('[refungible] Approve for a collection that does not exist', async function() {578 it('[refungible] Approve for a collection that does not exist', async function() {464 await requirePallets(this, [Pallets.ReFungible]);579 await usingPlaygrounds(async (helper) => {465466 await usingApi(async (api: ApiPromise) => {467 const reFungibleCollectionCount = await getCreatedCollectionCount(api);580 const collectionId = 1 << 32 - 1;468 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);581 const approveTx = async () => helper.rft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});582 await expect(approveTx()).to.be.rejected;469 });583 });470 });584 });471585472 it('[nft] Approve for a collection that was destroyed', async () => {586 it('[nft] Approve for a collection that was destroyed', async () => {473 const nftCollectionId = await createCollectionExpectSuccess();587 await usingPlaygrounds(async (helper) => {588 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});474 await destroyCollectionExpectSuccess(nftCollectionId);589 await helper.nft.burn(alice, collectionId);475 await approveExpectFail(nftCollectionId, 1, alice, bob);590 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 1, {Substrate: bob.address});591 await expect(approveTx()).to.be.rejected;592 });476 });593 });477594478 it('Approve for a collection that was destroyed', async () => {595 it('[fungible] Approve for a collection that was destroyed', async () => {479 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});596 await usingPlaygrounds(async (helper) => {597 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});480 await destroyCollectionExpectSuccess(fungibleCollectionId);598 await helper.ft.burn(alice, collectionId);481 await approveExpectFail(fungibleCollectionId, 0, alice, bob);599 const approveTx = async () => helper.ft.approveToken(alice, collectionId, 1, {Substrate: bob.address});600 await expect(approveTx()).to.be.rejected;601 });482 });602 });483603484 it('[refungible] Approve for a collection that was destroyed', async function() {604 it('[refungible] Approve for a collection that was destroyed', async function() {485 await requirePallets(this, [Pallets.ReFungible]);605 await usingPlaygrounds(async (helper) => {486487 const reFungibleCollectionId =606 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});488 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});489 await destroyCollectionExpectSuccess(reFungibleCollectionId);607 await helper.rft.burn(alice, collectionId);490 await approveExpectFail(reFungibleCollectionId, 1, alice, bob);608 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});609 await expect(approveTx()).to.be.rejected;610 });491 });611 });492612493 it('[nft] Approve transfer of a token that does not exist', async () => {613 it('[nft] Approve transfer of a token that does not exist', async () => {494 const nftCollectionId = await createCollectionExpectSuccess();614 await usingPlaygrounds(async (helper) => {615 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});495 await approveExpectFail(nftCollectionId, 2, alice, bob);616 const approveTx = async () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});617 await expect(approveTx()).to.be.rejected;618 });496 });619 });497620498 it('[refungible] Approve transfer of a token that does not exist', async function() {621 it('[refungible] Approve transfer of a token that does not exist', async function() {499 await requirePallets(this, [Pallets.ReFungible]);622 await usingPlaygrounds(async (helper) => {500501 const reFungibleCollectionId =623 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});502 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});503 await approveExpectFail(reFungibleCollectionId, 2, alice, bob);624 const approveTx = async () => helper.rft.approveToken(alice, collectionId, 2, {Substrate: bob.address});625 await expect(approveTx()).to.be.rejected;626 });504 });627 });505628506 it('[nft] Approve using the address that does not own the approved token', async () => {629 it('[nft] Approve using the address that does not own the approved token', async () => {507 const nftCollectionId = await createCollectionExpectSuccess();630 await usingPlaygrounds(async (helper) => {631 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});508 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');632 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});509 await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);633 const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});634 await expect(approveTx()).to.be.rejected;635 });510 });636 });511637512 it('[fungible] Approve using the address that does not own the approved token', async () => {638 it('[fungible] Approve using the address that does not own the approved token', async () => {513 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});639 await usingPlaygrounds(async (helper) => {640 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});514 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');641 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);515 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);642 const tokenId = await helper.ft.getLastTokenId(collectionId);643 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});644 await expect(approveTx()).to.be.rejected;645 });516 });646 });517647518 it('[refungible] Approve using the address that does not own the approved token', async function() {648 it('[refungible] Approve using the address that does not own the approved token', async function() {519 await requirePallets(this, [Pallets.ReFungible]);649 await usingPlaygrounds(async (helper) => {520521 const reFungibleCollectionId =650 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});522 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});523 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');651 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});524 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);652 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});653 await expect(approveTx()).to.be.rejected;654 });525 });655 });526656527 it('should fail if approved more ReFungibles than owned', async function() {657 it('should fail if approved more ReFungibles than owned', async function() {528 await requirePallets(this, [Pallets.ReFungible]);658 await usingPlaygrounds(async (helper) => {659 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});660 const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});661 await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);662 await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 100n);529663530 const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});664 const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 101n);531 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');532 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 100, 'ReFungible');533 await approveExpectSuccess(nftCollectionId, newNftTokenId, bob, alice.address, 100);534 await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice, 101);665 await expect(approveTx()).to.be.rejected;666 });535 });667 });536668537 it('should fail if approved more Fungibles than owned', async () => {669 it('should fail if approved more Fungibles than owned', async () => {538 const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});670 await usingPlaygrounds(async (helper) => {671 const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});539 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'Fungible');672 await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);540 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 10, 'Fungible');673 const tokenId = await helper.ft.getLastTokenId(collectionId);674675 await helper.ft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);541 await approveExpectSuccess(nftCollectionId, newNftTokenId, bob, alice.address, 10);676 await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 10n);542 await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice, 11);677 const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 11n);678 await expect(approveTx()).to.be.rejected;679 });543 });680 });544681545 it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {682 it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {546 const collectionId = await createCollectionExpectSuccess();683 await usingPlaygrounds(async (helper) => {684 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});547 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);685 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});548 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: false});686 await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});549687550 await approveExpectFail(collectionId, itemId, alice, charlie);688 const approveTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});689 await expect(approveTx()).to.be.rejected;690 });551 });691 });552});692});553693tests/src/util/playgrounds/unique.tsdiffbeforeafterboth475 return (await this.helper.callRpc('api.rpc.unique.nextSponsored', [collectionId, addressObj, tokenId])).toJSON();475 return (await this.helper.callRpc('api.rpc.unique.nextSponsored', [collectionId, addressObj, tokenId])).toJSON();476 }476 }477477478 /**478 /**479 * Get the number of created collections.479 * Get the number of created collections.480 * 480 *481 * @returns number of created collections481 * @returns number of created collections482 */482 */483 async getTotalCount(): Promise<number> {483 async getTotalCount(): Promise<number> {484 return (await this.helper.callRpc('api.rpc.unique.collectionStats')).created.toNumber();484 return (await this.helper.callRpc('api.rpc.unique.collectionStats')).created.toNumber();485 }485 }486486487 /**487 /**488 * Get information about the collection with additional data, 488 * Get information about the collection with additional data,489 * including the number of tokens it contains, its administrators, 489 * including the number of tokens it contains, its administrators,490 * the normalized address of the collection's owner, and decoded name and description.490 * the normalized address of the collection's owner, and decoded name and description.491 * 491 *492 * @param collectionId ID of collection492 * @param collectionId ID of collection493 * @example await getData(2)493 * @example await getData(2)494 * @returns collection information object494 * @returns collection information object495 */495 */496 async getData(collectionId: number): Promise<{496 async getData(collectionId: number): Promise<{497 id: number;497 id: number;498 name: string;498 name: string;523 return collectionData;523 return collectionData;524 }524 }525525526 /**526 /**527 * Get the addresses of the collection's administrators, optionally normalized.527 * Get the addresses of the collection's administrators, optionally normalized.528 * 528 *529 * @param collectionId ID of collection529 * @param collectionId ID of collection530 * @param normalize whether to normalize the addresses to the default ss58 format530 * @param normalize whether to normalize the addresses to the default ss58 format531 * @example await getAdmins(1)531 * @example await getAdmins(1)532 * @returns array of administrators532 * @returns array of administrators533 */533 */534 async getAdmins(collectionId: number, normalize = false): Promise<ICrossAccountId[]> {534 async getAdmins(collectionId: number, normalize = false): Promise<ICrossAccountId[]> {535 const admins = (await this.helper.callRpc('api.rpc.unique.adminlist', [collectionId])).toHuman();535 const admins = (await this.helper.callRpc('api.rpc.unique.adminlist', [collectionId])).toHuman();536536561 : allowListed;561 : allowListed;562 }562 }563563564 /**564 /**565 * Get the effective limits of the collection instead of null for default values565 * Get the effective limits of the collection instead of null for default values566 * 566 *567 * @param collectionId ID of collection567 * @param collectionId ID of collection568 * @example await getEffectiveLimits(2)568 * @example await getEffectiveLimits(2)569 * @returns object of collection limits569 * @returns object of collection limits570 */570 */571 async getEffectiveLimits(collectionId: number): Promise<ICollectionLimits> {571 async getEffectiveLimits(collectionId: number): Promise<ICollectionLimits> {572 return (await this.helper.callRpc('api.rpc.unique.effectiveCollectionLimits', [collectionId])).toJSON();572 return (await this.helper.callRpc('api.rpc.unique.effectiveCollectionLimits', [collectionId])).toJSON();573 }573 }574574575 /**575 /**576 * Burns the collection if the signer has sufficient permissions and collection is empty.576 * Burns the collection if the signer has sufficient permissions and collection is empty.577 * 577 *578 * @param signer keyring of signer578 * @param signer keyring of signer579 * @param collectionId ID of collection579 * @param collectionId ID of collection580 * @example await helper.collection.burn(aliceKeyring, 3);580 * @example await helper.collection.burn(aliceKeyring, 3);581 * @returns ```true``` if extrinsic success, otherwise ```false```581 * @returns ```true``` if extrinsic success, otherwise ```false```582 */582 */583 async burn(signer: TSigner, collectionId: number): Promise<boolean> {583 async burn(signer: TSigner, collectionId: number): Promise<boolean> {584 const result = await this.helper.executeExtrinsic(584 const result = await this.helper.executeExtrinsic(585 signer,585 signer,590 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionDestroyed');590 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionDestroyed');591 }591 }592592593 /**593 /**594 * Sets the sponsor for the collection (Requires the Substrate address). Needs confirmation by the sponsor.594 * Sets the sponsor for the collection (Requires the Substrate address). Needs confirmation by the sponsor.595 * 595 *596 * @param signer keyring of signer596 * @param signer keyring of signer597 * @param collectionId ID of collection597 * @param collectionId ID of collection598 * @param sponsorAddress Sponsor substrate address598 * @param sponsorAddress Sponsor substrate address599 * @example setSponsor(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")599 * @example setSponsor(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")600 * @returns ```true``` if extrinsic success, otherwise ```false```600 * @returns ```true``` if extrinsic success, otherwise ```false```601 */601 */602 async setSponsor(signer: TSigner, collectionId: number, sponsorAddress: TSubstrateAccount): Promise<boolean> {602 async setSponsor(signer: TSigner, collectionId: number, sponsorAddress: TSubstrateAccount): Promise<boolean> {603 const result = await this.helper.executeExtrinsic(603 const result = await this.helper.executeExtrinsic(604 signer,604 signer,609 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorSet');609 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorSet');610 }610 }611611612 /**612 /**613 * Confirms consent to sponsor the collection on behalf of the signer.613 * Confirms consent to sponsor the collection on behalf of the signer.614 * 614 *615 * @param signer keyring of signer615 * @param signer keyring of signer616 * @param collectionId ID of collection616 * @param collectionId ID of collection617 * @example confirmSponsorship(aliceKeyring, 10)617 * @example confirmSponsorship(aliceKeyring, 10)618 * @returns ```true``` if extrinsic success, otherwise ```false```618 * @returns ```true``` if extrinsic success, otherwise ```false```619 */619 */620 async confirmSponsorship(signer: TSigner, collectionId: number): Promise<boolean> {620 async confirmSponsorship(signer: TSigner, collectionId: number): Promise<boolean> {621 const result = await this.helper.executeExtrinsic(621 const result = await this.helper.executeExtrinsic(622 signer,622 signer,627 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'SponsorshipConfirmed');627 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'SponsorshipConfirmed');628 }628 }629629630 /**630 /**631 * Removes the sponsor of a collection, regardless if it consented or not.631 * Removes the sponsor of a collection, regardless if it consented or not.632 * 632 *633 * @param signer keyring of signer633 * @param signer keyring of signer634 * @param collectionId ID of collection634 * @param collectionId ID of collection635 * @example removeSponsor(aliceKeyring, 10)635 * @example removeSponsor(aliceKeyring, 10)636 * @returns ```true``` if extrinsic success, otherwise ```false```636 * @returns ```true``` if extrinsic success, otherwise ```false```637 */637 */638 async removeSponsor(signer: TSigner, collectionId: number): Promise<boolean> {638 async removeSponsor(signer: TSigner, collectionId: number): Promise<boolean> {639 const result = await this.helper.executeExtrinsic(639 const result = await this.helper.executeExtrinsic(640 signer,640 signer,645 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorRemoved');645 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorRemoved');646 }646 }647647648 /**648 /**649 * Sets the limits of the collection. At least one limit must be specified for a correct call.649 * Sets the limits of the collection. At least one limit must be specified for a correct call.650 * 650 *651 * @param signer keyring of signer651 * @param signer keyring of signer652 * @param collectionId ID of collection652 * @param collectionId ID of collection653 * @param limits collection limits object653 * @param limits collection limits object654 * @example654 * @example655 * await setLimits(655 * await setLimits(656 * aliceKeyring,656 * aliceKeyring,657 * 10,657 * 10,658 * {658 * {659 * sponsorTransferTimeout: 0,659 * sponsorTransferTimeout: 0,660 * ownerCanDestroy: false660 * ownerCanDestroy: false661 * }661 * }662 * )662 * )663 * @returns ```true``` if extrinsic success, otherwise ```false```663 * @returns ```true``` if extrinsic success, otherwise ```false```664 */664 */665 async setLimits(signer: TSigner, collectionId: number, limits: ICollectionLimits): Promise<boolean> {665 async setLimits(signer: TSigner, collectionId: number, limits: ICollectionLimits): Promise<boolean> {666 const result = await this.helper.executeExtrinsic(666 const result = await this.helper.executeExtrinsic(667 signer,667 signer,672 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionLimitSet');672 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionLimitSet');673 }673 }674674675 /**675 /**676 * Changes the owner of the collection to the new Substrate address.676 * Changes the owner of the collection to the new Substrate address.677 * 677 *678 * @param signer keyring of signer678 * @param signer keyring of signer679 * @param collectionId ID of collection679 * @param collectionId ID of collection680 * @param ownerAddress substrate address of new owner680 * @param ownerAddress substrate address of new owner681 * @example changeOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")681 * @example changeOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")682 * @returns ```true``` if extrinsic success, otherwise ```false```682 * @returns ```true``` if extrinsic success, otherwise ```false```683 */683 */684 async changeOwner(signer: TSigner, collectionId: number, ownerAddress: TSubstrateAccount): Promise<boolean> {684 async changeOwner(signer: TSigner, collectionId: number, ownerAddress: TSubstrateAccount): Promise<boolean> {685 const result = await this.helper.executeExtrinsic(685 const result = await this.helper.executeExtrinsic(686 signer,686 signer,691 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionOwnedChanged');691 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionOwnedChanged');692 }692 }693693694 /**694 /**695 * Adds a collection administrator. 695 * Adds a collection administrator.696 * 696 *697 * @param signer keyring of signer697 * @param signer keyring of signer698 * @param collectionId ID of collection698 * @param collectionId ID of collection699 * @param adminAddressObj Administrator address (substrate or ethereum)699 * @param adminAddressObj Administrator address (substrate or ethereum)700 * @example addAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})700 * @example addAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})701 * @returns ```true``` if extrinsic success, otherwise ```false```701 * @returns ```true``` if extrinsic success, otherwise ```false```702 */702 */703 async addAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {703 async addAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {704 const result = await this.helper.executeExtrinsic(704 const result = await this.helper.executeExtrinsic(705 signer,705 signer,710 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminAdded');710 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminAdded');711 }711 }712712713 /**713 /**714 * Removes a collection administrator.714 * Removes a collection administrator.715 * 715 *716 * @param signer keyring of signer716 * @param signer keyring of signer717 * @param collectionId ID of collection717 * @param collectionId ID of collection718 * @param adminAddressObj Administrator address (substrate or ethereum)718 * @param adminAddressObj Administrator address (substrate or ethereum)719 * @example removeAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})719 * @example removeAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})720 * @returns ```true``` if extrinsic success, otherwise ```false```720 * @returns ```true``` if extrinsic success, otherwise ```false```721 */721 */722 async removeAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {722 async removeAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {723 const result = await this.helper.executeExtrinsic(723 const result = await this.helper.executeExtrinsic(724 signer,724 signer,729 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');729 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');730 }730 }731731732 /**732 /**733 * Adds an address to allow list 733 * Adds an address to allow list734 * @param signer keyring of signer734 * @param signer keyring of signer735 * @param collectionId ID of collection735 * @param collectionId ID of collection736 * @param addressObj address to add to the allow list736 * @param addressObj address to add to the allow list737 * @returns ```true``` if extrinsic success, otherwise ```false```737 * @returns ```true``` if extrinsic success, otherwise ```false```738 */738 */739 async addToAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {739 async addToAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {740 const result = await this.helper.executeExtrinsic(740 const result = await this.helper.executeExtrinsic(741 signer,741 signer,746 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressAdded');746 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressAdded');747 }747 }748748749 /**749 /**750 * Removes an address from allow list 750 * Removes an address from allow list751 * 751 *752 * @param signer keyring of signer752 * @param signer keyring of signer753 * @param collectionId ID of collection753 * @param collectionId ID of collection754 * @param addressObj address to remove from the allow list754 * @param addressObj address to remove from the allow list755 * @returns ```true``` if extrinsic success, otherwise ```false```755 * @returns ```true``` if extrinsic success, otherwise ```false```756 */756 */757 async removeFromAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {757 async removeFromAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {758 const result = await this.helper.executeExtrinsic(758 const result = await this.helper.executeExtrinsic(759 signer,759 signer,764 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressRemoved');764 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressRemoved');765 }765 }766766767 /**767 /**768 * Sets onchain permissions for selected collection.768 * Sets onchain permissions for selected collection.769 * 769 *770 * @param signer keyring of signer770 * @param signer keyring of signer771 * @param collectionId ID of collection771 * @param collectionId ID of collection772 * @param permissions collection permissions object772 * @param permissions collection permissions object773 * @example setPermissions(aliceKeyring, 10, {access:'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true}});773 * @example setPermissions(aliceKeyring, 10, {access:'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true}});774 * @returns ```true``` if extrinsic success, otherwise ```false```774 * @returns ```true``` if extrinsic success, otherwise ```false```775 */775 */776 async setPermissions(signer: TSigner, collectionId: number, permissions: ICollectionPermissions): Promise<boolean> {776 async setPermissions(signer: TSigner, collectionId: number, permissions: ICollectionPermissions): Promise<boolean> {777 const result = await this.helper.executeExtrinsic(777 const result = await this.helper.executeExtrinsic(778 signer,778 signer,783 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionPermissionSet');783 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionPermissionSet');784 }784 }785785786 /**786 /**787 * Enables nesting for selected collection. If `restricted` set, you can nest only tokens from specified collections.787 * Enables nesting for selected collection. If `restricted` set, you can nest only tokens from specified collections.788 * 788 *789 * @param signer keyring of signer789 * @param signer keyring of signer790 * @param collectionId ID of collection790 * @param collectionId ID of collection791 * @param permissions nesting permissions object791 * @param permissions nesting permissions object792 * @example enableNesting(aliceKeyring, 10, {collectionAdmin: true, tokenOwner: true});792 * @example enableNesting(aliceKeyring, 10, {collectionAdmin: true, tokenOwner: true});793 * @returns ```true``` if extrinsic success, otherwise ```false```793 * @returns ```true``` if extrinsic success, otherwise ```false```794 */794 */795 async enableNesting(signer: TSigner, collectionId: number, permissions: INestingPermissions): Promise<boolean> {795 async enableNesting(signer: TSigner, collectionId: number, permissions: INestingPermissions): Promise<boolean> {796 return await this.setPermissions(signer, collectionId, {nesting: permissions});796 return await this.setPermissions(signer, collectionId, {nesting: permissions});797 }797 }798798799 /**799 /**800 * Disables nesting for selected collection.800 * Disables nesting for selected collection.801 * 801 *802 * @param signer keyring of signer802 * @param signer keyring of signer803 * @param collectionId ID of collection803 * @param collectionId ID of collection804 * @example disableNesting(aliceKeyring, 10);804 * @example disableNesting(aliceKeyring, 10);805 * @returns ```true``` if extrinsic success, otherwise ```false```805 * @returns ```true``` if extrinsic success, otherwise ```false```806 */806 */807 async disableNesting(signer: TSigner, collectionId: number): Promise<boolean> {807 async disableNesting(signer: TSigner, collectionId: number): Promise<boolean> {808 return await this.setPermissions(signer, collectionId, {nesting: {tokenOwner: false, collectionAdmin: false}});808 return await this.setPermissions(signer, collectionId, {nesting: {tokenOwner: false, collectionAdmin: false}});809 }809 }810810811 /**811 /**812 * Sets onchain properties to the collection.812 * Sets onchain properties to the collection.813 * 813 *814 * @param signer keyring of signer814 * @param signer keyring of signer815 * @param collectionId ID of collection815 * @param collectionId ID of collection816 * @param properties array of property objects816 * @param properties array of property objects817 * @example setProperties(aliceKeyring, 10, [{key: "gender", value: "male"}]);817 * @example setProperties(aliceKeyring, 10, [{key: "gender", value: "male"}]);818 * @returns ```true``` if extrinsic success, otherwise ```false```818 * @returns ```true``` if extrinsic success, otherwise ```false```819 */819 */820 async setProperties(signer: TSigner, collectionId: number, properties: IProperty[]): Promise<boolean> {820 async setProperties(signer: TSigner, collectionId: number, properties: IProperty[]): Promise<boolean> {821 const result = await this.helper.executeExtrinsic(821 const result = await this.helper.executeExtrinsic(822 signer,822 signer,827 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet');827 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet');828 }828 }829829830 /**830 /**831 * Deletes onchain properties from the collection.831 * Deletes onchain properties from the collection.832 * 832 *833 * @param signer keyring of signer833 * @param signer keyring of signer834 * @param collectionId ID of collection834 * @param collectionId ID of collection835 * @param propertyKeys array of property keys to delete835 * @param propertyKeys array of property keys to delete836 * @example deleteProperties(aliceKeyring, 10, ["gender", "age"]);836 * @example deleteProperties(aliceKeyring, 10, ["gender", "age"]);837 * @returns ```true``` if extrinsic success, otherwise ```false```837 * @returns ```true``` if extrinsic success, otherwise ```false```838 */838 */839 async deleteProperties(signer: TSigner, collectionId: number, propertyKeys: string[]): Promise<boolean> {839 async deleteProperties(signer: TSigner, collectionId: number, propertyKeys: string[]): Promise<boolean> {840 const result = await this.helper.executeExtrinsic(840 const result = await this.helper.executeExtrinsic(841 signer,841 signer,846 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertyDeleted');846 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertyDeleted');847 }847 }848848849 /**849 /**850 * Changes the owner of the token.850 * Changes the owner of the token.851 * 851 *852 * @param signer keyring of signer852 * @param signer keyring of signer853 * @param collectionId ID of collection853 * @param collectionId ID of collection854 * @param tokenId ID of token854 * @param tokenId ID of token855 * @param addressObj address of a new owner855 * @param addressObj address of a new owner856 * @param amount amount of tokens to be transfered. For NFT must be set to 1n856 * @param amount amount of tokens to be transfered. For NFT must be set to 1n857 * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})857 * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})858 * @returns true if the token success, otherwise false858 * @returns true if the token success, otherwise false859 */859 */860 async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {860 async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {861 const result = await this.helper.executeExtrinsic(861 const result = await this.helper.executeExtrinsic(862 signer,862 signer,867 return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, {Substrate: typeof signer === 'string' ? signer : signer.address}, addressObj, amount);867 return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, {Substrate: typeof signer === 'string' ? signer : signer.address}, addressObj, amount);868 }868 }869869870 /**870 /**871 * 871 *872 * Change ownership of a token(s) on behalf of the owner. 872 * Change ownership of a token(s) on behalf of the owner.873 * 873 *874 * @param signer keyring of signer874 * @param signer keyring of signer875 * @param collectionId ID of collection875 * @param collectionId ID of collection876 * @param tokenId ID of token876 * @param tokenId ID of token877 * @param fromAddressObj address on behalf of which the token will be sent877 * @param fromAddressObj address on behalf of which the token will be sent878 * @param toAddressObj new token owner878 * @param toAddressObj new token owner879 * @param amount amount of tokens to be transfered. For NFT must be set to 1n879 * @param amount amount of tokens to be transfered. For NFT must be set to 1n880 * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg"}, {Ethereum: "0x9F0583DbB85..."})880 * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg"}, {Ethereum: "0x9F0583DbB85..."})881 * @returns true if the token success, otherwise false881 * @returns true if the token success, otherwise false882 */882 */883 async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {883 async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {884 const result = await this.helper.executeExtrinsic(884 const result = await this.helper.executeExtrinsic(885 signer,885 signer,889 return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);889 return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);890 }890 }891891892 /**892 /**893 * 893 *894 * Destroys a concrete instance of NFT/RFT or burns a specified amount of fungible tokens.894 * Destroys a concrete instance of NFT/RFT or burns a specified amount of fungible tokens.895 * 895 *896 * @param signer keyring of signer896 * @param signer keyring of signer897 * @param collectionId ID of collection897 * @param collectionId ID of collection898 * @param tokenId ID of token898 * @param tokenId ID of token899 * @param amount amount of tokens to be burned. For NFT must be set to 1n899 * @param amount amount of tokens to be burned. For NFT must be set to 1n900 * @example burnToken(aliceKeyring, 10, 5);900 * @example burnToken(aliceKeyring, 10, 5);901 * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```901 * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```902 */902 */903 async burnToken(signer: TSigner, collectionId: number, tokenId: number, amount=1n): Promise<{903 async burnToken(signer: TSigner, collectionId: number, tokenId: number, amount=1n): Promise<{904 success: boolean,904 success: boolean,905 token: number | null905 token: number | null914 return {success: burnedTokens.success, token: burnedTokens.tokens.length > 0 ? burnedTokens.tokens[0] : null};914 return {success: burnedTokens.success, token: burnedTokens.tokens.length > 0 ? burnedTokens.tokens[0] : null};915 }915 }916916917 /**917 /**918 * Destroys a concrete instance of NFT on behalf of the owner918 * Destroys a concrete instance of NFT on behalf of the owner919 * 919 *920 * @param signer keyring of signer920 * @param signer keyring of signer921 * @param collectionId ID of collection921 * @param collectionId ID of collection922 * @param fromAddressObj address on behalf of which the token will be burnt922 * @param fromAddressObj address on behalf of which the token will be burnt923 * @param tokenId ID of token923 * @param tokenId ID of token924 * @param amount amount of tokens to be burned. For NFT must be set to 1n924 * @param amount amount of tokens to be burned. For NFT must be set to 1n925 * @example burnTokenFrom(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."}, 5, {Ethereum: "0x9F0583DbB85..."})925 * @example burnTokenFrom(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."}, 5, {Ethereum: "0x9F0583DbB85..."})926 * @returns ```true``` if extrinsic success, otherwise ```false```926 * @returns ```true``` if extrinsic success, otherwise ```false```927 */927 */928 async burnTokenFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, tokenId: number, amount=1n): Promise<boolean> {928 async burnTokenFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, tokenId: number, amount=1n): Promise<boolean> {929 const burnResult = await this.helper.executeExtrinsic(929 const burnResult = await this.helper.executeExtrinsic(930 signer,930 signer,935 return burnedTokens.success && burnedTokens.tokens.length > 0;935 return burnedTokens.success && burnedTokens.tokens.length > 0;936 }936 }937937938 /**938 /**939 * Set, change, or remove approved address to transfer the ownership of the NFT.939 * Set, change, or remove approved address to transfer the ownership of the NFT.940 * 940 *941 * @param signer keyring of signer941 * @param signer keyring of signer942 * @param collectionId ID of collection942 * @param collectionId ID of collection943 * @param tokenId ID of token943 * @param tokenId ID of token944 * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens944 * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens945 * @param amount amount of token to be approved. For NFT must be set to 1n945 * @param amount amount of token to be approved. For NFT must be set to 1n946 * @returns ```true``` if extrinsic success, otherwise ```false```946 * @returns ```true``` if extrinsic success, otherwise ```false```947 */947 */948 async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {948 async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {949 const approveResult = await this.helper.executeExtrinsic(949 const approveResult = await this.helper.executeExtrinsic(950 signer, 950 signer,955 return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');955 return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');956 }956 }957957958 /**958 /**959 * Get the amount of token pieces approved to transfer or burn. Normally 0.959 * Get the amount of token pieces approved to transfer or burn. Normally 0.960 * 960 *961 * @param collectionId ID of collection961 * @param collectionId ID of collection962 * @param tokenId ID of token962 * @param tokenId ID of token963 * @param toAccountObj address which is approved to use token pieces963 * @param toAccountObj address which is approved to use token pieces964 * @param fromAccountObj address which may have allowed the use of its owned tokens964 * @param fromAccountObj address which may have allowed the use of its owned tokens965 * @example getTokenApprovedPieces(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5ERZNF88Mm7UGfPP3mdG..."})965 * @example getTokenApprovedPieces(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5ERZNF88Mm7UGfPP3mdG..."})966 * @returns number of approved to transfer pieces966 * @returns number of approved to transfer pieces967 */967 */968 async getTokenApprovedPieces(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId, fromAccountObj: ICrossAccountId): Promise<bigint> {968 async getTokenApprovedPieces(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId, fromAccountObj: ICrossAccountId): Promise<bigint> {969 return (await this.helper.callRpc('api.rpc.unique.allowance', [collectionId, fromAccountObj, toAccountObj, tokenId])).toBigInt();969 return (await this.helper.callRpc('api.rpc.unique.allowance', [collectionId, fromAccountObj, toAccountObj, tokenId])).toBigInt();970 }970 }971971972 /**972 /**973 * Get the last created token ID in a collection973 * Get the last created token ID in a collection974 * 974 *975 * @param collectionId ID of collection975 * @param collectionId ID of collection976 * @example getLastTokenId(10);976 * @example getLastTokenId(10);977 * @returns id of the last created token977 * @returns id of the last created token978 */978 */979 async getLastTokenId(collectionId: number): Promise<number> {979 async getLastTokenId(collectionId: number): Promise<number> {980 return (await this.helper.callRpc('api.rpc.unique.lastTokenId', [collectionId])).toNumber();980 return (await this.helper.callRpc('api.rpc.unique.lastTokenId', [collectionId])).toNumber();981 }981 }982982983 /**983 /**984 * Check if token exists984 * Check if token exists985 * 985 *986 * @param collectionId ID of collection986 * @param collectionId ID of collection987 * @param tokenId ID of token987 * @param tokenId ID of token988 * @example isTokenExists(10, 20);988 * @example isTokenExists(10, 20);989 * @returns true if the token exists, otherwise false989 * @returns true if the token exists, otherwise false990 */990 */991 async isTokenExists(collectionId: number, tokenId: number): Promise<boolean> {991 async isTokenExists(collectionId: number, tokenId: number): Promise<boolean> {992 return (await this.helper.callRpc('api.rpc.unique.tokenExists', [collectionId, tokenId])).toJSON();992 return (await this.helper.callRpc('api.rpc.unique.tokenExists', [collectionId, tokenId])).toJSON();993 }993 }994}994}995995996class NFTnRFT extends CollectionGroup {996class NFTnRFT extends CollectionGroup {997 /**997 /**998 * Get tokens owned by account998 * Get tokens owned by account999 * 999 *1000 * @param collectionId ID of collection1000 * @param collectionId ID of collection1001 * @param addressObj tokens owner1001 * @param addressObj tokens owner1002 * @example getTokensByAddress(10, {Substrate: "5DyN4Y92vZCjv38fg..."})1002 * @example getTokensByAddress(10, {Substrate: "5DyN4Y92vZCjv38fg..."})1003 * @returns array of token ids owned by account1003 * @returns array of token ids owned by account1004 */1004 */1005 async getTokensByAddress(collectionId: number, addressObj: ICrossAccountId): Promise<number[]> {1005 async getTokensByAddress(collectionId: number, addressObj: ICrossAccountId): Promise<number[]> {1006 return (await this.helper.callRpc('api.rpc.unique.accountTokens', [collectionId, addressObj])).toJSON();1006 return (await this.helper.callRpc('api.rpc.unique.accountTokens', [collectionId, addressObj])).toJSON();1007 }1007 }100810081009 /**1009 /**1010 * Get token data1010 * Get token data1011 * 1011 *1012 * @param collectionId ID of collection1012 * @param collectionId ID of collection1013 * @param tokenId ID of token1013 * @param tokenId ID of token1014 * @param propertyKeys optionally filter the token properties to only these keys1014 * @param propertyKeys optionally filter the token properties to only these keys1015 * @param blockHashAt optionally query the data at some block with this hash1015 * @param blockHashAt optionally query the data at some block with this hash1016 * @example getToken(10, 5);1016 * @example getToken(10, 5);1017 * @returns human readable token data 1017 * @returns human readable token data1018 */1018 */1019 async getToken(collectionId: number, tokenId: number, propertyKeys: string[] = [], blockHashAt?: string): Promise<{1019 async getToken(collectionId: number, tokenId: number, propertyKeys: string[] = [], blockHashAt?: string): Promise<{1020 properties: IProperty[];1020 properties: IProperty[];1021 owner: ICrossAccountId;1021 owner: ICrossAccountId;1043 return tokenData;1043 return tokenData;1044 }1044 }104510451046 /**1046 /**1047 * Set permissions to change token properties1047 * Set permissions to change token properties1048 * 1048 *1049 * @param signer keyring of signer1049 * @param signer keyring of signer1050 * @param collectionId ID of collection1050 * @param collectionId ID of collection1051 * @param permissions permissions to change a property by the collection owner or admin1051 * @param permissions permissions to change a property by the collection owner or admin1052 * @example setTokenPropertyPermissions(1052 * @example setTokenPropertyPermissions(1053 * aliceKeyring, 10, [{key: "gender", permission: {tokenOwner: true, mutable: true, collectionAdmin: true}}]1053 * aliceKeyring, 10, [{key: "gender", permission: {tokenOwner: true, mutable: true, collectionAdmin: true}}]1054 * )1054 * )1055 * @returns true if extrinsic success otherwise false1055 * @returns true if extrinsic success otherwise false1056 */1056 */1057 async setTokenPropertyPermissions(signer: TSigner, collectionId: number, permissions: ITokenPropertyPermission[]): Promise<boolean> {1057 async setTokenPropertyPermissions(signer: TSigner, collectionId: number, permissions: ITokenPropertyPermission[]): Promise<boolean> {1058 const result = await this.helper.executeExtrinsic(1058 const result = await this.helper.executeExtrinsic(1059 signer,1059 signer,1064 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet');1064 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet');1065 }1065 }106610661067 /**1067 /**1068 * Set token properties1068 * Set token properties1069 * 1069 *1070 * @param signer keyring of signer1070 * @param signer keyring of signer1071 * @param collectionId ID of collection1071 * @param collectionId ID of collection1072 * @param tokenId ID of token1072 * @param tokenId ID of token1073 * @param properties key-value pairs of metadata which to add to a token. Keys must be permitted in the collection1073 * @param properties key-value pairs of metadata which to add to a token. Keys must be permitted in the collection1074 * @example setTokenProperties(aliceKeyring, 10, 5, [{key: "gender", value: "female"}, {key: "age", value: "23"}])1074 * @example setTokenProperties(aliceKeyring, 10, 5, [{key: "gender", value: "female"}, {key: "age", value: "23"}])1075 * @returns ```true``` if extrinsic success, otherwise ```false```1075 * @returns ```true``` if extrinsic success, otherwise ```false```1076 */1076 */1077 async setTokenProperties(signer: TSigner, collectionId: number, tokenId: number, properties: IProperty[]): Promise<boolean> {1077 async setTokenProperties(signer: TSigner, collectionId: number, tokenId: number, properties: IProperty[]): Promise<boolean> {1078 const result = await this.helper.executeExtrinsic(1078 const result = await this.helper.executeExtrinsic(1079 signer,1079 signer,1084 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet');1084 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet');1085 }1085 }108610861087 /**1087 /**1088 * Delete the provided properties of a token1088 * Delete the provided properties of a token1089 * @param signer keyring of signer1089 * @param signer keyring of signer1090 * @param collectionId ID of collection1090 * @param collectionId ID of collection1091 * @param tokenId ID of token1091 * @param tokenId ID of token1092 * @param propertyKeys property keys to be deleted 1092 * @param propertyKeys property keys to be deleted1093 * @example deleteTokenProperties(aliceKeyring, 10, 5, ["gender", "age"])1093 * @example deleteTokenProperties(aliceKeyring, 10, 5, ["gender", "age"])1094 * @returns ```true``` if extrinsic success, otherwise ```false```1094 * @returns ```true``` if extrinsic success, otherwise ```false```1095 */1095 */1096 async deleteTokenProperties(signer: TSigner, collectionId: number, tokenId: number, propertyKeys: string[]): Promise<boolean> {1096 async deleteTokenProperties(signer: TSigner, collectionId: number, tokenId: number, propertyKeys: string[]): Promise<boolean> {1097 const result = await this.helper.executeExtrinsic(1097 const result = await this.helper.executeExtrinsic(1098 signer,1098 signer,1103 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertyDeleted');1103 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertyDeleted');1104 }1104 }110511051106 /**1106 /**1107 * Mint new collection1107 * Mint new collection1108 * 1108 *1109 * @param signer keyring of signer1109 * @param signer keyring of signer1110 * @param collectionOptions basic collection options and properties 1110 * @param collectionOptions basic collection options and properties1111 * @param mode NFT or RFT type of a collection1111 * @param mode NFT or RFT type of a collection1112 * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")1112 * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")1113 * @returns object of the created collection1113 * @returns object of the created collection1114 */1114 */1115 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueCollectionBase> {1115 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueCollectionBase> {1116 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1116 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1117 collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};1117 collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};1187 return (await this.getTokenApprovedPieces(collectionId, tokenId, toAccountObj, await this.getTokenOwner(collectionId, tokenId))) === 1n;1187 return (await this.getTokenApprovedPieces(collectionId, tokenId, toAccountObj, await this.getTokenOwner(collectionId, tokenId))) === 1n;1188 }1188 }118911891190 /**1190 /**1191 * Changes the owner of the token.1191 * Changes the owner of the token.1192 * 1192 *1193 * @param signer keyring of signer1193 * @param signer keyring of signer1194 * @param collectionId ID of collection1194 * @param collectionId ID of collection1195 * @param tokenId ID of token1195 * @param tokenId ID of token1196 * @param addressObj address of a new owner1196 * @param addressObj address of a new owner1197 * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1197 * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1198 * @returns ```true``` if extrinsic success, otherwise ```false```1198 * @returns ```true``` if extrinsic success, otherwise ```false```1199 */1199 */1200 async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<boolean> {1200 async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<boolean> {1201 return await super.transferToken(signer, collectionId, tokenId, addressObj, 1n);1201 return await super.transferToken(signer, collectionId, tokenId, addressObj, 1n);1202 }1202 }120312031204 /**1204 /**1205 * 1205 *1206 * Change ownership of a NFT on behalf of the owner. 1206 * Change ownership of a NFT on behalf of the owner.1207 * 1207 *1208 * @param signer keyring of signer1208 * @param signer keyring of signer1209 * @param collectionId ID of collection1209 * @param collectionId ID of collection1210 * @param tokenId ID of token1210 * @param tokenId ID of token1211 * @param fromAddressObj address on behalf of which the token will be sent1211 * @param fromAddressObj address on behalf of which the token will be sent1212 * @param toAddressObj new token owner1212 * @param toAddressObj new token owner1213 * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Ethereum: "0x9F0583DbB85..."})1213 * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Ethereum: "0x9F0583DbB85..."})1214 * @returns ```true``` if extrinsic success, otherwise ```false```1214 * @returns ```true``` if extrinsic success, otherwise ```false```1215 */1215 */1216 async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId): Promise<boolean> {1216 async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId): Promise<boolean> {1217 return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, 1n);1217 return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, 1n);1218 }1218 }121912191220 /**1220 /**1221 * Recursively find the address that owns the token1221 * Recursively find the address that owns the token1222 * @param collectionId ID of collection1222 * @param collectionId ID of collection1223 * @param tokenId ID of token1223 * @param tokenId ID of token1224 * @param blockHashAt 1224 * @param blockHashAt1225 * @example getTokenTopmostOwner(10, 5);1225 * @example getTokenTopmostOwner(10, 5);1226 * @returns address in CrossAccountId format, e.g. {Substrate: "5DyN4Y92vZCjv38fg..."}1226 * @returns address in CrossAccountId format, e.g. {Substrate: "5DyN4Y92vZCjv38fg..."}1227 */1227 */1228 async getTokenTopmostOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<ICrossAccountId | null> {1228 async getTokenTopmostOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<ICrossAccountId | null> {1229 let owner;1229 let owner;1230 if (typeof blockHashAt === 'undefined') {1230 if (typeof blockHashAt === 'undefined') {1240 return owner.Substrate ? {Substrate: this.helper.address.normalizeSubstrate(owner.Substrate)} : owner;1240 return owner.Substrate ? {Substrate: this.helper.address.normalizeSubstrate(owner.Substrate)} : owner;1241 }1241 }124212421243 /**1243 /**1244 * Get tokens nested in the provided token1244 * Get tokens nested in the provided token1245 * @param collectionId ID of collection1245 * @param collectionId ID of collection1246 * @param tokenId ID of token1246 * @param tokenId ID of token1247 * @param blockHashAt optionally query the data at the block with this hash1247 * @param blockHashAt optionally query the data at the block with this hash1248 * @example getTokenChildren(10, 5);1248 * @example getTokenChildren(10, 5);1249 * @returns tokens whose depth of nesting is <= 5 1249 * @returns tokens whose depth of nesting is <= 51250 */1250 */1251 async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<IToken[]> {1251 async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<IToken[]> {1252 let children;1252 let children;1253 if(typeof blockHashAt === 'undefined') {1253 if(typeof blockHashAt === 'undefined') {1278 return result;1278 return result;1279 }1279 }128012801281 /**1281 /**1282 * Remove token from nested state1282 * Remove token from nested state1283 * @param signer keyring of signer1283 * @param signer keyring of signer1284 * @param tokenObj token to unnest1284 * @param tokenObj token to unnest1285 * @param rootTokenObj parent of a token1285 * @param rootTokenObj parent of a token1286 * @param toAddressObj address of a new token owner 1286 * @param toAddressObj address of a new token owner1287 * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});1287 * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});1288 * @returns ```true``` if extrinsic success, otherwise ```false```1288 * @returns ```true``` if extrinsic success, otherwise ```false```1289 */1289 */1290 async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {1290 async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {1291 const rootTokenAddress = {Ethereum: this.helper.util.getNestingTokenAddress(rootTokenObj.collectionId, rootTokenObj.tokenId)};1291 const rootTokenAddress = {Ethereum: this.helper.util.getNestingTokenAddress(rootTokenObj.collectionId, rootTokenObj.tokenId)};1292 const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);1292 const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);1296 return result;1296 return result;1297 }1297 }129812981299 /**1299 /**1300 * Mint new collection1300 * Mint new collection1301 * @param signer keyring of signer1301 * @param signer keyring of signer1302 * @param collectionOptions Collection options1302 * @param collectionOptions Collection options1303 * @example 1303 * @example1304 * mintCollection(aliceKeyring, {1304 * mintCollection(aliceKeyring, {1305 * name: 'New',1305 * name: 'New',1306 * description: 'New collection',1306 * description: 'New collection',1307 * tokenPrefix: 'NEW',1307 * tokenPrefix: 'NEW',1308 * })1308 * })1309 * @returns object of the created collection1309 * @returns object of the created collection1310 */1310 */1311 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions): Promise<UniqueNFTCollection> {1311 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions): Promise<UniqueNFTCollection> {1312 return await super.mintCollection(signer, collectionOptions, 'NFT') as UniqueNFTCollection;1312 return await super.mintCollection(signer, collectionOptions, 'NFT') as UniqueNFTCollection;1313 }1313 }1334 return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);1334 return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);1335 }1335 }133613361337 /**1337 /**1338 * Mint multiple NFT tokens1338 * Mint multiple NFT tokens1339 * @param signer keyring of signer1339 * @param signer keyring of signer1340 * @param collectionId ID of collection1340 * @param collectionId ID of collection1341 * @param tokens array of tokens with owner and properties1341 * @param tokens array of tokens with owner and properties1342 * @example 1342 * @example1343 * mintMultipleTokens(aliceKeyring, 10, [{1343 * mintMultipleTokens(aliceKeyring, 10, [{1344 * owner: {Substrate: "5DyN4Y92vZCjv38fg..."},1344 * owner: {Substrate: "5DyN4Y92vZCjv38fg..."},1345 * properties: [{key: "gender", value: "male"},{key: "age", value: "45"}],1345 * properties: [{key: "gender", value: "male"},{key: "age", value: "45"}],1346 * },{1346 * },{1347 * owner: {Ethereum: "0x9F0583DbB855d..."},1347 * owner: {Ethereum: "0x9F0583DbB855d..."},1348 * properties: [{key: "gender", value: "female"},{key: "age", value: "22"}],1348 * properties: [{key: "gender", value: "female"},{key: "age", value: "22"}],1349 * }]);1349 * }]);1350 * @returns ```true``` if extrinsic success, otherwise ```false```1350 * @returns ```true``` if extrinsic success, otherwise ```false```1351 */1351 */1352 async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]): Promise<UniqueNFTToken[]> {1352 async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]): Promise<UniqueNFTToken[]> {1353 const creationResult = await this.helper.executeExtrinsic(1353 const creationResult = await this.helper.executeExtrinsic(1354 signer,1354 signer,1392 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1392 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1393 }1393 }13941395 /**1396 * Destroys a concrete instance of NFT.1397 * @param signer keyring of signer1398 * @param collectionId ID of collection1399 * @param tokenId ID of token1400 * @example burnToken(aliceKeyring, 10, 5);1401 * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```1402 */1403 async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number): Promise<{ success: boolean; token: number | null; }> {1404 return await super.burnToken(signer, collectionId, tokenId, 1n);1405 }140613941407 /**1395 /**1408 * Set, change, or remove approved address to transfer the ownership of the NFT.1396 * Set, change, or remove approved address to transfer the ownership of the NFT.1409 * 1397 *1410 * @param signer keyring of signer1398 * @param signer keyring of signer1411 * @param collectionId ID of collection1399 * @param collectionId ID of collection1412 * @param tokenId ID of token1400 * @param tokenId ID of token1413 * @param toAddressObj address to approve1401 * @param toAddressObj address to approve1414 * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1402 * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})1415 * @returns ```true``` if extrinsic success, otherwise ```false```1403 * @returns ```true``` if extrinsic success, otherwise ```false```1416 */1404 */1417 async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId) {1405 async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId) {1418 return super.approveToken(signer, collectionId, tokenId, toAddressObj, 1n);1406 return super.approveToken(signer, collectionId, tokenId, toAddressObj, 1n);1419 }1407 }1442 return new UniqueRFTToken(tokenId, this.getCollectionObject(collectionId));1430 return new UniqueRFTToken(tokenId, this.getCollectionObject(collectionId));1443 }1431 }144414321445 /**1433 /**1446 * Get top 10 token owners with the largest number of pieces 1434 * Get top 10 token owners with the largest number of pieces1447 * @param collectionId ID of collection1435 * @param collectionId ID of collection1448 * @param tokenId ID of token1436 * @param tokenId ID of token1449 * @example getTokenTop10Owners(10, 5);1437 * @example getTokenTop10Owners(10, 5);1450 * @returns array of top 10 owners1438 * @returns array of top 10 owners1451 */1439 */1452 async getTokenTop10Owners(collectionId: number, tokenId: number): Promise<ICrossAccountId[]> {1440 async getTokenTop10Owners(collectionId: number, tokenId: number): Promise<ICrossAccountId[]> {1453 return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, tokenId])).toJSON().map(crossAccountIdFromLower);1441 return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, tokenId])).toJSON().map(crossAccountIdFromLower);1454 }1442 }1479 return await super.transferToken(signer, collectionId, tokenId, addressObj, amount);1467 return await super.transferToken(signer, collectionId, tokenId, addressObj, amount);1480 }1468 }148114691482 /**1470 /**1483 * Change ownership of some pieces of RFT on behalf of the owner. 1471 * Change ownership of some pieces of RFT on behalf of the owner.1484 * @param signer keyring of signer1472 * @param signer keyring of signer1485 * @param collectionId ID of collection1473 * @param collectionId ID of collection1486 * @param tokenId ID of token1474 * @param tokenId ID of token1487 * @param fromAddressObj address on behalf of which the token will be sent1475 * @param fromAddressObj address on behalf of which the token will be sent1488 * @param toAddressObj new token owner1476 * @param toAddressObj new token owner1489 * @param amount number of pieces to be transfered1477 * @param amount number of pieces to be transfered1490 * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5DfhbVfww7ThF8q6f3i..."}, 2000n)1478 * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5DfhbVfww7ThF8q6f3i..."}, 2000n)1491 * @returns ```true``` if extrinsic success, otherwise ```false```1479 * @returns ```true``` if extrinsic success, otherwise ```false```1492 */1480 */1493 async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1481 async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1494 return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1482 return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, amount);1495 }1483 }1582 return await super.burnToken(signer, collectionId, tokenId, amount);1570 return await super.burnToken(signer, collectionId, tokenId, amount);1583 }1571 }158415721585 /**1573 /**1586 * Set, change, or remove approved address to transfer the ownership of the RFT.1574 * Set, change, or remove approved address to transfer the ownership of the RFT.1587 * 1575 *1588 * @param signer keyring of signer1576 * @param signer keyring of signer1589 * @param collectionId ID of collection1577 * @param collectionId ID of collection1590 * @param tokenId ID of token1578 * @param tokenId ID of token1591 * @param toAddressObj address to approve1579 * @param toAddressObj address to approve1592 * @param amount number of pieces to be approved1580 * @param amount number of pieces to be approved1593 * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5GHoZe9c73RYbVzq..."}, "", 10000n);1581 * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5GHoZe9c73RYbVzq..."}, "", 10000n);1594 * @returns true if the token success, otherwise false1582 * @returns true if the token success, otherwise false1595 */1583 */1596 async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1584 async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {1597 return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);1585 return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);1598 }1586 }1641 return new UniqueFTCollection(collectionId, this.helper);1629 return new UniqueFTCollection(collectionId, this.helper);1642 }1630 }164316311644 /**1632 /**1645 * Mint new fungible collection1633 * Mint new fungible collection1646 * @param signer keyring of signer1634 * @param signer keyring of signer1647 * @param collectionOptions Collection options1635 * @param collectionOptions Collection options1648 * @param decimalPoints number of token decimals 1636 * @param decimalPoints number of token decimals1649 * @example1637 * @example1650 * mintCollection(aliceKeyring, {1638 * mintCollection(aliceKeyring, {1651 * name: 'New',1639 * name: 'New',1652 * description: 'New collection',1640 * description: 'New collection',1653 * tokenPrefix: 'NEW',1641 * tokenPrefix: 'NEW',1654 * }, 18)1642 * }, 18)1655 * @returns newly created fungible collection1643 * @returns newly created fungible collection1656 */1644 */1657 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, decimalPoints = 0): Promise<UniqueFTCollection> {1645 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, decimalPoints = 0): Promise<UniqueFTCollection> {1658 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1646 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1659 if(collectionOptions.tokenPropertyPermissions) throw Error('Fungible collections has no tokenPropertyPermissions');1647 if(collectionOptions.tokenPropertyPermissions) throw Error('Fungible collections has no tokenPropertyPermissions');1669 return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));1657 return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));1670 }1658 }167116591672 /**1660 /**1673 * Mint tokens1661 * Mint tokens1674 * @param signer keyring of signer1662 * @param signer keyring of signer1675 * @param collectionId ID of collection1663 * @param collectionId ID of collection1676 * @param owner address owner of new tokens1664 * @param owner address owner of new tokens1677 * @param amount amount of tokens to be meanted1665 * @param amount amount of tokens to be meanted1678 * @example mintTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq"}, 1000n);1666 * @example mintTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq"}, 1000n);1679 * @returns ```true``` if extrinsic success, otherwise ```false``` 1667 * @returns ```true``` if extrinsic success, otherwise ```false```1680 */1668 */1681 async mintTokens(signer: TSigner, collectionId: number, amount: bigint, owner: ICrossAccountId | string): Promise<boolean> {1669 async mintTokens(signer: TSigner, collectionId: number, amount: bigint, owner: ICrossAccountId | string): Promise<boolean> {1682 const creationResult = await this.helper.executeExtrinsic(1670 const creationResult = await this.helper.executeExtrinsic(1683 signer,1671 signer,1691 return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');1679 return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');1692 }1680 }169316811694 /**1682 /**1695 * Mint multiple Fungible tokens with one owner1683 * Mint multiple Fungible tokens with one owner1696 * @param signer keyring of signer1684 * @param signer keyring of signer1697 * @param collectionId ID of collection1685 * @param collectionId ID of collection1698 * @param owner tokens owner1686 * @param owner tokens owner1699 * @param tokens array of tokens with properties and pieces1687 * @param tokens array of tokens with properties and pieces1700 * @returns ```true``` if extrinsic success, otherwise ```false``` 1688 * @returns ```true``` if extrinsic success, otherwise ```false```1701 */1689 */1702 async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, tokens: {value: bigint}[], owner: ICrossAccountId): Promise<boolean> {1690 async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, tokens: {value: bigint}[], owner: ICrossAccountId): Promise<boolean> {1703 const rawTokens = [];1691 const rawTokens = [];1704 for (const token of tokens) {1692 for (const token of tokens) {1713 return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');1701 return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');1714 }1702 }171517031716 /**1704 /**1717 * Get the top 10 owners with the largest balance for the Fungible collection 1705 * Get the top 10 owners with the largest balance for the Fungible collection1718 * @param collectionId ID of collection1706 * @param collectionId ID of collection1719 * @example getTop10Owners(10);1707 * @example getTop10Owners(10);1720 * @returns array of ```ICrossAccountId```1708 * @returns array of ```ICrossAccountId```1721 */1709 */1722 async getTop10Owners(collectionId: number): Promise<ICrossAccountId[]> {1710 async getTop10Owners(collectionId: number): Promise<ICrossAccountId[]> {1723 return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, 0])).toJSON().map(crossAccountIdFromLower);1711 return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, 0])).toJSON().map(crossAccountIdFromLower);1724 }1712 }1734 return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, 0])).toBigInt();1722 return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, 0])).toBigInt();1735 }1723 }173617241737 /**1725 /**1738 * Transfer tokens to address1726 * Transfer tokens to address1739 * @param signer keyring of signer1727 * @param signer keyring of signer1740 * @param collectionId ID of collection1728 * @param collectionId ID of collection1741 * @param toAddressObj address recipient1729 * @param toAddressObj address recipient1742 * @param amount amount of tokens to be sent1730 * @param amount amount of tokens to be sent1743 * @example transfer(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);1731 * @example transfer(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);1744 * @returns ```true``` if extrinsic success, otherwise ```false``` 1732 * @returns ```true``` if extrinsic success, otherwise ```false```1745 */1733 */1746 async transfer(signer: TSigner, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {1734 async transfer(signer: TSigner, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {1747 return await super.transferToken(signer, collectionId, 0, toAddressObj, amount);1735 return await super.transferToken(signer, collectionId, 0, toAddressObj, amount);1748 }1736 }174917371750 /**1738 /**1751 * Transfer some tokens on behalf of the owner.1739 * Transfer some tokens on behalf of the owner.1752 * @param signer keyring of signer1740 * @param signer keyring of signer1753 * @param collectionId ID of collection1741 * @param collectionId ID of collection1754 * @param fromAddressObj address on behalf of which tokens will be sent1742 * @param fromAddressObj address on behalf of which tokens will be sent1755 * @param toAddressObj address where token to be sent1743 * @param toAddressObj address where token to be sent1756 * @param amount number of tokens to be sent1744 * @param amount number of tokens to be sent1757 * @example transferFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, {Substrate: "5DfhbVfww7ThF8q6f3ij..."}, 10000n);1745 * @example transferFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, {Substrate: "5DfhbVfww7ThF8q6f3ij..."}, 10000n);1758 * @returns ```true``` if extrinsic success, otherwise ```false``` 1746 * @returns ```true``` if extrinsic success, otherwise ```false```1759 */1747 */1760 async transferFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {1748 async transferFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {1761 return await super.transferTokenFrom(signer, collectionId, 0, fromAddressObj, toAddressObj, amount);1749 return await super.transferTokenFrom(signer, collectionId, 0, fromAddressObj, toAddressObj, amount);1762 }1750 }176317511764 /**1752 /**1765 * Destroy some amount of tokens1753 * Destroy some amount of tokens1766 * @param signer keyring of signer1754 * @param signer keyring of signer1767 * @param collectionId ID of collection1755 * @param collectionId ID of collection1768 * @param amount amount of tokens to be destroyed1756 * @param amount amount of tokens to be destroyed1769 * @example burnTokens(aliceKeyring, 10, 1000n);1757 * @example burnTokens(aliceKeyring, 10, 1000n);1770 * @returns ```true``` if extrinsic success, otherwise ```false``` 1758 * @returns ```true``` if extrinsic success, otherwise ```false```1771 */1759 */1772 async burnTokens(signer: IKeyringPair, collectionId: number, amount=1n): Promise<boolean> {1760 async burnTokens(signer: IKeyringPair, collectionId: number, amount=1n): Promise<boolean> {1773 return (await super.burnToken(signer, collectionId, 0, amount)).success;1761 return (await super.burnToken(signer, collectionId, 0, amount)).success;1774 }1762 }177517631776 /**1764 /**1777 * Burn some tokens on behalf of the owner.1765 * Burn some tokens on behalf of the owner.1778 * @param signer keyring of signer1766 * @param signer keyring of signer1779 * @param collectionId ID of collection1767 * @param collectionId ID of collection1780 * @param fromAddressObj address on behalf of which tokens will be burnt1768 * @param fromAddressObj address on behalf of which tokens will be burnt1781 * @param amount amount of tokens to be burnt1769 * @param amount amount of tokens to be burnt1782 * @example burnTokensFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);1770 * @example burnTokensFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);1783 * @returns ```true``` if extrinsic success, otherwise ```false``` 1771 * @returns ```true``` if extrinsic success, otherwise ```false```1784 */1772 */1785 async burnTokensFrom(signer: IKeyringPair, collectionId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1773 async burnTokensFrom(signer: IKeyringPair, collectionId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {1786 return await super.burnTokenFrom(signer, collectionId, fromAddressObj, 0, amount);1774 return await super.burnTokenFrom(signer, collectionId, fromAddressObj, 0, amount);1787 }1775 }178817761789 /**1777 /**1790 * Get total collection supply1778 * Get total collection supply1791 * @param collectionId 1779 * @param collectionId1792 * @returns 1780 * @returns1793 */1781 */1794 async getTotalPieces(collectionId: number): Promise<bigint> {1782 async getTotalPieces(collectionId: number): Promise<bigint> {1795 return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, 0])).unwrap().toBigInt();1783 return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, 0])).unwrap().toBigInt();1796 }1784 }179717851798 /**1786 /**1799 * Set, change, or remove approved address to transfer tokens.1787 * Set, change, or remove approved address to transfer tokens.1800 * 1788 *1801 * @param signer keyring of signer1789 * @param signer keyring of signer1802 * @param collectionId ID of collection1790 * @param collectionId ID of collection1803 * @param toAddressObj address to be approved1791 * @param toAddressObj address to be approved1804 * @param amount amount of tokens to be approved1792 * @param amount amount of tokens to be approved1805 * @example approveTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n)1793 * @example approveTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n)1806 * @returns ```true``` if extrinsic success, otherwise ```false``` 1794 * @returns ```true``` if extrinsic success, otherwise ```false```1807 */1795 */1808 async approveTokens(signer: IKeyringPair, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {1796 async approveTokens(signer: IKeyringPair, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {1809 return super.approveToken(signer, collectionId, 0, toAddressObj, amount);1797 return super.approveToken(signer, collectionId, 0, toAddressObj, amount);1810 }1798 }1898 return (await this.helper.callRpc('api.query.system.account', [address])).data.free.toBigInt();1886 return (await this.helper.callRpc('api.query.system.account', [address])).data.free.toBigInt();1899 }1887 }190018881901 /**1889 /**1902 * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved1890 * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved1903 * @param address substrate address1891 * @param address substrate address1904 * @returns 1892 * @returns1905 */1893 */1906 async getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {1894 async getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {1907 const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data;1895 const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data;1908 return {free: accountInfo.free.toBigInt(), miscFrozen: accountInfo.miscFrozen.toBigInt(), feeFrozen: accountInfo.feeFrozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};1896 return {free: accountInfo.free.toBigInt(), miscFrozen: accountInfo.miscFrozen.toBigInt(), feeFrozen: accountInfo.feeFrozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};