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 ]).send();115 const events = normalizeEvents(result.events);116117 expect(events).to.be.deep.contain({118 address:collectionIdAddress,119 event: 'Transfer',120 args: {121 from: '0x0000000000000000000000000000000000000000',122 to: receiver1,123 value: '10',124 },125 });126 127 expect(events).to.be.deep.contain({128 address:collectionIdAddress,129 event: 'Transfer',130 args: {131 from: '0x0000000000000000000000000000000000000000',132 to: receiver2,133 value: '20',134 },135 });136 137 expect(events).to.be.deep.contain({138 address:collectionIdAddress,139 event: 'Transfer',140 args: {141 from: '0x0000000000000000000000000000000000000000',142 to: receiver3,143 value: '30',144 },145 });146 });147148 itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {149 const alice = privateKeyWrapper('//Alice');150 const collection = await createCollection(api, alice, {151 name: 'token name',152 mode: {type: 'Fungible', decimalPoints: 0},153 });154155 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);156 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection.collectionId, {Ethereum: owner});157 await submitTransactionAsync(alice, changeAdminTx);158 const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);159160 const collectionIdAddress = collectionIdToAddress(collection.collectionId);161 const collectionContract = evmCollection(web3, owner, collectionIdAddress, {type: 'Fungible', decimalPoints: 0});162 await collectionContract.methods.mint(receiver, 100).send();163164 const result = await collectionContract.methods.burnFrom(receiver, 49).send({from: receiver});165 166 const events = normalizeEvents(result.events);167168 expect(events).to.be.deep.equal([169 {170 address: collectionIdAddress,171 event: 'Transfer',172 args: {173 from: receiver,174 to: '0x0000000000000000000000000000000000000000',175 value: '49',176 },177 },178 ]);179180 const balance = await collectionContract.methods.balanceOf(receiver).call();181 expect(balance).to.equal('51');182 });183184 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {185 const collection = await createCollectionExpectSuccess({186 name: 'token name',187 mode: {type: 'Fungible', decimalPoints: 0},188 });189 const alice = privateKeyWrapper('//Alice');190191 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);192193 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});194195 const spender = createEthAccount(web3);196197 const address = collectionIdToAddress(collection);198 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});199200 {201 const result = await contract.methods.approve(spender, 100).send({from: owner});202 const events = normalizeEvents(result.events);203204 expect(events).to.be.deep.equal([205 {206 address,207 event: 'Approval',208 args: {209 owner,210 spender,211 value: '100',212 },213 },214 ]);215 }216217 {218 const allowance = await contract.methods.allowance(owner, spender).call();219 expect(+allowance).to.equal(100);220 }221 });222223 itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {224 const collection = await createCollectionExpectSuccess({225 name: 'token name',226 mode: {type: 'Fungible', decimalPoints: 0},227 });228 const alice = privateKeyWrapper('//Alice');229230 const owner = createEthAccount(web3);231 await transferBalanceToEth(api, alice, owner);232233 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});234235 const spender = createEthAccount(web3);236 await transferBalanceToEth(api, alice, spender);237238 const receiver = createEthAccount(web3);239240 const address = collectionIdToAddress(collection);241 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});242243 await contract.methods.approve(spender, 100).send();244245 {246 const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});247 const events = normalizeEvents(result.events);248 expect(events).to.be.deep.equal([249 {250 address,251 event: 'Transfer',252 args: {253 from: owner,254 to: receiver,255 value: '49',256 },257 },258 {259 address,260 event: 'Approval',261 args: {262 owner,263 spender,264 value: '51',265 },266 },267 ]);268 }269270 {271 const balance = await contract.methods.balanceOf(receiver).call();272 expect(+balance).to.equal(49);273 }274275 {276 const balance = await contract.methods.balanceOf(owner).call();277 expect(+balance).to.equal(151);278 }279 });280281 itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {282 const collection = await createCollectionExpectSuccess({283 name: 'token name',284 mode: {type: 'Fungible', decimalPoints: 0},285 });286 const alice = privateKeyWrapper('//Alice');287288 const owner = createEthAccount(web3);289 await transferBalanceToEth(api, alice, owner);290291 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});292293 const receiver = createEthAccount(web3);294 await transferBalanceToEth(api, alice, receiver);295296 const address = collectionIdToAddress(collection);297 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});298299 {300 const result = await contract.methods.transfer(receiver, 50).send({from: owner});301 const events = normalizeEvents(result.events);302 expect(events).to.be.deep.equal([303 {304 address,305 event: 'Transfer',306 args: {307 from: owner,308 to: receiver,309 value: '50',310 },311 },312 ]);313 }314315 {316 const balance = await contract.methods.balanceOf(owner).call();317 expect(+balance).to.equal(150);318 }319320 {321 const balance = await contract.methods.balanceOf(receiver).call();322 expect(+balance).to.equal(50);323 }324 });325});326327describe('Fungible: Fees', () => {328 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {329 const collection = await createCollectionExpectSuccess({330 mode: {type: 'Fungible', decimalPoints: 0},331 });332 const alice = privateKeyWrapper('//Alice');333334 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);335 const spender = createEthAccount(web3);336337 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});338339 const address = collectionIdToAddress(collection);340 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});341342 const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));343 expect(cost < BigInt(0.2 * Number(UNIQUE)));344 });345346 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {347 const collection = await createCollectionExpectSuccess({348 mode: {type: 'Fungible', decimalPoints: 0},349 });350 const alice = privateKeyWrapper('//Alice');351352 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);353 const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);354355 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});356357 const address = collectionIdToAddress(collection);358 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});359360 await contract.methods.approve(spender, 100).send({from: owner});361362 const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));363 expect(cost < BigInt(0.2 * Number(UNIQUE)));364 });365366 itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {367 const collection = await createCollectionExpectSuccess({368 mode: {type: 'Fungible', decimalPoints: 0},369 });370 const alice = privateKeyWrapper('//Alice');371372 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);373 const receiver = createEthAccount(web3);374375 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});376377 const address = collectionIdToAddress(collection);378 const contract = new web3.eth.Contract(fungibleAbi as any, address, {from: owner, ...GAS_ARGS});379380 const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));381 expect(cost < BigInt(0.2 * Number(UNIQUE)));382 });383});384385describe('Fungible: Substrate calls', () => {386 itWeb3('Events emitted for approve()', async ({web3, privateKeyWrapper}) => {387 const collection = await createCollectionExpectSuccess({388 mode: {type: 'Fungible', decimalPoints: 0},389 });390 const alice = privateKeyWrapper('//Alice');391392 const receiver = createEthAccount(web3);393394 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});395396 const address = collectionIdToAddress(collection);397 const contract = new web3.eth.Contract(fungibleAbi as any, address);398399 const events = await recordEvents(contract, async () => {400 await approveExpectSuccess(collection, 0, alice, {Ethereum: receiver}, 100);401 });402403 expect(events).to.be.deep.equal([404 {405 address,406 event: 'Approval',407 args: {408 owner: subToEth(alice.address),409 spender: receiver,410 value: '100',411 },412 },413 ]);414 });415416 itWeb3('Events emitted for transferFrom()', async ({web3, privateKeyWrapper}) => {417 const collection = await createCollectionExpectSuccess({418 mode: {type: 'Fungible', decimalPoints: 0},419 });420 const alice = privateKeyWrapper('//Alice');421 const bob = privateKeyWrapper('//Bob');422423 const receiver = createEthAccount(web3);424425 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});426 await approveExpectSuccess(collection, 0, alice, bob.address, 100);427428 const address = collectionIdToAddress(collection);429 const contract = new web3.eth.Contract(fungibleAbi as any, address);430431 const events = await recordEvents(contract, async () => {432 await transferFromExpectSuccess(collection, 0, bob, alice, {Ethereum: receiver}, 51, 'Fungible');433 });434435 expect(events).to.be.deep.equal([436 {437 address,438 event: 'Transfer',439 args: {440 from: subToEth(alice.address),441 to: receiver,442 value: '51',443 },444 },445 {446 address,447 event: 'Approval',448 args: {449 owner: subToEth(alice.address),450 spender: subToEth(bob.address),451 value: '49',452 },453 },454 ]);455 });456457 itWeb3('Events emitted for transfer()', async ({web3, privateKeyWrapper}) => {458 const collection = await createCollectionExpectSuccess({459 mode: {type: 'Fungible', decimalPoints: 0},460 });461 const alice = privateKeyWrapper('//Alice');462463 const receiver = createEthAccount(web3);464465 await createFungibleItemExpectSuccess(alice, collection, {Value: 200n});466467 const address = collectionIdToAddress(collection);468 const contract = new web3.eth.Contract(fungibleAbi as any, address);469470 const events = await recordEvents(contract, async () => {471 await transferExpectSuccess(collection, 0, alice, {Ethereum:receiver}, 51, 'Fungible');472 });473474 expect(events).to.be.deep.equal([475 {476 address,477 event: 'Transfer',478 args: {479 from: subToEth(alice.address),480 to: receiver,481 value: '51',482 },483 },484 ]);485 });486});