git.delta.rocks / unique-network / refs/commits / 4da04995c680

difftreelog

source

js-packages/scripts/benchmarks/mintFee/index.ts11.0 KiBsourcehistory
1import {usingEthPlaygrounds} from '@unique/test-utils/eth/util.js';2import {EthUniqueHelper} from '@unique/test-utils/eth/index.js';3import {readFile} from 'fs/promises';4import type {ICrossAccountId} from '@unique-nft/playgrounds/types.js';5import type {IKeyringPair} from '@polkadot/types/types';6import {UniqueNFTCollection} from '@unique-nft/playgrounds/unique.js';7import {Contract} from 'web3-eth-contract';8import {createObjectCsvWriter} from 'csv-writer';9import {convertToTokens, createCollectionForBenchmarks, PERMISSIONS, PROPERTIES} from '../utils/common.js';10import {makeNames} from '@unique/test-utils/util.js';11import type {ContractImports} from '@unique/test-utils/eth/types.js';1213const {dirname} = makeNames(import.meta.url);1415const EVM_ABI_DIR = `${dirname}/../../../evm-abi`;1617export const CONTRACT_IMPORT: ContractImports[] = [18  {19    fsPath: `${EVM_ABI_DIR}/api/CollectionHelpers.sol`,20    solPath: 'eth/api/CollectionHelpers.sol',21  },22  {23    fsPath: `${EVM_ABI_DIR}/api/ContractHelpers.sol`,24    solPath: 'eth/api/ContractHelpers.sol',25  },26  {27    fsPath: `${EVM_ABI_DIR}/api/UniqueRefungibleToken.sol`,28    solPath: 'eth/api/UniqueRefungibleToken.sol',29  },30  {31    fsPath: `${EVM_ABI_DIR}/api/UniqueRefungible.sol`,32    solPath: 'eth/api/UniqueRefungible.sol',33  },34  {35    fsPath: `${EVM_ABI_DIR}/api/UniqueNFT.sol`,36    solPath: 'eth/api/UniqueNFT.sol',37  },38];3940interface IBenchmarkResultForProp {41	propertiesNumber: number;42	substrateFee: number;43	ethFee: number;44	ethBulkFee: number;45  ethMintCrossFee: number;46	evmProxyContractFee: number;47	evmProxyContractBulkFee: number;48}4950const main = async () => {51  const benchmarks = [52    'substrateFee',53    'ethFee',54    'ethBulkFee',55    'ethMintCrossFee',56    'evmProxyContractFee',57    'evmProxyContractBulkFee',58  ];59  const headers = [60    'propertiesNumber',61    ...benchmarks,62  ];636465  const csvWriter = createObjectCsvWriter({66    path: 'properties.csv',67    header: headers,68  });6970  await usingEthPlaygrounds(async (helper, privateKey) => {71    const CONTRACT_SOURCE = (72      await readFile(`${dirname}/proxyContract.sol`)73    ).toString();7475    const donor = await privateKey('//Alice'); // Seed from account with balance on this network76    const ethSigner = await helper.eth.createAccountWithBalance(donor);7778    const contract = await helper.ethContract.deployByCode(79      ethSigner,80      'ProxyMint',81      CONTRACT_SOURCE,82      CONTRACT_IMPORT,83    );8485    const fees = await benchMintFee(helper, privateKey, contract);86    console.log('Minting without properties');87    console.table(fees);8889    const result: IBenchmarkResultForProp[] = [];90    const csvResult: IBenchmarkResultForProp[] = [];9192    for(let i = 1; i <= 20; i++) {93      const benchResult = await benchMintWithProperties(helper, privateKey, contract, {94        propertiesNumber: i,95      }) as any;9697      csvResult.push(benchResult);9899      const minFee = Math.min(...(benchmarks.map(x => benchResult[x])));100      for(const key of benchmarks) {101        const keyPercent = Math.round((benchResult[key] / minFee) * 100);102        benchResult[key] = `${benchResult[key]} (${keyPercent}%)`;103      }104105      result.push(benchResult);106    }107108    await csvWriter.writeRecords(csvResult);109110    console.log('Minting with properties');111    console.table(result, headers);112  });113};114115main()116  .then(() => process.exit(0))117  .catch((e) => {118    console.log(e);119    process.exit(1);120  });121122123124async function benchMintFee(125  helper: EthUniqueHelper,126  privateKey: (seed: string) => Promise<IKeyringPair>,127  proxyContract: Contract,128): Promise<{129	substrateFee: number;130	ethFee: number;131	evmProxyContractFee: number;132}> {133  const donor = await privateKey('//Alice');134  const substrateReceiver = await privateKey('//Bob');135  const ethSigner = await helper.eth.createAccountWithBalance(donor);136137  const nominal = helper.balance.getOneTokenNominal();138139  await helper.eth.transferBalanceFromSubstrate(140    donor,141    proxyContract.options.address,142    100n,143  );144145  const collection = (await createCollectionForBenchmarks(146    'nft',147    helper,148    privateKey,149    ethSigner,150    proxyContract.options.address,151    PERMISSIONS,152  )) as UniqueNFTCollection;153154  const substrateFee = await helper.arrange.calculcateFee(155    {Substrate: donor.address},156    () => collection.mintToken(donor, {Substrate: substrateReceiver.address}),157  );158159  const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId);160  const collectionContract = await helper.ethNativeContract.collection(161    collectionEthAddress,162    'nft',163  );164165  const receiverEthAddress = helper.address.substrateToEth(substrateReceiver.address);166167  const encodedCall = collectionContract.methods168    .mint(receiverEthAddress)169    .encodeABI();170171  const ethFee = await helper.arrange.calculcateFee(172    {Substrate: donor.address},173    async () => {174      await helper.eth.sendEVM(175        donor,176        collectionContract.options.address,177        encodedCall,178        '0',179      );180    },181  );182183  const evmProxyContractFee = await helper.arrange.calculcateFee(184    {Ethereum: ethSigner},185    async () => {186      await proxyContract.methods187        .mintToSubstrate(188          helper.ethAddress.fromCollectionId(collection.collectionId),189          substrateReceiver.addressRaw,190        )191        .send({from: ethSigner});192    },193  );194195  return {196    substrateFee: convertToTokens(substrateFee, nominal),197    ethFee: convertToTokens(ethFee, nominal),198    evmProxyContractFee: convertToTokens(evmProxyContractFee, nominal),199  };200}201202async function benchMintWithProperties(203  helper: EthUniqueHelper,204  privateKey: (seed: string) => Promise<IKeyringPair>,205  proxyContract: Contract,206  setup: { propertiesNumber: number },207): Promise<IBenchmarkResultForProp> {208  const donor = await privateKey('//Alice'); // Seed from account with balance on this network209  const ethSigner = await helper.eth.createAccountWithBalance(donor);210211  const susbstrateReceiver = await privateKey('//Bob');212  const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);213214  const nominal = helper.balance.getOneTokenNominal();215216  const substrateFee = await calculateFeeNftMintWithProperties(217    helper,218    privateKey,219    {Substrate: donor.address},220    ethSigner,221    proxyContract.options.address,222    async (collection) => {223      await collection.mintToken(224        donor,225        {Substrate: susbstrateReceiver.address},226        PROPERTIES.slice(0, setup.propertiesNumber).map((p) => ({key: p.key, value: Buffer.from(p.value).toString()})),227      );228    },229  );230231  const ethFee = await calculateFeeNftMintWithProperties(232    helper,233    privateKey,234    {Substrate: donor.address},235    ethSigner,236    proxyContract.options.address,237    async (collection) => {238      const evmContract = await helper.ethNativeContract.collection(239        helper.ethAddress.fromCollectionId(collection.collectionId),240        'nft',241        undefined,242        true,243      );244245      const subTokenId = await evmContract.methods.nextTokenId().call();246247      let encodedCall = evmContract.methods248        .mint(receiverEthAddress)249        .encodeABI();250251      await helper.eth.sendEVM(252        donor,253        evmContract.options.address,254        encodedCall,255        '0',256      );257258      for(const val of PROPERTIES.slice(0, setup.propertiesNumber)) {259        encodedCall = await evmContract.methods260          .setProperty(subTokenId, val.key, Buffer.from(val.value))261          .encodeABI();262263        await helper.eth.sendEVM(264          donor,265          evmContract.options.address,266          encodedCall,267          '0',268        );269      }270    },271  );272273  const ethBulkFee = await calculateFeeNftMintWithProperties(274    helper,275    privateKey,276    {Substrate: donor.address},277    ethSigner,278    proxyContract.options.address,279    async (collection) => {280      const evmContract = await helper.ethNativeContract.collection(281        helper.ethAddress.fromCollectionId(collection.collectionId),282        'nft',283      );284285      const subTokenId = await evmContract.methods.nextTokenId().call();286287      let encodedCall = evmContract.methods288        .mint(receiverEthAddress)289        .encodeABI();290291      await helper.eth.sendEVM(292        donor,293        evmContract.options.address,294        encodedCall,295        '0',296      );297298      encodedCall = await evmContract.methods299        .setProperties(300          subTokenId,301          PROPERTIES.slice(0, setup.propertiesNumber),302        )303        .encodeABI();304305      await helper.eth.sendEVM(306        donor,307        evmContract.options.address,308        encodedCall,309        '0',310      );311    },312  );313314  const ethMintCrossFee = await calculateFeeNftMintWithProperties(315    helper,316    privateKey,317    {Ethereum: ethSigner},318    ethSigner,319    proxyContract.options.address,320    async (collection) => {321      const evmContract = await helper.ethNativeContract.collection(322        helper.ethAddress.fromCollectionId(collection.collectionId),323        'nft',324      );325326      await evmContract.methods.mintCross(327        helper.ethCrossAccount.fromAddress(receiverEthAddress),328        PROPERTIES.slice(0, setup.propertiesNumber),329      )330        .send({from: ethSigner});331    },332  );333334  const proxyContractFee = await calculateFeeNftMintWithProperties(335    helper,336    privateKey,337    {Ethereum: ethSigner},338    ethSigner,339    proxyContract.options.address,340    async (collection) => {341      await proxyContract.methods342        .mintToSubstrateWithProperty(343          helper.ethAddress.fromCollectionId(collection.collectionId),344          susbstrateReceiver.addressRaw,345          PROPERTIES.slice(0, setup.propertiesNumber),346        )347        .send({from: ethSigner});348    },349  );350351  const proxyContractBulkFee = await calculateFeeNftMintWithProperties(352    helper,353    privateKey,354    {Ethereum: ethSigner},355    ethSigner,356    proxyContract.options.address,357    async (collection) => {358      await proxyContract.methods359        .mintToSubstrateBulkProperty(360          helper.ethAddress.fromCollectionId(collection.collectionId),361          susbstrateReceiver.addressRaw,362          PROPERTIES.slice(0, setup.propertiesNumber),363        )364        .send({from: ethSigner});365    },366  );367368  return {369    propertiesNumber: setup.propertiesNumber,370    substrateFee: convertToTokens(substrateFee, nominal),371    ethFee: convertToTokens(ethFee, nominal),372    ethBulkFee: convertToTokens(ethBulkFee, nominal),373    ethMintCrossFee: convertToTokens(ethMintCrossFee, nominal),374    evmProxyContractFee: convertToTokens(proxyContractFee, nominal),375    evmProxyContractBulkFee: convertToTokens(proxyContractBulkFee, nominal),376  };377}378379async function calculateFeeNftMintWithProperties(380  helper: EthUniqueHelper,381  privateKey: (seed: string) => Promise<IKeyringPair>,382  payer: ICrossAccountId,383  ethSigner: string,384  proxyContractAddress: string,385  calculatedCall: (collection: UniqueNFTCollection) => Promise<any>,386): Promise<bigint> {387  const collection = (await createCollectionForBenchmarks(388    'nft',389    helper,390    privateKey,391    ethSigner,392    proxyContractAddress,393    PERMISSIONS,394  )) as UniqueNFTCollection;395  return helper.arrange.calculcateFee(payer, async () => {396    await calculatedCall(collection);397  });398}399400401