difftreelog
fix eth tests
in: master
5 files changed
tests/src/eth/base.test.tsdiffbeforeafterboth--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -23,7 +23,6 @@
import {IKeyringPair} from '@polkadot/types/types';
import {EthUniqueHelper, itEth, usingEthPlaygrounds, expect} from './util/playgrounds';
-import {UNIQUE} from '../util/helpers';
describe('Contract calls', () => {
let donor: IKeyringPair;
@@ -39,7 +38,7 @@
const flipper = await helper.eth.deployFlipper(deployer);
const cost = await recordEthFee(helper.api!, deployer, () => flipper.methods.flip().send({from: deployer}));
- expect(cost < BigInt(0.2 * Number(UNIQUE))).to.be.true;
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))).to.be.true;
});
itEth('Balance transfer fee is less than 0.2 UNQ', async ({helper}) => {
@@ -47,7 +46,7 @@
const userB = helper.eth.createAccount();
const cost = await recordEthFee(helper.api!, userA, () => helper.web3!.eth.sendTransaction({from: userA, to: userB, value: '1000000', ...GAS_ARGS}));
const balanceB = await ethBalanceViaSub(helper.api!, userB);
- expect(cost - balanceB < BigInt(0.2 * Number(UNIQUE))).to.be.true;
+ expect(cost - balanceB < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))).to.be.true;
});
itEth('NFT transfer is close to 0.15 UNQ', async ({helper}) => {
@@ -63,7 +62,7 @@
const cost = await recordEthFee(helper.api!, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));
- const fee = Number(cost) / Number(UNIQUE);
+ const fee = Number(cost) / Number(helper.balance.getOneTokenNominal());
const expectedFee = 0.15;
const tolerance = 0.001;
tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionAdmin.test.ts
+++ b/tests/src/eth/collectionAdmin.test.ts
@@ -14,11 +14,32 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
-import {UNIQUE} from '../util/helpers';
-import {
- recordEthFee,
-} from './util/helpers';
-import {usingEthPlaygrounds, itEth, expect} from './util/playgrounds';
+import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util/playgrounds';
+
+async function waitNewBlocks(helper: EthUniqueHelper, count: number) {
+ // eslint-disable-next-line no-async-promise-executor
+ return new Promise<void>(async (resolve) => {
+ const unsubscribe = await helper.callRpc('api.rpc.chain.subscribeNewHeads', [() => {
+ if (count > 0) {
+ count--;
+ } else {
+ unsubscribe();
+ resolve();
+ }
+ }]);
+ });
+}
+
+async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {
+ const before = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));
+ await call();
+ waitNewBlocks(helper, 1);
+ const after = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));
+
+ expect(after < before).to.be.true;
+
+ return before - after;
+}
describe('Add collection admins', () => {
let donor: IKeyringPair;
@@ -37,7 +58,7 @@
const newAdmin = helper.eth.createAccount();
await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
.to.be.eq(newAdmin.toLocaleLowerCase());
});
@@ -50,12 +71,11 @@
const [newAdmin] = await helper.arrange.createAccounts([10n], donor);
await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
.to.be.eq(newAdmin.address.toLocaleLowerCase());
});
- //FIXME:
itEth('Verify owner or admin', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
@@ -79,7 +99,7 @@
await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: admin}))
.to.be.rejectedWith('NoPermission');
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(1);
expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
.to.be.eq(admin.toLocaleLowerCase());
@@ -96,7 +116,7 @@
await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: notAdmin}))
.to.be.rejectedWith('NoPermission');
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(0);
});
@@ -112,7 +132,7 @@
await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin.addressRaw).call({from: admin}))
.to.be.rejectedWith('NoPermission');
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(1);
expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
.to.be.eq(admin.toLocaleLowerCase());
@@ -128,7 +148,7 @@
await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin1.addressRaw).call({from: notAdmin0}))
.to.be.rejectedWith('NoPermission');
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(0);
});
});
@@ -151,14 +171,14 @@
await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
{
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(1);
expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
.to.be.eq(newAdmin.toLocaleLowerCase());
}
await collectionEvm.methods.removeCollectionAdmin(newAdmin).send();
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(0);
});
@@ -170,13 +190,13 @@
const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();
{
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
.to.be.eq(newAdmin.address.toLocaleLowerCase());
}
await collectionEvm.methods.removeCollectionAdminSubstrate(newAdmin.addressRaw).send();
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(0);
});
@@ -194,7 +214,7 @@
await expect(collectionEvm.methods.removeCollectionAdmin(admin1).call({from: admin0}))
.to.be.rejectedWith('NoPermission');
{
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(2);
expect(adminList.toString().toLocaleLowerCase())
.to.be.deep.contains(admin0.toLocaleLowerCase())
@@ -215,7 +235,7 @@
await expect(collectionEvm.methods.removeCollectionAdmin(admin).call({from: notAdmin}))
.to.be.rejectedWith('NoPermission');
{
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
.to.be.eq(admin.toLocaleLowerCase());
expect(adminList.length).to.be.eq(1);
@@ -235,7 +255,7 @@
await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: adminEth}))
.to.be.rejectedWith('NoPermission');
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(2);
expect(adminList.toString().toLocaleLowerCase())
.to.be.deep.contains(adminSub.address.toLocaleLowerCase())
@@ -254,7 +274,7 @@
await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: notAdminEth}))
.to.be.rejectedWith('NoPermission');
- const adminList = await helper.api!.rpc.unique.adminlist(collectionId);
+ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);
expect(adminList.length).to.be.eq(1);
expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
.to.be.eq(adminSub.address.toLocaleLowerCase());
@@ -287,13 +307,11 @@
const newOwner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
-
- const cost = await recordEthFee(helper.api!, owner, () => collectionEvm.methods.setOwner(newOwner).send());
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwner(newOwner).send());
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
expect(cost > 0);
});
- //FIXME
itEth('(!negative tests!) call setOwner by non owner', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const newOwner = await helper.eth.createAccountWithBalance(donor);
@@ -314,7 +332,6 @@
});
});
- //FIXME
itEth.skip('Change owner', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const [newOwner] = await helper.arrange.createAccounts([10n], donor);
@@ -336,12 +353,11 @@
const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
- const cost = await recordEthFee(helper.api!, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());
- expect(cost < BigInt(0.2 * Number(UNIQUE)));
+ const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());
+ expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
expect(cost > 0);
});
- //FIXME
itEth.skip('(!negative tests!) call setOwner by non owner', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const otherReceiver = await helper.eth.createAccountWithBalance(donor);
tests/src/eth/collectionProperties.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionProperties.test.ts
+++ b/tests/src/eth/collectionProperties.test.ts
@@ -51,6 +51,6 @@
const contract = helper.ethNativeContract.collection(address, 'nft', caller);
const value = await contract.methods.collectionProperty('testKey').call();
- expect(value).to.equal(helper.web3?.utils.toHex('testValue'));
+ expect(value).to.equal(helper.getWeb3().utils.toHex('testValue'));
});
});
tests/src/eth/proxy/fungibleProxy.test.tsdiffbeforeafterboth--- a/tests/src/eth/proxy/fungibleProxy.test.ts
+++ b/tests/src/eth/proxy/fungibleProxy.test.ts
@@ -23,7 +23,8 @@
async function proxyWrap(helper: EthUniqueHelper, wrapped: any, donor: IKeyringPair) {
// Proxy owner has no special privilegies, we don't need to reuse them
const owner = await helper.eth.createAccountWithBalance(donor);
- const proxyContract = new helper.web3!.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {
+ const web3 = helper.getWeb3();
+ const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {
from: owner,
...GAS_ARGS,
});
tests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {GAS_ARGS, itWeb3, normalizeEvents} from '../util/helpers';18import {expect} from 'chai';19import {readFile} from 'fs/promises';20import {IKeyringPair} from '@polkadot/types/types';21import {EthUniqueHelper, itEth, usingEthPlaygrounds} from '../util/playgrounds';2223async function proxyWrap(helper: EthUniqueHelper, wrapped: any, donor: IKeyringPair) {24 // Proxy owner has no special privilegies, we don't need to reuse them25 const owner = await helper.eth.createAccountWithBalance(donor);26 const proxyContract = new helper.web3!.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {27 from: owner,28 ...GAS_ARGS,29 });30 const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});31 return proxy;32}3334describe('NFT (Via EVM proxy): Information getting', () => {35 let alice: IKeyringPair;36 let donor: IKeyringPair;3738 before(async function() {39 await usingEthPlaygrounds(async (helper, privateKey) => {40 donor = privateKey('//Alice');41 [alice] = await helper.arrange.createAccounts([10n], donor);42 });43 });4445 itEth('totalSupply', async ({helper}) => {46 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});47 const caller = await helper.eth.createAccountWithBalance(donor);48 await collection.mintToken(alice, {Substrate: alice.address});4950 const address = helper.ethAddress.fromCollectionId(collection.collectionId);51 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);52 const contract = await proxyWrap(helper, evmCollection, donor);53 const totalSupply = await contract.methods.totalSupply().call();5455 expect(totalSupply).to.equal('1');56 });5758 itEth('balanceOf', async ({helper}) => {59 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});6061 const caller = await helper.eth.createAccountWithBalance(donor);62 await collection.mintMultipleTokens(alice, [63 {owner: {Ethereum: caller}},64 {owner: {Ethereum: caller}},65 {owner: {Ethereum: caller}},66 ]);6768 const address = helper.ethAddress.fromCollectionId(collection.collectionId);69 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);70 const contract = await proxyWrap(helper, evmCollection, donor);71 const balance = await contract.methods.balanceOf(caller).call();7273 expect(balance).to.equal('3');74 });7576 itEth('ownerOf', async ({helper}) => {77 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});7879 const caller = await helper.eth.createAccountWithBalance(donor);80 const {tokenId} = await collection.mintToken(alice, {Ethereum: caller});8182 const address = helper.ethAddress.fromCollectionId(collection.collectionId);83 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);84 const contract = await proxyWrap(helper, evmCollection, donor);85 const owner = await contract.methods.ownerOf(tokenId).call();8687 expect(owner).to.equal(caller);88 });89});9091describe('NFT (Via EVM proxy): Plain calls', () => {92 let alice: IKeyringPair;93 let donor: IKeyringPair;9495 before(async function() {96 await usingEthPlaygrounds(async (helper, privateKey) => {97 donor = privateKey('//Alice');98 [alice] = await helper.arrange.createAccounts([10n], donor);99 });100 });101102 itEth('Can perform mint()', async ({helper}) => {103 const owner = await helper.eth.createAccountWithBalance(donor);104 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'A', 'A');105 const caller = await helper.eth.createAccountWithBalance(donor);106 const receiver = helper.eth.createAccount();107108 const collectionEvmOwned = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);109 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);110 const contract = await proxyWrap(helper, collectionEvm, donor);111 await collectionEvmOwned.methods.addCollectionAdmin(contract.options.address).send();112113 {114 const nextTokenId = await contract.methods.nextTokenId().call();115 expect(nextTokenId).to.be.equal('1');116 const result = await contract.methods.mintWithTokenURI(117 receiver,118 nextTokenId,119 'Test URI',120 ).send({from: caller});121 const events = normalizeEvents(result.events);122 events[0].address = events[0].address.toLocaleLowerCase();123124 expect(events).to.be.deep.equal([125 {126 address: collectionAddress.toLocaleLowerCase(),127 event: 'Transfer',128 args: {129 from: '0x0000000000000000000000000000000000000000',130 to: receiver,131 tokenId: nextTokenId,132 },133 },134 ]);135136 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');137 }138 });139140 //TODO: CORE-302 add eth methods141 itWeb3.skip('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {142 /*143 const collection = await createCollectionExpectSuccess({144 mode: {type: 'NFT'},145 });146 const alice = privateKeyWrapper('//Alice');147148 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);149 const receiver = createEthAccount(web3);150151 const address = collectionIdToAddress(collection);152 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);153 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});154 await submitTransactionAsync(alice, changeAdminTx);155156 {157 const nextTokenId = await contract.methods.nextTokenId().call();158 expect(nextTokenId).to.be.equal('1');159 const result = await contract.methods.mintBulkWithTokenURI(160 receiver,161 [162 [nextTokenId, 'Test URI 0'],163 [+nextTokenId + 1, 'Test URI 1'],164 [+nextTokenId + 2, 'Test URI 2'],165 ],166 ).send({from: caller});167 const events = normalizeEvents(result.events);168169 expect(events).to.be.deep.equal([170 {171 address,172 event: 'Transfer',173 args: {174 from: '0x0000000000000000000000000000000000000000',175 to: receiver,176 tokenId: nextTokenId,177 },178 },179 {180 address,181 event: 'Transfer',182 args: {183 from: '0x0000000000000000000000000000000000000000',184 to: receiver,185 tokenId: String(+nextTokenId + 1),186 },187 },188 {189 address,190 event: 'Transfer',191 args: {192 from: '0x0000000000000000000000000000000000000000',193 to: receiver,194 tokenId: String(+nextTokenId + 2),195 },196 },197 ]);198199 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');200 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');201 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');202 }203 */204 });205206 itEth('Can perform burn()', async ({helper}) => {207 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});208 const caller = await helper.eth.createAccountWithBalance(donor);209210 const address = helper.ethAddress.fromCollectionId(collection.collectionId);211 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);212 const contract = await proxyWrap(helper, evmCollection, donor);213 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});214 await collection.addAdmin(alice, {Ethereum: contract.options.address});215216 {217 const result = await contract.methods.burn(tokenId).send({from: caller});218 const events = normalizeEvents(result.events);219220 expect(events).to.be.deep.equal([221 {222 address,223 event: 'Transfer',224 args: {225 from: contract.options.address,226 to: '0x0000000000000000000000000000000000000000',227 tokenId: tokenId.toString(),228 },229 },230 ]);231 }232 });233234 itEth('Can perform approve()', async ({helper}) => {235 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});236 const caller = await helper.eth.createAccountWithBalance(donor);237 const spender = helper.eth.createAccount();238239 const address = helper.ethAddress.fromCollectionId(collection.collectionId);240 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);241 const contract = await proxyWrap(helper, evmCollection, donor);242 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});243244 {245 const result = await contract.methods.approve(spender, tokenId).send({from: caller, ...GAS_ARGS});246 const events = normalizeEvents(result.events);247248 expect(events).to.be.deep.equal([249 {250 address,251 event: 'Approval',252 args: {253 owner: contract.options.address,254 approved: spender,255 tokenId: tokenId.toString(),256 },257 },258 ]);259 }260 });261262 itEth('Can perform transferFrom()', async ({helper}) => {263 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});264 const caller = await helper.eth.createAccountWithBalance(donor);265 const owner = await helper.eth.createAccountWithBalance(donor);266267 const receiver = helper.eth.createAccount();268269 const address = helper.ethAddress.fromCollectionId(collection.collectionId);270 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);271 const contract = await proxyWrap(helper, evmCollection, donor);272 const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});273274 await evmCollection.methods.approve(contract.options.address, tokenId).send({from: owner});275276 {277 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: caller});278 const events = normalizeEvents(result.events);279 expect(events).to.be.deep.equal([280 {281 address,282 event: 'Transfer',283 args: {284 from: owner,285 to: receiver,286 tokenId: tokenId.toString(),287 },288 },289 ]);290 }291292 {293 const balance = await contract.methods.balanceOf(receiver).call();294 expect(+balance).to.equal(1);295 }296297 {298 const balance = await contract.methods.balanceOf(contract.options.address).call();299 expect(+balance).to.equal(0);300 }301 });302303 itEth('Can perform transfer()', async ({helper}) => {304 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});305 const caller = await helper.eth.createAccountWithBalance(donor);306 const receiver = helper.eth.createAccount();307308 const address = helper.ethAddress.fromCollectionId(collection.collectionId);309 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);310 const contract = await proxyWrap(helper, evmCollection, donor);311 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});312313 {314 const result = await contract.methods.transfer(receiver, tokenId).send({from: caller});315 const events = normalizeEvents(result.events);316 expect(events).to.be.deep.equal([317 {318 address,319 event: 'Transfer',320 args: {321 from: contract.options.address,322 to: receiver,323 tokenId: tokenId.toString(),324 },325 },326 ]);327 }328329 {330 const balance = await contract.methods.balanceOf(contract.options.address).call();331 expect(+balance).to.equal(0);332 }333334 {335 const balance = await contract.methods.balanceOf(receiver).call();336 expect(+balance).to.equal(1);337 }338 });339});1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {GAS_ARGS, itWeb3, normalizeEvents} from '../util/helpers';18import {expect} from 'chai';19import {readFile} from 'fs/promises';20import {IKeyringPair} from '@polkadot/types/types';21import {EthUniqueHelper, itEth, usingEthPlaygrounds} from '../util/playgrounds';2223async function proxyWrap(helper: EthUniqueHelper, wrapped: any, donor: IKeyringPair) {24 // Proxy owner has no special privilegies, we don't need to reuse them25 const owner = await helper.eth.createAccountWithBalance(donor);26 const web3 = helper.getWeb3();27 const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {28 from: owner,29 ...GAS_ARGS,30 });31 const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});32 return proxy;33}3435describe('NFT (Via EVM proxy): Information getting', () => {36 let alice: IKeyringPair;37 let donor: IKeyringPair;3839 before(async function() {40 await usingEthPlaygrounds(async (helper, privateKey) => {41 donor = privateKey('//Alice');42 [alice] = await helper.arrange.createAccounts([10n], donor);43 });44 });4546 itEth('totalSupply', async ({helper}) => {47 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});48 const caller = await helper.eth.createAccountWithBalance(donor);49 await collection.mintToken(alice, {Substrate: alice.address});5051 const address = helper.ethAddress.fromCollectionId(collection.collectionId);52 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);53 const contract = await proxyWrap(helper, evmCollection, donor);54 const totalSupply = await contract.methods.totalSupply().call();5556 expect(totalSupply).to.equal('1');57 });5859 itEth('balanceOf', async ({helper}) => {60 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});6162 const caller = await helper.eth.createAccountWithBalance(donor);63 await collection.mintMultipleTokens(alice, [64 {owner: {Ethereum: caller}},65 {owner: {Ethereum: caller}},66 {owner: {Ethereum: caller}},67 ]);6869 const address = helper.ethAddress.fromCollectionId(collection.collectionId);70 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);71 const contract = await proxyWrap(helper, evmCollection, donor);72 const balance = await contract.methods.balanceOf(caller).call();7374 expect(balance).to.equal('3');75 });7677 itEth('ownerOf', async ({helper}) => {78 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});7980 const caller = await helper.eth.createAccountWithBalance(donor);81 const {tokenId} = await collection.mintToken(alice, {Ethereum: caller});8283 const address = helper.ethAddress.fromCollectionId(collection.collectionId);84 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);85 const contract = await proxyWrap(helper, evmCollection, donor);86 const owner = await contract.methods.ownerOf(tokenId).call();8788 expect(owner).to.equal(caller);89 });90});9192describe('NFT (Via EVM proxy): Plain calls', () => {93 let alice: IKeyringPair;94 let donor: IKeyringPair;9596 before(async function() {97 await usingEthPlaygrounds(async (helper, privateKey) => {98 donor = privateKey('//Alice');99 [alice] = await helper.arrange.createAccounts([10n], donor);100 });101 });102103 itEth('Can perform mint()', async ({helper}) => {104 const owner = await helper.eth.createAccountWithBalance(donor);105 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'A', 'A');106 const caller = await helper.eth.createAccountWithBalance(donor);107 const receiver = helper.eth.createAccount();108109 const collectionEvmOwned = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);110 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', caller);111 const contract = await proxyWrap(helper, collectionEvm, donor);112 await collectionEvmOwned.methods.addCollectionAdmin(contract.options.address).send();113114 {115 const nextTokenId = await contract.methods.nextTokenId().call();116 expect(nextTokenId).to.be.equal('1');117 const result = await contract.methods.mintWithTokenURI(118 receiver,119 nextTokenId,120 'Test URI',121 ).send({from: caller});122 const events = normalizeEvents(result.events);123 events[0].address = events[0].address.toLocaleLowerCase();124125 expect(events).to.be.deep.equal([126 {127 address: collectionAddress.toLocaleLowerCase(),128 event: 'Transfer',129 args: {130 from: '0x0000000000000000000000000000000000000000',131 to: receiver,132 tokenId: nextTokenId,133 },134 },135 ]);136137 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');138 }139 });140141 //TODO: CORE-302 add eth methods142 itWeb3.skip('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {143 /*144 const collection = await createCollectionExpectSuccess({145 mode: {type: 'NFT'},146 });147 const alice = privateKeyWrapper('//Alice');148149 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);150 const receiver = createEthAccount(web3);151152 const address = collectionIdToAddress(collection);153 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);154 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});155 await submitTransactionAsync(alice, changeAdminTx);156157 {158 const nextTokenId = await contract.methods.nextTokenId().call();159 expect(nextTokenId).to.be.equal('1');160 const result = await contract.methods.mintBulkWithTokenURI(161 receiver,162 [163 [nextTokenId, 'Test URI 0'],164 [+nextTokenId + 1, 'Test URI 1'],165 [+nextTokenId + 2, 'Test URI 2'],166 ],167 ).send({from: caller});168 const events = normalizeEvents(result.events);169170 expect(events).to.be.deep.equal([171 {172 address,173 event: 'Transfer',174 args: {175 from: '0x0000000000000000000000000000000000000000',176 to: receiver,177 tokenId: nextTokenId,178 },179 },180 {181 address,182 event: 'Transfer',183 args: {184 from: '0x0000000000000000000000000000000000000000',185 to: receiver,186 tokenId: String(+nextTokenId + 1),187 },188 },189 {190 address,191 event: 'Transfer',192 args: {193 from: '0x0000000000000000000000000000000000000000',194 to: receiver,195 tokenId: String(+nextTokenId + 2),196 },197 },198 ]);199200 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');201 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');202 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');203 }204 */205 });206207 itEth('Can perform burn()', async ({helper}) => {208 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});209 const caller = await helper.eth.createAccountWithBalance(donor);210211 const address = helper.ethAddress.fromCollectionId(collection.collectionId);212 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);213 const contract = await proxyWrap(helper, evmCollection, donor);214 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});215 await collection.addAdmin(alice, {Ethereum: contract.options.address});216217 {218 const result = await contract.methods.burn(tokenId).send({from: caller});219 const events = normalizeEvents(result.events);220221 expect(events).to.be.deep.equal([222 {223 address,224 event: 'Transfer',225 args: {226 from: contract.options.address,227 to: '0x0000000000000000000000000000000000000000',228 tokenId: tokenId.toString(),229 },230 },231 ]);232 }233 });234235 itEth('Can perform approve()', async ({helper}) => {236 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});237 const caller = await helper.eth.createAccountWithBalance(donor);238 const spender = helper.eth.createAccount();239240 const address = helper.ethAddress.fromCollectionId(collection.collectionId);241 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);242 const contract = await proxyWrap(helper, evmCollection, donor);243 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});244245 {246 const result = await contract.methods.approve(spender, tokenId).send({from: caller, ...GAS_ARGS});247 const events = normalizeEvents(result.events);248249 expect(events).to.be.deep.equal([250 {251 address,252 event: 'Approval',253 args: {254 owner: contract.options.address,255 approved: spender,256 tokenId: tokenId.toString(),257 },258 },259 ]);260 }261 });262263 itEth('Can perform transferFrom()', async ({helper}) => {264 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});265 const caller = await helper.eth.createAccountWithBalance(donor);266 const owner = await helper.eth.createAccountWithBalance(donor);267268 const receiver = helper.eth.createAccount();269270 const address = helper.ethAddress.fromCollectionId(collection.collectionId);271 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);272 const contract = await proxyWrap(helper, evmCollection, donor);273 const {tokenId} = await collection.mintToken(alice, {Ethereum: owner});274275 await evmCollection.methods.approve(contract.options.address, tokenId).send({from: owner});276277 {278 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: caller});279 const events = normalizeEvents(result.events);280 expect(events).to.be.deep.equal([281 {282 address,283 event: 'Transfer',284 args: {285 from: owner,286 to: receiver,287 tokenId: tokenId.toString(),288 },289 },290 ]);291 }292293 {294 const balance = await contract.methods.balanceOf(receiver).call();295 expect(+balance).to.equal(1);296 }297298 {299 const balance = await contract.methods.balanceOf(contract.options.address).call();300 expect(+balance).to.equal(0);301 }302 });303304 itEth('Can perform transfer()', async ({helper}) => {305 const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});306 const caller = await helper.eth.createAccountWithBalance(donor);307 const receiver = helper.eth.createAccount();308309 const address = helper.ethAddress.fromCollectionId(collection.collectionId);310 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);311 const contract = await proxyWrap(helper, evmCollection, donor);312 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});313314 {315 const result = await contract.methods.transfer(receiver, tokenId).send({from: caller});316 const events = normalizeEvents(result.events);317 expect(events).to.be.deep.equal([318 {319 address,320 event: 'Transfer',321 args: {322 from: contract.options.address,323 to: receiver,324 tokenId: tokenId.toString(),325 },326 },327 ]);328 }329330 {331 const balance = await contract.methods.balanceOf(contract.options.address).call();332 expect(+balance).to.equal(0);333 }334335 {336 const balance = await contract.methods.balanceOf(receiver).call();337 expect(+balance).to.equal(1);338 }339 });340});