git.delta.rocks / unique-network / refs/commits / b24dbeee9dca

difftreelog

source

tests/src/eth/marketplace/marketplace.test.ts11.0 KiBsourcehistory
1import { readFile } from 'fs/promises';2import { getBalanceSingle, transferBalanceExpectSuccess } from '../../substrate/get-balance';3import privateKey from '../../substrate/privateKey';4import { createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, queryNftOwner, transferExpectSuccess, transferFromExpectSuccess } from '../../util/helpers';5import { collectionIdToAddress, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, subToEth, subToEthLowercase } from '../util/helpers';6import { evmToAddress } from '@polkadot/util-crypto';7import nonFungibleAbi from '../nonFungibleAbi.json';8import fungibleAbi from '../fungibleAbi.json';9import waitNewBlocks from '../../substrate/wait-new-blocks';10import { expect } from 'chai';1112const PRICE = 2000n;1314describe('Matcher contract usage', () => {15  itWeb3('With UNQ', async ({api, web3}) => {16    const matcherOwner = await createEthAccountWithBalance(api, web3);17    const Matcher = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceUNQ.abi`)).toString()), undefined, {18      from: matcherOwner,19      ...GAS_ARGS,20    });21    const matcher = await Matcher.deploy({ data: (await readFile(`${__dirname}/MarketPlaceUNQ.bin`)).toString() }).send({ from: matcherOwner });2223    const alice = privateKey('//Alice');24    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});25    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), { from: matcherOwner });2627    const seller = privateKey('//Bob');28  29    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);3031    // To transfer item to matcher it first needs to be transfered to EVM account of bob32    await transferExpectSuccess(collectionId, tokenId, seller, {ethereum: subToEth(seller.address)});33    // Fees will be paid from EVM account, so we should have some balance here34    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);35    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);36    await waitNewBlocks(api, 1);3738    // Token is owned by seller initially39    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(seller.address) });4041    // Ask42    {43      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));44      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, '0x0000000000000000000000000000000000000000', evmCollection.options.address, tokenId, 1));45    }46      47    // Token is transferred to matcher48    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: matcher.options.address.toLowerCase() });4950    // Buy51    {52      const sellerBalanceBeforePurchase = await getBalanceSingle(api, seller.address);53      // There is two functions named 'buy', so we should provide full signature54      await executeEthTxOnSub(api, alice, matcher, m => m['buy(address,uint256)'](evmCollection.options.address, tokenId), { value: PRICE });55      expect(await getBalanceSingle(api, seller.address) - sellerBalanceBeforePurchase === PRICE);56    }5758    // Token is transferred to evm account of alice59    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(alice.address) });6061  62    // Transfer token to substrate side of alice63    await transferFromExpectSuccess(collectionId, tokenId, alice, { ethereum: subToEth(alice.address) }, { substrate: alice.address });64    65    // Token is transferred to substrate account of alice, seller received funds66    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ substrate: alice.address });67  });6869  itWeb3('With custom ERC20', async ({api, web3}) => {70    const matcherOwner = await createEthAccountWithBalance(api, web3);71    const Matcher = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceUNQ.abi`)).toString()), undefined, {72      from: matcherOwner,73      ...GAS_ARGS,74    });75    const matcher = await Matcher.deploy({ data: (await readFile(`${__dirname}/MarketPlaceUNQ.bin`)).toString() }).send({ from: matcherOwner });7677    const alice = privateKey('//Alice');78    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});79    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), { from: matcherOwner });8081    const fungibleId = await createCollectionExpectSuccess({ mode: { type: 'Fungible', decimalPoints: 0 } });82    const evmFungible = new web3.eth.Contract(fungibleAbi as any, collectionIdToAddress(fungibleId), { from: matcherOwner, ...GAS_ARGS });83    await createFungibleItemExpectSuccess(alice, fungibleId, { Value: PRICE }, { ethereum: subToEth(alice.address) });8485    const seller = privateKey('//Bob');86  87    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);8889    // To transfer item to matcher it first needs to be transfered to EVM account of bob90    await transferExpectSuccess(collectionId, tokenId, seller, {ethereum: subToEth(seller.address)});91    // Fees will be paid from EVM account, so we should have some balance here92    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);93    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);94    await waitNewBlocks(api, 1);9596    // Token is owned by seller initially97    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(seller.address) });9899    // Ask100    {101      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));102      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, evmFungible.options.address, evmCollection.options.address, tokenId, 1));103    }104      105    // Token is transferred to matcher106    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: matcher.options.address.toLowerCase() });107108    // Buy109    {110      const sellerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call());111      const buyerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call());112113      await executeEthTxOnSub(api, alice, evmFungible, m => m.approve(matcher.options.address, PRICE));114      // There is two functions named 'buy', so we should provide full signature115      await executeEthTxOnSub(api, alice, matcher, m =>116        m['buy(address,uint256,address,uint256)'](evmCollection.options.address, tokenId, evmFungible.options.address, PRICE));117118      // Approved price is removed from buyer balance, and added to seller119      expect(BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call()) - sellerBalanceBeforePurchase === PRICE);120      expect(buyerBalanceBeforePurchase - BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call()) === PRICE);121    }122123    // Token is transferred to evm account of alice124    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(alice.address) });125126  127    // Transfer token to substrate side of alice128    await transferFromExpectSuccess(collectionId, tokenId, alice, { ethereum: subToEth(alice.address) }, { substrate: alice.address });129    130    // Token is transferred to substrate account of alice131    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ substrate: alice.address });132  });133134  itWeb3('With escrow', async ({ api, web3 }) => {135    const matcherOwner = await createEthAccountWithBalance(api, web3);136    const escrow = await createEthAccountWithBalance(api, web3);137    const Matcher = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlaceKSM.abi`)).toString()), undefined, {138      from: matcherOwner,139      ...GAS_ARGS,140    });141    const matcher = await Matcher.deploy({ data: (await readFile(`${__dirname}/MarketPlaceKSM.bin`)).toString(), arguments: [escrow] }).send({ from: matcherOwner });142    143    const ksmToken = 11;144145    const alice = privateKey('//Alice');146    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});147    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), { from: matcherOwner });148149    const seller = privateKey('//Bob');150  151    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);152153    // To transfer item to matcher it first needs to be transfered to EVM account of bob154    await transferExpectSuccess(collectionId, tokenId, seller, {ethereum: subToEth(seller.address)});155    // Fees will be paid from EVM account, so we should have some balance here156    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);157    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);158    await waitNewBlocks(api, 1);159160    // Token is owned by seller initially161    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(seller.address) });162163    // Ask164    {165      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));166      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, ksmToken, evmCollection.options.address, tokenId, 1));167    }168      169    // Token is transferred to matcher170    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: matcher.options.address.toLowerCase() });171172    // Give buyer KSM173    await matcher.methods.deposit(PRICE, ksmToken, subToEth(alice.address)).send({ from: escrow });174    await waitNewBlocks(api, 1);175  176    // Buy177    {178      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(seller.address)).call()).to.be.equal('0');179      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal(PRICE.toString());180181      await executeEthTxOnSub(api, alice, matcher, m => m.buy(evmCollection.options.address, tokenId));182      await waitNewBlocks(api, 1);183184      // Price is removed from buyer balance, and added to seller185      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(alice.address)).call()).to.be.equal('0');186      expect(await matcher.methods.escrowBalance(ksmToken, subToEth(seller.address)).call()).to.be.equal(PRICE.toString());187    }188189    // Token is transferred to evm account of alice190    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ ethereum: subToEthLowercase(alice.address) });191  192    // Transfer token to substrate side of alice193    await transferFromExpectSuccess(collectionId, tokenId, alice, { ethereum: subToEth(alice.address) }, { substrate: alice.address });194    195    // Token is transferred to substrate account of alice, seller received funds196    expect(await queryNftOwner(api, collectionId, tokenId)).to.be.deep.equal({ substrate: alice.address });197  });198});