123456import privateKey from '../substrate/privateKey';7import { approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE } 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 waitNewBlocks from '../substrate/wait-new-blocks';12import { submitTransactionAsync } from '../substrate/substrate-api';1314describe('NFT: Information getting', () => {15 itWeb3('totalSupply', async ({ api, web3 }) => {16 const collection = await createCollectionExpectSuccess({17 mode: { type: 'NFT' },18 });19 const alice = privateKey('//Alice');20 const caller = await createEthAccountWithBalance(api, web3);2122 await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address });2324 const address = collectionIdToAddress(collection);25 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});26 const totalSupply = await contract.methods.totalSupply().call();2728 29 expect(totalSupply).to.equal('0');30 });3132 itWeb3('balanceOf', async ({ api, web3 }) => {33 const collection = await createCollectionExpectSuccess({34 mode: { type: 'NFT' },35 });36 const alice = privateKey('//Alice');3738 const caller = await createEthAccountWithBalance(api, web3);39 await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });40 await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });41 await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });4243 const address = collectionIdToAddress(collection);44 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});45 const balance = await contract.methods.balanceOf(caller).call();4647 expect(balance).to.equal('3');48 });4950 itWeb3('ownerOf', async ({ api, web3 }) => {51 const collection = await createCollectionExpectSuccess({52 mode: { type: 'NFT' },53 });54 const alice = privateKey('//Alice');5556 const caller = await createEthAccountWithBalance(api, web3);57 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });5859 const address = collectionIdToAddress(collection);60 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});61 const owner = await contract.methods.ownerOf(tokenId).call();6263 expect(owner).to.equal(caller);64 });65});6667describe('NFT: Plain calls', () => {68 itWeb3('Can perform mint()', async ({ web3, api }) => {69 const collection = await createCollectionExpectSuccess({70 mode: { type: 'NFT' },71 });72 const alice = privateKey('//Alice');7374 const caller = await createEthAccountWithBalance(api, web3);75 const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: caller });76 await submitTransactionAsync(alice, changeAdminTx);77 const receiver = createEthAccount(web3);7879 const address = collectionIdToAddress(collection);80 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});8182 {83 const nextTokenId = await contract.methods.nextTokenId().call();84 expect(nextTokenId).to.be.equal('1');85 const result = await contract.methods.mintWithTokenURI(86 receiver,87 nextTokenId,88 'Test URI',89 ).send({from: caller});90 const events = normalizeEvents(result.events);9192 expect(events).to.be.deep.equal([93 {94 address,95 event: 'Transfer',96 args: {97 from: '0x0000000000000000000000000000000000000000',98 to: receiver,99 tokenId: nextTokenId,100 },101 },102 ]);103104 await waitNewBlocks(api, 1);105 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');106 }107 });108109 itWeb3('Can perform burn()', async ({ web3, api }) => {110 const collection = await createCollectionExpectSuccess({111 mode: {type: 'NFT'},112 });113 const alice = privateKey('//Alice');114115 const owner = await createEthAccountWithBalance(api, web3);116117 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });118 119 const address = collectionIdToAddress(collection);120 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});121122 {123 const result = await contract.methods.burn(tokenId).send({ from: owner });124 const events = normalizeEvents(result.events);125 126 expect(events).to.be.deep.equal([127 {128 address,129 event: 'Transfer',130 args: {131 from: owner,132 to: '0x0000000000000000000000000000000000000000',133 tokenId: tokenId.toString(),134 },135 },136 ]);137 }138 });139140 itWeb3('Can perform approve()', async ({ web3, api }) => {141 const collection = await createCollectionExpectSuccess({142 mode: { type: 'NFT' },143 });144 const alice = privateKey('//Alice');145146 const owner = createEthAccount(web3);147 await transferBalanceToEth(api, alice, owner, 999999999999999);148149 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });150151 const spender = createEthAccount(web3);152153 const address = collectionIdToAddress(collection);154 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);155156 {157 const result = await contract.methods.approve(spender, tokenId).send({ from: owner, gas: '0x1000000', gasPrice: '0x01' });158 const events = normalizeEvents(result.events);159160 expect(events).to.be.deep.equal([161 {162 address,163 event: 'Approval',164 args: {165 owner,166 approved: spender,167 tokenId: tokenId.toString(),168 },169 },170 ]);171 }172 });173174 itWeb3('Can perform transferFrom()', async ({ web3, api }) => {175 const collection = await createCollectionExpectSuccess({176 mode: { type: 'NFT' },177 });178 const alice = privateKey('//Alice');179180 const owner = createEthAccount(web3);181 await transferBalanceToEth(api, alice, owner, 999999999999999);182183 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });184185 const spender = createEthAccount(web3);186 await transferBalanceToEth(api, alice, spender, 999999999999999);187188 const receiver = createEthAccount(web3);189190 const address = collectionIdToAddress(collection);191 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});192193 await contract.methods.approve(spender, tokenId).send({ from: owner });194195 {196 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({ from: spender });197 const events = normalizeEvents(result.events);198 expect(events).to.be.deep.equal([199 {200 address,201 event: 'Transfer',202 args: {203 from: owner,204 to: receiver,205 tokenId: tokenId.toString(),206 },207 },208 ]);209 }210211 {212 const balance = await contract.methods.balanceOf(receiver).call();213 expect(+balance).to.equal(1);214 }215216 {217 const balance = await contract.methods.balanceOf(owner).call();218 expect(+balance).to.equal(0);219 }220 });221222 itWeb3('Can perform transfer()', async ({ web3, api }) => {223 const collection = await createCollectionExpectSuccess({224 mode: { type: 'NFT' },225 });226 const alice = privateKey('//Alice');227228 const owner = createEthAccount(web3);229 await transferBalanceToEth(api, alice, owner, 999999999999999);230231 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });232233 const receiver = createEthAccount(web3);234 await transferBalanceToEth(api, alice, receiver, 999999999999999);235236 const address = collectionIdToAddress(collection);237 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});238239 {240 const result = await contract.methods.transfer(receiver, tokenId).send({ from: owner });241 await waitNewBlocks(api, 1);242 const events = normalizeEvents(result.events);243 expect(events).to.be.deep.equal([244 {245 address,246 event: 'Transfer',247 args: {248 from: owner,249 to: receiver,250 tokenId: tokenId.toString(),251 },252 },253 ]);254 }255256 {257 const balance = await contract.methods.balanceOf(owner).call();258 expect(+balance).to.equal(0);259 }260261 {262 const balance = await contract.methods.balanceOf(receiver).call();263 expect(+balance).to.equal(1);264 }265 });266});267268describe('NFT: Fees', () => {269 itWeb3('approve() call fee is less than 0.2UNQ', async ({ web3, api }) => {270 const collection = await createCollectionExpectSuccess({271 mode: { type: 'NFT' },272 });273 const alice = privateKey('//Alice');274275 const owner = await createEthAccountWithBalance(api, web3);276 const spender = createEthAccount(web3);277278 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });279280 const address = collectionIdToAddress(collection);281 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });282283 const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, tokenId).send({ from: owner }));284 expect(cost < BigInt(0.2 * Number(UNIQUE)));285 });286287 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({ web3, api }) => {288 const collection = await createCollectionExpectSuccess({289 mode: { type: 'NFT' },290 });291 const alice = privateKey('//Alice');292 293 const owner = await createEthAccountWithBalance(api, web3);294 const spender = await createEthAccountWithBalance(api, web3);295296 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });297298 const address = collectionIdToAddress(collection);299 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });300301 await contract.methods.approve(spender, tokenId).send({ from: owner });302303 const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, tokenId).send({ from: spender }));304 expect(cost < BigInt(0.2 * Number(UNIQUE)));305 });306307 itWeb3('transfer() call fee is less than 0.2UNQ', async ({ web3, api }) => {308 const collection = await createCollectionExpectSuccess({309 mode: { type: 'NFT' },310 });311 const alice = privateKey('//Alice');312313 const owner = await createEthAccountWithBalance(api, web3);314 const receiver = createEthAccount(web3);315316 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });317318 const address = collectionIdToAddress(collection);319 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, { from: owner, ...GAS_ARGS });320321 const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, tokenId).send({ from: owner }));322 expect(cost < BigInt(0.2 * Number(UNIQUE)));323 });324});325326describe('NFT: Substrate calls', () => {327 itWeb3('Events emitted for mint()', async ({ web3 }) => {328 const collection = await createCollectionExpectSuccess({329 mode: { type: 'NFT' },330 });331 const alice = privateKey('//Alice');332333 const address = collectionIdToAddress(collection);334 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);335336 let tokenId: number;337 const events = await recordEvents(contract, async () => {338 tokenId = await createItemExpectSuccess(alice, collection, 'NFT');339 });340341 expect(events).to.be.deep.equal([342 {343 address,344 event: 'Transfer',345 args: {346 from: '0x0000000000000000000000000000000000000000',347 to: subToEth(alice.address),348 tokenId: tokenId!.toString(),349 },350 },351 ]);352 });353354 itWeb3('Events emitted for burn()', async ({ web3 }) => {355 const collection = await createCollectionExpectSuccess({356 mode: { type: 'NFT' },357 });358 const alice = privateKey('//Alice');359360 const address = collectionIdToAddress(collection);361 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);362363 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');364 const events = await recordEvents(contract, async () => {365 await burnItemExpectSuccess(alice, collection, tokenId);366 });367368 expect(events).to.be.deep.equal([369 {370 address,371 event: 'Transfer',372 args: {373 from: subToEth(alice.address),374 to: '0x0000000000000000000000000000000000000000',375 tokenId: tokenId.toString(),376 },377 },378 ]);379 });380381 itWeb3('Events emitted for approve()', async ({ web3 }) => {382 const collection = await createCollectionExpectSuccess({383 mode: { type: 'NFT' },384 });385 const alice = privateKey('//Alice');386387 const receiver = createEthAccount(web3);388389 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');390391 const address = collectionIdToAddress(collection);392 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);393394 const events = await recordEvents(contract, async () => {395 await approveExpectSuccess(collection, tokenId, alice, { ethereum: receiver }, 1);396 });397398 expect(events).to.be.deep.equal([399 {400 address,401 event: 'Approval',402 args: {403 owner: subToEth(alice.address),404 approved: receiver,405 tokenId: tokenId.toString(),406 },407 },408 ]);409 });410411 itWeb3('Events emitted for transferFrom()', async ({ web3 }) => {412 const collection = await createCollectionExpectSuccess({413 mode: { type: 'NFT' },414 });415 const alice = privateKey('//Alice');416 const bob = privateKey('//Bob');417418 const receiver = createEthAccount(web3);419420 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');421 await approveExpectSuccess(collection, tokenId, alice, bob, 1);422423 const address = collectionIdToAddress(collection);424 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);425426 const events = await recordEvents(contract, async () => {427 await transferFromExpectSuccess(collection, tokenId, bob, alice, { ethereum: receiver }, 1, 'NFT');428 });429430 expect(events).to.be.deep.equal([431 {432 address,433 event: 'Transfer',434 args: {435 from: subToEth(alice.address),436 to: receiver,437 tokenId: tokenId.toString(),438 },439 },440 ]);441 });442443 itWeb3('Events emitted for transfer()', async ({ web3 }) => {444 const collection = await createCollectionExpectSuccess({445 mode: { type: 'NFT' },446 });447 const alice = privateKey('//Alice');448449 const receiver = createEthAccount(web3);450451 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT');452453 const address = collectionIdToAddress(collection);454 const contract = new web3.eth.Contract(nonFungibleAbi as any, address);455456 const events = await recordEvents(contract, async () => {457 await transferExpectSuccess(collection, tokenId, alice, { ethereum: receiver }, 1, 'NFT');458 });459460 expect(events).to.be.deep.equal([461 {462 address,463 event: 'Transfer',464 args: {465 from: subToEth(alice.address),466 to: receiver,467 tokenId: tokenId.toString(),468 },469 },470 ]);471 });472});