1234567891011121314151617import {approveExpectSuccess, createCollection, createCollectionExpectSuccess, createFungibleItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';19import fungibleAbi from './fungibleAbi.json';20import {expect} from 'chai';21import {submitTransactionAsync} from '../substrate/substrate-api';2223describe('Fungible: Information getting', () => {24 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {25 const collection = await createCollectionExpectSuccess({26 name: 'token name',27 mode: {type: 'Fungible', decimalPoints: 0},28 });29 const alice = privateKeyWrapper('//Alice');3031 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);3233 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});3435 const address = collectionIdToAddress(collection);36 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});37 const totalSupply = await contract.methods.totalSupply().call();3839 expect(totalSupply).to.equal('200');40 });4142 itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {43 const collection = await createCollectionExpectSuccess({44 name: 'token name',45 mode: {type: 'Fungible', decimalPoints: 0},46 });47 const alice = privateKeyWrapper('//Alice');4849 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);5051 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});5253 const address = collectionIdToAddress(collection);54 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});55 const balance = await contract.methods.balanceOf(caller).call();5657 expect(balance).to.equal('200');58 });59});6061describe('Fungible: Plain calls', () => {62 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {63 const alice = privateKeyWrapper('//Alice');64 const collection = await createCollection(api, alice, {65 name: 'token name',66 mode: {type: 'Fungible', decimalPoints: 0},67 });6869 const receiver = createEthAccount(web3);7071 const collectionIdAddress = collectionIdToAddress(collection.collectionId);72 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);73 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});74 await submitTransactionAsync(alice, changeAdminTx);7576 const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});77 const result = await collectionContract.methods.mint(receiver, 100).send();78 const events = normalizeEvents(result.events);79 80 expect(events).to.be.deep.equal([81 {82 address: collectionIdAddress,83 event: 'Transfer',84 args: {85 from: '0x0000000000000000000000000000000000000000',86 to: receiver,87 value: '100',88 },89 },90 ]);91 });9293 itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {94 const alice = privateKeyWrapper('//Alice');95 const collection = await createCollection(api, alice, {96 name: 'token name',97 mode: {type: 'Fungible', decimalPoints: 0},98 });99100 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);101 const receiver1 = createEthAccount(web3);102 const receiver2 = createEthAccount(web3);103 const receiver3 = createEthAccount(web3);104105 const collectionIdAddress = collectionIdToAddress(collection.collectionId);106 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});107 await submitTransactionAsync(alice, changeAdminTx);108109 const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});110 const result = await collectionContract.methods.mintBulk([111 [receiver1, 10],112 [receiver2, 20],113 [receiver3, 30],114 ]).call();115 console.log(result);116 const events = normalizeEvents(result.events);117118 expect(events).to.be.deep.equal([119 {120 address:collectionIdAddress,121 event: 'Transfer',122 args: {123 from: '0x0000000000000000000000000000000000000000',124 to: receiver1,125 value: '10',126 },127 },128 {129 address:collectionIdAddress,130 event: 'Transfer',131 args: {132 from: '0x0000000000000000000000000000000000000000',133 to: receiver2,134 value: '20',135 },136 },137 {138 address:collectionIdAddress,139 event: 'Transfer',140 args: {141 from: '0x0000000000000000000000000000000000000000',142 to: receiver3,143 value: '30',144 },145 },146 ]);147 });148149 itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {150 const alice = privateKeyWrapper('//Alice');151 const collection = await createCollection(api, alice, {152 name: 'token name',153 mode: {type: 'Fungible', decimalPoints: 0},154 });155156 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);157 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});158 await submitTransactionAsync(alice, changeAdminTx);159 const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);160161 const collectionIdAddress = collectionIdToAddress(collection.collectionId);162 const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});163 await collectionContract.methods.mint(receiver, 100).send();164165 const result = await collectionContract.methods.burnFrom(receiver, 49).send({from: receiver});166 167 const events = normalizeEvents(result.events);168169 expect(events).to.be.deep.equal([170 {171 address: collectionIdAddress,172 event: 'Transfer',173 args: {174 from: receiver,175 to: '0x0000000000000000000000000000000000000000',176 value: '49',177 },178 },179 ]);180181 const balance = await collectionContract.methods.balanceOf(receiver).call();182 expect(balance).to.equal('51');183 });184185 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {186 const collection = await createCollectionExpectSuccess({187 name: 'token name',188 mode: {type: 'Fungible', decimalPoints: 0},189 });190 const alice = privateKeyWrapper('//Alice');191192 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);193194 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});195196 const spender = createEthAccount(web3);197198 const address = collectionIdToAddress(collection);199 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});200201 {202 const result = await contract.methods.approve(spender, 100).send({from: owner});203 const events = normalizeEvents(result.events);204205 expect(events).to.be.deep.equal([206 {207 address,208 event: 'Approval',209 args: {210 owner,211 spender,212 value: '100',213 },214 },215 ]);216 }217218 {219 const allowance = await contract.methods.allowance(owner, spender).call();220 expect(+allowance).to.equal(100);221 }222 });223224 itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {225 const collection = await createCollectionExpectSuccess({226 name: 'token name',227 mode: {type: 'Fungible', decimalPoints: 0},228 });229 const alice = privateKeyWrapper('//Alice');230231 const owner = createEthAccount(web3);232 await transferBalanceToEth(api, alice, owner);233234 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});235236 const spender = createEthAccount(web3);237 await transferBalanceToEth(api, alice, spender);238239 const receiver = createEthAccount(web3);240241 const address = collectionIdToAddress(collection);242 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});243244 await contract.methods.approve(spender, 100).send();245246 {247 const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});248 const events = normalizeEvents(result.events);249 expect(events).to.be.deep.equal([250 {251 address,252 event: 'Transfer',253 args: {254 from: owner,255 to: receiver,256 value: '49',257 },258 },259 {260 address,261 event: 'Approval',262 args: {263 owner,264 spender,265 value: '51',266 },267 },268 ]);269 }270271 {272 const balance = await contract.methods.balanceOf(receiver).call();273 expect(+balance).to.equal(49);274 }275276 {277 const balance = await contract.methods.balanceOf(owner).call();278 expect(+balance).to.equal(151);279 }280 });281282 itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {283 const collection = await createCollectionExpectSuccess({284 name: 'token name',285 mode: {type: 'Fungible', decimalPoints: 0},286 });287 const alice = privateKeyWrapper('//Alice');288289 const owner = createEthAccount(web3);290 await transferBalanceToEth(api, alice, owner);291292 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});293294 const receiver = createEthAccount(web3);295 await transferBalanceToEth(api, alice, receiver);296297 const address = collectionIdToAddress(collection);298 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});299300 {301 const result = await contract.methods.transfer(receiver, 50).send({from: owner});302 const events = normalizeEvents(result.events);303 expect(events).to.be.deep.equal([304 {305 address,306 event: 'Transfer',307 args: {308 from: owner,309 to: receiver,310 value: '50',311 },312 },313 ]);314 }315316 {317 const balance = await contract.methods.balanceOf(owner).call();318 expect(+balance).to.equal(150);319 }320321 {322 const balance = await contract.methods.balanceOf(receiver).call();323 expect(+balance).to.equal(50);324 }325 });326});327328describe('Fungible: Fees', () => {329 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {330 const collection = await createCollectionExpectSuccess({331 mode: {type: 'Fungible', decimalPoints: 0},332 });333 const alice = privateKeyWrapper('//Alice');334335 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);336 const spender = createEthAccount(web3);337338 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});339340 const address = collectionIdToAddress(collection);341 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});342343 const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));344 expect(cost < BigInt(0.2 * Number(UNIQUE)));345 });346347 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {348 const collection = await createCollectionExpectSuccess({349 mode: {type: 'Fungible', decimalPoints: 0},350 });351 const alice = privateKeyWrapper('//Alice');352353 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);354 const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);355356 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});357358 const address = collectionIdToAddress(collection);359 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});360361 await contract.methods.approve(spender, 100).send({from: owner});362363 const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));364 expect(cost < BigInt(0.2 * Number(UNIQUE)));365 });366367 itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {368 const collection = await createCollectionExpectSuccess({369 mode: {type: 'Fungible', decimalPoints: 0},370 });371 const alice = privateKeyWrapper('//Alice');372373 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);374 const receiver = createEthAccount(web3);375376 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});377378 const address = collectionIdToAddress(collection);379 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});380381 const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));382 expect(cost < BigInt(0.2 * Number(UNIQUE)));383 });384});385386describe('Fungible: Substrate calls', () => {387 itWeb3('Events emitted for approve()', async ({web3, privateKeyWrapper}) => {388 const collection = await createCollectionExpectSuccess({389 mode: {type: 'Fungible', decimalPoints: 0},390 });391 const alice = privateKeyWrapper('//Alice');392393 const receiver = createEthAccount(web3);394395 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});396397 const address = collectionIdToAddress(collection);398 const contract = new web3.eth.Contract(fungibleAbi as any, address);399400 const events = await recordEvents(contract, async () => {401 await approveExpectSuccess(collection, 0, alice, {Ethereum: receiver}, 100);402 });403404 expect(events).to.be.deep.equal([405 {406 address,407 event: 'Approval',408 args: {409 owner: subToEth(alice.address),410 spender: receiver,411 value: '100',412 },413 },414 ]);415 });416417 itWeb3('Events emitted for transferFrom()', async ({web3, privateKeyWrapper}) => {418 const collection = await createCollectionExpectSuccess({419 mode: {type: 'Fungible', decimalPoints: 0},420 });421 const alice = privateKeyWrapper('//Alice');422 const bob = privateKeyWrapper('//Bob');423424 const receiver = createEthAccount(web3);425426 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});427 await approveExpectSuccess(collection, 0, alice, bob.address, 100);428429 const address = collectionIdToAddress(collection);430 const contract = new web3.eth.Contract(fungibleAbi as any, address);431432 const events = await recordEvents(contract, async () => {433 await transferFromExpectSuccess(collection, 0, bob, alice, {Ethereum: receiver}, 51, 'Fungible');434 });435436 expect(events).to.be.deep.equal([437 {438 address,439 event: 'Transfer',440 args: {441 from: subToEth(alice.address),442 to: receiver,443 value: '51',444 },445 },446 {447 address,448 event: 'Approval',449 args: {450 owner: subToEth(alice.address),451 spender: subToEth(bob.address),452 value: '49',453 },454 },455 ]);456 });457458 itWeb3('Events emitted for transfer()', async ({web3, privateKeyWrapper}) => {459 const collection = await createCollectionExpectSuccess({460 mode: {type: 'Fungible', decimalPoints: 0},461 });462 const alice = privateKeyWrapper('//Alice');463464 const receiver = createEthAccount(web3);465466 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});467468 const address = collectionIdToAddress(collection);469 const contract = new web3.eth.Contract(fungibleAbi as any, address);470471 const events = await recordEvents(contract, async () => {472 await transferExpectSuccess(collection, 0, alice, {Ethereum:receiver}, 51, 'Fungible');473 });474475 expect(events).to.be.deep.equal([476 {477 address,478 event: 'Transfer',479 args: {480 from: subToEth(alice.address),481 to: receiver,482 value: '51',483 },484 },485 ]);486 });487});