123456import privateKey from '../../substrate/privateKey';7import { createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, setMetadataUpdatePermissionFlagExpectSuccess } from '../../util/helpers';8import { collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents } 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';13import Web3 from 'web3';14import { readFile } from 'fs/promises';15import { ApiPromise } from '@polkadot/api';1617async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {18 19 const owner = await createEthAccountWithBalance(api, web3);20 const Proxy = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {21 from: owner,22 ...GAS_ARGS,23 });24 const proxy = await Proxy.deploy({ data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address] }).send({ from: owner });25 return proxy;26}2728describe('NFT (Via EVM proxy): Information getting', () => {29 itWeb3('totalSupply', async ({ api, web3 }) => {30 const collection = await createCollectionExpectSuccess({31 mode: { type: 'NFT' },32 });33 const alice = privateKey('//Alice');34 const caller = await createEthAccountWithBalance(api, web3);3536 await createItemExpectSuccess(alice, collection, 'NFT', { substrate: alice.address });3738 const address = collectionIdToAddress(collection);39 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));40 const totalSupply = await contract.methods.totalSupply().call();4142 43 expect(totalSupply).to.equal('0');44 });4546 itWeb3('balanceOf', async ({ api, web3 }) => {47 const collection = await createCollectionExpectSuccess({48 mode: { type: 'NFT' },49 });50 const alice = privateKey('//Alice');5152 const caller = await createEthAccountWithBalance(api, web3);53 await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });54 await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });55 await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });5657 const address = collectionIdToAddress(collection);58 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));59 const balance = await contract.methods.balanceOf(caller).call();6061 expect(balance).to.equal('3');62 });6364 itWeb3('ownerOf', async ({ api, web3 }) => {65 const collection = await createCollectionExpectSuccess({66 mode: { type: 'NFT' },67 });68 const alice = privateKey('//Alice');6970 const caller = await createEthAccountWithBalance(api, web3);71 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: caller });7273 const address = collectionIdToAddress(collection);74 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));75 const owner = await contract.methods.ownerOf(tokenId).call();7677 expect(owner).to.equal(caller);78 });79});8081describe('NFT (Via EVM proxy): Plain calls', () => {82 itWeb3('Can perform mint()', async ({ web3, api }) => {83 const collection = await createCollectionExpectSuccess({84 mode: { type: 'NFT' },85 });86 const alice = privateKey('//Alice');87 const caller = await createEthAccountWithBalance(api, web3);88 const receiver = createEthAccount(web3);8990 const address = collectionIdToAddress(collection);91 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, { from: caller, ...GAS_ARGS }));9293 const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: contract.options.address });94 await submitTransactionAsync(alice, changeAdminTx);9596 {97 const nextTokenId = await contract.methods.nextTokenId().call();98 expect(nextTokenId).to.be.equal('1');99 const result = await contract.methods.mintWithTokenURI(100 receiver,101 nextTokenId,102 'Test URI',103 ).send({ from: caller });104 const events = normalizeEvents(result.events);105106 expect(events).to.be.deep.equal([107 {108 address,109 event: 'Transfer',110 args: {111 from: '0x0000000000000000000000000000000000000000',112 to: receiver,113 tokenId: nextTokenId,114 },115 },116 ]);117118 await waitNewBlocks(api, 1);119 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');120 }121 });122 itWeb3('Can perform mintBulk()', async ({ web3, api }) => {123 const collection = await createCollectionExpectSuccess({124 mode: { type: 'NFT' },125 });126 const alice = privateKey('//Alice');127128 const caller = await createEthAccountWithBalance(api, web3);129 const receiver = createEthAccount(web3);130131 const address = collectionIdToAddress(collection);132 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, { from: caller, ...GAS_ARGS }));133 const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: contract.options.address });134 await submitTransactionAsync(alice, changeAdminTx);135136 {137 const nextTokenId = await contract.methods.nextTokenId().call();138 expect(nextTokenId).to.be.equal('1');139 const result = await contract.methods.mintBulkWithTokenURI(140 receiver,141 [142 [nextTokenId, 'Test URI 0'],143 [+nextTokenId + 1, 'Test URI 1'],144 [+nextTokenId + 2, 'Test URI 2'],145 ],146 ).send({ from: caller });147 const events = normalizeEvents(result.events);148149 expect(events).to.be.deep.equal([150 {151 address,152 event: 'Transfer',153 args: {154 from: '0x0000000000000000000000000000000000000000',155 to: receiver,156 tokenId: nextTokenId,157 },158 },159 {160 address,161 event: 'Transfer',162 args: {163 from: '0x0000000000000000000000000000000000000000',164 to: receiver,165 tokenId: String(+nextTokenId + 1),166 },167 },168 {169 address,170 event: 'Transfer',171 args: {172 from: '0x0000000000000000000000000000000000000000',173 to: receiver,174 tokenId: String(+nextTokenId + 2),175 },176 },177 ]);178179 await waitNewBlocks(api, 1);180 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');181 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');182 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');183 }184 });185186 itWeb3('Can perform burn()', async ({ web3, api }) => {187 const collection = await createCollectionExpectSuccess({188 mode: {type: 'NFT'},189 });190 const alice = privateKey('//Alice');191 const caller = await createEthAccountWithBalance(api, web3);192 193 const address = collectionIdToAddress(collection);194 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));195 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });196197 const changeAdminTx = api.tx.nft.addCollectionAdmin(collection, { ethereum: contract.options.address });198 await submitTransactionAsync(alice, changeAdminTx);199200 {201 const result = await contract.methods.burn(tokenId).send({ from: caller });202 const events = normalizeEvents(result.events);203 204 expect(events).to.be.deep.equal([205 {206 address,207 event: 'Transfer',208 args: {209 from: contract.options.address,210 to: '0x0000000000000000000000000000000000000000',211 tokenId: tokenId.toString(),212 },213 },214 ]);215 }216 });217218 itWeb3('Can perform approve()', async ({ web3, api }) => {219 const collection = await createCollectionExpectSuccess({220 mode: { type: 'NFT' },221 });222 const alice = privateKey('//Alice');223 const caller = await createEthAccountWithBalance(api, web3);224 const spender = createEthAccount(web3);225226 const address = collectionIdToAddress(collection);227 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address));228 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });229230 {231 const result = await contract.methods.approve(spender, tokenId).send({ from: caller, gas: '0x1000000', gasPrice: '0x01' });232 const events = normalizeEvents(result.events);233234 expect(events).to.be.deep.equal([235 {236 address,237 event: 'Approval',238 args: {239 owner: contract.options.address,240 approved: spender,241 tokenId: tokenId.toString(),242 },243 },244 ]);245 }246 });247248 itWeb3('Can perform transferFrom()', async ({ web3, api }) => {249 const collection = await createCollectionExpectSuccess({250 mode: { type: 'NFT' },251 });252 const alice = privateKey('//Alice');253 const caller = await createEthAccountWithBalance(api, web3);254 const owner = await createEthAccountWithBalance(api, web3);255256 const receiver = createEthAccount(web3);257258 const address = collectionIdToAddress(collection);259 const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, address, { from: caller, ...GAS_ARGS });260 const contract = await proxyWrap(api, web3, evmCollection);261 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: owner });262263 await evmCollection.methods.approve(contract.options.address, tokenId).send({ from: owner });264265 {266 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({ from: caller });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(contract.options.address).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');297 const caller = await createEthAccountWithBalance(api, web3);298 const receiver = createEthAccount(web3);299300 const address = collectionIdToAddress(collection);301 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));302 const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });303304 {305 const result = await contract.methods.transfer(receiver, tokenId).send({ from: caller });306 await waitNewBlocks(api, 1);307 const events = normalizeEvents(result.events);308 expect(events).to.be.deep.equal([309 {310 address,311 event: 'Transfer',312 args: {313 from: contract.options.address,314 to: receiver,315 tokenId: tokenId.toString(),316 },317 },318 ]);319 }320321 {322 const balance = await contract.methods.balanceOf(contract.options.address).call();323 expect(+balance).to.equal(0);324 }325326 {327 const balance = await contract.methods.balanceOf(receiver).call();328 expect(+balance).to.equal(1);329 }330 });331332 itWeb3('Can perform getVariableMetadata', async ({ web3, api }) => {333 const collection = await createCollectionExpectSuccess({334 mode: { type: 'NFT' },335 });336 const alice = privateKey('//Alice');337 const caller = await createEthAccountWithBalance(api, web3);338339 const address = collectionIdToAddress(collection);340 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, { from: caller, ...GAS_ARGS }));341 const item = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });342 await setMetadataUpdatePermissionFlagExpectSuccess(alice, collection, 'Admin');343 await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);344 345 expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');346 });347348 itWeb3('Can perform setVariableMetadata', async ({ web3, api }) => {349 const collection = await createCollectionExpectSuccess({350 mode: { type: 'NFT' },351 });352 const alice = privateKey('//Alice');353 const caller = await createEthAccountWithBalance(api, web3);354355 const address = collectionIdToAddress(collection);356 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, { from: caller, ...GAS_ARGS }));357 const item = await createItemExpectSuccess(alice, collection, 'NFT', { ethereum: contract.options.address });358 359 expect(await contract.methods.setVariableMetadata(item, '0x010203').send({ from: caller }));360 await waitNewBlocks(api, 1);361 expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');362 });363});