123456import privateKey from '../substrate/privateKey';7import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE, setMetadataUpdatePermissionFlagExpectSuccess} from '../util/helpers';8import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';9import nonFungibleAbi from './nonFungibleAbi.json';10import {expect} from 'chai';11import {submitTransactionAsync} from '../substrate/substrate-api';1213describe('NFT: Information getting', () => {14 itWeb3('totalSupply', async ({api, web3}) => {15 const collection = await createCollectionExpectSuccess({16 mode: {type: 'NFT'},17 });18 const alice = privateKey('//Alice');19 const caller = await createEthAccountWithBalance(api, web3);2021 await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});2223 const address = collectionIdToAddress(collection);24 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});25 const totalSupply = await contract.methods.totalSupply().call();2627 expect(totalSupply).to.equal('1');28 });2930 itWeb3('balanceOf', async ({api, web3}) => {31 const collection = await createCollectionExpectSuccess({32 mode: {type: 'NFT'},33 });34 const alice = privateKey('//Alice');3536 const caller = await createEthAccountWithBalance(api, web3);37 await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum:caller});38 await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});39 await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});4041 const address = collectionIdToAddress(collection);42 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});43 const balance = await contract.methods.balanceOf(caller).call();4445 expect(balance).to.equal('3');46 });4748 itWeb3('ownerOf', async ({api, web3}) => {49 const collection = await createCollectionExpectSuccess({50 mode: {type: 'NFT'},51 });52 const alice = privateKey('//Alice');5354 const caller = await createEthAccountWithBalance(api, web3);55 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});5657 const address = collectionIdToAddress(collection);58 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});59 const owner = await contract.methods.ownerOf(tokenId).call();6061 expect(owner).to.equal(caller);62 });63});6465describe('NFT: Plain calls', () => {66 itWeb3('Can perform mint()', async ({web3, api}) => {67 const collection = await createCollectionExpectSuccess({68 mode: {type: 'NFT'},69 });70 const alice = privateKey('//Alice');7172 const caller = await createEthAccountWithBalance(api, web3);73 const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: caller});74 await submitTransactionAsync(alice, changeAdminTx);75 const receiver = createEthAccount(web3);7677 const address = collectionIdToAddress(collection);78 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});7980 {81 const nextTokenId = await contract.methods.nextTokenId().call();82 expect(nextTokenId).to.be.equal('1');83 const result = await contract.methods.mintWithTokenURI(84 receiver,85 nextTokenId,86 'Test URI',87 ).send({from: caller});88 const events = normalizeEvents(result.events);8990 expect(events).to.be.deep.equal([91 {92 address,93 event: 'Transfer',94 args: {95 from: '0x0000000000000000000000000000000000000000',96 to: receiver,97 tokenId: nextTokenId,98 },99 },100 ]);101102 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');103 }104 });105 itWeb3('Can perform mintBulk()', async ({web3, api}) => {106 const collection = await createCollectionExpectSuccess({107 mode: {type: 'NFT'},108 });109 const alice = privateKey('//Alice');110111 const caller = await createEthAccountWithBalance(api, web3);112 const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, {Ethereum: caller});113 await submitTransactionAsync(alice, changeAdminTx);114 const receiver = createEthAccount(web3);115116 const address = collectionIdToAddress(collection);117 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});118119 {120 const nextTokenId = await contract.methods.nextTokenId().call();121 expect(nextTokenId).to.be.equal('1');122 const result = await contract.methods.mintBulkWithTokenURI(123 receiver,124 [125 [nextTokenId, 'Test URI 0'],126 [+nextTokenId + 1, 'Test URI 1'],127 [+nextTokenId + 2, 'Test URI 2'],128 ],129 ).send({from: caller});130 const events = normalizeEvents(result.events);131132 expect(events).to.be.deep.equal([133 {134 address,135 event: 'Transfer',136 args: {137 from: '0x0000000000000000000000000000000000000000',138 to: receiver,139 tokenId: nextTokenId,140 },141 },142 {143 address,144 event: 'Transfer',145 args: {146 from: '0x0000000000000000000000000000000000000000',147 to: receiver,148 tokenId: String(+nextTokenId + 1),149 },150 },151 {152 address,153 event: 'Transfer',154 args: {155 from: '0x0000000000000000000000000000000000000000',156 to: receiver,157 tokenId: String(+nextTokenId + 2),158 },159 },160 ]);161162 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');163 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');164 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');165 }166 });167168 itWeb3('Can perform burn()', async ({web3, api}) => {169 const collection = await createCollectionExpectSuccess({170 mode: {type: 'NFT'},171 });172 const alice = privateKey('//Alice');173174 const owner = await createEthAccountWithBalance(api, web3);175176 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});177178 const address = collectionIdToAddress(collection);179 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});180181 {182 const result = await contract.methods.burn(tokenId).send({from: owner});183 const events = normalizeEvents(result.events);184185 expect(events).to.be.deep.equal([186 {187 address,188 event: 'Transfer',189 args: {190 from: owner,191 to: '0x0000000000000000000000000000000000000000',192 tokenId: tokenId.toString(),193 },194 },195 ]);196 }197 });198199 itWeb3('Can perform approve()', async ({web3, api}) => {200 const collection = await createCollectionExpectSuccess({201 mode: {type: 'NFT'},202 });203 const alice = privateKey('//Alice');204205 const owner = createEthAccount(web3);206 await transferBalanceToEth(api, alice, owner, 999999999999999);207208 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});209210 const spender = createEthAccount(web3);211212 const address = collectionIdToAddress(collection);213 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);214215 {216 const result = await contract.methods.approve(spender, tokenId).send({from: owner, gas: '0x1000000', gasPrice: '0x01'});217 const events = normalizeEvents(result.events);218219 expect(events).to.be.deep.equal([220 {221 address,222 event: 'Approval',223 args: {224 owner,225 approved: spender,226 tokenId: tokenId.toString(),227 },228 },229 ]);230 }231 });232233 itWeb3('Can perform transferFrom()', async ({web3, api}) => {234 const collection = await createCollectionExpectSuccess({235 mode: {type: 'NFT'},236 });237 const alice = privateKey('//Alice');238239 const owner = createEthAccount(web3);240 await transferBalanceToEth(api, alice, owner, 999999999999999);241242 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});243244 const spender = createEthAccount(web3);245 await transferBalanceToEth(api, alice, spender, 999999999999999);246247 const receiver = createEthAccount(web3);248249 const address = collectionIdToAddress(collection);250 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});251252 await contract.methods.approve(spender, tokenId).send({from: owner});253254 {255 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: spender});256 const events = normalizeEvents(result.events);257 expect(events).to.be.deep.equal([258 {259 address,260 event: 'Transfer',261 args: {262 from: owner,263 to: receiver,264 tokenId: tokenId.toString(),265 },266 },267 ]);268 }269270 {271 const balance = await contract.methods.balanceOf(receiver).call();272 expect(+balance).to.equal(1);273 }274275 {276 const balance = await contract.methods.balanceOf(owner).call();277 expect(+balance).to.equal(0);278 }279 });280281 itWeb3('Can perform transfer()', async ({web3, api}) => {282 const collection = await createCollectionExpectSuccess({283 mode: {type: 'NFT'},284 });285 const alice = privateKey('//Alice');286287 const owner = createEthAccount(web3);288 await transferBalanceToEth(api, alice, owner, 999999999999999);289290 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});291292 const receiver = createEthAccount(web3);293 await transferBalanceToEth(api, alice, receiver, 999999999999999);294295 const address = collectionIdToAddress(collection);296 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});297298 {299 const result = await contract.methods.transfer(receiver, tokenId).send({from: owner});300 const events = normalizeEvents(result.events);301 expect(events).to.be.deep.equal([302 {303 address,304 event: 'Transfer',305 args: {306 from: owner,307 to: receiver,308 tokenId: tokenId.toString(),309 },310 },311 ]);312 }313314 {315 const balance = await contract.methods.balanceOf(owner).call();316 expect(+balance).to.equal(0);317 }318319 {320 const balance = await contract.methods.balanceOf(receiver).call();321 expect(+balance).to.equal(1);322 }323 });324325 itWeb3('Can perform getVariableMetadata', async ({web3, api}) => {326 const collection = await createCollectionExpectSuccess({327 mode: {type: 'NFT'},328 });329 const alice = privateKey('//Alice');330331 const owner = await createEthAccountWithBalance(api, web3);332333 const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});334 await setMetadataUpdatePermissionFlagExpectSuccess(alice, collection, 'Admin');335 await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);336337 const address = collectionIdToAddress(collection);338 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});339340 expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');341 });342343 itWeb3('Can perform setVariableMetadata', async ({web3, api}) => {344 const collection = await createCollectionExpectSuccess({345 mode: {type: 'NFT'},346 });347 const alice = privateKey('//Alice');348349 const owner = await createEthAccountWithBalance(api, web3);350351 const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});352353 const address = collectionIdToAddress(collection);354 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});355356 expect(await contract.methods.setVariableMetadata(item, '0x010203').send({from: owner}));357 expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');358 });359});360361describe('NFT: Fees', () => {362 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api}) => {363 const collection = await createCollectionExpectSuccess({364 mode: {type: 'NFT'},365 });366 const alice = privateKey('//Alice');367368 const owner = await createEthAccountWithBalance(api, web3);369 const spender = createEthAccount(web3);370371 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});372373 const address = collectionIdToAddress(collection);374 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});375376 const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, tokenId).send({from: owner}));377 expect(cost < BigInt(0.2 * Number(UNIQUE)));378 });379380 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api}) => {381 const collection = await createCollectionExpectSuccess({382 mode: {type: 'NFT'},383 });384 const alice = privateKey('//Alice');385386 const owner = await createEthAccountWithBalance(api, web3);387 const spender = await createEthAccountWithBalance(api, web3);388389 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});390391 const address = collectionIdToAddress(collection);392 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});393394 await contract.methods.approve(spender, tokenId).send({from: owner});395396 const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({from: spender}));397 expect(cost < BigInt(0.2 * Number(UNIQUE)));398 });399400 itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api}) => {401 const collection = await createCollectionExpectSuccess({402 mode: {type: 'NFT'},403 });404 const alice = privateKey('//Alice');405406 const owner = await createEthAccountWithBalance(api, web3);407 const receiver = createEthAccount(web3);408409 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});410411 const address = collectionIdToAddress(collection);412 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});413414 const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner}));415 expect(cost < BigInt(0.2 * Number(UNIQUE)));416 });417});418419describe('NFT: Substrate calls', () => {420 itWeb3('Events emitted for mint()', async ({web3}) => {421 const collection = await createCollectionExpectSuccess({422 mode: {type: 'NFT'},423 });424 const alice = privateKey('//Alice');425426 const address = collectionIdToAddress(collection);427 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);428429 let tokenId: number;430 const events = await recordEvents(contract, async () => {431 tokenId = await createItemExpectSuccess(alice, collection, 'NFT');432 });433434 expect(events).to.be.deep.equal([435 {436 address,437 event: 'Transfer',438 args: {439 from: '0x0000000000000000000000000000000000000000',440 to: subToEth(alice.address),441 tokenId: tokenId!.toString(),442 },443 },444 ]);445 });446447 itWeb3('Events emitted for burn()', async ({web3}) => {448 const collection = await createCollectionExpectSuccess({449 mode: {type: 'NFT'},450 });451 const alice = privateKey('//Alice');452453 const address = collectionIdToAddress(collection);454 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);455456 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');457 const events = await recordEvents(contract, async () => {458 await burnItemExpectSuccess(alice, collection, tokenId);459 });460461 expect(events).to.be.deep.equal([462 {463 address,464 event: 'Transfer',465 args: {466 from: subToEth(alice.address),467 to: '0x0000000000000000000000000000000000000000',468 tokenId: tokenId.toString(),469 },470 },471 ]);472 });473474 itWeb3('Events emitted for approve()', async ({web3}) => {475 const collection = await createCollectionExpectSuccess({476 mode: {type: 'NFT'},477 });478 const alice = privateKey('//Alice');479480 const receiver = createEthAccount(web3);481482 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');483484 const address = collectionIdToAddress(collection);485 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);486487 const events = await recordEvents(contract, async () => {488 await approveExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1);489 });490491 expect(events).to.be.deep.equal([492 {493 address,494 event: 'Approval',495 args: {496 owner: subToEth(alice.address),497 approved: receiver,498 tokenId: tokenId.toString(),499 },500 },501 ]);502 });503504 itWeb3('Events emitted for transferFrom()', async ({web3}) => {505 const collection = await createCollectionExpectSuccess({506 mode: {type: 'NFT'},507 });508 const alice = privateKey('//Alice');509 const bob = privateKey('//Bob');510511 const receiver = createEthAccount(web3);512513 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');514 await approveExpectSuccess(collection, tokenId, alice, bob.address, 1);515516 const address = collectionIdToAddress(collection);517 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);518519 const events = await recordEvents(contract, async () => {520 await transferFromExpectSuccess(collection, tokenId, bob, alice, {Ethereum: receiver}, 1, 'NFT');521 });522523 expect(events).to.be.deep.equal([524 {525 address,526 event: 'Transfer',527 args: {528 from: subToEth(alice.address),529 to: receiver,530 tokenId: tokenId.toString(),531 },532 },533 ]);534 });535536 itWeb3('Events emitted for transfer()', async ({web3}) => {537 const collection = await createCollectionExpectSuccess({538 mode: {type: 'NFT'},539 });540 const alice = privateKey('//Alice');541542 const receiver = createEthAccount(web3);543544 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');545546 const address = collectionIdToAddress(collection);547 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);548549 const events = await recordEvents(contract, async () => {550 await transferExpectSuccess(collection, tokenId, alice, {Ethereum: receiver}, 1, 'NFT');551 });552553 expect(events).to.be.deep.equal([554 {555 address,556 event: 'Transfer',557 args: {558 from: subToEth(alice.address),559 to: receiver,560 tokenId: tokenId.toString(),561 },562 },563 ]);564 });565});