--- a/tests/package.json +++ b/tests/package.json @@ -87,8 +87,11 @@ "testLimits": "mocha --timeout 9999999 -r ts-node/register ./**/limits.test.ts", "testEthCreateNFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createNFTCollection.test.ts", "testEthCreateRFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createRFTCollection.test.ts", + "testEthNFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/nonFungible.test.ts", "testRFT": "mocha --timeout 9999999 -r ts-node/register ./**/refungible.test.ts", + "testEthRFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/reFungible.test.ts ./**/eth/reFungibleToken.test.ts", "testFT": "mocha --timeout 9999999 -r ts-node/register ./**/fungible.test.ts", + "testEthFT": "mocha --timeout 9999999 -r ts-node/register ./**/eth/fungible.test.ts", "testRPC": "mocha --timeout 9999999 -r ts-node/register ./**/rpc.test.ts", "testPromotion": "mocha --timeout 9999999 -r ts-node/register ./**/app-promotion.test.ts", "polkadot-types-fetch-metadata": "curl -H 'Content-Type: application/json' -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9933 > src/interfaces/metadata.json", --- a/tests/src/eth/fungible.test.ts +++ b/tests/src/eth/fungible.test.ts @@ -14,204 +14,132 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -import {approveExpectSuccess, createCollection, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers'; -import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers'; -import fungibleAbi from './fungibleAbi.json'; -import {expect} from 'chai'; -import {submitTransactionAsync} from '../substrate/substrate-api'; +import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds'; +import {IKeyringPair} from '@polkadot/types/types'; describe('Fungible: Information getting', () => { - itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); }); - const alice = privateKeyWrapper('//Alice'); + }); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + itEth('totalSupply', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n); - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address}); - - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); const totalSupply = await contract.methods.totalSupply().call(); - expect(totalSupply).to.equal('200'); }); - itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('balanceOf', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: caller}); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller}); - - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); const balance = await contract.methods.balanceOf(caller).call(); - expect(balance).to.equal('200'); }); }); describe('Fungible: Plain calls', () => { - itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - const collection = await createCollection(api, alice, { - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); }); + }); - const receiver = createEthAccount(web3); + itEth('Can perform mint()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.addAdmin(alice, {Ethereum: owner}); - const collectionIdAddress = collectionIdToAddress(collection.collectionId); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner}); - await submitTransactionAsync(alice, changeAdminTx); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); - const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0}); - const result = await collectionContract.methods.mint(receiver, 100).send(); - const events = normalizeEvents(result.events); + const result = await contract.methods.mint(receiver, 100).send(); - expect(events).to.be.deep.equal([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - value: '100', - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.equal(receiver); + expect(event.returnValues.value).to.equal('100'); }); - - itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - const collection = await createCollection(api, alice, { - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver1 = createEthAccount(web3); - const receiver2 = createEthAccount(web3); - const receiver3 = createEthAccount(web3); - - const collectionIdAddress = collectionIdToAddress(collection.collectionId); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner}); - await submitTransactionAsync(alice, changeAdminTx); + itEth('Can perform mintBulk()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const bulkSize = 3; + const receivers = [...new Array(bulkSize)].map(() => helper.eth.createAccount()); + const collection = await helper.ft.mintCollection(alice); + await collection.addAdmin(alice, {Ethereum: owner}); - const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0}); - const result = await collectionContract.methods.mintBulk([ - [receiver1, 10], - [receiver2, 20], - [receiver3, 30], - ]).send(); - const events = normalizeEvents(result.events); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); - expect(events).to.be.deep.contain({ - address:collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver1, - value: '10', - }, - }); - - expect(events).to.be.deep.contain({ - address:collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver2, - value: '20', - }, - }); - - expect(events).to.be.deep.contain({ - address:collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver3, - value: '30', - }, - }); + const result = await contract.methods.mintBulk(Array.from({length: bulkSize}, (_, i) => ( + [receivers[i], (i + 1) * 10] + ))).send(); + const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.value - b.returnValues.value); + for (let i = 0; i < bulkSize; i++) { + const event = events[i]; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.equal(receivers[i]); + expect(event.returnValues.value).to.equal(String(10 * (i + 1))); + } }); - itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - const collection = await createCollection(api, alice, { - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, - }); - - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner}); - await submitTransactionAsync(alice, changeAdminTx); - const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + itEth('Can perform burn()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.ft.mintCollection(alice); + await collection.addAdmin(alice, {Ethereum: owner}); - const collectionIdAddress = collectionIdToAddress(collection.collectionId); - const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0}); - await collectionContract.methods.mint(receiver, 100).send(); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + await contract.methods.mint(receiver, 100).send(); - const result = await collectionContract.methods.burnFrom(receiver, 49).send({from: receiver}); + const result = await contract.methods.burnFrom(receiver, 49).send({from: receiver}); - const events = normalizeEvents(result.events); - - expect(events).to.be.deep.equal([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: receiver, - to: '0x0000000000000000000000000000000000000000', - value: '49', - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal(receiver); + expect(event.returnValues.to).to.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.value).to.equal('49'); - const balance = await collectionContract.methods.balanceOf(receiver).call(); + const balance = await contract.methods.balanceOf(receiver).call(); expect(balance).to.equal('51'); }); - itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('Can perform approve()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: owner}); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner}); - - const spender = createEthAccount(web3); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS}); - { const result = await contract.methods.approve(spender, 100).send({from: owner}); - const events = normalizeEvents(result.events); - expect(events).to.be.deep.equal([ - { - address, - event: 'Approval', - args: { - owner, - spender, - value: '100', - }, - }, - ]); + const event = result.events.Approval; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(owner); + expect(event.returnValues.spender).to.be.equal(spender); + expect(event.returnValues.value).to.be.equal('100'); } { @@ -220,51 +148,32 @@ } }); - itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner}); - - const spender = createEthAccount(web3); - await transferBalanceToEth(api, alice, spender); - - const receiver = createEthAccount(web3); + itEth('Can perform transferFrom()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); await contract.methods.approve(spender, 100).send(); { const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender}); - const events = normalizeEvents(result.events); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: receiver, - value: '49', - }, - }, - { - address, - event: 'Approval', - args: { - owner, - spender, - value: '51', - }, - }, - ]); + + let event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('49'); + + event = result.events.Approval; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(owner); + expect(event.returnValues.spender).to.be.equal(spender); + expect(event.returnValues.value).to.be.equal('51'); } { @@ -278,38 +187,23 @@ } }); - itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - name: 'token name', - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner}); - - const receiver = createEthAccount(web3); - await transferBalanceToEth(api, alice, receiver); + itEth('Can perform transfer()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); { const result = await contract.methods.transfer(receiver, 50).send({from: owner}); - const events = normalizeEvents(result.events); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: receiver, - value: '50', - }, - }, - ]); + + const event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('50'); } { @@ -325,162 +219,141 @@ }); describe('Fungible: Fees', () => { - itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'Fungible', decimalPoints: 0}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); }); - const alice = privateKeyWrapper('//Alice'); + }); + + itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: owner}); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const spender = createEthAccount(web3); - - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS}); - - const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); - itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); - - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner}); + itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); await contract.methods.approve(spender, 100).send({from: owner}); - const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); - - itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = createEthAccount(web3); - - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner}); + itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); - const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); }); describe('Fungible: Substrate calls', () => { - itWeb3('Events emitted for approve()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'Fungible', decimalPoints: 0}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); }); - const alice = privateKeyWrapper('//Alice'); + }); - const receiver = createEthAccount(web3); + itEth('Events emitted for approve()', async ({helper}) => { + const receiver = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n); - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft'); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address); - - const events = await recordEvents(contract, async () => { - await approveExpectSuccess(collection, 0, alice, {Ethereum: receiver}, 100); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); + await collection.approveTokens(alice, {Ethereum: receiver}, 100n); - expect(events).to.be.deep.equal([ - { - address, - event: 'Approval', - args: { - owner: subToEth(alice.address), - spender: receiver, - value: '100', - }, - }, - ]); + const event = events[0]; + expect(event.event).to.be.equal('Approval'); + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.spender).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('100'); }); - itWeb3('Events emitted for transferFrom()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); + itEth('Events emitted for transferFrom()', async ({helper}) => { + const [bob] = await helper.arrange.createAccounts([10n], donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n); + await collection.approveTokens(alice, {Substrate: bob.address}, 100n); - const receiver = createEthAccount(web3); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft'); - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}); - await approveExpectSuccess(collection, 0, alice, bob.address, 100); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); + }); + await collection.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver}, 51n); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address); + let event = events[0]; + expect(event.event).to.be.equal('Transfer'); + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('51'); - const events = await recordEvents(contract, async () => { - await transferFromExpectSuccess(collection, 0, bob, alice, {Ethereum: receiver}, 51, 'Fungible'); - }); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: subToEth(alice.address), - to: receiver, - value: '51', - }, - }, - { - address, - event: 'Approval', - args: { - owner: subToEth(alice.address), - spender: subToEth(bob.address), - value: '49', - }, - }, - ]); + event = events[1]; + expect(event.event).to.be.equal('Approval'); + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(bob.address)); + expect(event.returnValues.value).to.be.equal('49'); }); - itWeb3('Events emitted for transfer()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'Fungible', decimalPoints: 0}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('Events emitted for transfer()', async ({helper}) => { + const receiver = helper.eth.createAccount(); + const collection = await helper.ft.mintCollection(alice); + await collection.mint(alice, 200n); - const receiver = createEthAccount(web3); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'ft'); - await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}); - - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(fungibleAbi as any, address); - - const events = await recordEvents(contract, async () => { - await transferExpectSuccess(collection, 0, alice, {Ethereum:receiver}, 51, 'Fungible'); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); + await collection.transfer(alice, {Ethereum:receiver}, 51n); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: subToEth(alice.address), - to: receiver, - value: '51', - }, - }, - ]); + const event = events[0]; + expect(event.event).to.be.equal('Transfer'); + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('51'); }); }); --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -14,72 +14,78 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers'; -import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers'; -import nonFungibleAbi from './nonFungibleAbi.json'; -import {expect} from 'chai'; -import {submitTransactionAsync} from '../substrate/substrate-api'; +import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util/playgrounds'; +import {IKeyringPair} from '@polkadot/types/types'; +import {Contract} from 'web3-eth-contract'; describe('NFT: Information getting', () => { - itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([10n], donor); }); - const alice = privateKeyWrapper('//Alice'); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + }); + + itEth('totalSupply', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {}); + await collection.mintToken(alice); - await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address}); + const caller = await helper.eth.createAccountWithBalance(donor); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const totalSupply = await contract.methods.totalSupply().call(); expect(totalSupply).to.equal('1'); }); - itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('balanceOf', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {}); + const caller = await helper.eth.createAccountWithBalance(donor); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum:caller}); - await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller}); - await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller}); + await collection.mintToken(alice, {Ethereum: caller}); + await collection.mintToken(alice, {Ethereum: caller}); + await collection.mintToken(alice, {Ethereum: caller}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const balance = await contract.methods.balanceOf(caller).call(); expect(balance).to.equal('3'); }); - itWeb3('ownerOf', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('ownerOf', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {}); + const caller = await helper.eth.createAccountWithBalance(donor); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller}); + const token = await collection.mintToken(alice, {Ethereum: caller}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}); - const owner = await contract.methods.ownerOf(tokenId).call(); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); + + const owner = await contract.methods.ownerOf(token.tokenId).call(); expect(owner).to.equal(caller); }); }); describe('Check ERC721 token URI for NFT', () => { - itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress); + let donor: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (_helper, privateKey) => { + donor = privateKey('//Alice'); + }); + }); + + async function setup(helper: EthUniqueHelper, tokenPrefix: string, propertyKey?: string, propertyValue?: string): Promise<{contract: Contract, nextTokenId: string}> { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + + const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send(); + const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const nextTokenId = await contract.methods.nextTokenId().call(); expect(nextTokenId).to.be.equal('1'); @@ -88,162 +94,73 @@ nextTokenId, ).send(); - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); + if (propertyKey && propertyValue) { + // Set URL or suffix + await contract.methods.setProperty(nextTokenId, propertyKey, Buffer.from(propertyValue)).send(); + } - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(nextTokenId); + return {contract, nextTokenId}; + } + + itEth('Empty tokenURI', async ({helper}) => { + const {contract, nextTokenId} = await setup(helper, ''); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal(''); }); - itWeb3('TokenURI from url', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress); - - const nextTokenId = await contract.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mint( - receiver, - nextTokenId, - ).send(); - - // Set URL - await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send(); - - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); - + itEth('TokenURI from url', async ({helper}) => { + const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'url', 'Token URI'); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI'); }); - itWeb3('TokenURI from baseURI + tokenId', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress); - - const nextTokenId = await contract.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mint( - receiver, - nextTokenId, - ).send(); - - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); - + itEth('TokenURI from baseURI + tokenId', async ({helper}) => { + const {contract, nextTokenId} = await setup(helper, 'BaseURI_'); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + nextTokenId); }); - itWeb3('TokenURI from baseURI + suffix', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress); - - const nextTokenId = await contract.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mint( - receiver, - nextTokenId, - ).send(); - - // Set suffix + itEth('TokenURI from baseURI + suffix', async ({helper}) => { const suffix = '/some/suffix'; - await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send(); - - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); - + const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'suffix', suffix); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix); }); }); describe('NFT: Plain calls', () => { - itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createNonfungibleCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress); + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([10n], donor); + }); + }); + + itEth('Can perform mint()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + + const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Minty', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const nextTokenId = await contract.methods.nextTokenId().call(); expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mintWithTokenURI( + const result = await contract.methods.mintWithTokenURI( receiver, nextTokenId, 'Test URI', ).send(); - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(nextTokenId); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI'); @@ -254,7 +171,8 @@ }); //TODO: CORE-302 add eth methods - itWeb3.skip('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => { + /* todo:playgrounds skipped test! + itWeb3.skip('Can perform mintBulk()', async ({helper}) => { const collection = await createCollectionExpectSuccess({ mode: {type: 'NFT'}, }); @@ -316,107 +234,70 @@ expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2'); } }); - - itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); + */ - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + itEth('Can perform burn()', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner}); + const collection = await helper.nft.mintCollection(alice, {}); + const {tokenId} = await collection.mintToken(alice, {Ethereum: caller}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller); { - const result = await contract.methods.burn(tokenId).send({from: owner}); - const events = normalizeEvents(result.events); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: '0x0000000000000000000000000000000000000000', - tokenId: tokenId.toString(), - }, - }, - ]); + const result = await contract.methods.burn(tokenId).send({from: caller}); + + const event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(caller); + expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); } }); - itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner}); + itEth('Can perform approve()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = helper.eth.createAccount(); - const spender = createEthAccount(web3); + const collection = await helper.nft.mintCollection(alice, {}); + const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); { - const result = await contract.methods.approve(spender, tokenId).send({from: owner, ...GAS_ARGS}); - const events = normalizeEvents(result.events); + const result = await contract.methods.approve(spender, tokenId).send({from: owner}); - expect(events).to.be.deep.equal([ - { - address, - event: 'Approval', - args: { - owner, - approved: spender, - tokenId: tokenId.toString(), - }, - }, - ]); + const event = result.events.Approval; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(owner); + expect(event.returnValues.approved).to.be.equal(spender); + expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); } }); - itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); + itEth('Can perform transferFrom()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner}); - - const spender = createEthAccount(web3); - await transferBalanceToEth(api, alice, spender); - - const receiver = createEthAccount(web3); + const collection = await helper.nft.mintCollection(alice, {}); + const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await contract.methods.approve(spender, tokenId).send({from: owner}); { const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: spender}); - const events = normalizeEvents(result.events); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + + const event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); } { @@ -430,37 +311,24 @@ } }); - itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner}); + itEth('Can perform transfer()', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {}); + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); - const receiver = createEthAccount(web3); - await transferBalanceToEth(api, alice, receiver); + const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); { const result = await contract.methods.transfer(receiver, tokenId).send({from: owner}); - const events = normalizeEvents(result.events); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + + const event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); } { @@ -476,237 +344,209 @@ }); describe('NFT: Fees', () => { - itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([10n], donor); }); - const alice = privateKeyWrapper('//Alice'); + }); + + itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = helper.eth.createAccount(); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const spender = createEthAccount(web3); + const collection = await helper.nft.mintCollection(alice, {}); + const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS}); - - const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, tokenId).send({from: owner})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, tokenId).send({from: owner})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); - itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); - - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = await helper.eth.createAccountWithBalance(donor); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner}); + const collection = await helper.nft.mintCollection(alice, {}); + const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); await contract.methods.approve(spender, tokenId).send({from: owner}); - const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); - itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = createEthAccount(web3); + const collection = await helper.nft.mintCollection(alice, {}); + const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS}); - - const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); }); describe('NFT: Substrate calls', () => { - itWeb3('Events emitted for mint()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); }); - const alice = privateKeyWrapper('//Alice'); + }); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address); + itEth('Events emitted for mint()', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {}); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); - let tokenId: number; - const events = await recordEvents(contract, async () => { - tokenId = await createItemExpectSuccess(alice, collection, 'NFT'); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); + const {tokenId} = await collection.mintToken(alice); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: subToEth(alice.address), - tokenId: tokenId!.toString(), - }, - }, - ]); + const event = events[0]; + expect(event.event).to.be.equal('Transfer'); + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.tokenId).to.be.equal(tokenId.toString()); }); - itWeb3('Events emitted for burn()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, + itEth('Events emitted for burn()', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {}); + const token = await collection.mintToken(alice); + + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); - const alice = privateKeyWrapper('//Alice'); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address); + await token.burn(alice); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT'); - const events = await recordEvents(contract, async () => { - await burnItemExpectSuccess(alice, collection, tokenId); - }); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: subToEth(alice.address), - to: '0x0000000000000000000000000000000000000000', - tokenId: tokenId.toString(), - }, - }, - ]); + const event = events[0]; + expect(event.event).to.be.equal('Transfer'); + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString()); }); - itWeb3('Events emitted for approve()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('Events emitted for approve()', async ({helper}) => { + const receiver = helper.eth.createAccount(); - const receiver = createEthAccount(web3); - - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT'); - - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address); + const collection = await helper.nft.mintCollection(alice, {}); + const token = await collection.mintToken(alice); - const events = await recordEvents(contract, async () => { - await approveExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); - expect(events).to.be.deep.equal([ - { - address, - event: 'Approval', - args: { - owner: subToEth(alice.address), - approved: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + await token.approve(alice, {Ethereum: receiver}); + + const event = events[0]; + expect(event.event).to.be.equal('Approval'); + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.approved).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(token.tokenId.toString()); }); - itWeb3('Events emitted for transferFrom()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); + itEth('Events emitted for transferFrom()', async ({helper}) => { + const [bob] = await helper.arrange.createAccounts([10n], donor); + const receiver = helper.eth.createAccount(); - const receiver = createEthAccount(web3); - - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT'); - await approveExpectSuccess(collection, tokenId, alice, bob.address, 1); - - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address); + const collection = await helper.nft.mintCollection(alice, {}); + const token = await collection.mintToken(alice); + await token.approve(alice, {Substrate: bob.address}); - const events = await recordEvents(contract, async () => { - await transferFromExpectSuccess(collection, tokenId, bob, alice, {Ethereum: receiver}, 1, 'NFT'); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: subToEth(alice.address), - to: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver}); + + const event = events[0]; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`); }); - itWeb3('Events emitted for transfer()', async ({web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - mode: {type: 'NFT'}, - }); - const alice = privateKeyWrapper('//Alice'); + itEth('Events emitted for transfer()', async ({helper}) => { + const receiver = helper.eth.createAccount(); - const receiver = createEthAccount(web3); + const collection = await helper.nft.mintCollection(alice, {}); + const token = await collection.mintToken(alice); - const tokenId = await createItemExpectSuccess(alice, collection, 'NFT'); - - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address); - - const events = await recordEvents(contract, async () => { - await transferExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1, 'NFT'); + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: subToEth(alice.address), - to: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + await token.transfer(alice, {Ethereum: receiver}); + + const event = events[0]; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`); }); }); describe('Common metadata', () => { - itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - name: 'token name', - mode: {type: 'NFT'}, + let donor: IKeyringPair; + let alice: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); }); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + }); + + itEth('Returns collection name', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.nft.mintCollection(alice, {name: 'oh River', tokenPrefix: 'CHANGE'}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const name = await contract.methods.name().call(); - - expect(name).to.equal('token name'); + expect(name).to.equal('oh River'); }); - itWeb3('Returns symbol name', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - tokenPrefix: 'TOK', - mode: {type: 'NFT'}, - }); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + itEth('Returns symbol name', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.nft.mintCollection(alice, {name: 'oh River', tokenPrefix: 'CHANGE'}); - const address = collectionIdToAddress(collection); - const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}); + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const symbol = await contract.methods.symbol().call(); - - expect(symbol).to.equal('TOK'); + expect(symbol).to.equal('CHANGE'); }); }); \ No newline at end of file --- a/tests/src/eth/reFungible.test.ts +++ b/tests/src/eth/reFungible.test.ts @@ -14,33 +14,35 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -import {createCollectionExpectSuccess, UNIQUE, requirePallets, Pallets} from '../util/helpers'; -import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress, uniqueRefungibleToken} from './util/helpers'; -import {expect} from 'chai'; +import {Pallets, requirePalletsOrSkip} from '../util/playgrounds'; +import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds'; +import {IKeyringPair} from '@polkadot/types/types'; describe('Refungible: Information getting', () => { + let donor: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + + donor = privateKey('//Alice'); + }); }); - itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('totalSupply', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TotalSupply', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const nextTokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, nextTokenId).send(); const totalSupply = await contract.methods.totalSupply().call(); expect(totalSupply).to.equal('1'); }); - itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('balanceOf', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'BalanceOf', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); { const nextTokenId = await contract.methods.nextTokenId().call(); @@ -56,38 +58,30 @@ } const balance = await contract.methods.balanceOf(caller).call(); - expect(balance).to.equal('3'); }); - itWeb3('ownerOf', async ({api, web3, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('ownerOf', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); const owner = await contract.methods.ownerOf(tokenId).call(); - expect(owner).to.equal(caller); }); - itWeb3('ownerOf after burn', async ({api, web3, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = createEthAccount(web3); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('ownerOf after burn', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf-AfterBurn', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); - - const tokenAddress = tokenIdToAddress(collectionId, tokenId); - const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller); + const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); @@ -95,80 +89,67 @@ await tokenContract.methods.burnFrom(caller, 1).send(); const owner = await contract.methods.ownerOf(tokenId).call(); - expect(owner).to.equal(receiver); }); - itWeb3('ownerOf for partial ownership', async ({api, web3, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = createEthAccount(web3); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('ownerOf for partial ownership', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Partial-OwnerOf', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); - - const tokenAddress = tokenIdToAddress(collectionId, tokenId); - const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller); + const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); const owner = await contract.methods.ownerOf(tokenId).call(); - expect(owner).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'); }); }); describe('Refungible: Plain calls', () => { + let donor: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + + donor = privateKey('//Alice'); + }); }); - itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'}); + itEth('Can perform mint()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Minty', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const nextTokenId = await contract.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mintWithTokenURI( + const result = await contract.methods.mintWithTokenURI( receiver, nextTokenId, 'Test URI', ).send(); - const events = normalizeEvents(result.events); - - expect(events).to.include.deep.members([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.equal(receiver); + expect(event.returnValues.tokenId).to.equal(nextTokenId); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI'); }); - itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('Can perform mintBulk()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'MintBulky', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); - const receiver = createEthAccount(web3); - { const nextTokenId = await contract.methods.nextTokenId().call(); expect(nextTokenId).to.be.equal('1'); @@ -180,37 +161,15 @@ [+nextTokenId + 2, 'Test URI 2'], ], ).send(); - const events = normalizeEvents(result.events); - expect(events).to.include.deep.members([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: String(+nextTokenId + 1), - }, - }, - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: String(+nextTokenId + 2), - }, - }, - ]); + const events = result.events.Transfer; + for (let i = 0; i < 2; i++) { + const event = events[i]; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.equal(receiver); + expect(event.returnValues.tokenId).to.equal(String(+nextTokenId + i)); + } expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0'); expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1'); @@ -218,76 +177,54 @@ } }); - itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('Can perform burn()', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Burny', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); { const result = await contract.methods.burn(tokenId).send(); - const events = normalizeEvents(result.events); - expect(events).to.include.deep.members([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: caller, - to: '0x0000000000000000000000000000000000000000', - tokenId: tokenId.toString(), - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal(caller); + expect(event.returnValues.to).to.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.tokenId).to.equal(tokenId.toString()); } }); - itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); - - const receiver = createEthAccount(web3); + itEth('Can perform transferFrom()', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TransferFromy', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); + const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId); await contract.methods.mint(caller, tokenId).send(); - const address = tokenIdToAddress(collectionId, tokenId); - const tokenContract = uniqueRefungibleToken(web3, address, caller); + const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller); await tokenContract.methods.repartition(15).send(); { - const erc20Events = await recordEvents(tokenContract, async () => { - const result = await contract.methods.transferFrom(caller, receiver, tokenId).send(); - const events = normalizeEvents(result.events); - expect(events).to.include.deep.members([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: caller, - to: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + const tokenEvents: any = []; + tokenContract.events.allEvents((_: any, event: any) => { + tokenEvents.push(event); }); + const result = await contract.methods.transferFrom(caller, receiver, tokenId).send(); + + let event = result.events.Transfer; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal(caller); + expect(event.returnValues.to).to.equal(receiver); + expect(event.returnValues.tokenId).to.equal(tokenId.toString()); - expect(erc20Events).to.include.deep.members([ - { - address, - event: 'Transfer', - args: { - from: caller, - to: receiver, - value: '15', - }, - }, - ]); + event = tokenEvents[0]; + expect(event.address).to.equal(tokenAddress); + expect(event.returnValues.from).to.equal(caller); + expect(event.returnValues.to).to.equal(receiver); + expect(event.returnValues.value).to.equal('15'); } { @@ -301,32 +238,23 @@ } }); - itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); - - const receiver = createEthAccount(web3); + itEth('Can perform transfer()', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); { const result = await contract.methods.transfer(receiver, tokenId).send(); - const events = normalizeEvents(result.events); - expect(events).to.include.deep.members([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: caller, - to: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + + const event = result.events.Transfer; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal(caller); + expect(event.returnValues.to).to.equal(receiver); + expect(event.returnValues.tokenId).to.equal(tokenId.toString()); } { @@ -340,141 +268,127 @@ } }); - itWeb3('transfer event on transfer from partial ownership to full ownership', async ({api, web3, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = createEthAccount(web3); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Partial-to-Full', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); - const tokenAddress = tokenIdToAddress(collectionId, tokenId); - const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller); + const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); - const events = await recordEvents(contract, async () => - await tokenContract.methods.transfer(receiver, 1).send()); - expect(events).to.deep.equal([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF', - to: receiver, - tokenId: tokenId.toString(), - }, - }, - ]); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); + }); + await tokenContract.methods.transfer(receiver, 1).send(); + + const event = events[0]; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'); + expect(event.returnValues.to).to.equal(receiver); + expect(event.returnValues.tokenId).to.equal(tokenId.toString()); }); - itWeb3('transfer event on transfer from full ownership to partial ownership', async ({api, web3, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = createEthAccount(web3); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('transfer event on transfer from full ownership to partial ownership', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Full-to-Partial', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); - const tokenAddress = tokenIdToAddress(collectionId, tokenId); - const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller); + const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); - const events = await recordEvents(contract, async () => - await tokenContract.methods.transfer(receiver, 1).send()); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); + }); + await tokenContract.methods.transfer(receiver, 1).send(); - expect(events).to.deep.equal([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: caller, - to: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF', - tokenId: tokenId.toString(), - }, - }, - ]); + const event = events[0]; + expect(event.address).to.equal(collectionAddress); + expect(event.returnValues.from).to.equal(caller); + expect(event.returnValues.to).to.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'); + expect(event.returnValues.tokenId).to.equal(tokenId.toString()); }); }); describe('RFT: Fees', () => { + let donor: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + + donor = privateKey('//Alice'); + }); }); - itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); - - const receiver = createEthAccount(web3); + itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer-From', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); - const cost = await recordEthFee(api, caller, () => contract.methods.transferFrom(caller, receiver, tokenId).send()); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(caller, () => contract.methods.transferFrom(caller, receiver, tokenId).send()); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); expect(cost > 0n); }); - itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); - - const receiver = createEthAccount(web3); + itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); - const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send()); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(caller, () => contract.methods.transfer(receiver, tokenId).send()); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); expect(cost > 0n); }); }); describe('Common metadata', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); - }); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - name: 'token name', - mode: {type: 'ReFungible'}, + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); }); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + }); - const address = collectionIdToAddress(collection); - const contract = evmCollection(web3, caller, address, {type: 'ReFungible'}); + itEth('Returns collection name', async ({helper}) => { + const caller = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice, {name: 'Leviathan', tokenPrefix: '11'}); + + const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'rft', caller); const name = await contract.methods.name().call(); - - expect(name).to.equal('token name'); + expect(name).to.equal('Leviathan'); }); - itWeb3('Returns symbol name', async ({api, web3, privateKeyWrapper}) => { - const collection = await createCollectionExpectSuccess({ - tokenPrefix: 'TOK', - mode: {type: 'ReFungible'}, - }); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - const address = collectionIdToAddress(collection); - const contract = evmCollection(web3, caller, address, {type: 'ReFungible'}); + itEth('Returns symbol name', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Leviathan', '', '12'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const symbol = await contract.methods.symbol().call(); - - expect(symbol).to.equal('TOK'); + expect(symbol).to.equal('12'); }); }); --- a/tests/src/eth/reFungibleToken.test.ts +++ b/tests/src/eth/reFungibleToken.test.ts @@ -14,82 +14,76 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers'; -import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createRFTCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueRefungible, uniqueRefungibleToken} from './util/helpers'; +import {Pallets, requirePalletsOrSkip} from '../util/playgrounds'; +import {EthUniqueHelper, expect, itEth, usingEthPlaygrounds} from './util/playgrounds'; +import {IKeyringPair} from '@polkadot/types/types'; +import {Contract} from 'web3-eth-contract'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -chai.use(chaiAsPromised); -const expect = chai.expect; +describe('Refungible token: Information getting', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; -describe('Refungible token: Information getting', () => { before(async function() { - await requirePallets(this, [Pallets.ReFungible]); - }); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; - - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([20n], donor); + }); + }); - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId; + itEth('totalSupply', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, caller); + const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); const totalSupply = await contract.methods.totalSupply().call(); - expect(totalSupply).to.equal('200'); }); - itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; + itEth('balanceOf', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId; - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, caller); + const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); const balance = await contract.methods.balanceOf(caller).call(); - expect(balance).to.equal('200'); }); - itWeb3('decimals', async ({api, web3, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('decimals', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; - - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId; - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, caller); + const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); const decimals = await contract.methods.decimals().call(); - expect(decimals).to.equal('0'); }); }); // FIXME: Need erc721 for ReFubgible. describe('Check ERC721 token URI for ReFungible', () => { + let donor: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + + donor = privateKey('//Alice'); + }); }); - itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'}); + async function setup(helper: EthUniqueHelper, tokenPrefix: string, propertyKey?: string, propertyValue?: string): Promise<{contract: Contract, nextTokenId: string}> { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send(); + const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const nextTokenId = await contract.methods.nextTokenId().call(); expect(nextTokenId).to.be.equal('1'); result = await contract.methods.mint( @@ -97,166 +91,71 @@ nextTokenId, ).send(); - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); + if (propertyKey && propertyValue) { + // Set URL or suffix + await contract.methods.setProperty(nextTokenId, propertyKey, Buffer.from(propertyValue)).send(); + } + + const event = result.events.Transfer; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(nextTokenId); - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); + return {contract, nextTokenId}; + } + itEth('Empty tokenURI', async ({helper}) => { + const {contract, nextTokenId} = await setup(helper, ''); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal(''); }); - - itWeb3('TokenURI from url', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'}); - const nextTokenId = await contract.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mint( - receiver, - nextTokenId, - ).send(); - - // Set URL - await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send(); - - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); - + itEth('TokenURI from url', async ({helper}) => { + const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'url', 'Token URI'); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI'); }); - - itWeb3('TokenURI from baseURI + tokenId', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'}); - const nextTokenId = await contract.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mint( - receiver, - nextTokenId, - ).send(); - - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); - + itEth('TokenURI from baseURI + tokenId', async ({helper}) => { + const {contract, nextTokenId} = await setup(helper, 'BaseURI_'); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + nextTokenId); }); - itWeb3('TokenURI from baseURI + suffix', async ({web3, api, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, owner); - let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const receiver = createEthAccount(web3); - const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'}); - - const nextTokenId = await contract.methods.nextTokenId().call(); - expect(nextTokenId).to.be.equal('1'); - result = await contract.methods.mint( - receiver, - nextTokenId, - ).send(); - - // Set suffix + itEth('TokenURI from baseURI + suffix', async ({helper}) => { const suffix = '/some/suffix'; - await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send(); - - const events = normalizeEvents(result.events); - const address = collectionIdToAddress(collectionId); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: receiver, - tokenId: nextTokenId, - }, - }, - ]); - + const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'suffix', suffix); expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix); }); }); describe('Refungible: Plain calls', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([50n], donor); + }); }); - itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('Can perform approve()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; - - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId; - - const address = tokenIdToAddress(collectionId, tokenId); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); - const spender = createEthAccount(web3); - - const contract = uniqueRefungibleToken(web3, address, owner); - { const result = await contract.methods.approve(spender, 100).send({from: owner}); - const events = normalizeEvents(result.events); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Approval', - args: { - owner, - spender, - value: '100', - }, - }, - ]); + const event = result.events.Approval; + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.owner).to.be.equal(owner); + expect(event.returnValues.spender).to.be.equal(spender); + expect(event.returnValues.value).to.be.equal('100'); } { @@ -265,49 +164,31 @@ } }); - itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; + itEth('Can perform transferFrom()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId; - - const spender = createEthAccount(web3); - await transferBalanceToEth(api, alice, spender); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); - const receiver = createEthAccount(web3); - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); - await contract.methods.approve(spender, 100).send(); { const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender}); - const events = normalizeEvents(result.events); - expect(events).to.include.deep.members([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: receiver, - value: '49', - }, - }, - { - address, - event: 'Approval', - args: { - owner, - spender, - value: '51', - }, - }, - ]); + let event = result.events.Transfer; + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('49'); + + event = result.events.Approval; + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.owner).to.be.equal(owner); + expect(event.returnValues.spender).to.be.equal(spender); + expect(event.returnValues.value).to.be.equal('51'); } { @@ -321,36 +202,22 @@ } }); - itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('Can perform transfer()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId; - - const receiver = createEthAccount(web3); - await transferBalanceToEth(api, alice, receiver); - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); { const result = await contract.methods.transfer(receiver, 50).send({from: owner}); - const events = normalizeEvents(result.events); - expect(events).to.include.deep.members([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: receiver, - value: '50', - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('50'); } { @@ -364,311 +231,262 @@ } }); - itWeb3('Can perform repartition()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; + itEth('Can perform repartition()', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); - const receiver = createEthAccount(web3); - await transferBalanceToEth(api, alice, receiver); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId; - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); - await contract.methods.repartition(200).send({from: owner}); expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200); await contract.methods.transfer(receiver, 110).send({from: owner}); expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90); expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110); - await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected; + await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected; // Transaction is reverted await contract.methods.transfer(receiver, 90).send({from: owner}); expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(0); expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(200); await contract.methods.repartition(150).send({from: receiver}); - await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected; + await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected; // Transaction is reverted expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(150); }); - itWeb3('Can repartition with increased amount', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId; + itEth('Can repartition with increased amount', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); const result = await contract.methods.repartition(200).send(); - const events = normalizeEvents(result.events); - expect(events).to.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: '0x0000000000000000000000000000000000000000', - to: owner, - value: '100', - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.to).to.be.equal(owner); + expect(event.returnValues.value).to.be.equal('100'); }); - itWeb3('Can repartition with decreased amount', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('Can repartition with decreased amount', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); - const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId; - - const owner = createEthAccount(web3); - await transferBalanceToEth(api, alice, owner); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId; - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); const result = await contract.methods.repartition(50).send(); - const events = normalizeEvents(result.events); - expect(events).to.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: owner, - to: '0x0000000000000000000000000000000000000000', - value: '50', - }, - }, - ]); + const event = result.events.Transfer; + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.from).to.be.equal(owner); + expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000'); + expect(event.returnValues.value).to.be.equal('50'); }); - itWeb3('Receiving Transfer event on burning into full ownership', async ({web3, api, privateKeyWrapper}) => { - const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const helper = evmCollectionHelpers(web3, caller); - const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send(); - const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result); - const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'}); + itEth('Receiving Transfer event on burning into full ownership', async ({helper}) => { + const caller = await helper.eth.createAccountWithBalance(donor); + const receiver = await helper.eth.createAccountWithBalance(donor); + const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Devastation', '6', '6'); + const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const tokenId = await contract.methods.nextTokenId().call(); await contract.methods.mint(caller, tokenId).send(); + const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId); + const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller); - const address = tokenIdToAddress(collectionId, tokenId); - - const tokenContract = uniqueRefungibleToken(web3, address, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); - const events = await recordEvents(contract, async () => - await tokenContract.methods.burnFrom(caller, 1).send()); - expect(events).to.deep.equal([ - { - address: collectionIdAddress, - event: 'Transfer', - args: { - from: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF', - to: receiver, - tokenId, - }, - }, - ]); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); + }); + await tokenContract.methods.burnFrom(caller, 1).send(); + + const event = events[0]; + expect(event.address).to.be.equal(collectionAddress); + expect(event.returnValues.from).to.be.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.tokenId).to.be.equal(tokenId); }); }); describe('Refungible: Fees', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([50n], donor); + }); }); - itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); - const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const spender = createEthAccount(web3); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId; - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); - - const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); - itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - - const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; - - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId; + itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const spender = await helper.eth.createAccountWithBalance(donor); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); await contract.methods.approve(spender, 100).send({from: owner}); - const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); - itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); - const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); - const receiver = createEthAccount(web3); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId; - - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address, owner); - - const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner})); - expect(cost < BigInt(0.2 * Number(UNIQUE))); + const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner})); + expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); }); }); describe('Refungible: Substrate calls', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); - }); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); - - const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; - - const receiver = createEthAccount(web3); + donor = privateKey('//Alice'); + [alice] = await helper.arrange.createAccounts([50n], donor); + }); + }); - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId; + itEth('Events emitted for approve()', async ({helper}) => { + const receiver = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const token = await collection.mintToken(alice, 200n); - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress); - const events = await recordEvents(contract, async () => { - expect(await approve(api, collectionId, tokenId, alice, {Ethereum: receiver}, 100n)).to.be.true; + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); }); + expect(await token.approve(alice, {Ethereum: receiver}, 100n)).to.be.true; - expect(events).to.be.deep.equal([ - { - address, - event: 'Approval', - args: { - owner: subToEth(alice.address), - spender: receiver, - value: '100', - }, - }, - ]); + const event = events[0]; + expect(event.event).to.be.equal('Approval'); + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.spender).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('100'); }); - itWeb3('Events emitted for transferFrom()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('Events emitted for transferFrom()', async ({helper}) => { + const [bob] = await helper.arrange.createAccounts([10n], donor); + const receiver = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const token = await collection.mintToken(alice, 200n); + await token.approve(alice, {Substrate: bob.address}, 100n); - const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; - const bob = privateKeyWrapper('//Bob'); + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress); - const receiver = createEthAccount(web3); + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); + }); - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId; - expect(await approve(api, collectionId, tokenId, alice, bob.address, 100n)).to.be.true; + expect(await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver}, 51n)).to.be.true; - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address); + let event = events[0]; + expect(event.event).to.be.equal('Transfer'); + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('51'); - const events = await recordEvents(contract, async () => { - expect(await transferFrom(api, collectionId, tokenId, bob, alice, {Ethereum: receiver}, 51n)).to.be.true; - }); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: subToEth(alice.address), - to: receiver, - value: '51', - }, - }, - { - address, - event: 'Approval', - args: { - owner: subToEth(alice.address), - spender: subToEth(bob.address), - value: '49', - }, - }, - ]); + event = events[1]; + expect(event.event).to.be.equal('Approval'); + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(bob.address)); + expect(event.returnValues.value).to.be.equal('49'); }); - itWeb3('Events emitted for transfer()', async ({web3, api, privateKeyWrapper}) => { - const alice = privateKeyWrapper('//Alice'); + itEth('Events emitted for transfer()', async ({helper}) => { + const receiver = helper.eth.createAccount(); + const collection = await helper.rft.mintCollection(alice); + const token = await collection.mintToken(alice, 200n); - const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); + const contract = helper.ethNativeContract.rftToken(tokenAddress); - const receiver = createEthAccount(web3); - - const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId; + const events: any = []; + contract.events.allEvents((_: any, event: any) => { + events.push(event); + }); - const address = tokenIdToAddress(collectionId, tokenId); - const contract = uniqueRefungibleToken(web3, address); + expect(await token.transfer(alice, {Ethereum: receiver}, 51n)).to.be.true; - const events = await recordEvents(contract, async () => { - expect(await transfer(api, collectionId, tokenId, alice, {Ethereum: receiver}, 51n)).to.be.true; - }); - - expect(events).to.be.deep.equal([ - { - address, - event: 'Transfer', - args: { - from: subToEth(alice.address), - to: receiver, - value: '51', - }, - }, - ]); + const event = events[0]; + expect(event.event).to.be.equal('Transfer'); + expect(event.address).to.be.equal(tokenAddress); + expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address)); + expect(event.returnValues.to).to.be.equal(receiver); + expect(event.returnValues.value).to.be.equal('51'); }); }); describe('ERC 1633 implementation', () => { + let donor: IKeyringPair; + before(async function() { - await requirePallets(this, [Pallets.ReFungible]); - }); + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - itWeb3('Default parent token address and id', async ({api, web3, privateKeyWrapper}) => { - const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + donor = privateKey('//Alice'); + }); + }); - const {collectionIdAddress, collectionId} = await createRFTCollection(api, web3, owner); - const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner); - const refungibleTokenId = await refungibleContract.methods.nextTokenId().call(); - await refungibleContract.methods.mint(owner, refungibleTokenId).send(); + itEth('Default parent token address and id', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); - const rftTokenAddress = tokenIdToAddress(collectionId, refungibleTokenId); - const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner); + const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sands', '', 'GRAIN'); + const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + + const tokenId = await collectionContract.methods.nextTokenId().call(); + await collectionContract.methods.mint(owner, tokenId).send(); + const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId); + const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner); - const tokenAddress = await refungibleTokenContract.methods.parentToken().call(); - const tokenId = await refungibleTokenContract.methods.parentTokenId().call(); - expect(tokenAddress).to.be.equal(collectionIdAddress); - expect(tokenId).to.be.equal(refungibleTokenId); + expect(await tokenContract.methods.parentToken().call()).to.be.equal(collectionAddress); + expect(await tokenContract.methods.parentTokenId().call()).to.be.equal(tokenId); }); }); --- a/tests/src/eth/util/playgrounds/unique.dev.ts +++ b/tests/src/eth/util/playgrounds/unique.dev.ts @@ -117,13 +117,17 @@ return new web3.eth.Contract(abi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})}); } - rftTokenByAddress(address: string, caller?: string): Contract { + collectionById(collectionId: number, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract { + return this.collection(this.helper.ethAddress.fromCollectionId(collectionId), mode, caller); + } + + rftToken(address: string, caller?: string): Contract { const web3 = this.helper.getWeb3(); return new web3.eth.Contract(refungibleTokenAbi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})}); } - rftToken(collectionId: number, tokenId: number, caller?: string): Contract { - return this.rftTokenByAddress(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller); + rftTokenById(collectionId: number, tokenId: number, caller?: string): Contract { + return this.rftToken(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller); } } @@ -176,6 +180,17 @@ return {collectionId, collectionAddress}; } + async createRefungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> { + const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); + + const result = await collectionHelper.methods.createRFTCollection(name, description, tokenPrefix).send(); + + const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); + const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress); + + return {collectionId, collectionAddress}; + } + async deployCollectorContract(signer: string): Promise { return await this.helper.ethContract.deployByCode(signer, 'Collector', ` // SPDX-License-Identifier: UNLICENSED @@ -220,6 +235,16 @@ } `); } + + async recordCallFee(user: string, call: () => Promise): Promise { + const before = await this.helper.balance.getEthereum(user); + await call(); + // In dev mode, the transaction might not finish processing in time + await this.helper.wait.newBlocks(1); + const after = await this.helper.balance.getEthereum(user); + + return before - after; + } } class EthAddressGroup extends EthGroupBase {