1234567891011121314151617import privateKey from '../substrate/privateKey';18import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE, setMetadataUpdatePermissionFlagExpectSuccess} from '../util/helpers';19import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';20import nonFungibleAbi from './nonFungibleAbi.json';21import {expect} from 'chai';22import {submitTransactionAsync} from '../substrate/substrate-api';2324describe('NFT: Information getting', () => {25 itWeb3('totalSupply', async ({api, web3}) => {26 const collection = await createCollectionExpectSuccess({27 mode: {type: 'NFT'},28 });29 const alice = privateKey('//Alice');30 const caller = await createEthAccountWithBalance(api, web3);3132 await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});3334 const address = collectionIdToAddress(collection);35 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});36 const totalSupply = await contract.methods.totalSupply().call();3738 expect(totalSupply).to.equal('1');39 });4041 itWeb3('balanceOf', async ({api, web3}) => {42 const collection = await createCollectionExpectSuccess({43 mode: {type: 'NFT'},44 });45 const alice = privateKey('//Alice');4647 const caller = await createEthAccountWithBalance(api, web3);48 await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum:caller});49 await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});50 await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});5152 const address = collectionIdToAddress(collection);53 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});54 const balance = await contract.methods.balanceOf(caller).call();5556 expect(balance).to.equal('3');57 });5859 itWeb3('ownerOf', async ({api, web3}) => {60 const collection = await createCollectionExpectSuccess({61 mode: {type: 'NFT'},62 });63 const alice = privateKey('//Alice');6465 const caller = await createEthAccountWithBalance(api, web3);66 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});6768 const address = collectionIdToAddress(collection);69 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});70 const owner = await contract.methods.ownerOf(tokenId).call();7172 expect(owner).to.equal(caller);73 });74});7576describe('NFT: Plain calls', () => {77 itWeb3('Can perform mint()', async ({web3, api}) => {78 const collection = await createCollectionExpectSuccess({79 mode: {type: 'NFT'},80 });81 const alice = privateKey('//Alice');8283 const caller = await createEthAccountWithBalance(api, web3);84 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});85 await submitTransactionAsync(alice, changeAdminTx);86 const receiver = createEthAccount(web3);8788 const address = collectionIdToAddress(collection);89 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});9091 {92 const nextTokenId = await contract.methods.nextTokenId().call();93 expect(nextTokenId).to.be.equal('1');94 const result = await contract.methods.mintWithTokenURI(95 receiver,96 nextTokenId,97 'Test URI',98 ).send({from: caller});99 const events = normalizeEvents(result.events);100101 expect(events).to.be.deep.equal([102 {103 address,104 event: 'Transfer',105 args: {106 from: '0x0000000000000000000000000000000000000000',107 to: receiver,108 tokenId: nextTokenId,109 },110 },111 ]);112113 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');114 }115 });116 itWeb3('Can perform mintBulk()', async ({web3, api}) => {117 const collection = await createCollectionExpectSuccess({118 mode: {type: 'NFT'},119 });120 const alice = privateKey('//Alice');121122 const caller = await createEthAccountWithBalance(api, web3);123 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});124 await submitTransactionAsync(alice, changeAdminTx);125 const receiver = createEthAccount(web3);126127 const address = collectionIdToAddress(collection);128 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});129130 {131 const nextTokenId = await contract.methods.nextTokenId().call();132 expect(nextTokenId).to.be.equal('1');133 const result = await contract.methods.mintBulkWithTokenURI(134 receiver,135 [136 [nextTokenId, 'Test URI 0'],137 [+nextTokenId + 1, 'Test URI 1'],138 [+nextTokenId + 2, 'Test URI 2'],139 ],140 ).send({from: caller});141 const events = normalizeEvents(result.events);142143 expect(events).to.be.deep.equal([144 {145 address,146 event: 'Transfer',147 args: {148 from: '0x0000000000000000000000000000000000000000',149 to: receiver,150 tokenId: nextTokenId,151 },152 },153 {154 address,155 event: 'Transfer',156 args: {157 from: '0x0000000000000000000000000000000000000000',158 to: receiver,159 tokenId: String(+nextTokenId + 1),160 },161 },162 {163 address,164 event: 'Transfer',165 args: {166 from: '0x0000000000000000000000000000000000000000',167 to: receiver,168 tokenId: String(+nextTokenId + 2),169 },170 },171 ]);172173 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');174 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');175 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');176 }177 });178179 itWeb3('Can perform burn()', async ({web3, api}) => {180 const collection = await createCollectionExpectSuccess({181 mode: {type: 'NFT'},182 });183 const alice = privateKey('//Alice');184185 const owner = await createEthAccountWithBalance(api, web3);186187 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});188189 const address = collectionIdToAddress(collection);190 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});191192 {193 const result = await contract.methods.burn(tokenId).send({from: owner});194 const events = normalizeEvents(result.events);195196 expect(events).to.be.deep.equal([197 {198 address,199 event: 'Transfer',200 args: {201 from: owner,202 to: '0x0000000000000000000000000000000000000000',203 tokenId: tokenId.toString(),204 },205 },206 ]);207 }208 });209210 itWeb3('Can perform approve()', async ({web3, api}) => {211 const collection = await createCollectionExpectSuccess({212 mode: {type: 'NFT'},213 });214 const alice = privateKey('//Alice');215216 const owner = createEthAccount(web3);217 await transferBalanceToEth(api, alice, owner);218219 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});220221 const spender = createEthAccount(web3);222223 const address = collectionIdToAddress(collection);224 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);225226 {227 const result = await contract.methods.approve(spender, tokenId).send({from: owner, ...GAS_ARGS});228 const events = normalizeEvents(result.events);229230 expect(events).to.be.deep.equal([231 {232 address,233 event: 'Approval',234 args: {235 owner,236 approved: spender,237 tokenId: tokenId.toString(),238 },239 },240 ]);241 }242 });243244 itWeb3('Can perform transferFrom()', async ({web3, api}) => {245 const collection = await createCollectionExpectSuccess({246 mode: {type: 'NFT'},247 });248 const alice = privateKey('//Alice');249250 const owner = createEthAccount(web3);251 await transferBalanceToEth(api, alice, owner);252253 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});254255 const spender = createEthAccount(web3);256 await transferBalanceToEth(api, alice, spender);257258 const receiver = createEthAccount(web3);259260 const address = collectionIdToAddress(collection);261 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});262263 await contract.methods.approve(spender, tokenId).send({from: owner});264265 {266 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: spender});267 const events = normalizeEvents(result.events);268 expect(events).to.be.deep.equal([269 {270 address,271 event: 'Transfer',272 args: {273 from: owner,274 to: receiver,275 tokenId: tokenId.toString(),276 },277 },278 ]);279 }280281 {282 const balance = await contract.methods.balanceOf(receiver).call();283 expect(+balance).to.equal(1);284 }285286 {287 const balance = await contract.methods.balanceOf(owner).call();288 expect(+balance).to.equal(0);289 }290 });291292 itWeb3('Can perform transfer()', async ({web3, api}) => {293 const collection = await createCollectionExpectSuccess({294 mode: {type: 'NFT'},295 });296 const alice = privateKey('//Alice');297298 const owner = createEthAccount(web3);299 await transferBalanceToEth(api, alice, owner);300301 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});302303 const receiver = createEthAccount(web3);304 await transferBalanceToEth(api, alice, receiver);305306 const address = collectionIdToAddress(collection);307 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});308309 {310 const result = await contract.methods.transfer(receiver, tokenId).send({from: owner});311 const events = normalizeEvents(result.events);312 expect(events).to.be.deep.equal([313 {314 address,315 event: 'Transfer',316 args: {317 from: owner,318 to: receiver,319 tokenId: tokenId.toString(),320 },321 },322 ]);323 }324325 {326 const balance = await contract.methods.balanceOf(owner).call();327 expect(+balance).to.equal(0);328 }329330 {331 const balance = await contract.methods.balanceOf(receiver).call();332 expect(+balance).to.equal(1);333 }334 });335336 itWeb3('Can perform getVariableMetadata', async ({web3, api}) => {337 const collection = await createCollectionExpectSuccess({338 mode: {type: 'NFT'},339 });340 const alice = privateKey('//Alice');341342 const owner = await createEthAccountWithBalance(api, web3);343344 const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});345 await setMetadataUpdatePermissionFlagExpectSuccess(alice, collection, 'Admin');346 await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);347348 const address = collectionIdToAddress(collection);349 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});350351 expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');352 });353354 itWeb3('Can perform setVariableMetadata', async ({web3, api}) => {355 const collection = await createCollectionExpectSuccess({356 mode: {type: 'NFT'},357 });358 const alice = privateKey('//Alice');359360 const owner = await createEthAccountWithBalance(api, web3);361362 const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});363364 const address = collectionIdToAddress(collection);365 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});366367 expect(await contract.methods.setVariableMetadata(item, '0x010203').send({from: owner}));368 expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');369 });370});371372describe('NFT: Fees', () => {373 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api}) => {374 const collection = await createCollectionExpectSuccess({375 mode: {type: 'NFT'},376 });377 const alice = privateKey('//Alice');378379 const owner = await createEthAccountWithBalance(api, web3);380 const spender = createEthAccount(web3);381382 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});383384 const address = collectionIdToAddress(collection);385 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});386387 const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, tokenId).send({from: owner}));388 expect(cost < BigInt(0.2 * Number(UNIQUE)));389 });390391 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api}) => {392 const collection = await createCollectionExpectSuccess({393 mode: {type: 'NFT'},394 });395 const alice = privateKey('//Alice');396397 const owner = await createEthAccountWithBalance(api, web3);398 const spender = await createEthAccountWithBalance(api, web3);399400 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});401402 const address = collectionIdToAddress(collection);403 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});404405 await contract.methods.approve(spender, tokenId).send({from: owner});406407 const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender}));408 expect(cost < BigInt(0.2 * Number(UNIQUE)));409 });410411 itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api}) => {412 const collection = await createCollectionExpectSuccess({413 mode: {type: 'NFT'},414 });415 const alice = privateKey('//Alice');416417 const owner = await createEthAccountWithBalance(api, web3);418 const receiver = createEthAccount(web3);419420 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});421422 const address = collectionIdToAddress(collection);423 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});424425 const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner}));426 expect(cost < BigInt(0.2 * Number(UNIQUE)));427 });428});429430describe('NFT: Substrate calls', () => {431 itWeb3('Events emitted for mint()', async ({web3}) => {432 const collection = await createCollectionExpectSuccess({433 mode: {type: 'NFT'},434 });435 const alice = privateKey('//Alice');436437 const address = collectionIdToAddress(collection);438 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);439440 let tokenId: number;441 const events = await recordEvents(contract, async () => {442 tokenId = await createItemExpectSuccess(alice, collection, 'NFT');443 });444445 expect(events).to.be.deep.equal([446 {447 address,448 event: 'Transfer',449 args: {450 from: '0x0000000000000000000000000000000000000000',451 to: subToEth(alice.address),452 tokenId: tokenId!.toString(),453 },454 },455 ]);456 });457458 itWeb3('Events emitted for burn()', async ({web3}) => {459 const collection = await createCollectionExpectSuccess({460 mode: {type: 'NFT'},461 });462 const alice = privateKey('//Alice');463464 const address = collectionIdToAddress(collection);465 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);466467 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');468 const events = await recordEvents(contract, async () => {469 await burnItemExpectSuccess(alice, collection, tokenId);470 });471472 expect(events).to.be.deep.equal([473 {474 address,475 event: 'Transfer',476 args: {477 from: subToEth(alice.address),478 to: '0x0000000000000000000000000000000000000000',479 tokenId: tokenId.toString(),480 },481 },482 ]);483 });484485 itWeb3('Events emitted for approve()', async ({web3}) => {486 const collection = await createCollectionExpectSuccess({487 mode: {type: 'NFT'},488 });489 const alice = privateKey('//Alice');490491 const receiver = createEthAccount(web3);492493 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');494495 const address = collectionIdToAddress(collection);496 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);497498 const events = await recordEvents(contract, async () => {499 await approveExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1);500 });501502 expect(events).to.be.deep.equal([503 {504 address,505 event: 'Approval',506 args: {507 owner: subToEth(alice.address),508 approved: receiver,509 tokenId: tokenId.toString(),510 },511 },512 ]);513 });514515 itWeb3('Events emitted for transferFrom()', async ({web3}) => {516 const collection = await createCollectionExpectSuccess({517 mode: {type: 'NFT'},518 });519 const alice = privateKey('//Alice');520 const bob = privateKey('//Bob');521522 const receiver = createEthAccount(web3);523524 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');525 await approveExpectSuccess(collection, tokenId, alice, bob.address, 1);526527 const address = collectionIdToAddress(collection);528 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);529530 const events = await recordEvents(contract, async () => {531 await transferFromExpectSuccess(collection, tokenId, bob, alice, {Ethereum: receiver}, 1, 'NFT');532 });533534 expect(events).to.be.deep.equal([535 {536 address,537 event: 'Transfer',538 args: {539 from: subToEth(alice.address),540 to: receiver,541 tokenId: tokenId.toString(),542 },543 },544 ]);545 });546547 itWeb3('Events emitted for transfer()', async ({web3}) => {548 const collection = await createCollectionExpectSuccess({549 mode: {type: 'NFT'},550 });551 const alice = privateKey('//Alice');552553 const receiver = createEthAccount(web3);554555 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');556557 const address = collectionIdToAddress(collection);558 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);559560 const events = await recordEvents(contract, async () => {561 await transferExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1, 'NFT');562 });563564 expect(events).to.be.deep.equal([565 {566 address,567 event: 'Transfer',568 args: {569 from: subToEth(alice.address),570 to: receiver,571 tokenId: tokenId.toString(),572 },573 },574 ]);575 });576});