github.com/ethereum-optimism/optimism@v1.7.2/packages/web3js-plugin/src/plugin.spec.ts (about)

     1  import { beforeAll, describe, expect, test } from 'vitest'
     2  import { z } from 'zod'
     3  import Web3, { Contract, FMT_BYTES, FMT_NUMBER } from 'web3'
     4  import {
     5    l2StandardBridgeABI,
     6    l2StandardBridgeAddress,
     7    optimistABI,
     8    optimistAddress,
     9  } from '@eth-optimism/contracts-ts'
    10  
    11  import { OptimismPlugin } from './plugin'
    12  
    13  const defaultProvider = 'https://mainnet.optimism.io'
    14  const provider = z
    15    .string()
    16    .url()
    17    .default(defaultProvider)
    18    .parse(process.env['VITE_L2_RPC_URL'])
    19  if (provider === defaultProvider)
    20    console.warn(
    21      'Warning: Using default public provider, this could cause tests to fail due to rate limits. Set the VITE_L2_RPC_URL env to override default provider'
    22    )
    23  
    24  describe('OptimismPlugin', () => {
    25    let web3: Web3
    26  
    27    beforeAll(() => {
    28      web3 = new Web3(provider)
    29      web3.registerPlugin(new OptimismPlugin())
    30    })
    31  
    32    test('should be registered under .op namespace', () =>
    33      expect(web3.op).toMatchInlineSnapshot(`
    34        OptimismPlugin {
    35          "_accountProvider": {
    36            "create": [Function],
    37            "decrypt": [Function],
    38            "encrypt": [Function],
    39            "hashMessage": [Function],
    40            "privateKeyToAccount": [Function],
    41            "recover": [Function],
    42            "recoverTransaction": [Function],
    43            "sign": [Function],
    44            "signTransaction": [Function],
    45            "wallet": Wallet [],
    46          },
    47          "_emitter": EventEmitter {
    48            "_events": {},
    49            "_eventsCount": 0,
    50            "_maxListeners": undefined,
    51            Symbol(kCapture): false,
    52          },
    53          "_gasPriceOracleContract": undefined,
    54          "_requestManager": Web3RequestManager {
    55            "_emitter": EventEmitter {
    56              "_events": {
    57                "BEFORE_PROVIDER_CHANGE": [Function],
    58                "PROVIDER_CHANGED": [Function],
    59              },
    60              "_eventsCount": 2,
    61              "_maxListeners": undefined,
    62              Symbol(kCapture): false,
    63            },
    64            "_provider": HttpProvider {
    65              "clientUrl": "https://opt-mainnet.g.alchemy.com/v2/OVlbpe9COlhG-ijOXGvL_phb5ns6p9-w",
    66              "httpProviderOptions": undefined,
    67            },
    68            "useRpcCallSpecification": undefined,
    69          },
    70          "_subscriptionManager": Web3SubscriptionManager {
    71            "_subscriptions": Map {},
    72            "registeredSubscriptions": {
    73              "logs": [Function],
    74              "newBlockHeaders": [Function],
    75              "newHeads": [Function],
    76              "newPendingTransactions": [Function],
    77              "pendingTransactions": [Function],
    78              "syncing": [Function],
    79            },
    80            "requestManager": Web3RequestManager {
    81              "_emitter": EventEmitter {
    82                "_events": {
    83                  "BEFORE_PROVIDER_CHANGE": [Function],
    84                  "PROVIDER_CHANGED": [Function],
    85                },
    86                "_eventsCount": 2,
    87                "_maxListeners": undefined,
    88                Symbol(kCapture): false,
    89              },
    90              "_provider": HttpProvider {
    91                "clientUrl": "https://opt-mainnet.g.alchemy.com/v2/OVlbpe9COlhG-ijOXGvL_phb5ns6p9-w",
    92                "httpProviderOptions": undefined,
    93              },
    94              "useRpcCallSpecification": undefined,
    95            },
    96            "tolerateUnlinkedSubscription": false,
    97          },
    98          "_wallet": Wallet [],
    99          "config": {
   100            "blockHeaderTimeout": 10,
   101            "defaultAccount": undefined,
   102            "defaultBlock": "latest",
   103            "defaultChain": "mainnet",
   104            "defaultCommon": undefined,
   105            "defaultHardfork": "london",
   106            "defaultMaxPriorityFeePerGas": "0x9502f900",
   107            "defaultNetworkId": undefined,
   108            "defaultTransactionType": "0x0",
   109            "enableExperimentalFeatures": {
   110              "useRpcCallSpecification": false,
   111              "useSubscriptionWhenCheckingBlockTimeout": false,
   112            },
   113            "handleRevert": false,
   114            "maxListenersWarningThreshold": 100,
   115            "transactionBlockTimeout": 50,
   116            "transactionBuilder": undefined,
   117            "transactionConfirmationBlocks": 24,
   118            "transactionConfirmationPollingInterval": undefined,
   119            "transactionPollingInterval": 1000,
   120            "transactionPollingTimeout": 750000,
   121            "transactionReceiptPollingInterval": undefined,
   122            "transactionSendTimeout": 750000,
   123            "transactionTypeParser": undefined,
   124          },
   125          "pluginNamespace": "op",
   126          "providers": {
   127            "HttpProvider": [Function],
   128            "WebsocketProvider": [Function],
   129          },
   130        }
   131      `))
   132  
   133    describe('should return a bigint by default', () => {
   134      test('getBaseFee', async () =>
   135        expect(await web3.op.getBaseFee()).toBeTypeOf('bigint'))
   136  
   137      test('getDecimals should return 6n', async () =>
   138        expect(await web3.op.getDecimals()).toBe(BigInt(6)))
   139  
   140      test('getGasPrice', async () =>
   141        expect(await web3.op.getGasPrice()).toBeTypeOf('bigint'))
   142  
   143      test('getL1BaseFee', async () =>
   144        expect(await web3.op.getL1BaseFee()).toBeTypeOf('bigint'))
   145  
   146      test('getOverhead should return 188n', async () =>
   147        expect(await web3.op.getOverhead()).toBe(BigInt(188)))
   148  
   149      test('getScalar should return 684000n', async () =>
   150        expect(await web3.op.getScalar()).toBe(BigInt(684000)))
   151    })
   152  
   153    describe('should return a number', () => {
   154      const numberFormat = { number: FMT_NUMBER.NUMBER, bytes: FMT_BYTES.HEX }
   155  
   156      test('getBaseFee', async () =>
   157        expect(await web3.op.getBaseFee(numberFormat)).toBeTypeOf('number'))
   158  
   159      test('getDecimals should return 6', async () =>
   160        expect(await web3.op.getDecimals(numberFormat)).toBe(6))
   161  
   162      test('getGasPrice', async () =>
   163        expect(await web3.op.getGasPrice(numberFormat)).toBeTypeOf('number'))
   164  
   165      test('getL1BaseFee', async () =>
   166        expect(await web3.op.getL1BaseFee(numberFormat)).toBeTypeOf('number'))
   167  
   168      test('getOverhead should return 188', async () =>
   169        expect(await web3.op.getOverhead(numberFormat)).toBe(188))
   170  
   171      test('getScalar should return 684000', async () =>
   172        expect(await web3.op.getScalar(numberFormat)).toBe(684000))
   173    })
   174  
   175    test('getVersion should return the string 1.0.0', async () =>
   176      expect(await web3.op.getVersion()).toBe('1.0.0'))
   177  
   178    describe('Contract transaction gas estimates - optimistABI.burn', () => {
   179      let optimistContract: Contract<typeof optimistABI>
   180      let encodedBurnMethod: string
   181  
   182      beforeAll(() => {
   183        optimistContract = new web3.eth.Contract(optimistABI)
   184        encodedBurnMethod = optimistContract.methods
   185          .burn('0x77194aa25a06f932c10c0f25090f3046af2c85a6')
   186          .encodeABI()
   187      })
   188  
   189      describe('should return a bigint by default', () => {
   190        test('getL1Fee', async () => {
   191          expect(
   192            await web3.op.getL1Fee({
   193              chainId: '0xa',
   194              data: encodedBurnMethod,
   195              type: '0x2',
   196            })
   197          ).toBeTypeOf('bigint')
   198        })
   199  
   200        test('getL1GasUsed should return 1884n', async () =>
   201          expect(
   202            await web3.op.getL1GasUsed({
   203              chainId: '0xa',
   204              data: encodedBurnMethod,
   205              type: '0x2',
   206            })
   207          ).toBe(BigInt(1884)))
   208  
   209        test('estimateFees', async () =>
   210          expect(
   211            await web3.op.estimateFees({
   212              chainId: 10,
   213              data: encodedBurnMethod,
   214              type: 2,
   215              to: optimistAddress[10],
   216              from: '0x77194aa25a06f932c10c0f25090f3046af2c85a6',
   217            })
   218          ).toBeTypeOf('bigint'))
   219  
   220        test('getL2Fee', async () => {
   221          expect(
   222            await web3.op.getL2Fee({
   223              chainId: '0xa',
   224              data: encodedBurnMethod,
   225              type: '0x2',
   226              to: optimistAddress[10],
   227              from: '0x77194aa25a06f932c10c0f25090f3046af2c85a6',
   228            })
   229          ).toBeTypeOf('bigint')
   230        })
   231  
   232        test('estimateFees', async () =>
   233          expect(
   234            await web3.op.estimateFees({
   235              chainId: 10,
   236              data: encodedBurnMethod,
   237              type: 2,
   238              to: optimistAddress[10],
   239              from: '0x77194aa25a06f932c10c0f25090f3046af2c85a6',
   240            })
   241          ).toBeTypeOf('bigint'))
   242      })
   243  
   244      describe('should return a hexString', () => {
   245        const hexStringFormat = { number: FMT_NUMBER.HEX, bytes: FMT_BYTES.HEX }
   246  
   247        test('getL1Fee', async () => {
   248          expect(
   249            await web3.op.getL1Fee(
   250              {
   251                chainId: '0xa',
   252                data: encodedBurnMethod,
   253                type: '0x2',
   254              },
   255              hexStringFormat
   256            )
   257          ).toBeTypeOf('string')
   258        })
   259  
   260        test('getL1GasUsed should return 0x75c', async () =>
   261          expect(
   262            await web3.op.getL1GasUsed(
   263              {
   264                chainId: '0xa',
   265                data: encodedBurnMethod,
   266                type: '0x2',
   267              },
   268              hexStringFormat
   269            )
   270          ).toBe('0x75c'))
   271  
   272        test('estimateFees', async () =>
   273          expect(
   274            await web3.op.estimateFees(
   275              {
   276                chainId: 10,
   277                data: encodedBurnMethod,
   278                type: 2,
   279                to: optimistAddress[10],
   280                from: '0x77194aa25a06f932c10c0f25090f3046af2c85a6',
   281              },
   282              hexStringFormat
   283            )
   284          ).toBeTypeOf('string'))
   285      })
   286    })
   287  
   288    describe('Contract transaction gas estimates - l2StandardBridgeABI.withdraw', () => {
   289      let l2BridgeContract: Contract<typeof l2StandardBridgeABI>
   290      let encodedWithdrawMethod: string
   291  
   292      beforeAll(() => {
   293        l2BridgeContract = new Contract(
   294          l2StandardBridgeABI,
   295          l2StandardBridgeAddress[420]
   296        )
   297        encodedWithdrawMethod = l2BridgeContract.methods
   298          .withdraw(
   299            // l2 token address
   300            '0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000',
   301            // amount
   302            Web3.utils.toWei('0.00000001', 'ether'),
   303            // l1 gas
   304            0,
   305            // extra data
   306            '0x00'
   307          )
   308          .encodeABI()
   309      })
   310  
   311      describe('should return a bigint by default', () => {
   312        test('getL1Fee', async () => {
   313          expect(
   314            await web3.op.getL1Fee({
   315              chainId: '0xa',
   316              data: encodedWithdrawMethod,
   317              type: '0x2',
   318            })
   319          ).toBeTypeOf('bigint')
   320        })
   321  
   322        test('getL1GasUsed should return 2592n', async () =>
   323          expect(
   324            await web3.op.getL1GasUsed({
   325              chainId: '0xa',
   326              data: encodedWithdrawMethod,
   327              type: '0x2',
   328            })
   329          ).toBe(BigInt(2592)))
   330  
   331        test('estimateFees', async () =>
   332          expect(
   333            await web3.op.estimateFees({
   334              chainId: 10,
   335              data: encodedWithdrawMethod,
   336              value: Web3.utils.toWei('0.00000001', 'ether'),
   337              type: 2,
   338              to: l2StandardBridgeAddress[420],
   339              from: '0x6387a88a199120aD52Dd9742C7430847d3cB2CD4',
   340              maxFeePerGas: Web3.utils.toWei('0.2', 'gwei'),
   341              maxPriorityFeePerGas: Web3.utils.toWei('0.1', 'gwei'),
   342            })
   343          ).toBeTypeOf('bigint'))
   344      })
   345    })
   346  })