git.delta.rocks / unique-network / refs/commits / 2c2e9d0721a6

difftreelog

chore fix eslint

Grigoriy Simonov2022-11-15parent: #0f00097.patch.diff
in: master

2 files changed

modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
before · tests/src/eth/nonFungible.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util';18import {IKeyringPair} from '@polkadot/types/types';19import {Contract} from 'web3-eth-contract';202122describe('NFT: Information getting', () => {23  let donor: IKeyringPair;24  let alice: IKeyringPair;2526  before(async function() {27    await usingEthPlaygrounds(async (helper, privateKey) => {28      donor = await privateKey({filename: __filename});29      [alice] = await helper.arrange.createAccounts([10n], donor);30    });31  });3233  itEth('totalSupply', async ({helper}) => {34    const collection = await helper.nft.mintCollection(alice, {});35    await collection.mintToken(alice);3637    const caller = await helper.eth.createAccountWithBalance(donor);3839    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);40    const totalSupply = await contract.methods.totalSupply().call();4142    expect(totalSupply).to.equal('1');43  });4445  itEth('balanceOf', async ({helper}) => {46    const collection = await helper.nft.mintCollection(alice, {});47    const caller = await helper.eth.createAccountWithBalance(donor);4849    await collection.mintToken(alice, {Ethereum: caller});50    await collection.mintToken(alice, {Ethereum: caller});51    await collection.mintToken(alice, {Ethereum: caller});5253    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);54    const balance = await contract.methods.balanceOf(caller).call();5556    expect(balance).to.equal('3');57  });5859  itEth('ownerOf', async ({helper}) => {60    const collection = await helper.nft.mintCollection(alice, {});61    const caller = await helper.eth.createAccountWithBalance(donor);6263    const token = await collection.mintToken(alice, {Ethereum: caller});6465    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);6667    const owner = await contract.methods.ownerOf(token.tokenId).call();6869    expect(owner).to.equal(caller);70  });7172  itEth('name/symbol is available regardless of ERC721Metadata support', async ({helper}) => {73    const collection = await helper.nft.mintCollection(alice, {name: 'test', tokenPrefix: 'TEST'});74    const caller = helper.eth.createAccount();7576    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);7778    expect(await contract.methods.name().call()).to.equal('test');79    expect(await contract.methods.symbol().call()).to.equal('TEST');80  });81});8283describe('Check ERC721 token URI for NFT', () => {84  let donor: IKeyringPair;8586  before(async function() {87    await usingEthPlaygrounds(async (_helper, privateKey) => {88      donor = await privateKey({filename: __filename});89    });90  });9192  async function setup(helper: EthUniqueHelper, baseUri: string, propertyKey?: string, propertyValue?: string): Promise<{contract: Contract, nextTokenId: string}> {93    const owner = await helper.eth.createAccountWithBalance(donor);94    const receiver = helper.eth.createAccount();9596    const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Mint collection', 'a', 'b', baseUri);97    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);9899    const result = await contract.methods.mint(receiver).send();100    const tokenId = result.events.Transfer.returnValues.tokenId;101    expect(tokenId).to.be.equal('1');102103    if (propertyKey && propertyValue) {104      // Set URL or suffix105      await contract.methods.setProperties(tokenId, [{ key: propertyKey, value: Buffer.from(propertyValue)}]).send();106    }107108    const event = result.events.Transfer;109    expect(event.address).to.be.equal(collectionAddress);110    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');111    expect(event.returnValues.to).to.be.equal(receiver);112    expect(event.returnValues.tokenId).to.be.equal(tokenId);113114    return {contract, nextTokenId: tokenId};115  }116117  itEth('Empty tokenURI', async ({helper}) => {118    const {contract, nextTokenId} = await setup(helper, '');119    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');120  });121122  itEth('TokenURI from url', async ({helper}) => {123    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URI', 'Token URI');124    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');125  });126127  itEth('TokenURI from baseURI', async ({helper}) => {128    const {contract, nextTokenId} = await setup(helper, 'BaseURI_');129    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_');130  });131132  itEth('TokenURI from baseURI + suffix', async ({helper}) => {133    const suffix = '/some/suffix';134    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URISuffix', suffix);135    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);136  });137});138139describe('NFT: Plain calls', () => {140  let donor: IKeyringPair;141  let minter: IKeyringPair;142  let bob: IKeyringPair;143  let charlie: IKeyringPair;144145  before(async function() {146    await usingEthPlaygrounds(async (helper, privateKey) => {147      donor = await privateKey({filename: __filename});148      [minter, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);149    });150  });151152  itEth('Can perform mint()', async ({helper}) => {153    const owner = await helper.eth.createAccountWithBalance(donor);154    const receiver = helper.eth.createAccount();155156    const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Mint collection', '6', '6', '');157    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);158159    const result = await contract.methods.mintWithTokenURI(receiver, 'Test URI').send();160    const tokenId = result.events.Transfer.returnValues.tokenId;161    expect(tokenId).to.be.equal('1');162163    const event = result.events.Transfer;164    expect(event.address).to.be.equal(collectionAddress);165    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');166    expect(event.returnValues.to).to.be.equal(receiver);167168    expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');169170    // TODO: this wont work right now, need release 919000 first171    // await helper.methods.setOffchainSchema(collectionIdAddress, 'https://offchain-service.local/token-info/{id}').send();172    // const tokenUri = await contract.methods.tokenURI(nextTokenId).call();173    // expect(tokenUri).to.be.equal(`https://offchain-service.local/token-info/${nextTokenId}`);174  });175176  //TODO: CORE-302 add eth methods177  itEth.skip('Can perform mintBulk()', async ({helper}) => {178    const caller = await helper.eth.createAccountWithBalance(donor);179    const receiver = helper.eth.createAccount();180181    const collection = await helper.nft.mintCollection(minter);182    await collection.addAdmin(minter, {Ethereum: caller});183184    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);185    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);186    {187      const bulkSize = 3;188      const nextTokenId = await contract.methods.nextTokenId().call();189      expect(nextTokenId).to.be.equal('1');190      const result = await contract.methods.mintBulkWithTokenURI(191        receiver,192        Array.from({length: bulkSize}, (_, i) => (193          [+nextTokenId + i, `Test URI ${i}`]194        )),195      ).send({from: caller});196197      const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.tokenId - b.returnValues.tokenId);198      for (let i = 0; i < bulkSize; i++) {199        const event = events[i];200        expect(event.address).to.equal(collectionAddress);201        expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');202        expect(event.returnValues.to).to.equal(receiver);203        expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);204205        expect(await contract.methods.tokenURI(+nextTokenId + i).call()).to.be.equal(`Test URI ${i}`);206      }207    }208  });209210  itEth('Can perform burn()', async ({helper}) => {211    const caller = await helper.eth.createAccountWithBalance(donor);212213    const collection = await helper.nft.mintCollection(minter, {});214    const {tokenId} = await collection.mintToken(minter, {Ethereum: caller});215216    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);217    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);218219    {220      const result = await contract.methods.burn(tokenId).send({from: caller});221222      const event = result.events.Transfer;223      expect(event.address).to.be.equal(collectionAddress);224      expect(event.returnValues.from).to.be.equal(caller);225      expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');226      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);227    }228  });229230  itEth('Can perform approve()', async ({helper}) => {231    const owner = await helper.eth.createAccountWithBalance(donor);232    const spender = helper.eth.createAccount();233234    const collection = await helper.nft.mintCollection(minter, {});235    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});236237    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);238    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);239240    {241      const result = await contract.methods.approve(spender, tokenId).send({from: owner});242243      const event = result.events.Approval;244      expect(event.address).to.be.equal(collectionAddress);245      expect(event.returnValues.owner).to.be.equal(owner);246      expect(event.returnValues.approved).to.be.equal(spender);247      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);248    }249  });250251  itEth('Can perform burnFromCross()', async ({helper}) => {252    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});253254    const owner = bob;255    const spender = await helper.eth.createAccountWithBalance(donor, 100n);256257    const token = await collection.mintToken(minter, {Substrate: owner.address});258259    const address = helper.ethAddress.fromCollectionId(collection.collectionId);260    const contract = helper.ethNativeContract.collection(address, 'nft');261262    {263      await token.approve(owner, {Ethereum: spender});264      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);265      const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});266      const events = result.events.Transfer;267268      expect(events).to.be.like({269        address,270        event: 'Transfer',271        returnValues: {272          from: helper.address.substrateToEth(owner.address),273          to: '0x0000000000000000000000000000000000000000',274          tokenId: token.tokenId.toString(),275        },276      });277    }278  });279280  itEth('Can perform approveCross()', async ({helper}) => {281    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});282283    const owner = await helper.eth.createAccountWithBalance(donor, 100n);284    const receiver = charlie;285286    const token = await collection.mintToken(minter, {Ethereum: owner});287288    const address = helper.ethAddress.fromCollectionId(collection.collectionId);289    const contract = helper.ethNativeContract.collection(address, 'nft');290291    {292      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);293      const result = await contract.methods.approveCross(recieverCross, token.tokenId).send({from: owner});294      const event = result.events.Approval;295      expect(event).to.be.like({296        address: helper.ethAddress.fromCollectionId(collection.collectionId),297        event: 'Approval',298        returnValues: {299          owner,300          approved: helper.address.substrateToEth(receiver.address),301          tokenId: token.tokenId.toString(),302        },303      });304    }305  });306307  itEth('Can perform transferFrom()', async ({helper}) => {308    const owner = await helper.eth.createAccountWithBalance(donor);309    const spender = await helper.eth.createAccountWithBalance(donor);310    const receiver = helper.eth.createAccount();311312    const collection = await helper.nft.mintCollection(minter, {});313    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});314315    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);316    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);317318    await contract.methods.approve(spender, tokenId).send({from: owner});319320    {321      const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: spender});322323      const event = result.events.Transfer;324      expect(event.address).to.be.equal(collectionAddress);325      expect(event.returnValues.from).to.be.equal(owner);326      expect(event.returnValues.to).to.be.equal(receiver);327      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);328    }329330    {331      const balance = await contract.methods.balanceOf(receiver).call();332      expect(+balance).to.equal(1);333    }334335    {336      const balance = await contract.methods.balanceOf(owner).call();337      expect(+balance).to.equal(0);338    }339  });340341  itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {342    const minter = await privateKey('//Alice');343    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});344345    const owner = await privateKey('//Bob');346    const spender = await helper.eth.createAccountWithBalance(donor);347    const receiver = await privateKey('//Charlie');348349    const token = await collection.mintToken(minter, {Substrate: owner.address});350351    const address = helper.ethAddress.fromCollectionId(collection.collectionId);352    const contract = helper.ethNativeContract.collection(address, 'nft');353354    await token.approve(owner, {Ethereum: spender});355356    {357      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);358      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);359      const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});360      const event = result.events.Transfer;361      expect(event).to.be.like({362        address: helper.ethAddress.fromCollectionId(collection.collectionId),363        event: 'Transfer',364        returnValues: {365          from: helper.address.substrateToEth(owner.address),366          to: helper.address.substrateToEth(receiver.address),367          tokenId: token.tokenId.toString(),368        },369      });370    }371372    expect(await token.getOwner()).to.be.like({Substrate: receiver.address});373  });374375  itEth('Can perform transfer()', async ({helper}) => {376    const collection = await helper.nft.mintCollection(minter, {});377    const owner = await helper.eth.createAccountWithBalance(donor);378    const receiver = helper.eth.createAccount();379380    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});381382    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);383    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);384385    {386      const result = await contract.methods.transfer(receiver, tokenId).send({from: owner});387388      const event = result.events.Transfer;389      expect(event.address).to.be.equal(collectionAddress);390      expect(event.returnValues.from).to.be.equal(owner);391      expect(event.returnValues.to).to.be.equal(receiver);392      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);393    }394395    {396      const balance = await contract.methods.balanceOf(owner).call();397      expect(+balance).to.equal(0);398    }399400    {401      const balance = await contract.methods.balanceOf(receiver).call();402      expect(+balance).to.equal(1);403    }404  });405  406  itEth('Can perform transferCross()', async ({helper}) => {407    const collection = await helper.nft.mintCollection(minter, {});408    const owner = await helper.eth.createAccountWithBalance(donor);409    const receiver = await helper.eth.createAccountWithBalance(donor);410    const to = helper.ethCrossAccount.fromAddress(receiver);411    const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter);412    413    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});414415    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);416    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);417418    {419      const result = await contract.methods.transferCross(to, tokenId).send({from: owner});420421      const event = result.events.Transfer;422      expect(event.address).to.be.equal(collectionAddress);423      expect(event.returnValues.from).to.be.equal(owner);424      expect(event.returnValues.to).to.be.equal(receiver);425      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);426    }427428    {429      const balance = await contract.methods.balanceOf(owner).call();430      expect(+balance).to.equal(0);431    }432433    {434      const balance = await contract.methods.balanceOf(receiver).call();435      expect(+balance).to.equal(1);436    }437    438    {439      const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver});440      441442      const event = substrateResult.events.Transfer;443      expect(event.address).to.be.equal(collectionAddress);444      expect(event.returnValues.from).to.be.equal(receiver);445      expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));446      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);447    }448449    {450      const balance = await contract.methods.balanceOf(receiver).call();451      expect(+balance).to.equal(0);452    }453454    {455      const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});456      expect(balance).to.be.contain(tokenId);457    }458  });459});460461describe('NFT: Fees', () => {462  let donor: IKeyringPair;463  let alice: IKeyringPair;464  let bob: IKeyringPair;465  let charlie: IKeyringPair;466467  before(async function() {468    await usingEthPlaygrounds(async (helper, privateKey) => {469      donor = await privateKey({filename: __filename});470      [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);471    });472  });473474  itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {475    const owner = await helper.eth.createAccountWithBalance(donor);476    const spender = helper.eth.createAccount();477478    const collection = await helper.nft.mintCollection(alice, {});479    const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});480481    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);482483    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, tokenId).send({from: owner}));484    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));485  });486487  itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {488    const owner = await helper.eth.createAccountWithBalance(donor);489    const spender = await helper.eth.createAccountWithBalance(donor);490491    const collection = await helper.nft.mintCollection(alice, {});492    const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});493494    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);495496    await contract.methods.approve(spender, tokenId).send({from: owner});497498    const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender}));499    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));500  });501502  itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {503    const collectionMinter = alice;504    const owner = bob;505    const receiver = charlie;506    const collection = await helper.nft.mintCollection(collectionMinter, {name: 'A', description: 'B', tokenPrefix: 'C'});507508    const spender = await helper.eth.createAccountWithBalance(donor, 100n);509510    const token = await collection.mintToken(collectionMinter, {Substrate: owner.address});511512    const address = helper.ethAddress.fromCollectionId(collection.collectionId);513    const contract = helper.ethNativeContract.collection(address, 'nft');514515    await token.approve(owner, {Ethereum: spender});516517    {518      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);519      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);520      const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});521      const event = result.events.Transfer;522      expect(event).to.be.like({523        address: helper.ethAddress.fromCollectionId(collection.collectionId),524        event: 'Transfer',525        returnValues: {526          from: helper.address.substrateToEth(owner.address),527          to: helper.address.substrateToEth(receiver.address),528          tokenId: token.tokenId.toString(),529        },530      });531    }532533    expect(await token.getOwner()).to.be.like({Substrate: receiver.address});534  });535536  itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {537    const owner = await helper.eth.createAccountWithBalance(donor);538    const receiver = helper.eth.createAccount();539540    const collection = await helper.nft.mintCollection(alice, {});541    const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});542543    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);544545    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner}));546    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));547  });548});549550describe('NFT: Substrate calls', () => {551  let donor: IKeyringPair;552  let alice: IKeyringPair;553554  before(async function() {555    await usingEthPlaygrounds(async (helper, privateKey) => {556      donor = await privateKey({filename: __filename});557      [alice] = await helper.arrange.createAccounts([20n], donor);558    });559  });560561  itEth('Events emitted for mint()', async ({helper}) => {562    const collection = await helper.nft.mintCollection(alice, {});563    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);564    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');565566    const events: any = [];567    contract.events.allEvents((_: any, event: any) => {568      events.push(event);569    });570571    const {tokenId} = await collection.mintToken(alice);572    if (events.length == 0) await helper.wait.newBlocks(1);573    const event = events[0];574575    expect(event.event).to.be.equal('Transfer');576    expect(event.address).to.be.equal(collectionAddress);577    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');578    expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(alice.address));579    expect(event.returnValues.tokenId).to.be.equal(tokenId.toString());580  });581582  itEth('Events emitted for burn()', async ({helper}) => {583    const collection = await helper.nft.mintCollection(alice, {});584    const token = await collection.mintToken(alice);585586    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);587    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');588589    const events: any = [];590    contract.events.allEvents((_: any, event: any) => {591      events.push(event);592    });593594    await token.burn(alice);595    if (events.length == 0) await helper.wait.newBlocks(1);596    const event = events[0];597598    expect(event.event).to.be.equal('Transfer');599    expect(event.address).to.be.equal(collectionAddress);600    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));601    expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');602    expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString());603  });604605  itEth('Events emitted for approve()', async ({helper}) => {606    const receiver = helper.eth.createAccount();607608    const collection = await helper.nft.mintCollection(alice, {});609    const token = await collection.mintToken(alice);610611    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);612    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');613614    const events: any = [];615    contract.events.allEvents((_: any, event: any) => {616      events.push(event);617    });618619    await token.approve(alice, {Ethereum: receiver});620    if (events.length == 0) await helper.wait.newBlocks(1);621    const event = events[0];622623    expect(event.event).to.be.equal('Approval');624    expect(event.address).to.be.equal(collectionAddress);625    expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));626    expect(event.returnValues.approved).to.be.equal(receiver);627    expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString());628  });629630  itEth('Events emitted for transferFrom()', async ({helper}) => {631    const [bob] = await helper.arrange.createAccounts([10n], donor);632    const receiver = helper.eth.createAccount();633634    const collection = await helper.nft.mintCollection(alice, {});635    const token = await collection.mintToken(alice);636    await token.approve(alice, {Substrate: bob.address});637638    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);639    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');640641    const events: any = [];642    contract.events.allEvents((_: any, event: any) => {643      events.push(event);644    });645646    await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver});647648    if (events.length == 0) await helper.wait.newBlocks(1);649    const event = events[0];650651    expect(event.address).to.be.equal(collectionAddress);652    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));653    expect(event.returnValues.to).to.be.equal(receiver);654    expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);655  });656657  itEth('Events emitted for transfer()', async ({helper}) => {658    const receiver = helper.eth.createAccount();659660    const collection = await helper.nft.mintCollection(alice, {});661    const token = await collection.mintToken(alice);662663    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);664    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');665666    const events: any = [];667    contract.events.allEvents((_: any, event: any) => {668      events.push(event);669    });670671    await token.transfer(alice, {Ethereum: receiver});672673    if (events.length == 0) await helper.wait.newBlocks(1);674    const event = events[0];675676    expect(event.address).to.be.equal(collectionAddress);677    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));678    expect(event.returnValues.to).to.be.equal(receiver);679    expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);680  });681});682683describe('Common metadata', () => {684  let donor: IKeyringPair;685  let alice: IKeyringPair;686687  before(async function() {688    await usingEthPlaygrounds(async (helper, privateKey) => {689      donor = await privateKey({filename: __filename});690      [alice] = await helper.arrange.createAccounts([20n], donor);691    });692  });693694  itEth('Returns collection name', async ({helper}) => {695    const caller = await helper.eth.createAccountWithBalance(donor);696    const tokenPropertyPermissions = [{697      key: 'URI',698      permission: {699        mutable: true,700        collectionAdmin: true,701        tokenOwner: false,702      },703    }];704    const collection = await helper.nft.mintCollection(705      alice,706      {707        name: 'oh River',708        tokenPrefix: 'CHANGE',709        properties: [{key: 'ERC721Metadata', value: '1'}],710        tokenPropertyPermissions,711      },712    );713714    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);715    const name = await contract.methods.name().call();716    expect(name).to.equal('oh River');717  });718719  itEth('Returns symbol name', async ({helper}) => {720    const caller = await helper.eth.createAccountWithBalance(donor);721    const tokenPropertyPermissions = [{722      key: 'URI',723      permission: {724        mutable: true,725        collectionAdmin: true,726        tokenOwner: false,727      },728    }];729    const collection = await helper.nft.mintCollection(730      alice,731      {732        name: 'oh River',733        tokenPrefix: 'CHANGE',734        properties: [{key: 'ERC721Metadata', value: '1'}],735        tokenPropertyPermissions,736      },737    );738739    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);740    const symbol = await contract.methods.symbol().call();741    expect(symbol).to.equal('CHANGE');742  });743});
after · tests/src/eth/nonFungible.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util';18import {IKeyringPair} from '@polkadot/types/types';19import {Contract} from 'web3-eth-contract';202122describe('NFT: Information getting', () => {23  let donor: IKeyringPair;24  let alice: IKeyringPair;2526  before(async function() {27    await usingEthPlaygrounds(async (helper, privateKey) => {28      donor = await privateKey({filename: __filename});29      [alice] = await helper.arrange.createAccounts([10n], donor);30    });31  });3233  itEth('totalSupply', async ({helper}) => {34    const collection = await helper.nft.mintCollection(alice, {});35    await collection.mintToken(alice);3637    const caller = await helper.eth.createAccountWithBalance(donor);3839    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);40    const totalSupply = await contract.methods.totalSupply().call();4142    expect(totalSupply).to.equal('1');43  });4445  itEth('balanceOf', async ({helper}) => {46    const collection = await helper.nft.mintCollection(alice, {});47    const caller = await helper.eth.createAccountWithBalance(donor);4849    await collection.mintToken(alice, {Ethereum: caller});50    await collection.mintToken(alice, {Ethereum: caller});51    await collection.mintToken(alice, {Ethereum: caller});5253    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);54    const balance = await contract.methods.balanceOf(caller).call();5556    expect(balance).to.equal('3');57  });5859  itEth('ownerOf', async ({helper}) => {60    const collection = await helper.nft.mintCollection(alice, {});61    const caller = await helper.eth.createAccountWithBalance(donor);6263    const token = await collection.mintToken(alice, {Ethereum: caller});6465    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);6667    const owner = await contract.methods.ownerOf(token.tokenId).call();6869    expect(owner).to.equal(caller);70  });7172  itEth('name/symbol is available regardless of ERC721Metadata support', async ({helper}) => {73    const collection = await helper.nft.mintCollection(alice, {name: 'test', tokenPrefix: 'TEST'});74    const caller = helper.eth.createAccount();7576    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);7778    expect(await contract.methods.name().call()).to.equal('test');79    expect(await contract.methods.symbol().call()).to.equal('TEST');80  });81});8283describe('Check ERC721 token URI for NFT', () => {84  let donor: IKeyringPair;8586  before(async function() {87    await usingEthPlaygrounds(async (_helper, privateKey) => {88      donor = await privateKey({filename: __filename});89    });90  });9192  async function setup(helper: EthUniqueHelper, baseUri: string, propertyKey?: string, propertyValue?: string): Promise<{contract: Contract, nextTokenId: string}> {93    const owner = await helper.eth.createAccountWithBalance(donor);94    const receiver = helper.eth.createAccount();9596    const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Mint collection', 'a', 'b', baseUri);97    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);9899    const result = await contract.methods.mint(receiver).send();100    const tokenId = result.events.Transfer.returnValues.tokenId;101    expect(tokenId).to.be.equal('1');102103    if (propertyKey && propertyValue) {104      // Set URL or suffix105      await contract.methods.setProperties(tokenId, [{key: propertyKey, value: Buffer.from(propertyValue)}]).send();106    }107108    const event = result.events.Transfer;109    expect(event.address).to.be.equal(collectionAddress);110    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');111    expect(event.returnValues.to).to.be.equal(receiver);112    expect(event.returnValues.tokenId).to.be.equal(tokenId);113114    return {contract, nextTokenId: tokenId};115  }116117  itEth('Empty tokenURI', async ({helper}) => {118    const {contract, nextTokenId} = await setup(helper, '');119    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');120  });121122  itEth('TokenURI from url', async ({helper}) => {123    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URI', 'Token URI');124    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');125  });126127  itEth('TokenURI from baseURI', async ({helper}) => {128    const {contract, nextTokenId} = await setup(helper, 'BaseURI_');129    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_');130  });131132  itEth('TokenURI from baseURI + suffix', async ({helper}) => {133    const suffix = '/some/suffix';134    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URISuffix', suffix);135    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);136  });137});138139describe('NFT: Plain calls', () => {140  let donor: IKeyringPair;141  let minter: IKeyringPair;142  let bob: IKeyringPair;143  let charlie: IKeyringPair;144145  before(async function() {146    await usingEthPlaygrounds(async (helper, privateKey) => {147      donor = await privateKey({filename: __filename});148      [minter, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);149    });150  });151152  itEth('Can perform mint()', async ({helper}) => {153    const owner = await helper.eth.createAccountWithBalance(donor);154    const receiver = helper.eth.createAccount();155156    const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Mint collection', '6', '6', '');157    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);158159    const result = await contract.methods.mintWithTokenURI(receiver, 'Test URI').send();160    const tokenId = result.events.Transfer.returnValues.tokenId;161    expect(tokenId).to.be.equal('1');162163    const event = result.events.Transfer;164    expect(event.address).to.be.equal(collectionAddress);165    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');166    expect(event.returnValues.to).to.be.equal(receiver);167168    expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');169170    // TODO: this wont work right now, need release 919000 first171    // await helper.methods.setOffchainSchema(collectionIdAddress, 'https://offchain-service.local/token-info/{id}').send();172    // const tokenUri = await contract.methods.tokenURI(nextTokenId).call();173    // expect(tokenUri).to.be.equal(`https://offchain-service.local/token-info/${nextTokenId}`);174  });175176  //TODO: CORE-302 add eth methods177  itEth.skip('Can perform mintBulk()', async ({helper}) => {178    const caller = await helper.eth.createAccountWithBalance(donor);179    const receiver = helper.eth.createAccount();180181    const collection = await helper.nft.mintCollection(minter);182    await collection.addAdmin(minter, {Ethereum: caller});183184    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);185    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);186    {187      const bulkSize = 3;188      const nextTokenId = await contract.methods.nextTokenId().call();189      expect(nextTokenId).to.be.equal('1');190      const result = await contract.methods.mintBulkWithTokenURI(191        receiver,192        Array.from({length: bulkSize}, (_, i) => (193          [+nextTokenId + i, `Test URI ${i}`]194        )),195      ).send({from: caller});196197      const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.tokenId - b.returnValues.tokenId);198      for (let i = 0; i < bulkSize; i++) {199        const event = events[i];200        expect(event.address).to.equal(collectionAddress);201        expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');202        expect(event.returnValues.to).to.equal(receiver);203        expect(event.returnValues.tokenId).to.equal(`${+nextTokenId + i}`);204205        expect(await contract.methods.tokenURI(+nextTokenId + i).call()).to.be.equal(`Test URI ${i}`);206      }207    }208  });209210  itEth('Can perform burn()', async ({helper}) => {211    const caller = await helper.eth.createAccountWithBalance(donor);212213    const collection = await helper.nft.mintCollection(minter, {});214    const {tokenId} = await collection.mintToken(minter, {Ethereum: caller});215216    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);217    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);218219    {220      const result = await contract.methods.burn(tokenId).send({from: caller});221222      const event = result.events.Transfer;223      expect(event.address).to.be.equal(collectionAddress);224      expect(event.returnValues.from).to.be.equal(caller);225      expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');226      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);227    }228  });229230  itEth('Can perform approve()', async ({helper}) => {231    const owner = await helper.eth.createAccountWithBalance(donor);232    const spender = helper.eth.createAccount();233234    const collection = await helper.nft.mintCollection(minter, {});235    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});236237    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);238    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);239240    {241      const result = await contract.methods.approve(spender, tokenId).send({from: owner});242243      const event = result.events.Approval;244      expect(event.address).to.be.equal(collectionAddress);245      expect(event.returnValues.owner).to.be.equal(owner);246      expect(event.returnValues.approved).to.be.equal(spender);247      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);248    }249  });250251  itEth('Can perform burnFromCross()', async ({helper}) => {252    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});253254    const owner = bob;255    const spender = await helper.eth.createAccountWithBalance(donor, 100n);256257    const token = await collection.mintToken(minter, {Substrate: owner.address});258259    const address = helper.ethAddress.fromCollectionId(collection.collectionId);260    const contract = helper.ethNativeContract.collection(address, 'nft');261262    {263      await token.approve(owner, {Ethereum: spender});264      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);265      const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});266      const events = result.events.Transfer;267268      expect(events).to.be.like({269        address,270        event: 'Transfer',271        returnValues: {272          from: helper.address.substrateToEth(owner.address),273          to: '0x0000000000000000000000000000000000000000',274          tokenId: token.tokenId.toString(),275        },276      });277    }278  });279280  itEth('Can perform approveCross()', async ({helper}) => {281    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});282283    const owner = await helper.eth.createAccountWithBalance(donor, 100n);284    const receiver = charlie;285286    const token = await collection.mintToken(minter, {Ethereum: owner});287288    const address = helper.ethAddress.fromCollectionId(collection.collectionId);289    const contract = helper.ethNativeContract.collection(address, 'nft');290291    {292      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);293      const result = await contract.methods.approveCross(recieverCross, token.tokenId).send({from: owner});294      const event = result.events.Approval;295      expect(event).to.be.like({296        address: helper.ethAddress.fromCollectionId(collection.collectionId),297        event: 'Approval',298        returnValues: {299          owner,300          approved: helper.address.substrateToEth(receiver.address),301          tokenId: token.tokenId.toString(),302        },303      });304    }305  });306307  itEth('Can perform transferFrom()', async ({helper}) => {308    const owner = await helper.eth.createAccountWithBalance(donor);309    const spender = await helper.eth.createAccountWithBalance(donor);310    const receiver = helper.eth.createAccount();311312    const collection = await helper.nft.mintCollection(minter, {});313    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});314315    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);316    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);317318    await contract.methods.approve(spender, tokenId).send({from: owner});319320    {321      const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: spender});322323      const event = result.events.Transfer;324      expect(event.address).to.be.equal(collectionAddress);325      expect(event.returnValues.from).to.be.equal(owner);326      expect(event.returnValues.to).to.be.equal(receiver);327      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);328    }329330    {331      const balance = await contract.methods.balanceOf(receiver).call();332      expect(+balance).to.equal(1);333    }334335    {336      const balance = await contract.methods.balanceOf(owner).call();337      expect(+balance).to.equal(0);338    }339  });340341  itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {342    const minter = await privateKey('//Alice');343    const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});344345    const owner = await privateKey('//Bob');346    const spender = await helper.eth.createAccountWithBalance(donor);347    const receiver = await privateKey('//Charlie');348349    const token = await collection.mintToken(minter, {Substrate: owner.address});350351    const address = helper.ethAddress.fromCollectionId(collection.collectionId);352    const contract = helper.ethNativeContract.collection(address, 'nft');353354    await token.approve(owner, {Ethereum: spender});355356    {357      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);358      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);359      const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});360      const event = result.events.Transfer;361      expect(event).to.be.like({362        address: helper.ethAddress.fromCollectionId(collection.collectionId),363        event: 'Transfer',364        returnValues: {365          from: helper.address.substrateToEth(owner.address),366          to: helper.address.substrateToEth(receiver.address),367          tokenId: token.tokenId.toString(),368        },369      });370    }371372    expect(await token.getOwner()).to.be.like({Substrate: receiver.address});373  });374375  itEth('Can perform transfer()', async ({helper}) => {376    const collection = await helper.nft.mintCollection(minter, {});377    const owner = await helper.eth.createAccountWithBalance(donor);378    const receiver = helper.eth.createAccount();379380    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});381382    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);383    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);384385    {386      const result = await contract.methods.transfer(receiver, tokenId).send({from: owner});387388      const event = result.events.Transfer;389      expect(event.address).to.be.equal(collectionAddress);390      expect(event.returnValues.from).to.be.equal(owner);391      expect(event.returnValues.to).to.be.equal(receiver);392      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);393    }394395    {396      const balance = await contract.methods.balanceOf(owner).call();397      expect(+balance).to.equal(0);398    }399400    {401      const balance = await contract.methods.balanceOf(receiver).call();402      expect(+balance).to.equal(1);403    }404  });405  406  itEth('Can perform transferCross()', async ({helper}) => {407    const collection = await helper.nft.mintCollection(minter, {});408    const owner = await helper.eth.createAccountWithBalance(donor);409    const receiver = await helper.eth.createAccountWithBalance(donor);410    const to = helper.ethCrossAccount.fromAddress(receiver);411    const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter);412    413    const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});414415    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);416    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);417418    {419      const result = await contract.methods.transferCross(to, tokenId).send({from: owner});420421      const event = result.events.Transfer;422      expect(event.address).to.be.equal(collectionAddress);423      expect(event.returnValues.from).to.be.equal(owner);424      expect(event.returnValues.to).to.be.equal(receiver);425      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);426    }427428    {429      const balance = await contract.methods.balanceOf(owner).call();430      expect(+balance).to.equal(0);431    }432433    {434      const balance = await contract.methods.balanceOf(receiver).call();435      expect(+balance).to.equal(1);436    }437    438    {439      const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver});440      441442      const event = substrateResult.events.Transfer;443      expect(event.address).to.be.equal(collectionAddress);444      expect(event.returnValues.from).to.be.equal(receiver);445      expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));446      expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);447    }448449    {450      const balance = await contract.methods.balanceOf(receiver).call();451      expect(+balance).to.equal(0);452    }453454    {455      const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});456      expect(balance).to.be.contain(tokenId);457    }458  });459});460461describe('NFT: Fees', () => {462  let donor: IKeyringPair;463  let alice: IKeyringPair;464  let bob: IKeyringPair;465  let charlie: IKeyringPair;466467  before(async function() {468    await usingEthPlaygrounds(async (helper, privateKey) => {469      donor = await privateKey({filename: __filename});470      [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);471    });472  });473474  itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {475    const owner = await helper.eth.createAccountWithBalance(donor);476    const spender = helper.eth.createAccount();477478    const collection = await helper.nft.mintCollection(alice, {});479    const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});480481    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);482483    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, tokenId).send({from: owner}));484    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));485  });486487  itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {488    const owner = await helper.eth.createAccountWithBalance(donor);489    const spender = await helper.eth.createAccountWithBalance(donor);490491    const collection = await helper.nft.mintCollection(alice, {});492    const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});493494    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);495496    await contract.methods.approve(spender, tokenId).send({from: owner});497498    const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender}));499    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));500  });501502  itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {503    const collectionMinter = alice;504    const owner = bob;505    const receiver = charlie;506    const collection = await helper.nft.mintCollection(collectionMinter, {name: 'A', description: 'B', tokenPrefix: 'C'});507508    const spender = await helper.eth.createAccountWithBalance(donor, 100n);509510    const token = await collection.mintToken(collectionMinter, {Substrate: owner.address});511512    const address = helper.ethAddress.fromCollectionId(collection.collectionId);513    const contract = helper.ethNativeContract.collection(address, 'nft');514515    await token.approve(owner, {Ethereum: spender});516517    {518      const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);519      const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);520      const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});521      const event = result.events.Transfer;522      expect(event).to.be.like({523        address: helper.ethAddress.fromCollectionId(collection.collectionId),524        event: 'Transfer',525        returnValues: {526          from: helper.address.substrateToEth(owner.address),527          to: helper.address.substrateToEth(receiver.address),528          tokenId: token.tokenId.toString(),529        },530      });531    }532533    expect(await token.getOwner()).to.be.like({Substrate: receiver.address});534  });535536  itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {537    const owner = await helper.eth.createAccountWithBalance(donor);538    const receiver = helper.eth.createAccount();539540    const collection = await helper.nft.mintCollection(alice, {});541    const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});542543    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner);544545    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner}));546    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));547  });548});549550describe('NFT: Substrate calls', () => {551  let donor: IKeyringPair;552  let alice: IKeyringPair;553554  before(async function() {555    await usingEthPlaygrounds(async (helper, privateKey) => {556      donor = await privateKey({filename: __filename});557      [alice] = await helper.arrange.createAccounts([20n], donor);558    });559  });560561  itEth('Events emitted for mint()', async ({helper}) => {562    const collection = await helper.nft.mintCollection(alice, {});563    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);564    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');565566    const events: any = [];567    contract.events.allEvents((_: any, event: any) => {568      events.push(event);569    });570571    const {tokenId} = await collection.mintToken(alice);572    if (events.length == 0) await helper.wait.newBlocks(1);573    const event = events[0];574575    expect(event.event).to.be.equal('Transfer');576    expect(event.address).to.be.equal(collectionAddress);577    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');578    expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(alice.address));579    expect(event.returnValues.tokenId).to.be.equal(tokenId.toString());580  });581582  itEth('Events emitted for burn()', async ({helper}) => {583    const collection = await helper.nft.mintCollection(alice, {});584    const token = await collection.mintToken(alice);585586    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);587    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');588589    const events: any = [];590    contract.events.allEvents((_: any, event: any) => {591      events.push(event);592    });593594    await token.burn(alice);595    if (events.length == 0) await helper.wait.newBlocks(1);596    const event = events[0];597598    expect(event.event).to.be.equal('Transfer');599    expect(event.address).to.be.equal(collectionAddress);600    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));601    expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');602    expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString());603  });604605  itEth('Events emitted for approve()', async ({helper}) => {606    const receiver = helper.eth.createAccount();607608    const collection = await helper.nft.mintCollection(alice, {});609    const token = await collection.mintToken(alice);610611    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);612    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');613614    const events: any = [];615    contract.events.allEvents((_: any, event: any) => {616      events.push(event);617    });618619    await token.approve(alice, {Ethereum: receiver});620    if (events.length == 0) await helper.wait.newBlocks(1);621    const event = events[0];622623    expect(event.event).to.be.equal('Approval');624    expect(event.address).to.be.equal(collectionAddress);625    expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));626    expect(event.returnValues.approved).to.be.equal(receiver);627    expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString());628  });629630  itEth('Events emitted for transferFrom()', async ({helper}) => {631    const [bob] = await helper.arrange.createAccounts([10n], donor);632    const receiver = helper.eth.createAccount();633634    const collection = await helper.nft.mintCollection(alice, {});635    const token = await collection.mintToken(alice);636    await token.approve(alice, {Substrate: bob.address});637638    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);639    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');640641    const events: any = [];642    contract.events.allEvents((_: any, event: any) => {643      events.push(event);644    });645646    await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver});647648    if (events.length == 0) await helper.wait.newBlocks(1);649    const event = events[0];650651    expect(event.address).to.be.equal(collectionAddress);652    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));653    expect(event.returnValues.to).to.be.equal(receiver);654    expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);655  });656657  itEth('Events emitted for transfer()', async ({helper}) => {658    const receiver = helper.eth.createAccount();659660    const collection = await helper.nft.mintCollection(alice, {});661    const token = await collection.mintToken(alice);662663    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);664    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');665666    const events: any = [];667    contract.events.allEvents((_: any, event: any) => {668      events.push(event);669    });670671    await token.transfer(alice, {Ethereum: receiver});672673    if (events.length == 0) await helper.wait.newBlocks(1);674    const event = events[0];675676    expect(event.address).to.be.equal(collectionAddress);677    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));678    expect(event.returnValues.to).to.be.equal(receiver);679    expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);680  });681});682683describe('Common metadata', () => {684  let donor: IKeyringPair;685  let alice: IKeyringPair;686687  before(async function() {688    await usingEthPlaygrounds(async (helper, privateKey) => {689      donor = await privateKey({filename: __filename});690      [alice] = await helper.arrange.createAccounts([20n], donor);691    });692  });693694  itEth('Returns collection name', async ({helper}) => {695    const caller = await helper.eth.createAccountWithBalance(donor);696    const tokenPropertyPermissions = [{697      key: 'URI',698      permission: {699        mutable: true,700        collectionAdmin: true,701        tokenOwner: false,702      },703    }];704    const collection = await helper.nft.mintCollection(705      alice,706      {707        name: 'oh River',708        tokenPrefix: 'CHANGE',709        properties: [{key: 'ERC721Metadata', value: '1'}],710        tokenPropertyPermissions,711      },712    );713714    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);715    const name = await contract.methods.name().call();716    expect(name).to.equal('oh River');717  });718719  itEth('Returns symbol name', async ({helper}) => {720    const caller = await helper.eth.createAccountWithBalance(donor);721    const tokenPropertyPermissions = [{722      key: 'URI',723      permission: {724        mutable: true,725        collectionAdmin: true,726        tokenOwner: false,727      },728    }];729    const collection = await helper.nft.mintCollection(730      alice,731      {732        name: 'oh River',733        tokenPrefix: 'CHANGE',734        properties: [{key: 'ERC721Metadata', value: '1'}],735        tokenPropertyPermissions,736      },737    );738739    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);740    const symbol = await contract.methods.symbol().call();741    expect(symbol).to.equal('CHANGE');742  });743});
modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -111,7 +111,7 @@
     return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});
   }
 
-  collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated: boolean = false): Contract {
+  collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false): Contract {
     let abi = {
       'nft': nonFungibleAbi,
       'rft': refungibleAbi,