1234567891011121314151617import type {IKeyringPair} from '@polkadot/types/types';18import {readFile} from 'fs/promises';19import {itEth, usingEthPlaygrounds, expect, SponsoringMode} from '../util/index.js';20import {makeNames} from '@unique/test-utils/util.js';2122const {dirname} = makeNames(import.meta.url);2324describe('Matcher contract usage', () => {25 const PRICE = 2000n;26 let donor: IKeyringPair;27 let alice: IKeyringPair;28 let aliceMirror: string;29 let aliceDoubleMirror: string;30 let seller: IKeyringPair;31 let sellerMirror: string;3233 before(async () => {34 await usingEthPlaygrounds(async (_helper, privateKey) => {35 donor = await privateKey({url: import.meta.url});36 });37 });3839 beforeEach(async () => {40 await usingEthPlaygrounds(async (helper, privateKey) => {41 [alice] = await helper.arrange.createAccounts([1000n], donor);42 aliceMirror = helper.address.substrateToEth(alice.address).toLowerCase();43 aliceDoubleMirror = helper.address.ethToSubstrate(aliceMirror);44 seller = await privateKey(`//Seller/${Date.now()}`);45 sellerMirror = helper.address.substrateToEth(seller.address).toLowerCase();4647 await helper.balance.transferToSubstrate(donor, aliceDoubleMirror, 10_000_000_000_000_000_000n);48 });49 });5051 itEth('With UNQ', async ({helper}) => {52 const matcherOwner = await helper.eth.createAccountWithBalance(donor);53 const matcher = await helper.ethContract.deployByCode(matcherOwner, 'MarketPlace', (await readFile(`${dirname}/MarketPlace.sol`)).toString(), [{solPath: 'api/UniqueNFT.sol', fsPath: `${dirname}/../api/UniqueNFT.sol`}], helper.eth.DEFAULT_GAS * 2);5455 const sponsor = await helper.eth.createAccountWithBalance(donor);56 const helpers = await helper.ethNativeContract.contractHelpers(matcherOwner);57 await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});58 await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});5960 await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner});61 await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor});6263 const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}, pendingSponsor: {Substrate: alice.address}});64 await collection.confirmSponsorship(alice);65 await collection.addToAllowList(alice, {Substrate: aliceDoubleMirror});66 const evmCollection = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft');67 await helper.eth.transferBalanceFromSubstrate(donor, aliceMirror);6869 await helpers.methods.toggleAllowed(matcher.options.address, aliceMirror, true).send({from: matcherOwner});70 await helpers.methods.toggleAllowed(matcher.options.address, sellerMirror, true).send({from: matcherOwner});7172 const token = await collection.mintToken(alice, {Ethereum: sellerMirror});7374 75 expect(await token.getOwner()).to.be.deep.equal({Ethereum: sellerMirror});7677 78 {79 await helper.eth.sendEVM(seller, evmCollection.options.address, evmCollection.methods.approve(matcher.options.address, token.tokenId).encodeABI(), '0');80 await helper.eth.sendEVM(seller, matcher.options.address, matcher.methods.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, token.tokenId).encodeABI(), '0');81 }8283 84 expect(await token.getOwner()).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});8586 87 {88 const sellerBalanceBeforePurchase = await helper.balance.getSubstrate(seller.address);89 await helper.eth.sendEVM(alice, matcher.options.address, matcher.methods.buy(evmCollection.options.address, token.tokenId).encodeABI(), PRICE.toString());90 expect(await helper.balance.getSubstrate(seller.address) - sellerBalanceBeforePurchase === PRICE);91 }9293 94 expect(await token.getOwner()).to.be.deep.equal({Ethereum: aliceMirror});9596 97 await token.transferFrom(alice, {Ethereum: aliceMirror}, {Substrate: alice.address});9899 100 expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});101 });102103 itEth('With escrow', async ({helper}) => {104 const matcherOwner = await helper.eth.createAccountWithBalance(donor);105 const matcher = await helper.ethContract.deployByCode(matcherOwner, 'MarketPlace', (await readFile(`${dirname}/MarketPlace.sol`)).toString(), [{solPath: 'api/UniqueNFT.sol', fsPath: `${dirname}/../api/UniqueNFT.sol`}], helper.eth.DEFAULT_GAS * 2);106107 const sponsor = await helper.eth.createAccountWithBalance(donor);108 const escrow = await helper.eth.createAccountWithBalance(donor);109 await matcher.methods.setEscrow(escrow, true).send({from: matcherOwner});110 const helpers = await helper.ethNativeContract.contractHelpers(matcherOwner);111 await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});112 await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});113114 await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner});115 await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor});116117 const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}, pendingSponsor: {Substrate: alice.address}});118 await collection.confirmSponsorship(alice);119 await collection.addToAllowList(alice, {Substrate: aliceDoubleMirror});120 const evmCollection = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft');121 await helper.eth.transferBalanceFromSubstrate(donor, aliceMirror);122123124 await helpers.methods.toggleAllowed(matcher.options.address, aliceMirror, true).send({from: matcherOwner});125126 await helpers.methods.toggleAllowed(matcher.options.address, sellerMirror, true).send({from: matcherOwner});127128 const token = await collection.mintToken(alice, {Ethereum: sellerMirror});129130 131 expect(await token.getOwner()).to.be.deep.equal({Ethereum: sellerMirror});132133 134 {135 await helper.eth.sendEVM(seller, evmCollection.options.address, evmCollection.methods.approve(matcher.options.address, token.tokenId).encodeABI(), '0');136 await helper.eth.sendEVM(seller, matcher.options.address, matcher.methods.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, token.tokenId).encodeABI(), '0');137 }138139 140 expect(await token.getOwner()).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});141142 143 await matcher.methods.depositKSM(PRICE, aliceMirror).send({from: escrow});144145 146 {147 expect(await matcher.methods.balanceKSM(sellerMirror).call()).to.be.equal('0');148 expect(await matcher.methods.balanceKSM(aliceMirror).call()).to.be.equal(PRICE.toString());149150 await helper.eth.sendEVM(alice, matcher.options.address, matcher.methods.buyKSM(evmCollection.options.address, token.tokenId, aliceMirror, aliceMirror).encodeABI(), '0');151152 153 expect(await matcher.methods.balanceKSM(aliceMirror).call()).to.be.equal('0');154 expect(await matcher.methods.balanceKSM(sellerMirror).call()).to.be.equal(PRICE.toString());155 }156157 158 expect(await token.getOwner()).to.be.deep.equal({Ethereum: aliceMirror});159160 161 await token.transferFrom(alice, {Ethereum: aliceMirror}, {Substrate: alice.address});162163 164 expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});165 });166167 itEth('Sell tokens from substrate user via EVM contract', async ({helper}) => {168 const matcherOwner = await helper.eth.createAccountWithBalance(donor);169 const matcher = await helper.ethContract.deployByCode(matcherOwner, 'MarketPlace', (await readFile(`${dirname}/MarketPlace.sol`)).toString(), [{solPath: 'api/UniqueNFT.sol', fsPath: `${dirname}/../api/UniqueNFT.sol`}], helper.eth.DEFAULT_GAS * 2);170171 await helper.eth.transferBalanceFromSubstrate(donor, matcher.options.address);172173 const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}});174 const evmCollection = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft');175176 await helper.balance.transferToSubstrate(donor, seller.address, 100_000_000_000_000_000_000n);177178 const token = await collection.mintToken(alice, {Ethereum: sellerMirror});179180 181 expect(await token.getOwner()).to.be.deep.equal({Ethereum: sellerMirror});182183 184 {185 await helper.eth.sendEVM(seller, evmCollection.options.address, evmCollection.methods.approve(matcher.options.address, token.tokenId).encodeABI(), '0');186 await helper.eth.sendEVM(seller, matcher.options.address, matcher.methods.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, token.tokenId).encodeABI(), '0');187 }188189 190 expect(await token.getOwner()).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});191192 193 {194 const sellerBalanceBeforePurchase = await helper.balance.getSubstrate(seller.address);195 await helper.eth.sendEVM(alice, matcher.options.address, matcher.methods.buy(evmCollection.options.address, token.tokenId).encodeABI(), PRICE.toString());196 expect(await helper.balance.getSubstrate(seller.address) - sellerBalanceBeforePurchase === PRICE);197 }198199 200 expect(await token.getOwner()).to.be.deep.equal({Ethereum: aliceMirror});201202 203 await token.transferFrom(alice, {Ethereum: aliceMirror}, {Substrate: alice.address});204205 206 expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});207 });208});