difftreelog
test basic evm integration tests
in: master
7 files changed
tests/src/eth/fungible.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/fungible.test.ts
@@ -0,0 +1,289 @@
+import privateKey from "../substrate/privateKey";
+import { approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess } from "../util/helpers";
+import { collectionIdToAddress, createEthAccount, itWeb3, normalizeEvents, recordEvents, subToEth, transferBalanceToEth } from "./util/helpers"
+import fungibleAbi from './fungibleAbi.json';
+import { expect } from "chai";
+
+describe('Information getting', () => {
+ itWeb3('totalSupply', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ name: 'token name',
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+
+ await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { substrate: alice.address });
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleAbi as any, address);
+ const totalSupply = await contract.methods.totalSupply().call();
+
+ // FIXME: always equals to 0, because this method is not implemented
+ expect(totalSupply).to.equal('0');
+ });
+
+ itWeb3('balanceOf', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ name: 'token name',
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+
+ const caller = createEthAccount(web3);
+ await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: caller });
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleAbi as any, address);
+ const balance = await contract.methods.balanceOf(caller).call();
+
+ expect(balance).to.equal('200');
+ });
+});
+
+describe('Plain calls', () => {
+ itWeb3('Can perform approve()', async ({ web3, api }) => {
+ const collection = await createCollectionExpectSuccess({
+ name: 'token name',
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+
+ const owner = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, owner, 999999999999999);
+
+ await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
+
+ const spender = createEthAccount(web3);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleAbi as any, address);
+
+ {
+ const result = await contract.methods.approve(spender, 100).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+ const events = normalizeEvents(result.events);
+
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Approval',
+ args: {
+ owner,
+ spender,
+ value: '100',
+ }
+ }
+ ]);
+ }
+
+ {
+ const allowance = await contract.methods.allowance(owner, spender).call();
+ expect(+allowance).to.equal(100);
+ }
+ });
+
+ itWeb3('Can perform transferFrom()', async ({ web3, api }) => {
+ const collection = await createCollectionExpectSuccess({
+ name: 'token name',
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+
+ const owner = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, owner, 999999999999999);
+
+ await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
+
+ const spender = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, spender, 999999999999999);
+
+ const receiver = createEthAccount(web3);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleAbi as any, address);
+
+ await contract.methods.approve(spender, 100).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+
+ {
+ const result = await contract.methods.transferFrom(owner, receiver, 49).send({ from: spender, gas: '0x1000000', gasPrice: '0x01' });
+ 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',
+ }
+ }
+ ]);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(49);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(owner).call();
+ expect(+balance).to.equal(151);
+ }
+ });
+
+ itWeb3('Can perform transfer()', async ({ web3, api }) => {
+ const collection = await createCollectionExpectSuccess({
+ name: 'token name',
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+
+ const owner = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, owner, 999999999999999);
+
+ await createFungibleItemExpectSuccess(alice, collection, { Value: 200n }, { ethereum: owner });
+
+ const receiver = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, receiver, 999999999999999);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleAbi as any, address);
+
+ {
+ const result = await contract.methods.transfer(receiver, 50).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+ const events = normalizeEvents(result.events);
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Transfer',
+ args: {
+ from: owner,
+ to: receiver,
+ value: '50',
+ }
+ },
+ ])
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(owner).call();
+ expect(+balance).to.equal(150);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(50);
+ }
+ });
+});
+
+describe('Substrate calls', () => {
+ itWeb3('Events emitted for approve()', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+
+ const receiver = createEthAccount(web3);
+
+ 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 approveExpectSuccess(collection, 1, alice, { ethereum: receiver }, 100);
+ });
+
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Approval',
+ args: {
+ owner: subToEth(alice.address),
+ spender: receiver,
+ value: '100',
+ }
+ }
+ ]);
+ });
+
+ itWeb3('Events emitted for transferFrom()', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+ const bob = privateKey('//Bob');
+
+ const receiver = createEthAccount(web3);
+
+ await createFungibleItemExpectSuccess(alice, collection, { Value: 200n });
+ await approveExpectSuccess(collection, 1, alice, bob, 100);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleAbi as any, address);
+
+ const events = await recordEvents(contract, async () => {
+ await transferFromExpectSuccess(collection, 1, 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',
+ }
+ }
+ ]);
+ });
+
+ itWeb3('Events emitted for transfer()', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'Fungible', decimalPoints: 0 }
+ });
+ const alice = privateKey('//Alice');
+
+ const receiver = createEthAccount(web3);
+
+ 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, 1, alice, { ethereum: receiver }, 51, 'Fungible');
+ });
+
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Transfer',
+ args: {
+ from: subToEth(alice.address),
+ to: receiver,
+ value: '51',
+ }
+ },
+ ]);
+ });
+});
\ No newline at end of file
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/fungibleAbi.json
@@ -0,0 +1,175 @@
+[
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "name": "balance",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "name": "_spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ }
+]
\ No newline at end of file
tests/src/eth/fungibleMetadataAbi.jsondiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/fungibleMetadataAbi.json
@@ -0,0 +1,41 @@
+[
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "decimals",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+]
\ No newline at end of file
tests/src/eth/metadata.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/metadata.test.ts
@@ -0,0 +1,53 @@
+import { expect } from "chai";
+import privateKey from "../substrate/privateKey";
+import { createCollectionExpectSuccess } from "../util/helpers";
+import { collectionIdToAddress, createEthAccount, itWeb3, transferBalanceToEth } from "./util/helpers";
+import fungibleMetadataAbi from './fungibleMetadataAbi.json';
+
+describe('Common metadata', () => {
+ itWeb3('Returns collection name', async ({ api, web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ name: 'token name',
+ mode: { type: 'NFT' }
+ });
+ const caller = createEthAccount(web3);
+ await transferBalanceToEth(api, privateKey('//Alice'), caller, 999999);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address);
+ const name = await contract.methods.name().call({ from: caller });
+
+ expect(name).to.equal('token name');
+ });
+
+ itWeb3('Returns symbol name', async ({ api, web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ tokenPrefix: 'TOK',
+ mode: { type: 'NFT' }
+ });
+ const caller = createEthAccount(web3);
+ await transferBalanceToEth(api, privateKey('//Alice'), caller, 999999);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address);
+ const symbol = await contract.methods.symbol().call({ from: caller });
+
+ expect(symbol).to.equal('TOK');
+ });
+});
+
+describe('Fungible metadata', () => {
+ itWeb3('Returns fungible decimals', async ({ api, web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'Fungible', decimalPoints: 6 }
+ });
+ const caller = createEthAccount(web3);
+ await transferBalanceToEth(api, privateKey('//Alice'), caller, 999999);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(fungibleMetadataAbi as any, address);
+ const decimals = await contract.methods.decimals().call({ from: caller });
+
+ expect(+decimals).to.equal(6);
+ })
+})
\ No newline at end of file
tests/src/eth/nonFungible.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/nonFungible.test.ts
@@ -0,0 +1,280 @@
+import privateKey from "../substrate/privateKey";
+import { approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess } from "../util/helpers";
+import { collectionIdToAddress, createEthAccount, itWeb3, normalizeEvents, recordEvents, subToEth, transferBalanceToEth } from "./util/helpers"
+import nonFungibleAbi from './nonFungibleAbi.json';
+import { expect } from "chai";
+
+describe('Information getting', () => {
+ itWeb3('totalSupply', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address });
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ const totalSupply = await contract.methods.totalSupply().call();
+
+ // FIXME: always equals to 0, because this method is not implemented
+ expect(totalSupply).to.equal('0');
+ });
+
+ itWeb3('balanceOf', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ const caller = createEthAccount(web3);
+ await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+ await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+ await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ const balance = await contract.methods.balanceOf(caller).call();
+
+ expect(balance).to.equal('3');
+ });
+
+ itWeb3('ownerOf', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ const caller = createEthAccount(web3);
+ const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+ const owner = await contract.methods.ownerOf(tokenId).call();
+
+ expect(owner).to.equal(caller);
+ });
+});
+
+describe.only('Plain calls', () => {
+ itWeb3('Can perform approve()', async ({ web3, api }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ const owner = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, owner, 999999999999999);
+
+ const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+ const spender = createEthAccount(web3);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+
+ {
+ const result = await contract.methods.approve(spender, tokenId).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+ const events = normalizeEvents(result.events);
+
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Approval',
+ args: {
+ owner,
+ approved: spender,
+ tokenId: tokenId.toString(),
+ }
+ }
+ ]);
+ }
+ });
+
+ itWeb3('Can perform transferFrom()', async ({ web3, api }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ const owner = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, owner, 999999999999999);
+
+ const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+ const spender = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, spender, 999999999999999);
+
+ const receiver = createEthAccount(web3);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+
+ await contract.methods.approve(spender, tokenId).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+
+ {
+ const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({ from: spender, gas: '0x1000000', gasPrice: '0x01' });
+ const events = normalizeEvents(result.events);
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Transfer',
+ args: {
+ from: owner,
+ to: receiver,
+ tokenId: tokenId.toString(),
+ },
+ },
+ ]);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(1);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(owner).call();
+ expect(+balance).to.equal(0);
+ }
+ });
+
+ itWeb3('Can perform transfer()', async ({ web3, api }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ const owner = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, owner, 999999999999999);
+
+ const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });
+
+ const receiver = createEthAccount(web3);
+ await transferBalanceToEth(api, alice, receiver, 999999999999999);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+
+ {
+ const result = await contract.methods.transfer(receiver, tokenId).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });
+ console.log(result);
+ const events = normalizeEvents(result.events);
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Transfer',
+ args: {
+ from: owner,
+ to: receiver,
+ tokenId: tokenId.toString(),
+ }
+ },
+ ])
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(owner).call();
+ expect(+balance).to.equal(0);
+ }
+
+ {
+ const balance = await contract.methods.balanceOf(receiver).call();
+ expect(+balance).to.equal(1);
+ }
+ });
+});
+
+describe('Substrate calls', () => {
+ itWeb3('Events emitted for approve()', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ 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 events = await recordEvents(contract, async () => {
+ await approveExpectSuccess(collection, tokenId, alice, { ethereum: receiver }, 1);
+ });
+
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Approval',
+ args: {
+ owner: subToEth(alice.address),
+ approved: receiver,
+ tokenId: tokenId.toString(),
+ }
+ }
+ ]);
+ });
+
+ itWeb3('Events emitted for transferFrom()', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+ const bob = privateKey('//Bob');
+
+ const receiver = createEthAccount(web3);
+
+ const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');
+ await approveExpectSuccess(collection, tokenId, alice, bob, 1);
+
+ const address = collectionIdToAddress(collection);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address);
+
+ const events = await recordEvents(contract, async () => {
+ await transferFromExpectSuccess(collection, tokenId, bob, alice, { ethereum: receiver }, 1, 'NFT');
+ });
+
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Transfer',
+ args: {
+ from: subToEth(alice.address),
+ to: receiver,
+ tokenId: tokenId.toString(),
+ }
+ },
+ ]);
+ });
+
+ itWeb3('Events emitted for transfer()', async ({ web3 }) => {
+ const collection = await createCollectionExpectSuccess({
+ mode: { type: 'NFT' }
+ });
+ const alice = privateKey('//Alice');
+
+ 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 events = await recordEvents(contract, async () => {
+ await transferExpectSuccess(collection, tokenId, alice, { ethereum: receiver }, 1, 'NFT');
+ });
+
+ expect(events).to.be.deep.equal([
+ {
+ address,
+ event: 'Transfer',
+ args: {
+ from: subToEth(alice.address),
+ to: receiver,
+ tokenId: tokenId.toString(),
+ }
+ },
+ ]);
+ });
+});
\ No newline at end of file
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -0,0 +1,406 @@
+[
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "approved",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "name": "ApprovalForAll",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "approved",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getApproved",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ }
+ ],
+ "name": "isApprovedForAll",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "res_name",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "ownerOf",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "name": "setApprovalForAll",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceID",
+ "type": "bytes4"
+ }
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "res_symbol",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenByIndex",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenOfOwnerByIndex",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenURI",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ }
+]
\ No newline at end of file
tests/src/eth/util/helpers.tsdiffbeforeafterbothno changes