From 8b21b3ceed2ab42d016427e7867d3eb4bf1f90a7 Mon Sep 17 00:00:00 2001 From: kollegian Date: Fri, 29 May 2026 17:25:54 +0300 Subject: [PATCH 1/4] tests: rpc initial setup and some tests --- integration_test/rpc_tests/.gitignore | 8 + .../rpc_tests/.mocharc.bootstrap.json | 14 + integration_test/rpc_tests/.mocharc.run.json | 20 + integration_test/rpc_tests/README.md | 216 + .../rpc_tests/_start/00_bootstrap.spec.ts | 221 + .../rpc_tests/config/endpoints.ts | 37 + .../rpc_tests/contracts/GasBurner.sol | 29 + .../rpc_tests/contracts/SimpleAccount7702.sol | 34 + .../rpc_tests/contracts/TestERC20.sol | 65 + .../rpc_tests/debug/debug_getRawBlock.spec.ts | 0 .../debug/debug_getRawHeader.spec.ts | 0 .../debug/debug_getRawReceipts.spec.ts | 0 .../debug/debug_getRawTransaction.spec.ts | 0 .../debug/debug_traceBlockByHash.spec.ts | 0 .../debug/debug_traceBlockByNumber.spec.ts | 0 .../rpc_tests/debug/debug_traceCall.spec.ts | 0 .../debug/debug_traceStateAccess.spec.ts | 0 .../debug/debug_traceTransaction.spec.ts | 0 .../debug_traceTransactionProfile.spec.ts | 0 .../rpc_tests/echo/echo_echo.spec.ts | 0 .../rpc_tests/eth/eth_accounts.spec.ts | 107 + .../rpc_tests/eth/eth_blockNumber.spec.ts | 97 + .../rpc_tests/eth/eth_call.spec.ts | 570 + .../rpc_tests/eth/eth_chainId.spec.ts | 62 + .../rpc_tests/eth/eth_coinbase.spec.ts | 137 + .../eth/eth_createAccessList.spec.ts | 0 .../rpc_tests/eth/eth_estimateGas.spec.ts | 506 + .../eth/eth_estimateGasAfterCalls.spec.ts | 0 .../rpc_tests/eth/eth_feeHistory.spec.ts | 474 + .../rpc_tests/eth/eth_gasPrice.spec.ts | 325 + .../rpc_tests/eth/eth_getBalance.spec.ts | 0 .../rpc_tests/eth/eth_getBlockByHash.spec.ts | 0 .../eth/eth_getBlockByNumber.spec.ts | 0 .../eth/eth_getBlockReceipts.spec.ts | 0 ...eth_getBlockTransactionCountByHash.spec.ts | 0 ...h_getBlockTransactionCountByNumber.spec.ts | 0 .../rpc_tests/eth/eth_getCode.spec.ts | 0 .../eth/eth_getFilterChanges.spec.ts | 0 .../rpc_tests/eth/eth_getFilterLogs.spec.ts | 0 .../rpc_tests/eth/eth_getLogs.spec.ts | 0 .../rpc_tests/eth/eth_getProof.spec.ts | 0 .../rpc_tests/eth/eth_getStorageAt.spec.ts | 0 ..._getTransactionByBlockHashAndIndex.spec.ts | 0 ...etTransactionByBlockNumberAndIndex.spec.ts | 0 .../eth/eth_getTransactionByHash.spec.ts | 0 .../eth/eth_getTransactionCount.spec.ts | 0 .../eth/eth_getTransactionErrorByHash.spec.ts | 0 .../eth/eth_getTransactionReceipt.spec.ts | 0 .../rpc_tests/eth/eth_getVMError.spec.ts | 0 .../eth/eth_maxPriorityFeePerGas.spec.ts | 0 .../rpc_tests/eth/eth_newBlockFilter.spec.ts | 0 .../rpc_tests/eth/eth_newFilter.spec.ts | 0 .../eth_newPendingTransactionFilter.spec.ts | 0 .../eth/eth_sendRawTransaction.spec.ts | 0 .../rpc_tests/eth/eth_sendTransaction.spec.ts | 0 .../rpc_tests/eth/eth_sign.spec.ts | 0 .../rpc_tests/eth/eth_signTransaction.spec.ts | 0 .../rpc_tests/eth/eth_subscribe.spec.ts | 0 .../rpc_tests/eth/eth_syncing.spec.ts | 0 .../rpc_tests/eth/eth_uninstallFilter.spec.ts | 0 integration_test/rpc_tests/hardhat.config.ts | 26 + integration_test/rpc_tests/hardhat/README.md | 37 + .../rpc_tests/hardhat/hardhat.config.ts | 50 + .../rpc_tests/net/net_version.spec.ts | 0 integration_test/rpc_tests/package-lock.json | 9368 +++++++++++++++++ integration_test/rpc_tests/package.json | 43 + integration_test/rpc_tests/runtime/.gitkeep | 0 .../rpc_tests/scripts/run-full.sh | 170 + .../rpc_tests/scripts/run-parallel.sh | 77 + integration_test/rpc_tests/tsconfig.json | 18 + integration_test/rpc_tests/utils/auth7702.ts | 73 + integration_test/rpc_tests/utils/cosmos.ts | 28 + integration_test/rpc_tests/utils/deploy.ts | 76 + integration_test/rpc_tests/utils/eip1559.ts | 99 + integration_test/rpc_tests/utils/format.ts | 31 + integration_test/rpc_tests/utils/funding.ts | 74 + integration_test/rpc_tests/utils/providers.ts | 67 + integration_test/rpc_tests/utils/rpc.ts | 110 + integration_test/rpc_tests/utils/seiAdmin.ts | 128 + integration_test/rpc_tests/utils/state.ts | 83 + .../rpc_tests/utils/testHelpers.ts | 62 + integration_test/rpc_tests/utils/waitFor.ts | 31 + integration_test/rpc_tests/utils/wallet.ts | 37 + .../rpc_tests/web3/web3_clientVersion.spec.ts | 0 84 files changed, 13610 insertions(+) create mode 100644 integration_test/rpc_tests/.gitignore create mode 100644 integration_test/rpc_tests/.mocharc.bootstrap.json create mode 100644 integration_test/rpc_tests/.mocharc.run.json create mode 100644 integration_test/rpc_tests/README.md create mode 100644 integration_test/rpc_tests/_start/00_bootstrap.spec.ts create mode 100644 integration_test/rpc_tests/config/endpoints.ts create mode 100644 integration_test/rpc_tests/contracts/GasBurner.sol create mode 100644 integration_test/rpc_tests/contracts/SimpleAccount7702.sol create mode 100644 integration_test/rpc_tests/contracts/TestERC20.sol create mode 100644 integration_test/rpc_tests/debug/debug_getRawBlock.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_getRawHeader.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_getRawReceipts.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_getRawTransaction.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_traceBlockByHash.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_traceBlockByNumber.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_traceCall.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_traceStateAccess.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_traceTransaction.spec.ts create mode 100644 integration_test/rpc_tests/debug/debug_traceTransactionProfile.spec.ts create mode 100644 integration_test/rpc_tests/echo/echo_echo.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_accounts.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_blockNumber.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_call.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_chainId.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_coinbase.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_createAccessList.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_estimateGas.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_estimateGasAfterCalls.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_feeHistory.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_gasPrice.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getBalance.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getBlockByHash.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getBlockByNumber.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getBlockReceipts.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getBlockTransactionCountByHash.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getBlockTransactionCountByNumber.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getCode.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getFilterChanges.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getFilterLogs.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getLogs.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getProof.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getStorageAt.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getTransactionByBlockHashAndIndex.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getTransactionByBlockNumberAndIndex.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getTransactionByHash.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getTransactionCount.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getTransactionErrorByHash.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getTransactionReceipt.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_getVMError.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_maxPriorityFeePerGas.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_newBlockFilter.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_newFilter.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_newPendingTransactionFilter.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_sendRawTransaction.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_sendTransaction.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_sign.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_signTransaction.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_subscribe.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_syncing.spec.ts create mode 100644 integration_test/rpc_tests/eth/eth_uninstallFilter.spec.ts create mode 100644 integration_test/rpc_tests/hardhat.config.ts create mode 100644 integration_test/rpc_tests/hardhat/README.md create mode 100644 integration_test/rpc_tests/hardhat/hardhat.config.ts create mode 100644 integration_test/rpc_tests/net/net_version.spec.ts create mode 100644 integration_test/rpc_tests/package-lock.json create mode 100644 integration_test/rpc_tests/package.json create mode 100644 integration_test/rpc_tests/runtime/.gitkeep create mode 100755 integration_test/rpc_tests/scripts/run-full.sh create mode 100755 integration_test/rpc_tests/scripts/run-parallel.sh create mode 100644 integration_test/rpc_tests/tsconfig.json create mode 100644 integration_test/rpc_tests/utils/auth7702.ts create mode 100644 integration_test/rpc_tests/utils/cosmos.ts create mode 100644 integration_test/rpc_tests/utils/deploy.ts create mode 100644 integration_test/rpc_tests/utils/eip1559.ts create mode 100644 integration_test/rpc_tests/utils/format.ts create mode 100644 integration_test/rpc_tests/utils/funding.ts create mode 100644 integration_test/rpc_tests/utils/providers.ts create mode 100644 integration_test/rpc_tests/utils/rpc.ts create mode 100644 integration_test/rpc_tests/utils/seiAdmin.ts create mode 100644 integration_test/rpc_tests/utils/state.ts create mode 100644 integration_test/rpc_tests/utils/testHelpers.ts create mode 100644 integration_test/rpc_tests/utils/waitFor.ts create mode 100644 integration_test/rpc_tests/utils/wallet.ts create mode 100644 integration_test/rpc_tests/web3/web3_clientVersion.spec.ts diff --git a/integration_test/rpc_tests/.gitignore b/integration_test/rpc_tests/.gitignore new file mode 100644 index 0000000000..6a066f2829 --- /dev/null +++ b/integration_test/rpc_tests/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +artifacts/ +cache/ +typechain-types/ +reports/ +runtime/runtime.json +hardhat/.artifacts/ +hardhat/.cache/ diff --git a/integration_test/rpc_tests/.mocharc.bootstrap.json b/integration_test/rpc_tests/.mocharc.bootstrap.json new file mode 100644 index 0000000000..71a2afea46 --- /dev/null +++ b/integration_test/rpc_tests/.mocharc.bootstrap.json @@ -0,0 +1,14 @@ +{ + "require": ["tsx"], + "timeout": 600000, + "exit": true, + "reporter": "mochawesome", + "reporter-option": [ + "reportDir=reports/new_rpc", + "reportFilename=bootstrap", + "html=false", + "json=true", + "overwrite=true" + ], + "spec": ["_start/*.spec.ts"] +} diff --git a/integration_test/rpc_tests/.mocharc.run.json b/integration_test/rpc_tests/.mocharc.run.json new file mode 100644 index 0000000000..589dd344ae --- /dev/null +++ b/integration_test/rpc_tests/.mocharc.run.json @@ -0,0 +1,20 @@ +{ + "require": ["tsx"], + "timeout": 600000, + "exit": true, + "reporter": "mochawesome", + "reporter-option": [ + "reportDir=reports/new_rpc", + "reportFilename=run", + "html=false", + "json=true", + "overwrite=true" + ], + "spec": [ + "debug/*.spec.ts", + "echo/*.spec.ts", + "eth/*.spec.ts", + "net/*.spec.ts", + "web3/*.spec.ts" + ] +} diff --git a/integration_test/rpc_tests/README.md b/integration_test/rpc_tests/README.md new file mode 100644 index 0000000000..cc5de5d898 --- /dev/null +++ b/integration_test/rpc_tests/README.md @@ -0,0 +1,216 @@ +# rpc_tests + +Self-contained module for verifying Sei's EVM JSON-RPC against a real local +**geth** reference node. Spec files in here intentionally do **not** import from +`shared/User`, `shared/Deployer`, or any other top-level utility — everything +the suite needs (utilities, contracts, tooling) lives under +`integration_test/rpc_tests/`, and the module has its own `package.json`, +`tsconfig.json`, and Hardhat compile config so it installs and runs in isolation. + +## Install (one-time) + +```bash +cd integration_test/rpc_tests +npm install # installs ethers v6, cosmjs, @sei-js/cosmos, mocha + tsx, hardhat +npm run compile # compiles ./contracts -> ./artifacts (TestERC20, RealGasBurner, SimpleAccount7702) +``` + +## What this suite proves + +For every JSON-RPC method we care about, the spec file in `eth/`, , `debug/`, etc. answers one or more of: + +- **Happy path.** The method returns the expected value/shape for valid input. +- **Schema parity.** The response shape on Sei matches geth for the same call. +- **Empty / null handling.** Absent data is represented correctly (`[]`, `null`, + `0x`, etc.) and never as the wrong empty form. +- **Wrong params / error handling.** Bad input yields the correct JSON-RPC error + code and message — asserted **byte-for-byte against geth**. + +### Reference clients + +- **geth `--dev` (primary).** Sei vendors go-ethereum's RPC layer, so a local + `geth --dev` node reproduces geth's *exact* response and error envelopes + (e.g. `-32602 "non-array args"`). We replicate the same deploy/tx scenario on + both geth and Sei, then diff responses for the same logical operation. This is + true apples-to-apples parity for schema, errors, and execution. geth cannot + fork mainnet, so it runs an empty dev chain we drive with our own contracts. +- **anvil/Hardhat mainnet fork (optional secondary).** Only a sanity check that + Sei's response *shape* holds up against messy real-world mainnet data. It is + **not** a reliable reference for error envelopes — anvil/Hardhat reimplement + the RPC layer (Rust) and diverge from geth. Tests must never assert exact + error parity against the fork. + +## Layout + +``` +integration_test/rpc_tests/ +├── package.json # module deps + scripts (compile / rpc:* / test:rpc) +├── tsconfig.json # TypeScript config for the module +├── hardhat.config.ts # compile-only config: contracts/ -> artifacts/ +├── contracts/ # TestERC20.sol, GasBurner.sol, SimpleAccount7702.sol +├── .mocharc.bootstrap.json # runs _start/ sequentially +├── scripts/run-parallel.sh # shards specs into N mocha processes (parallel run) +├── .mocharc.run.json # single-process fallback config +├── config/endpoints.ts # env-driven endpoints +├── utils/ +│ ├── providers.ts # seiRpc() / gethRpc() / forkRpc() / bothProviders() +│ ├── rpc.ts # rawJsonRpc + rawSei/rawGeth + captureRpcError + expectJsonRpcError +│ ├── format.ts # HEX_QUANTITY / ADDRESS / HEX_DATA matchers +│ ├── wallet.ts # EvmAccount (mnemonic / privkey / random) +│ ├── funding.ts # fundEvm / fundManyEvm +│ ├── deploy.ts # deployContract / deployTestErc20 / abiOf +│ ├── state.ts # read/write runtime/runtime.json +│ └── waitFor.ts # sleep + waitUntil +├── hardhat/ # standalone fork config (chainId 1) +├── runtime/ # gitignored, holds runtime.json +├── _start/ +│ └── 00_bootstrap.spec.ts # one-time setup +└── eth/ sei/ sei2/ debug/ ... # the actual specs +``` + +## One-shot runner (recommended) + +```bash +cd integration_test/rpc_tests +npm install && npm run compile # one-time +npm run test:rpc:full +``` + +`test:rpc:full` (see `scripts/run-full.sh`) does everything end to end: + +1. `DOCKER_DETACH=true make docker-cluster-start` at the repo root and waits for the + 4-node cluster (`build/generated/launch.complete`) **and** the EVM RPC on `:8545`. +2. Starts the geth `--dev` reference node (`npm run rpc:geth`) and waits for `:9547`. +3. Runs the suite (`rpc:bootstrap` then `rpc:run`) — it does **not** abort on test + failures, so you always get a report. +4. Merges the per-phase mochawesome JSON into one combined HTML report at + `reports/merged/rpc-tests.html`. + +The geth node it starts is always killed on exit. The docker cluster is left up by +default (re-running is still safe — `docker-cluster-start` stops any prior cluster +first); set `STOP_CLUSTER=true` to tear it down too. Other knobs: `CLUSTER_TIMEOUT`, +`GETH_TIMEOUT`, `SEI_TIMEOUT`. + +## Reporting + +Each phase writes a mochawesome JSON (`reports/new_rpc/bootstrap.json`, +`reports/new_rpc/run.json`). `npm run report:merge` combines them via +`mochawesome-merge` + `mochawesome-report-generator` into a single interactive +report at `reports/merged/rpc-tests.html` (the one-shot runner does this for you). + +## Running manually + +All commands run from `integration_test/rpc_tests/`. + +```bash +# 1. In a dedicated terminal, start the geth reference node. Leave it up. +npm run rpc:geth # geth --dev on http://127.0.0.1:9547 (requires geth on PATH) + +# 2. Make sure a local Sei node is up on http://localhost:8545 (the project's +# usual local devnet, e.g. `make docker-cluster-start` from the repo root). + +# 3. (Optional) start the anvil/Hardhat mainnet fork for data-shape sanity checks. +npm run rpc:fork # http://127.0.0.1:9546 + +# 4. Run the suite. +npm run test:rpc # bootstrap + parallel run, recommended +# or, piecewise: +npm run rpc:bootstrap # writes runtime/runtime.json +npm run rpc:run # parallel run (process-sharded), requires runtime.json +npm run rpc:run:serial # single-process fallback via .mocharc.run.json +``` + +> **How parallelism + reporting coexist.** mocha's own `--parallel` mode is +> incompatible with mochawesome — its single main-process reporter can't +> consolidate worker results and writes a corrupt `results: [false]`, dropping the +> rpc specs from the merged report. So `rpc:run` (`scripts/run-parallel.sh`) shards +> the spec files into `RPC_JOBS` buckets (default 8) and runs one mocha **process** +> per bucket concurrently. Each process writes its own well-formed shard +> (`reports/new_rpc/run-.json`); `report:merge` globs them with `bootstrap.json` +> into a single combined report. Tune concurrency with `RPC_JOBS`. + +Individual files can be run with `mocha` (which picks up `tsx` via `.mocharc`): + +```bash +npx mocha --require tsx eth/eth_blockNumber.spec.ts +``` + +…but only after `npm run rpc:bootstrap` has produced `runtime/runtime.json`. + +## Configuration + +| Variable | Default | +| ----------------------- | -------------------------------------------------- | +| `SEI_EVM_RPC` | `http://localhost:8545` | +| `SEI_COSMOS_RPC` | `http://localhost:26657` | +| `SEI_REST` | `http://localhost:1317` | +| `RPC_ETH_GETH` | `http://127.0.0.1:9547` (geth --dev, primary) | +| `RPC_ETH_FORK` | `http://127.0.0.1:9546` (anvil/Hardhat, optional) | +| `ETH_MAINNET_UPSTREAM` | Alchemy mainnet URL (used only by `yarn rpc:fork`) | +| `ETH_MAINNET_FORK_BLOCK`| unset (latest) | +| `SEI_ADMIN_MNEMONIC` | local devnet admin (in `endpoints.ts`) | +| `RPC_POLLING_INTERVAL_MS`| `100` (Sei blocks are ~400ms; ethers default 4s is too slow) | + +## Authoring a new spec + +Structure every spec into the four sections (happy path / schema matching / +empty-null / wrong params), e.g.: + +```ts +import { expect } from 'chai'; +import { bothProviders } from '../utils/providers'; +import { rawSei, rawGeth, expectJsonRpcError } from '../utils/rpc'; +import { HEX_QUANTITY } from '../utils/format'; +import { readRuntimeState, RuntimeState } from '../utils/state'; + +describe('eth_getBalance', function () { + this.timeout(60 * 1000); + + const { sei, geth } = bothProviders(); + let runtime: RuntimeState; + + before(() => { + runtime = readRuntimeState(); + }); + + describe('happy path', () => { + it('returns a canonical hex quantity', async () => { + const bal = await sei.send('eth_getBalance', [runtime.funded.admin, 'latest']); + expect(bal).to.match(HEX_QUANTITY); + }); + }); + + describe('wrong params / error handling', () => { + it('rejects a missing block tag identically to geth', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_getBalance', [runtime.funded.admin]), + rawGeth('eth_getBalance', [runtime.funded.admin]), + ]); + // assert Sei matches geth's exact code + message + expect(s.error?.code).to.equal(g.error?.code); + }); + }); +}); +``` + +Rules of the road for new specs: + +1. **Read-only at runtime.** Bootstrap is the only writer of `runtime.json`. If + you need new pre-computed state, add it to the `RuntimeState` interface and + populate it in `_start/00_bootstrap.spec.ts`. +2. **Pool accounts are single-use.** Each parallel worker that needs a fresh + account should claim a different `runtime.funded.pool[i]` — usually by + hashing its spec file name or by index. +3. **No imports from `shared/`** — keep this module self-contained. +4. **Negative tests go through `rawSei` / `rawGeth`** to bypass ethers' + client-side validation, so we assert the *node's* behavior, not ethers'. +5. **geth is the error/schema source of truth.** Assert Sei matches `rawGeth` + exactly for shared methods. The anvil fork (`rawFork`) is only for real-data + shape sanity checks, never exact error parity. Sei-only methods (`sei_*`) + have no reference — just assert the Sei behavior. + +## Pending migration + +Empty placeholder spec files (`*.spec.ts` with no content) under `debug/`, +`echo/`, `net/`, and `web3/` are stubs waiting to be filled in. They are safe to +run (mocha just registers nothing) but assert nothing yet. diff --git a/integration_test/rpc_tests/_start/00_bootstrap.spec.ts b/integration_test/rpc_tests/_start/00_bootstrap.spec.ts new file mode 100644 index 0000000000..78ef66cb71 --- /dev/null +++ b/integration_test/rpc_tests/_start/00_bootstrap.spec.ts @@ -0,0 +1,221 @@ +/** + * Bootstrap for the new_rpc_tests module. + * + * Runs ONCE, sequentially, before any other spec file in this module. It is + * responsible for: + * + * 1. Verifying both endpoints (local Sei EVM RPC + local Hardhat mainnet fork) + * are reachable. We refuse to deploy anything until the reference fork is up + * because most parallel specs will compare its responses against Sei's. + * 2. Capturing chain ids and block numbers at well-defined points so spec files + * can make precise historical-state assertions (`eth_call` at the block + * before deploy, `eth_getStorageAt` at the deploy block, etc.) without + * coordinating with each other. + * 3. Deploying the common contracts (currently just TestERC20) every spec might + * need, recording their addresses, and minting an initial supply to the + * admin. + * 4. Pre-funding a small pool of fresh EVM accounts so individual specs do not + * have to fund their own throw-away signers and serialize against the admin + * nonce. Each pool entry is meant for at most one parallel spec. + * 5. Writing all of the above to runtime/runtime.json, which every other spec + * reads via utils/state.ts:readRuntimeState(). + * + * The bootstrap is the ONLY place that writes runtime.json. Spec files MUST treat + * the state as read-only — writing back to it from a parallel worker would race. + */ +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import { AdminMnemonic, Endpoints } from '../config/endpoints'; +import { gethRpc, isReachable, seiRpc } from '../utils/providers'; +import { EvmAccount } from '../utils/wallet'; +import { deployContract, deployTestErc20 } from '../utils/deploy'; +import { fundFromUnlocked, fundManyEvm } from '../utils/funding'; +import { fundAdminOnSei } from '../utils/seiAdmin'; +import { writeRuntimeState, RuntimeState } from '../utils/state'; +import { sleep } from '../utils/waitFor'; + +const POOL_SIZE = 24; +const POOL_FUND_WEI = ethers.parseEther('0.5'); +const ADMIN_MINT = ethers.parseEther('1000000'); +// Geth --dev pre-funds its dev account with 10^49 ETH, so we can seed the mirror +// deployer generously; the deploy + mint costs a tiny fraction of this. +const GETH_ADMIN_FUND_WEI = ethers.parseEther('100'); + +describe('new_rpc_tests bootstrap', function () { + this.timeout(10 * 60 * 1000); + + let admin: EvmAccount; + // Deployer/owner of the geth-side mirror. Created and funded mid-bootstrap; we + // hold its key so specs can sign geth txs against the same contract layout. + let gethAdmin: EvmAccount | undefined; + let state: Partial = {}; + + before(async () => { + admin = EvmAccount.fromMnemonic(AdminMnemonic); + }); + + it('Sei EVM RPC is reachable', async () => { + const ok = await isReachable(Endpoints.sei.evmRpc); + expect(ok, `Sei EVM RPC at ${Endpoints.sei.evmRpc} is not reachable`).to.equal(true); + }); + + it('geth reference node is reachable', async () => { + const ok = await isReachable(Endpoints.eth.geth); + expect( + ok, + `geth --dev at ${Endpoints.eth.geth} is not reachable. ` + + 'Run `yarn rpc:geth` in another terminal before running this suite.', + ).to.equal(true); + }); + + it('captures chain ids from both endpoints', async () => { + const [seiChainId, gethChainId] = await Promise.all([ + seiRpc().send('eth_chainId', []), + gethRpc().send('eth_chainId', []), + ]); + state.chainIds = { + sei: Number(seiChainId), + eth: Number(gethChainId), + }; + }); + + it('captures block heights before any deploys', async () => { + const [seiBlock, gethBlock] = await Promise.all([ + seiRpc().getBlockNumber(), + gethRpc().getBlockNumber(), + ]); + state.blocks = { + seiBeforeDeploy: seiBlock, + seiErc20Deploy: -1, + seiAfterDeploy: -1, + ethAtBootstrap: gethBlock, + ethErc20Deploy: -1, + }; + }); + + it('funds and associates the admin on Sei (mirror of UserFactory.fundAdminOnSei)', async () => { + await fundAdminOnSei(admin.address, AdminMnemonic, seiRpc()); + expect( + (await admin.balance()) > 0n, + 'admin should hold a spendable EVM balance after funding + association', + ).to.equal(true); + }); + + it('deploys the canonical TestERC20 and mints to admin', async () => { + const { address, receipt } = await deployTestErc20(admin); + // erc20Geth is filled in by the geth mirror step that runs next; simpleAccount7702 + // by the delegation-target step. + state.contracts = { erc20: address, erc20Geth: '', simpleAccount7702: '', gasBurner: '' }; + state.blocks!.seiErc20Deploy = receipt.blockNumber; + + const erc20 = new ethers.Contract( + address, + ['function mint(address,uint256)', 'function balanceOf(address) view returns (uint256)'], + admin.wallet, + ); + const mintTx = await erc20.mint(admin.address, ADMIN_MINT); + await mintTx.wait(); + + const balance: bigint = await erc20.balanceOf(admin.address); + expect(balance).to.equal(ADMIN_MINT); + }); + + it('deploys the SimpleAccount7702 delegation target on Sei', async () => { + // Shared EIP-7702 delegation implementation so specs never redeploy it. + const { address } = await deployContract(admin, 'SimpleAccount7702.sol', [], 'SimpleAccount7702'); + state.contracts!.simpleAccount7702 = address; + expect(address).to.match(/^0x[0-9a-fA-F]{40}$/); + }); + + it('deploys the RealGasBurner on Sei', async () => { + // Lets eth_estimateGas (and fee-market specs) burn arbitrary gas to push the + // base fee up without depending on other suites' traffic. + const { address } = await deployContract(admin, 'GasBurner.sol', [], 'RealGasBurner'); + state.contracts!.gasBurner = address; + expect(address).to.match(/^0x[0-9a-fA-F]{40}$/); + }); + + it('mirrors the TestERC20 deploy on the geth reference and mints to the geth admin', async () => { + const geth = gethRpc(); + + // geth --dev exposes exactly one pre-funded, auto-unlocked dev account. We + // fund a fresh key from it (node-signed) so we control the deployer locally. + const devAccounts: string[] = await geth.send('eth_accounts', []); + expect(devAccounts.length, 'geth --dev should expose a pre-funded dev account').to.be.greaterThan(0); + const devAccount = devAccounts[0]; + + gethAdmin = EvmAccount.random(geth); + await fundFromUnlocked(geth, devAccount, gethAdmin.address, GETH_ADMIN_FUND_WEI); + const funded = await gethAdmin.balance(); + expect(funded).to.equal(GETH_ADMIN_FUND_WEI); + + // Same contract, same constructor (initialOwner = deployer), same mint as Sei + // so contract-touching parity specs see an identical layout on both chains. + const { address, receipt } = await deployTestErc20(gethAdmin); + state.contracts!.erc20Geth = address; + state.blocks!.ethErc20Deploy = receipt.blockNumber; + + const erc20 = new ethers.Contract( + address, + ['function mint(address,uint256)', 'function balanceOf(address) view returns (uint256)'], + gethAdmin.wallet, + ); + // geth --dev instamines, so the deploy's `pending` nonce can briefly still + // read 0 right after the receipt; pin the mint to the mined (`latest`) nonce + // to avoid a "nonce too low" race. + const mintNonce = await geth.getTransactionCount(gethAdmin.address, 'latest'); + const mintTx = await erc20.mint(gethAdmin.address, ADMIN_MINT, { nonce: mintNonce }); + await mintTx.wait(); + + const balance: bigint = await erc20.balanceOf(gethAdmin.address); + expect(balance).to.equal(ADMIN_MINT); + }); + + it('pre-funds a pool of fresh EVM accounts', async () => { + const pool = Array.from({ length: POOL_SIZE }, () => EvmAccount.random(seiRpc())); + await fundManyEvm(admin, pool.map(p => p.address), POOL_FUND_WEI); + + // Sanity check one balance; we trust the receipts for the rest. + const sample = await pool[0].balance(); + expect(sample).to.equal(POOL_FUND_WEI); + + if (!gethAdmin) throw new Error('geth admin was not initialised by the mirror deploy step'); + state.funded = { + admin: admin.address, + gethAdmin: { + address: gethAdmin.address, + privateKey: (gethAdmin.wallet as ethers.Wallet | ethers.HDNodeWallet).privateKey, + }, + pool: pool.map(p => ({ + address: p.address, + privateKey: (p.wallet as ethers.Wallet | ethers.HDNodeWallet).privateKey, + })), + }; + }); + + it('records the post-deploy block height and writes runtime/runtime.json', async () => { + // Give the chain a moment to finalize the funding txs. + await sleep(500); + const seiAfter = await seiRpc().getBlockNumber(); + state.blocks!.seiAfterDeploy = seiAfter; + state.bootstrappedAt = new Date().toISOString(); + + const finalised = state as RuntimeState; + writeRuntimeState(finalised); + + expect(finalised.blocks.seiAfterDeploy).to.be.greaterThan( + finalised.blocks.seiBeforeDeploy, + 'expected Sei to advance at least one block during bootstrap', + ); + expect(finalised.contracts.erc20Geth, 'geth mirror contract address missing').to.match( + /^0x[0-9a-fA-F]{40}$/, + ); + expect(finalised.blocks.ethErc20Deploy, 'geth mirror deploy block missing').to.be.greaterThan(0); + expect(finalised.contracts.simpleAccount7702, 'SimpleAccount7702 address missing').to.match( + /^0x[0-9a-fA-F]{40}$/, + ); + expect(finalised.contracts.gasBurner, 'RealGasBurner address missing').to.match( + /^0x[0-9a-fA-F]{40}$/, + ); + }); +}); diff --git a/integration_test/rpc_tests/config/endpoints.ts b/integration_test/rpc_tests/config/endpoints.ts new file mode 100644 index 0000000000..5abee0c1d3 --- /dev/null +++ b/integration_test/rpc_tests/config/endpoints.ts @@ -0,0 +1,37 @@ +const env = (key: string, fallback: string): string => { + const v = process.env[key]; + return v && v.length > 0 ? v : fallback; +}; + +const envOptional = (key: string): string | undefined => { + const v = process.env[key]; + return v && v.length > 0 ? v : undefined; +}; + +export const Endpoints = { + sei: { + evmRpc: env('SEI_EVM_RPC', 'http://localhost:8545'), + cosmosRpc: env('SEI_COSMOS_RPC', 'http://localhost:26657'), + rest: env('SEI_REST', 'http://localhost:1317'), + }, + eth: { + geth: env('RPC_ETH_GETH', 'http://127.0.0.1:9547'), + fork: env('RPC_ETH_FORK', 'http://127.0.0.1:9546'), + upstream: env( + 'ETH_MAINNET_UPSTREAM', + 'https://eth-mainnet.g.alchemy.com/v2/Dmh5eMv-DYo4wvFHE2e3E', + ), + forkBlock: envOptional('ETH_MAINNET_FORK_BLOCK'), + }, + accountless: env('RPC_ACCOUNTLESS', 'https://evm-rpc.sei-apis.com'), +} as const; + +export const AdminMnemonic = env( + 'SEI_ADMIN_MNEMONIC', + 'cover brand danger absent gas worth sustain rural powder auction shadow find merge domain promote glimpse burger embody favorite lake rain plate present soda', +); + +export const RuntimeStatePath = env( + 'RPC_TESTS_RUNTIME_STATE', + 'runtime/runtime.json', +); diff --git a/integration_test/rpc_tests/contracts/GasBurner.sol b/integration_test/rpc_tests/contracts/GasBurner.sol new file mode 100644 index 0000000000..4d2f239925 --- /dev/null +++ b/integration_test/rpc_tests/contracts/GasBurner.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/** + * RealGasBurner burns a deterministic, caller-controlled amount of gas by doing + * real SSTOREs in a loop. Fee-market specs (eth_feeHistory / eth_gasPrice / + * eth_estimateGas) call `burnGasIterations` to push the base fee up without + * depending on other suites' traffic. + * + * The writes are kept non-trivial (hash-chained into storage) so the optimizer + * cannot elide them, guaranteeing the gas is actually consumed. + */ +contract RealGasBurner { + uint256 public accumulator; + mapping(uint256 => uint256) public sink; + + /** + * @param salt Distinguishes otherwise-identical calls so each writes unique slots. + * @param iterations Number of storage-writing rounds to perform. + */ + function burnGasIterations(uint256 salt, uint256 iterations) external { + uint256 acc = accumulator; + for (uint256 i = 0; i < iterations; i++) { + acc = uint256(keccak256(abi.encode(acc, salt, i))); + sink[acc % 256] = acc; + } + accumulator = acc; + } +} diff --git a/integration_test/rpc_tests/contracts/SimpleAccount7702.sol b/integration_test/rpc_tests/contracts/SimpleAccount7702.sol new file mode 100644 index 0000000000..b5df0577f7 --- /dev/null +++ b/integration_test/rpc_tests/contracts/SimpleAccount7702.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/** + * Minimal EIP-7702 delegation target. An EOA delegates to this implementation via + * a type-4 SetCode transaction, after which calls to the EOA execute this code in + * the EOA's context (so `address(this)` is the EOA). `executeBatch` lets the + * delegated account perform a list of calls atomically — enough for the RPC + * suite's 7702 parity specs. + */ +contract SimpleAccount7702 { + struct Call { + address target; + uint256 value; + bytes data; + } + + event BatchExecuted(uint256 count); + + function executeBatch(Call[] calldata calls) external payable { + for (uint256 i = 0; i < calls.length; i++) { + Call calldata c = calls[i]; + (bool ok, bytes memory ret) = c.target.call{value: c.value}(c.data); + if (!ok) { + assembly { + revert(add(ret, 0x20), mload(ret)) + } + } + } + emit BatchExecuted(calls.length); + } + + receive() external payable {} +} diff --git a/integration_test/rpc_tests/contracts/TestERC20.sol b/integration_test/rpc_tests/contracts/TestERC20.sol new file mode 100644 index 0000000000..9714dea717 --- /dev/null +++ b/integration_test/rpc_tests/contracts/TestERC20.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/** + * Minimal, self-contained ERC20 used as the canonical contract across the RPC + * suite. Deployed identically on Sei and the geth reference so contract-touching + * parity specs see the same layout on both chains. + * + * Constructor takes `initialOwner` purely to mirror an Ownable-style deployment; + * `mint` is intentionally permissionless so any test signer can top itself up. + */ +contract TestERC20 { + string public name = "TestERC20"; + string public symbol = "TERC20"; + uint8 public constant decimals = 18; + + uint256 public totalSupply; + address public owner; + + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + + constructor(address initialOwner) { + owner = initialOwner; + } + + function transfer(address to, uint256 value) external returns (bool) { + _transfer(msg.sender, to, value); + return true; + } + + function approve(address spender, uint256 value) external returns (bool) { + allowance[msg.sender][spender] = value; + emit Approval(msg.sender, spender, value); + return true; + } + + function transferFrom(address from, address to, uint256 value) external returns (bool) { + uint256 allowed = allowance[from][msg.sender]; + require(allowed >= value, "ERC20: insufficient allowance"); + if (allowed != type(uint256).max) { + allowance[from][msg.sender] = allowed - value; + } + _transfer(from, to, value); + return true; + } + + function mint(address to, uint256 value) external { + totalSupply += value; + balanceOf[to] += value; + emit Transfer(address(0), to, value); + } + + function _transfer(address from, address to, uint256 value) internal { + require(balanceOf[from] >= value, "ERC20: insufficient balance"); + unchecked { + balanceOf[from] -= value; + balanceOf[to] += value; + } + emit Transfer(from, to, value); + } +} diff --git a/integration_test/rpc_tests/debug/debug_getRawBlock.spec.ts b/integration_test/rpc_tests/debug/debug_getRawBlock.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_getRawHeader.spec.ts b/integration_test/rpc_tests/debug/debug_getRawHeader.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_getRawReceipts.spec.ts b/integration_test/rpc_tests/debug/debug_getRawReceipts.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_getRawTransaction.spec.ts b/integration_test/rpc_tests/debug/debug_getRawTransaction.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_traceBlockByHash.spec.ts b/integration_test/rpc_tests/debug/debug_traceBlockByHash.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_traceBlockByNumber.spec.ts b/integration_test/rpc_tests/debug/debug_traceBlockByNumber.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_traceCall.spec.ts b/integration_test/rpc_tests/debug/debug_traceCall.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_traceStateAccess.spec.ts b/integration_test/rpc_tests/debug/debug_traceStateAccess.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_traceTransaction.spec.ts b/integration_test/rpc_tests/debug/debug_traceTransaction.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/debug/debug_traceTransactionProfile.spec.ts b/integration_test/rpc_tests/debug/debug_traceTransactionProfile.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/echo/echo_echo.spec.ts b/integration_test/rpc_tests/echo/echo_echo.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_accounts.spec.ts b/integration_test/rpc_tests/eth/eth_accounts.spec.ts new file mode 100644 index 0000000000..3c3ab51ce1 --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_accounts.spec.ts @@ -0,0 +1,107 @@ +import { expect } from 'chai'; +import { bothProviders, isReachable } from '../utils/providers'; +import { rawSei, rawGeth, rawAccountless, expectJsonRpcError } from '../utils/rpc'; +import { ADDRESS, ADDRESS_LOWER } from '../utils/format'; +import { Endpoints } from '../config/endpoints'; + +describe('eth_accounts', function () { + this.timeout(60 * 1000); + + const { sei, geth } = bothProviders(); + + describe('Accounts queries', () => { + it('returns a JSON array', async () => { + const accounts = await sei.send('eth_accounts', []); + expect(accounts).to.be.an('array'); + }); + + it('every entry is a well-formed 20-byte address', async () => { + const accounts: string[] = await sei.send('eth_accounts', []); + for (const acct of accounts) { + expect(acct, `account ${acct}`).to.match(ADDRESS); + } + }); + + it('contains no duplicate addresses', async () => { + const accounts: string[] = await sei.send('eth_accounts', []); + const lower = accounts.map(a => a.toLowerCase()); + expect(new Set(lower).size).to.equal(lower.length); + }); + + it('returns the same set of accounts across repeated calls', async () => { + // NOTE: Sei does not guarantee a stable *order* — it serializes the keyring + // from a Go map, so the order varies call-to-call (geth, by contrast, returns + // stable insertion order). Consumers must treat the result as a set, not a + // positional list. We assert the sorted set is stable. + const results: string[][] = await Promise.all( + Array.from({ length: 4 }, () => sei.send('eth_accounts', [])), + ); + const sortedSet = (a: string[]) => [...a].map(x => x.toLowerCase()).sort(); + const baseline = sortedSet(results[0]); + for (const r of results) { + expect(sortedSet(r)).to.deep.equal(baseline); + } + }); + }); + + // ── 2. Schema matching vs the geth reference ──────────────────────────────── + describe('schema matching', () => { + it('Sei and geth both return arrays of address strings', async () => { + const [seiAccounts, gethAccounts] = await Promise.all([ + sei.send('eth_accounts', []), + geth.send('eth_accounts', []), + ]); + + expect(seiAccounts).to.be.an('array'); + expect(gethAccounts).to.be.an('array'); + for (const acct of [...seiAccounts, ...gethAccounts]) { + expect(acct).to.be.a('string'); + expect(acct).to.match(ADDRESS); + } + }); + + it('Sei and geth both serialize addresses in lower-case (non-checksummed) form', async () => { + const [seiAccounts, gethAccounts] = await Promise.all([ + sei.send('eth_accounts', []), + geth.send('eth_accounts', []), + ]); + for (const acct of [...seiAccounts, ...gethAccounts]) { + expect(acct, `account ${acct}`).to.match(ADDRESS_LOWER); + } + }); + }); + + describe('empty / null handling', () => { + it('a keyless node returns [] (empty array), never null', async function () { + const body = await rawAccountless('eth_accounts', []); + console.log(body); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result, 'keyless node must encode the empty set as []').to.deep.equal([]); + expect(body.result).to.not.equal(null); + }); + }); + + describe('wrong params / error handling', () => { + it('Sei rejects an extra positional parameter with -32602, identically to geth', async () => { + const [seiBody, gethBody] = await Promise.all([ + rawSei('eth_accounts', ['latest']), + rawGeth('eth_accounts', ['latest']), + ]); + expectJsonRpcError(seiBody, -32602, /too many arguments, want at most 0/i); + expectJsonRpcError(gethBody, -32602, /too many arguments, want at most 0/i); + expect(seiBody.error?.code).to.equal(gethBody.error?.code); + expect(seiBody.error?.message).to.equal(gethBody.error?.message); + }); + + it('Sei rejects non-array params with -32602 non-array args, identically to geth', async () => { + const [seiBody, gethBody] = await Promise.all([ + rawSei('eth_accounts', 'latest'), + rawGeth('eth_accounts', 'latest'), + ]); + expectJsonRpcError(seiBody, -32602, /non-array args/i); + expectJsonRpcError(gethBody, -32602, /non-array args/i); + expect(seiBody.error?.code).to.equal(gethBody.error?.code); + expect(seiBody.error?.message).to.equal(gethBody.error?.message); + }); + }); +}); diff --git a/integration_test/rpc_tests/eth/eth_blockNumber.spec.ts b/integration_test/rpc_tests/eth/eth_blockNumber.spec.ts new file mode 100644 index 0000000000..c4b8bf840e --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_blockNumber.spec.ts @@ -0,0 +1,97 @@ +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import { bothProviders } from '../utils/providers'; +import { rawSei, rawGeth, expectJsonRpcError } from '../utils/rpc'; +import { readRuntimeState, RuntimeState } from '../utils/state'; +import { HEX_QUANTITY } from '../utils/format'; +import { sleep } from '../utils/waitFor'; + +describe('eth_blockNumber', function () { + this.timeout(60 * 1000); + + const { sei, geth } = bothProviders(); + let runtime: RuntimeState; + + before(() => { + runtime = readRuntimeState(); + }); + + describe('happy path', () => { + it('returns a canonical hex quantity > 0', async () => { + const hex = await sei.send('eth_blockNumber', []); + expect(hex).to.match(HEX_QUANTITY); + expect(ethers.toNumber(hex)).to.be.greaterThan(0); + }); + + it('agrees with ethers Provider.getBlockNumber()', async () => { + const [raw, viaProvider] = await Promise.all([ + sei.send('eth_blockNumber', []), + sei.getBlockNumber(), + ]); + // Heights can advance by a block between the two calls; allow a small drift. + expect(Math.abs(ethers.toNumber(raw) - viaProvider)).to.be.lte(2); + }); + }); + + describe('schema matching', () => { + it('Sei and geth both return canonical hex quantities', async () => { + const [seiHex, gethHex] = await Promise.all([ + sei.send('eth_blockNumber', []), + geth.send('eth_blockNumber', []), + ]); + expect(seiHex, 'sei').to.match(HEX_QUANTITY); + expect(gethHex, 'geth').to.match(HEX_QUANTITY); + }); + + it('the value parses to a safe positive integer', async () => { + const hex = await sei.send('eth_blockNumber', []); + const n = ethers.toNumber(hex); + expect(Number.isSafeInteger(n)).to.equal(true); + expect(n).to.be.greaterThan(0); + }); + + it('has no leading zeros in the hex encoding', async () => { + const hex: string = await sei.send('eth_blockNumber', []); + expect(hex === '0x0' || !/^0x0/.test(hex), `non-minimal encoding: ${hex}`).to.equal(true); + }); + }); + + describe('empty / null handling', () => { + it('never returns null or undefined', async () => { + const hex = await sei.send('eth_blockNumber', []); + expect(hex).to.not.equal(null); + expect(hex).to.not.equal(undefined); + }); + + it('always returns a non-empty hex string (raw transport)', async () => { + const body = await rawSei('eth_blockNumber', []); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result).to.be.a('string'); + expect(body.result).to.match(HEX_QUANTITY); + }); + }); + + describe('wrong params / error handling', () => { + it('Sei rejects an extra positional parameter with -32602, identically to geth', async () => { + const [seiBody, gethBody] = await Promise.all([ + rawSei('eth_blockNumber', ['latest']), + rawGeth('eth_blockNumber', ['latest']), + ]); + expectJsonRpcError(seiBody, -32602, /too many arguments, want at most 0/i); + expectJsonRpcError(gethBody, -32602, /too many arguments, want at most 0/i); + expect(seiBody.error?.code).to.equal(gethBody.error?.code); + expect(seiBody.error?.message).to.equal(gethBody.error?.message); + }); + + it('Sei rejects non-array params with -32602 non-array args, identically to geth', async () => { + const [seiBody, gethBody] = await Promise.all([ + rawSei('eth_blockNumber', 'latest'), + rawGeth('eth_blockNumber', 'latest'), + ]); + expectJsonRpcError(seiBody, -32602, /non-array args/i); + expectJsonRpcError(gethBody, -32602, /non-array args/i); + expect(seiBody.error?.code).to.equal(gethBody.error?.code); + expect(seiBody.error?.message).to.equal(gethBody.error?.message); + }); + }); +}); diff --git a/integration_test/rpc_tests/eth/eth_call.spec.ts b/integration_test/rpc_tests/eth/eth_call.spec.ts new file mode 100644 index 0000000000..7d28ab93f1 --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_call.spec.ts @@ -0,0 +1,570 @@ +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import { bothProviders } from '../utils/providers'; +import { rawSei, rawGeth, captureRpcError, expectJsonRpcError } from '../utils/rpc'; +import { readRuntimeState, RuntimeState } from '../utils/state'; +import { abiOf } from '../utils/deploy'; +import { EvmAccount } from '../utils/wallet'; +import { HEX_DATA } from '../utils/format'; +import { SIMPLE_ACCOUNT_ABI, delegationDesignator, selfAuthorize, setCodeForEOA } from '../utils/auth7702'; +import { Erc20Calldata, claimPool, encodeUint, expectSameError } from '../utils/testHelpers'; + +describe('eth_call', function () { + this.timeout(120 * 1000); + + const { sei, geth } = bothProviders(); + const erc20Iface = new ethers.Interface(abiOf('TestERC20.sol', 'TestERC20')); + const erc20 = new Erc20Calldata(erc20Iface); + const STAKING_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000001005'; + const ADMIN_MINT = ethers.parseEther('1000000'); + + let runtime: RuntimeState; + let erc20Sei: string; + let erc20Geth: string; + let seiAdmin: string; + let gethAdmin: string; + + // Claimed from the pre-funded pool to avoid serialising on the shared admin nonce. + let minter: EvmAccount; + let alice: EvmAccount; + let aliceRevert: EvmAccount; + let simpleAccountAddress: string; + + before(async function () { + runtime = readRuntimeState(); + erc20Sei = runtime.contracts.erc20; + erc20Geth = runtime.contracts.erc20Geth; + seiAdmin = runtime.funded.admin; + gethAdmin = runtime.funded.gethAdmin.address; + + [minter, alice, aliceRevert] = claimPool(runtime, sei, 3, 'eth_call'); + simpleAccountAddress = runtime.contracts.simpleAccount7702; + }); + + describe('happy path', () => { + it('balanceOf returns the expected balance at latest', async () => { + const result = await sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + 'latest', + ]); + expect(erc20.decodeBalance(result)).to.equal(ADMIN_MINT); + }); + + it('omitting the block tag defaults to latest', async () => { + const [withoutTag, withLatest] = await Promise.all([ + sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }]), + sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, 'latest']), + ]); + expect(withoutTag).to.equal(withLatest); + }); + + it('a call against an EOA (no code) returns 0x', async () => { + const result = await sei.send('eth_call', [ + { to: seiAdmin, data: '0x12345678' }, + 'latest', + ]); + expect(result).to.equal('0x'); + }); + + it('simulating an ERC20 transfer does not change state', async () => { + const before = erc20.decodeBalance( + await sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, 'latest']), + ); + const simulated = await sei.send('eth_call', [ + { from: seiAdmin, to: erc20Sei, data: erc20.transfer(seiAdmin, ethers.parseEther('1')) }, + 'latest', + ]); + expect(erc20Iface.decodeFunctionResult('transfer', simulated)[0]).to.equal(true); + + const after = erc20.decodeBalance( + await sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, 'latest']), + ); + expect(after).to.equal(before); + }); + + it('a call at a block before the contract was deployed returns 0x', async () => { + const result = await sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + ethers.toQuantity(runtime.blocks.seiBeforeDeploy), + ]); + expect(result).to.equal('0x'); + }); + + it('respects historical state across distinct mint blocks and does not leak latest state', async () => { + const recipient = ethers.Wallet.createRandom().address; + const FIRST_MINT = ethers.parseEther('100'); + const SECOND_MINT = ethers.parseEther('50'); + + const blockBeforeFirstMint = await sei.getBlockNumber(); + const erc20Contract = new ethers.Contract(erc20Sei, erc20Iface, minter.wallet); + + const firstReceipt = await (await erc20Contract.mint(recipient, FIRST_MINT)).wait(); + const blockOfFirstMint = firstReceipt!.blockNumber; + const secondReceipt = await (await erc20Contract.mint(recipient, SECOND_MINT)).wait(); + const blockOfSecondMint = secondReceipt!.blockNumber; + + expect(blockOfSecondMint).to.be.greaterThan( + blockOfFirstMint, + 'second mint must land in a strictly later block', + ); + + const balanceAt = async (block: number): Promise => + erc20.decodeBalance( + await sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(recipient) }, + ethers.toQuantity(block), + ]), + ); + + expect(await balanceAt(blockBeforeFirstMint)).to.equal(0n); + expect(await balanceAt(blockOfFirstMint)).to.equal(FIRST_MINT); + expect(await balanceAt(blockOfSecondMint - 1)).to.equal(FIRST_MINT); + expect(await balanceAt(blockOfSecondMint)).to.equal(FIRST_MINT + SECOND_MINT); + }); + + it('accepts an EIP-1898 blockNumber object equivalently to a tag', async () => { + const latest = await sei.getBlockNumber(); + const [viaTag, viaObject] = await Promise.all([ + sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, ethers.toQuantity(latest)]), + sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + { blockNumber: ethers.toQuantity(latest) }, + ]), + ]); + expect(viaObject).to.equal(viaTag); + }); + + it('accepts an EIP-1898 blockHash object equivalently to a tag', async () => { + const latest = await sei.getBlock('latest'); + expect(latest, 'latest block should exist').to.not.equal(null); + const [viaTag, viaObject] = await Promise.all([ + sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, ethers.toQuantity(latest!.number)]), + sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, { blockHash: latest!.hash! }]), + ]); + expect(viaObject).to.equal(viaTag); + }); + + it('returns the same result across latest, pending, safe and finalized tags', async () => { + const latest = await sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, 'latest']); + for (const tag of ['pending', 'safe', 'finalized']) { + const result = await sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, tag]); + expect(result, `tag ${tag} must equal latest`).to.equal(latest); + } + }); + + it('Honours a state override that replaces contract bytecode', async () => { + const stub = '0x7f00000000000000000000000000000000000000000000000000000000deadbeef60005260206000f3'; + const result = await sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + 'latest', + { [erc20Sei.toLowerCase()]: { code: stub } }, + ]); + expect(result).to.equal( + '0x00000000000000000000000000000000000000000000000000000000deadbeef', + ); + }); + + it('[Sei-specific] the staking validators() precompile decodes to a complete ValidatorsResponse', async () => { + // ValidatorsResponse { Validator[] validators; bytes nextKey; } + // see sei-chain/precompiles/staking/Staking.sol. + const iface = new ethers.Interface([ + 'function validators(string status, bytes nextKey) view returns (' + + 'tuple(tuple(string operatorAddress, bytes consensusPubkey, bool jailed, int32 status, ' + + 'string tokens, string delegatorShares, string description, int64 unbondingHeight, ' + + 'int64 unbondingTime, string commissionRate, string commissionMaxRate, ' + + 'string commissionMaxChangeRate, int64 commissionUpdateTime, string minSelfDelegation)[] ' + + 'validators, bytes nextKey) response)', + ]); + const data = iface.encodeFunctionData('validators', ['BOND_STATUS_BONDED', '0x']); + const result = await sei.send('eth_call', [{ to: STAKING_PRECOMPILE_ADDRESS, data }, 'latest']); + expect(result).to.match(HEX_DATA); + + const [response] = iface.decodeFunctionResult('validators', result); + const validators = response.validators as ReadonlyArray<{ + operatorAddress: string; + consensusPubkey: string; + jailed: boolean; + status: bigint; + tokens: string; + commissionRate: string; + }>; + + expect(validators.length, 'the devnet exposes bonded validators').to.be.greaterThan(0); + expect(response.nextKey, 'a single page covers all validators').to.equal('0x'); + + for (const v of validators) { + expect(v.operatorAddress, 'bech32 valoper address').to.match(/^seivaloper1[0-9a-z]{38}$/); + expect(Number(v.status), 'BOND_STATUS_BONDED == 3').to.equal(3); + expect(v.jailed, 'a bonded validator is not jailed').to.equal(false); + expect(BigInt(v.tokens) > 0n, `staked tokens positive (got ${v.tokens})`).to.equal(true); + expect(v.consensusPubkey, 'consensus pubkey present').to.match(HEX_DATA); + expect(v.consensusPubkey.length, 'consensus pubkey non-empty').to.be.greaterThan(2); + expect(v.commissionRate, 'commission rate present').to.match(/^\d+\.\d+$/); + } + }); + }); + + describe('schema matching', () => { + it('balanceOf returns identical 32-byte data on Sei and geth (same minted amount)', async () => { + const [seiResult, gethResult] = await Promise.all([ + sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, 'latest']), + geth.send('eth_call', [{ to: erc20Geth, data: erc20.balanceOf(gethAdmin) }, 'latest']), + ]); + expect(seiResult, 'sei').to.match(HEX_DATA); + expect(gethResult, 'geth').to.match(HEX_DATA); + expect(erc20.decodeBalance(seiResult)).to.equal(ADMIN_MINT); + expect(erc20.decodeBalance(gethResult)).to.equal(ADMIN_MINT); + expect(seiResult).to.equal(gethResult); + }); + + it('a call against an EOA returns 0x on both Sei and geth', async () => { + const [seiResult, gethResult] = await Promise.all([ + sei.send('eth_call', [{ to: seiAdmin, data: '0x12345678' }, 'latest']), + geth.send('eth_call', [{ to: gethAdmin, data: '0x12345678' }, 'latest']), + ]); + expect(seiResult).to.equal('0x'); + expect(gethResult).to.equal('0x'); + }); + + it('a call before the contract existed returns 0x on both Sei and geth', async () => { + const [seiResult, gethResult] = await Promise.all([ + sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + ethers.toQuantity(runtime.blocks.seiBeforeDeploy), + ]), + geth.send('eth_call', [ + { to: erc20Geth, data: erc20.balanceOf(gethAdmin) }, + ethers.toQuantity(runtime.blocks.ethErc20Deploy - 1), + ]), + ]); + expect(seiResult).to.equal('0x'); + expect(gethResult).to.equal('0x'); + }); + + it('historical state transitions are byte-identical across the contract lifecycle on Sei and geth', async () => { + // before deploy ("0x") → deploy block, pre-mint (zero word) → post-mint (ADMIN_MINT). + const [seiPhases, gethPhases] = await Promise.all([ + Promise.all([ + sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + ethers.toQuantity(runtime.blocks.seiBeforeDeploy), + ]), + sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + ethers.toQuantity(runtime.blocks.seiErc20Deploy), + ]), + sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + ethers.toQuantity(runtime.blocks.seiAfterDeploy), + ]), + ]), + Promise.all([ + geth.send('eth_call', [ + { to: erc20Geth, data: erc20.balanceOf(gethAdmin) }, + ethers.toQuantity(runtime.blocks.ethErc20Deploy - 1), + ]), + geth.send('eth_call', [ + { to: erc20Geth, data: erc20.balanceOf(gethAdmin) }, + ethers.toQuantity(runtime.blocks.ethErc20Deploy), + ]), + geth.send('eth_call', [{ to: erc20Geth, data: erc20.balanceOf(gethAdmin) }, 'latest']), + ]), + ]); + + const expected = ['0x', encodeUint(0n), encodeUint(ADMIN_MINT)]; + expect(seiPhases, 'sei lifecycle').to.deep.equal(expected); + expect(gethPhases, 'geth lifecycle').to.deep.equal(expected); + expect(seiPhases, 'lifecycle parity').to.deep.equal(gethPhases); + }); + + it('a state override replacing bytecode yields identical output on Sei and geth', async () => { + const stub = '0x7f00000000000000000000000000000000000000000000000000000000deadbeef60005260206000f3'; + const [seiResult, gethResult] = await Promise.all([ + sei.send('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + 'latest', + { [erc20Sei.toLowerCase()]: { code: stub } }, + ]), + geth.send('eth_call', [ + { to: erc20Geth, data: erc20.balanceOf(gethAdmin) }, + 'latest', + { [erc20Geth.toLowerCase()]: { code: stub } }, + ]), + ]); + expect(seiResult).to.equal(gethResult); + expect(seiResult).to.equal( + '0x00000000000000000000000000000000000000000000000000000000deadbeef', + ); + }); + }); + + describe('empty / null handling', () => { + it('a void call returns the canonical "0x", not null (raw transport)', async () => { + const body = await rawSei('eth_call', [{ to: seiAdmin, data: '0x' }, 'latest']); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result).to.equal('0x'); + expect(body.result).to.not.equal(null); + }); + + it('a successful read never returns null (raw transport)', async () => { + const body = await rawSei('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + 'latest', + ]); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result).to.be.a('string'); + expect(body.result).to.match(HEX_DATA); + }); + }); + + describe('wrong params / error handling', () => { + it('rejects an invalid block tag identically to geth (-32602, exact message)', async () => { + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data }, 'banana']), + rawGeth('eth_call', [{ to: erc20Geth, data }, 'banana']), + ]); + expectJsonRpcError(s, -32602, /hex string without 0x prefix/); + expectSameError(s, g); + }); + + it('rejects a malformed from address identically to geth (-32602, exact message)', async () => { + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ from: '0xdeadbeef', to: erc20Sei, data }, 'latest']), + rawGeth('eth_call', [{ from: '0xdeadbeef', to: erc20Geth, data }, 'latest']), + ]); + expectJsonRpcError(s, -32602, /hex string has length 8, want 40 for common\.Address/); + expectSameError(s, g); + }); + + it('rejects an odd-length to address identically to geth (-32602, exact message)', async () => { + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: '0x123', data }, 'latest']), + rawGeth('eth_call', [{ to: '0x123', data }, 'latest']), + ]); + expectJsonRpcError(s, -32602, /unmarshal hex string of odd length .*TransactionArgs\.to/); + expectSameError(s, g); + }); + + it('rejects non-hex data identically to geth (-32602, exact message)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data: 'notHex' }, 'latest']), + rawGeth('eth_call', [{ to: erc20Geth, data: 'notHex' }, 'latest']), + ]); + expectJsonRpcError(s, -32602, /without 0x prefix .*TransactionArgs\.data of type hexutil\.Bytes/); + expectSameError(s, g); + }); + + it('rejects odd-length data identically to geth (-32602, exact message)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data: '0x123' }, 'latest']), + rawGeth('eth_call', [{ to: erc20Geth, data: '0x123' }, 'latest']), + ]); + expectJsonRpcError(s, -32602, /odd length .*TransactionArgs\.data of type hexutil\.Bytes/); + expectSameError(s, g); + }); + + it('rejects a non-hex gas value identically to geth (-32602, exact message)', async () => { + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data, gas: '-0x1' }, 'latest']), + rawGeth('eth_call', [{ to: erc20Geth, data, gas: '-0x1' }, 'latest']), + ]); + expectJsonRpcError(s, -32602, /TransactionArgs\.gas of type hexutil\.Uint64/); + expectSameError(s, g); + }); + + it('rejects non-array params identically to geth (-32602 "non-array args")', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_call', { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }), + rawGeth('eth_call', { to: erc20Geth, data: erc20.balanceOf(gethAdmin) }), + ]); + expectJsonRpcError(s, -32602, /^non-array args$/); + expectSameError(s, g); + }); + + it('rejects empty params identically to geth (-32602 missing required argument 0)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_call', []), + rawGeth('eth_call', []), + ]); + expectJsonRpcError(s, -32602, /missing value for required argument 0/); + expectSameError(s, g); + }); + + it('rejects too many positional args identically to geth (-32602 "want at most 4")', async () => { + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data }, 'latest', {}, {}, {}]), + rawGeth('eth_call', [{ to: erc20Geth, data }, 'latest', {}, {}, {}]), + ]); + expectJsonRpcError(s, -32602, /too many arguments, want at most 4/); + expectSameError(s, g); + }); + + it('rejects gas below the intrinsic minimum identically to geth (-32000, exact "want" value)', async () => { + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data, gas: '0x10' }, 'latest']), + rawGeth('eth_call', [{ to: erc20Geth, data, gas: '0x10' }, 'latest']), + ]); + expectJsonRpcError(s, -32000, /intrinsic gas too low: have 16, want \d+ \(supplied gas 16\)/); + expectSameError(s, g); + }); + + it('treats a missing to-address as contract creation identically to geth (-32000 invalid opcode)', async () => { + // No `to` ⇒ the calldata is run as init code, hitting an invalid opcode. + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ data }, 'latest']), + rawGeth('eth_call', [{ data }, 'latest']), + ]); + expectJsonRpcError(s, -32000, /invalid opcode/); + expectSameError(s, g); + }); + + it('surfaces a revert with identical code 3, message and ABI-encoded error data on both', async () => { + const huge = ethers.parseEther('1000000000'); + const data = erc20.transfer(seiAdmin, huge); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data }, 'latest']), + rawGeth('eth_call', [{ to: erc20Geth, data }, 'latest']), + ]); + const err = expectJsonRpcError(s, 3, /execution reverted/i); + expect(err.data).to.equal( + '0x96c6fd1e0000000000000000000000000000000000000000000000000000000000000000', + ); + expectSameError(s, g); + }); + + it('[divergence] value sent to a non-payable function: geth → code 3 (data 0x), Sei → -32000', async () => { + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ from: seiAdmin, to: erc20Sei, data, value: '0x1' }, 'latest']), + rawGeth('eth_call', [{ from: gethAdmin, to: erc20Geth, data, value: '0x1' }, 'latest']), + ]); + expectJsonRpcError(g, 3, /execution reverted/i); + expect(g.error!.data, 'geth attaches empty revert data').to.equal('0x'); + expectJsonRpcError(s, -32000, /execution reverted/i); + expect(s.error!.data, 'Sei omits the revert data here').to.equal(undefined); + expect(s.error!.code, 'documented divergence in error code').to.not.equal(g.error!.code); + }); + + it('[divergence] far-future block: both -32000 but different messages', async () => { + const latest = await sei.getBlockNumber(); + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data }, ethers.toQuantity(latest + 1_000_000)]), + rawGeth('eth_call', [{ to: erc20Geth, data }, '0xffffffff']), + ]); + expect(s.error?.code, 'sei code').to.equal(-32000); + expect(g.error?.code, 'geth code').to.equal(-32000); + expect(s.error?.code, 'codes still agree').to.equal(g.error?.code); + expect(s.error?.message).to.match(/not yet available/i); + expect(g.error?.message).to.match(/header not found/i); + expect(s.error?.message, 'documented divergence in message').to.not.equal(g.error?.message); + }); + + it('[divergence] unknown block hash: both -32000 but different messages', async () => { + const zeroHash = '0x' + '00'.repeat(32); + const data = erc20.balanceOf(seiAdmin); + const [s, g] = await Promise.all([ + rawSei('eth_call', [{ to: erc20Sei, data }, { blockHash: zeroHash }]), + rawGeth('eth_call', [{ to: erc20Geth, data }, { blockHash: zeroHash }]), + ]); + expect(s.error?.code, 'sei code').to.equal(-32000); + expect(g.error?.code, 'geth code').to.equal(-32000); + expect(s.error?.code, 'codes still agree').to.equal(g.error?.code); + expect(s.error?.message).to.match(/block not found by hash/i); + expect(g.error?.message).to.match(/header for hash not found/i); + expect(s.error?.message, 'documented divergence in message').to.not.equal(g.error?.message); + }); + + // A pruning node rejects genesis with -32000; a node whose EVM module postdates + // genesis rejects it as "evm module does not exist"; a full-history node serves + // it and returns "0x" since the contract did not exist that early. + const earlyState = /pruned|evm module does not exist/i; + + it('[Sei-specific] the earliest tag either errors (-32000) or reads genesis state (0x)', async () => { + const body = await rawSei('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + 'earliest', + ]); + if (body.error) { + expect(body.error.code).to.equal(-32000); + expect(body.error.message).to.match(earlyState); + } else { + expect(body.result).to.equal('0x'); + } + }); + + it('[Sei-specific] an early historical block either errors (-32000) or reads pre-deploy state (0x)', async () => { + const body = await rawSei('eth_call', [ + { to: erc20Sei, data: erc20.balanceOf(seiAdmin) }, + '0x1', + ]); + if (body.error) { + expect(body.error.code).to.equal(-32000); + expect(body.error.message).to.match(earlyState); + } else { + expect(body.result).to.equal('0x'); + } + }); + }); + + describe('EIP-7702 delegated execution', () => { + const accountIface = new ethers.Interface(SIMPLE_ACCOUNT_ABI); + + it('dispatches into the delegated implementation and returns 0x for a void executeBatch', async () => { + const receipt = await setCodeForEOA(alice, [await selfAuthorize(alice, simpleAccountAddress)]); + expect(receipt?.status).to.equal(1); + + const code = await sei.send('eth_getCode', [alice.address, 'latest']); + expect(code.toLowerCase()).to.equal(delegationDesignator(simpleAccountAddress)); + + const balanceBefore = erc20.decodeBalance( + await sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(alice.address) }, 'latest']), + ); + const mintCall = { + target: erc20Sei, + value: 0n, + data: erc20Iface.encodeFunctionData('mint', [alice.address, ethers.parseEther('10')]), + }; + const batchData = accountIface.encodeFunctionData('executeBatch', [[mintCall]]); + + const result = await sei.send('eth_call', [ + { from: alice.address, to: alice.address, data: batchData }, + 'latest', + ]); + expect(result).to.equal('0x'); + + const balanceAfter = erc20.decodeBalance( + await sei.send('eth_call', [{ to: erc20Sei, data: erc20.balanceOf(alice.address) }, 'latest']), + ); + expect(balanceAfter).to.equal(balanceBefore); + }); + + it('propagates an inner revert as code 3 execution reverted', async () => { + const receipt = await setCodeForEOA(aliceRevert, [await selfAuthorize(aliceRevert, simpleAccountAddress)]); + expect(receipt?.status).to.equal(1); + + const transferCall = { + target: erc20Sei, + value: 0n, + data: erc20.transfer(seiAdmin, ethers.parseEther('1000000000')), + }; + const batchData = accountIface.encodeFunctionData('executeBatch', [[transferCall]]); + + const err = await captureRpcError( + sei.send('eth_call', [ + { from: aliceRevert.address, to: aliceRevert.address, data: batchData }, + 'latest', + ]), + ); + expect(err.code).to.equal(3); + expect(err.message).to.match(/execution reverted/i); + }); + }); +}); diff --git a/integration_test/rpc_tests/eth/eth_chainId.spec.ts b/integration_test/rpc_tests/eth/eth_chainId.spec.ts new file mode 100644 index 0000000000..33cfebf582 --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_chainId.spec.ts @@ -0,0 +1,62 @@ +import { expect } from 'chai'; +import { ethers } from 'ethers'; +import { bothProviders } from '../utils/providers'; +import { rawSei, rawGeth, expectJsonRpcError } from '../utils/rpc'; +import { readRuntimeState, RuntimeState } from '../utils/state'; +import { claimPool, expectSameError } from '../utils/testHelpers'; + +const COSMOS_TO_EVM_CHAIN_ID: Readonly> = Object.freeze({ + 'pacific-1': 1329, + 'atlantic-2': 1328, + 'arctic-1': 713715, +}); +const DEFAULT_EVM_CHAIN_ID = 713714; + +describe('eth_chainId', function () { + this.timeout(60 * 1000); + + const { sei, geth } = bothProviders(); + let runtime: RuntimeState; + + before(() => { + runtime = readRuntimeState(); + }); + + it('returns a canonical 0x-prefixed quantity on Sei', async () => { + const hex = await sei.send('eth_chainId', []); + expect(hex).to.match(/^0x(0|[1-9a-f][0-9a-f]*)$/); + expect(Number(hex)).to.equal(runtime.chainIds.sei); + }); + + it('agrees with the Sei chain id mapping table', async () => { + const hex = await sei.send('eth_chainId', []); + const expected = Object.values(COSMOS_TO_EVM_CHAIN_ID).includes(Number(hex)) + ? Number(hex) + : DEFAULT_EVM_CHAIN_ID; + expect(Number(hex)).to.equal(expected); + }); + + it('ethers Provider.getNetwork() agrees with raw eth_chainId on Sei', async () => { + const network = await sei.getNetwork(); + const hex = await sei.send('eth_chainId', []); + expect(network.chainId).to.equal(BigInt(hex)); + }); + + it('net_version returns the same chain id in decimal form on Sei', async () => { + const [hex, netVersion] = await Promise.all([ + sei.send('eth_chainId', []), + sei.send('net_version', []), + ]); + expect(netVersion).to.match(/^[0-9]+$/, 'net_version must be a decimal string'); + expect(Number(netVersion)).to.equal(Number(hex)); + }); + + it('rejects extra positional parameters identically to geth (-32602, exact message)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_chainId', ['latest']), + rawGeth('eth_chainId', ['latest']), + ]); + expectJsonRpcError(s, -32602, /too many arguments, want at most 0/); + expectSameError(s, g); + }); +}); diff --git a/integration_test/rpc_tests/eth/eth_coinbase.spec.ts b/integration_test/rpc_tests/eth/eth_coinbase.spec.ts new file mode 100644 index 0000000000..6a406824a0 --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_coinbase.spec.ts @@ -0,0 +1,137 @@ +import { ethers } from "ethers"; +import { expect } from "chai"; +import { createHash } from "crypto"; +import { fromBech32, toBech32 } from "@cosmjs/encoding"; + +import { seiRpc } from "../utils/providers"; +import { AdminMnemonic } from "../config/endpoints"; +import { readRuntimeState } from "../utils/state"; +import { claimPool } from "../utils/testHelpers"; +import { isSeiDocker, seiAddressFromMnemonic } from "../utils/seiAdmin"; +import { bankBalanceUsei } from "../utils/cosmos"; +import { rawSei, rawGeth, expectJsonRpcError } from "../utils/rpc"; + +function feeCollectorCosmosAddress(seiPrefix: string): string { + const hash = createHash('sha256').update('fee_collector').digest(); + return toBech32(seiPrefix, hash.subarray(0, 20)); +} + +const ZERO_ADDRESS = '0x' + '0'.repeat(40); +const WEI_PER_USEI = 10n ** 12n; + +describe('Eth Coinbase Rpc Tests', function () { + this.timeout(120 * 1000); + + let seiProvider: ethers.JsonRpcProvider; + let feeCollectorAddr: string; + + before(async () => { + seiProvider = seiRpc(); + const { prefix } = fromBech32(await seiAddressFromMnemonic(AdminMnemonic)); + feeCollectorAddr = feeCollectorCosmosAddress(prefix); + }); + + it('eth_coinbase returns a syntactically valid 20-byte EVM address', async () => { + const coinbase = await seiProvider.send('eth_coinbase', []); + expect(coinbase).to.match(/^0x[0-9a-fA-F]{40}$/); + expect(coinbase.toLowerCase()).to.not.equal(ZERO_ADDRESS); + }); + + it('eth_coinbase is distinct from block.coinbase (the per-block proposer)', async () => { + const [coinbase, block] = await Promise.all([ + seiProvider.send('eth_coinbase', []), + seiProvider.send('eth_getBlockByNumber', ['latest', false]), + ]); + expect(block.miner).to.match(/^0x[0-9a-fA-F]{40}$/); + expect(coinbase.toLowerCase()).to.not.equal(block.miner.toLowerCase()); + }); + + it('eth_coinbase equals the EVM-mapped address of the cosmos fee_collector module account', async () => { + const coinbase = (await seiProvider.send('eth_coinbase', [])).toLowerCase(); + + const evmAddress: string = await seiProvider.send('sei_getEVMAddress', [feeCollectorAddr]); + expect(evmAddress).to.match( + /^0x[0-9a-fA-F]{40}$/, + 'fee_collector module account must be associated on a live Sei chain', + ); + expect(evmAddress.toLowerCase()).to.equal(coinbase); + }); + + it('eth_coinbase round-trips: sei_getSeiAddress(coinbase) equals the derived fee_collector address', async () => { + const coinbase = await seiProvider.send('eth_coinbase', []); + + const seiAddress: string = await seiProvider.send('sei_getSeiAddress', [coinbase]); + expect(seiAddress).to.equal(feeCollectorAddr); + }); + + it('EVM tx fees accrue to eth_coinbase (the fee_collector) and are swept each block', async function () { + if (!(await isSeiDocker())) this.skip(); + + const coinbase = (await seiProvider.send('eth_coinbase', [])).toLowerCase(); + const [signer] = claimPool(readRuntimeState(), seiProvider, 1, 'eth_coinbase'); + + const gasPrice = BigInt(await seiProvider.send('eth_gasPrice', [])); + const tip = ethers.parseUnits('2', 'gwei'); + const tx = await signer.wallet.sendTransaction({ + to: signer.address, + value: 0n, + maxFeePerGas: gasPrice * 3n + tip, + maxPriorityFeePerGas: tip, + }); + const receipt = await tx.wait(1, 30_000); + const blockN = receipt!.blockNumber; + const ourFeeWei = receipt!.gasUsed * receipt!.gasPrice!; + + // The fee_collector holds at least our fee at the tx's height (>= leaves room for + // other txs sharing the block under parallel runs); 1 usei == 1e12 wei. + const balN = await bankBalanceUsei(feeCollectorAddr, blockN); + expect(balN * WEI_PER_USEI >= ourFeeWei).to.equal( + true, + `fee_collector at height ${blockN} (${balN} usei) must include our ${ourFeeWei} wei fee`, + ); + + // Divergence from geth: the same fee never shows up on the EVM balance surface. + const evmBalAtN = BigInt( + await seiProvider.send('eth_getBalance', [coinbase, '0x' + blockN.toString(16)]), + ); + expect(evmBalAtN, 'eth_getBalance must not surface the swept fee_collector balance').to.equal( + 0n, + ); + + // Non-cumulative: a later txless block shows a zero balance again, proving the + // sweep (a cumulative account would keep growing). + let emptyHeight: number | undefined; + for (let i = 0; i < 12 && emptyHeight === undefined; i++) { + const head = Number(await seiProvider.send('eth_blockNumber', [])); + for (let b = blockN + 1; b <= head; b++) { + const blk = await seiProvider.send('eth_getBlockByNumber', [ + '0x' + b.toString(16), + false, + ]); + if (blk.transactions.length === 0) { + emptyHeight = b; + break; + } + } + if (emptyHeight === undefined) await new Promise(r => setTimeout(r, 1000)); + } + expect(emptyHeight, 'expected a txless block after the tx to verify the sweep').to.not.equal( + undefined, + ); + const balEmpty = await bankBalanceUsei(feeCollectorAddr, emptyHeight!); + expect(balEmpty, `fee_collector must be empty at the txless block ${emptyHeight}`).to.equal( + 0n, + ); + }); + + it('rejects extra parameters on Sei with -32602 and go-ethereum\'s exact message', async () => { + // ethers strips extras client-side, so go raw. eth_coinbase takes no args, so + // both a positional and an object argument must fail identically. + const [positional, object] = await Promise.all([ + rawSei('eth_coinbase', ['latest']), + rawSei('eth_coinbase', [{}]), + ]); + expectJsonRpcError(positional, -32602, /^too many arguments, want at most 0$/); + expectJsonRpcError(object, -32602, /^too many arguments, want at most 0$/); + }); +}); \ No newline at end of file diff --git a/integration_test/rpc_tests/eth/eth_createAccessList.spec.ts b/integration_test/rpc_tests/eth/eth_createAccessList.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_estimateGas.spec.ts b/integration_test/rpc_tests/eth/eth_estimateGas.spec.ts new file mode 100644 index 0000000000..8afdbde351 --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_estimateGas.spec.ts @@ -0,0 +1,506 @@ +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import { bothProviders } from '../utils/providers'; +import { rawSei, rawGeth, expectJsonRpcError, JsonRpcEnvelope } from '../utils/rpc'; +import { readRuntimeState, RuntimeState } from '../utils/state'; +import { abiOf, bytecodeOf } from '../utils/deploy'; +import { EvmAccount } from '../utils/wallet'; +import { HEX_QUANTITY } from '../utils/format'; + +// eth_estimateGas parity against a local `geth --dev` reference. The bootstrap deploys +// the same TestERC20 (and a RealGasBurner) on both chains, so estimates and error +// envelopes are compared apples-to-apples. Sei-only behaviours are labelled. +describe('eth_estimateGas', function () { + this.timeout(180 * 1000); + + const { sei, geth } = bothProviders(); + const erc20Iface = new ethers.Interface(abiOf('TestERC20.sol', 'TestERC20')); + const burnerIface = new ethers.Interface(abiOf('GasBurner.sol', 'RealGasBurner')); + const STAKING_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000001005'; + const BOB = '0x000000000000000000000000000000000000bEEF'; + const INTRINSIC = 21000n; + + let runtime: RuntimeState; + let erc20Sei: string; + let erc20Geth: string; + let seiAdmin: string; + let gethAdmin: string; + let gasBurner: string; + let simpleAccountAddress: string; + + let actor: EvmAccount; + let spammers: EvmAccount[]; + + const transferData = (to: string, amount: bigint): string => + erc20Iface.encodeFunctionData('transfer', [to, amount]); + const validatorsData = (): string => + new ethers.Interface([ + 'function validators(string status, bytes pagination) returns (bytes,bytes)', + ]).encodeFunctionData('validators', ['BOND_STATUS_BONDED', '0x']); + + const estimate = async ( + provider: ethers.JsonRpcProvider, + tx: Record, + block?: string, + ): Promise => + BigInt(await provider.send('eth_estimateGas', block ? [tx, block] : [tx])); + + function expectSameError(s: JsonRpcEnvelope, g: JsonRpcEnvelope): void { + expect(g.error, `geth must error, got result ${JSON.stringify(g.result)}`).to.not.equal( + undefined, + ); + expect(s.error, `sei must error, got result ${JSON.stringify(s.result)}`).to.not.equal( + undefined, + ); + expect(s.error!.code, 'error.code parity').to.equal(g.error!.code); + expect(s.error!.message, 'error.message parity').to.equal(g.error!.message); + expect(s.error!.data, 'error.data parity').to.deep.equal(g.error!.data); + } + + function claimPool(count: number, salt: string): EvmAccount[] { + const pool = runtime.funded.pool; + let h = 0; + for (const ch of salt) h = (h * 31 + ch.charCodeAt(0)) >>> 0; + const start = h % pool.length; + return Array.from({ length: count }, (_, i) => + EvmAccount.fromPrivateKey(pool[(start + i) % pool.length].privateKey, sei), + ); + } + + before(async () => { + runtime = readRuntimeState(); + erc20Sei = runtime.contracts.erc20; + erc20Geth = runtime.contracts.erc20Geth; + seiAdmin = runtime.funded.admin; + gethAdmin = runtime.funded.gethAdmin.address; + gasBurner = runtime.contracts.gasBurner; + simpleAccountAddress = runtime.contracts.simpleAccount7702; + + const pool = claimPool(6, 'eth_estimateGas'); + actor = pool[0]; + spammers = pool.slice(1); + }); + + describe('happy path', () => { + it('a bare native transfer costs exactly the intrinsic 21000', async () => { + expect(await estimate(sei, { from: seiAdmin, to: BOB, value: '0x1' })).to.equal(INTRINSIC); + }); + + it('a zero-value transfer still costs the intrinsic 21000', async () => { + expect(await estimate(sei, { from: seiAdmin, to: BOB, value: '0x0' })).to.equal(INTRINSIC); + }); + + it('a self-transfer costs the intrinsic 21000', async () => { + expect(await estimate(sei, { from: seiAdmin, to: seiAdmin, value: '0x1' })).to.equal( + INTRINSIC, + ); + }); + + it('calldata on a plain transfer raises the estimate above the intrinsic', async () => { + const withData = await estimate(sei, { from: seiAdmin, to: BOB, data: '0x1234567890' }); + expect(withData > INTRINSIC).to.equal(true); + }); + + it('an ERC20 transfer estimates within a sane band and is non-trivial', async () => { + const est = await estimate(sei, { + from: seiAdmin, + to: erc20Sei, + data: transferData(BOB, ethers.parseEther('1')), + }); + expect(est > INTRINSIC && est < 200_000n, `estimate ${est} out of band`).to.equal(true); + }); + + it('an ERC20 approve and mint both estimate above the intrinsic', async () => { + const [approveEst, mintEst] = await Promise.all([ + estimate(sei, { + from: seiAdmin, + to: erc20Sei, + data: erc20Iface.encodeFunctionData('approve', [BOB, ethers.parseEther('100')]), + }), + estimate(sei, { + from: seiAdmin, + to: erc20Sei, + data: erc20Iface.encodeFunctionData('mint', [seiAdmin, ethers.parseEther('100')]), + }), + ]); + expect(approveEst > INTRINSIC).to.equal(true); + expect(mintEst > INTRINSIC).to.equal(true); + }); + + it('a contract deployment estimates into the hundreds of thousands of gas', async () => { + const deployData = + bytecodeOf('TestERC20.sol', 'TestERC20') + + ethers.AbiCoder.defaultAbiCoder().encode(['address'], [seiAdmin]).slice(2); + const est = await estimate(sei, { data: deployData }); + expect(est > 500_000n).to.equal(true); + }); + + it('accepts an explicit latest block tag', async () => { + const est = await estimate(sei, { from: seiAdmin, to: BOB, value: '0x1' }, 'latest'); + expect(est).to.equal(INTRINSIC); + }); + + it('estimating against pending agrees with latest for a stable call', async () => { + const [atLatest, atPending] = await Promise.all([ + estimate(sei, { from: seiAdmin, to: erc20Sei, data: transferData(BOB, 1n) }, 'latest'), + estimate(sei, { from: seiAdmin, to: erc20Sei, data: transferData(BOB, 1n) }, 'pending'), + ]); + expect(atPending).to.equal(atLatest); + }); + }); + + describe('transaction types', () => { + const base = () => ({ from: seiAdmin, to: BOB, value: '0x1' }); + + it('legacy (type 0) and EIP-1559 (type 2) estimate the same units as a bare transfer', async () => { + const [legacy, eip1559] = await Promise.all([ + estimate(sei, { ...base(), type: '0x0' }), + estimate(sei, { ...base(), type: '0x2' }), + ]); + expect(legacy, 'type 0').to.equal(INTRINSIC); + expect(eip1559, 'type 2').to.equal(INTRINSIC); + }); + + it('an access-list (type 1) tx adds the EIP-2930 surcharge', async () => { + const accessList = [ + { address: erc20Sei, storageKeys: ['0x' + '00'.repeat(32)] }, + ]; + const withAccessList = await estimate(sei, { ...base(), type: '0x1', accessList }); + // 2400 per address + 1900 per storage key on top of the intrinsic transfer. + expect(withAccessList - INTRINSIC >= 2400n + 1900n).to.equal(true); + }); + + it('a set-code (type 4) tx adds the per-authorization cost', async () => { + const authority = ethers.Wallet.createRandom(); + const auth = await authority.authorize({ + address: simpleAccountAddress, + chainId: 0, + nonce: 0, + }); + const est = await estimate(sei, { + from: seiAdmin, + to: seiAdmin, + type: '0x4', + authorizationList: [authToRpc(auth)], + }); + // A fresh authority is an empty account: PER_EMPTY_ACCOUNT_COST is 25000. + expect(est - INTRINSIC >= 25_000n).to.equal(true); + }); + }); + + describe('estimate accuracy', () => { + it('the ERC20 transfer estimate bounds and closely tracks real gas used', async () => { + const erc20 = new ethers.Contract(erc20Sei, erc20Iface, actor.wallet); + await (await erc20.mint(actor.address, ethers.parseEther('100'))).wait(); + + const recipient = ethers.Wallet.createRandom().address; + const data = transferData(recipient, ethers.parseEther('1')); + const est = await estimate(sei, { from: actor.address, to: erc20Sei, data }); + + const tx = await actor.wallet.sendTransaction({ to: erc20Sei, data, gasLimit: est }); + const receipt = await tx.wait(); + expect(receipt!.status).to.equal(1); + expect(receipt!.gasUsed <= est, 'estimate must bound actual usage').to.equal(true); + + const overshootPct = Number((est - receipt!.gasUsed) * 100n) / Number(est); + expect(overshootPct, 'estimate should be close to actual').to.be.lessThan(25); + }); + + it('a native transfer estimate equals its exact gas used', async () => { + const est = await estimate(sei, { from: actor.address, to: BOB, value: '0x1' }); + const tx = await actor.wallet.sendTransaction({ to: BOB, value: 1n, gasLimit: est }); + const receipt = await tx.wait(); + expect(receipt!.gasUsed).to.equal(INTRINSIC); + expect(est).to.equal(INTRINSIC); + }); + + it('repeated estimates of the same call are deterministic', async () => { + const tx = { from: seiAdmin, to: erc20Sei, data: transferData(BOB, 1n) }; + const results = await Promise.all(Array.from({ length: 5 }, () => estimate(sei, tx))); + results.forEach(r => expect(r).to.equal(results[0])); + }); + + it('a generous gas cap does not change the estimate', async () => { + const tx = { from: seiAdmin, to: erc20Sei, data: transferData(BOB, 1n) }; + const [withCap, withoutCap] = await Promise.all([ + estimate(sei, { ...tx, gas: '0x4c4b40' }), + estimate(sei, tx), + ]); + expect(withCap).to.equal(withoutCap); + }); + }); + + describe('precompiles (Sei-specific)', () => { + it('estimates the staking validators() precompile call above the intrinsic', async () => { + const est = await estimate(sei, { + from: seiAdmin, + to: STAKING_PRECOMPILE_ADDRESS, + data: validatorsData(), + }); + expect(est > INTRINSIC).to.equal(true); + }); + + it('the precompile estimate is deterministic and bounds real execution', async () => { + const data = validatorsData(); + const est = await estimate(sei, { + from: actor.address, + to: STAKING_PRECOMPILE_ADDRESS, + data, + }); + const again = await estimate(sei, { + from: actor.address, + to: STAKING_PRECOMPILE_ADDRESS, + data, + }); + expect(again).to.equal(est); + + const tx = await actor.wallet.sendTransaction({ + to: STAKING_PRECOMPILE_ADDRESS, + data, + gasLimit: est, + }); + const receipt = await tx.wait(); + expect(receipt!.status).to.equal(1); + expect(receipt!.gasUsed <= est, 'estimate must bound actual precompile usage').to.equal( + true, + ); + }); + }); + + describe('schema matching vs geth', () => { + it('a native transfer estimates to 21000 on both Sei and geth', async () => { + const [s, g] = await Promise.all([ + estimate(sei, { from: seiAdmin, to: BOB, value: '0x1' }), + estimate(geth, { from: gethAdmin, to: BOB, value: '0x1' }), + ]); + expect(s).to.equal(INTRINSIC); + expect(g).to.equal(INTRINSIC); + }); + + it('an ERC20 transfer estimates identically on Sei and geth', async () => { + // A never-seen recipient is a cold (new) balance slot on both chains, so the + // estimate is the full-write cost and matches byte-for-byte. + const data = transferData(ethers.Wallet.createRandom().address, ethers.parseEther('1')); + const [s, g] = await Promise.all([ + estimate(sei, { from: seiAdmin, to: erc20Sei, data }), + estimate(geth, { from: gethAdmin, to: erc20Geth, data }), + ]); + expect(s).to.equal(g); + }); + + it('access-list, EIP-1559 and set-code estimates all match geth', async () => { + const accessList = [{ address: '0x' + '11'.repeat(20), storageKeys: ['0x' + '00'.repeat(32)] }]; + const authority = ethers.Wallet.createRandom(); + const auth = authToRpc( + await authority.authorize({ address: '0x' + '22'.repeat(20), chainId: 0, nonce: 0 }), + ); + + const variants: Record[] = [ + { value: '0x1', type: '0x2' }, + { value: '0x1', type: '0x1', accessList }, + { to: undefined, type: '0x4', authorizationList: [auth] }, + ]; + for (const v of variants) { + const { to: vTo, ...rest } = v as { to?: string }; + const [s, g] = await Promise.all([ + estimate(sei, { from: seiAdmin, to: vTo ?? seiAdmin, ...rest }), + estimate(geth, { from: gethAdmin, to: vTo ?? gethAdmin, ...rest }), + ]); + expect(s, `variant ${JSON.stringify(v)}`).to.equal(g); + } + }); + + it('an identical contract deployment estimates the same on Sei and geth', async () => { + const deployData = + bytecodeOf('TestERC20.sol', 'TestERC20') + + ethers.AbiCoder.defaultAbiCoder().encode(['address'], [seiAdmin]).slice(2); + const [s, g] = await Promise.all([ + estimate(sei, { data: deployData }), + estimate(geth, { data: deployData }), + ]); + expect(s).to.equal(g); + }); + }); + + describe('empty / null handling', () => { + it('returns a canonical quantity, never null (raw transport)', async () => { + const body = await rawSei('eth_estimateGas', [ + { from: seiAdmin, to: BOB, value: '0x1' }, + ]); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result).to.match(HEX_QUANTITY); + expect(body.result).to.not.equal(null); + }); + + it('a contract call returns a quantity, never null (raw transport)', async () => { + const body = await rawSei('eth_estimateGas', [ + { from: seiAdmin, to: erc20Sei, data: transferData(BOB, 1n) }, + ]); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result).to.match(HEX_QUANTITY); + }); + }); + + describe('wrong params / error handling', () => { + it('a revert surfaces with identical code 3, message and error data on both', async () => { + // A shared, never-funded sender has zero token balance on both chains, so the + // ERC20InsufficientBalance(sender,0,amount) payload is byte-identical. + const sender = ethers.Wallet.createRandom().address; + const data = transferData(BOB, ethers.parseEther('1000000000')); + const [s, g] = await Promise.all([ + rawSei('eth_estimateGas', [{ from: sender, to: erc20Sei, data }]), + rawGeth('eth_estimateGas', [{ from: sender, to: erc20Geth, data }]), + ]); + const err = expectJsonRpcError(s, 3, /execution reverted/i); + expect(err.data).to.be.a('string'); + expectSameError(s, g); + }); + + it('a bad selector reverts with code 3 and empty data on both', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_estimateGas', [{ from: seiAdmin, to: erc20Sei, data: '0x12345678' }]), + rawGeth('eth_estimateGas', [{ from: gethAdmin, to: erc20Geth, data: '0x12345678' }]), + ]); + expectJsonRpcError(s, 3, /execution reverted/i); + expect(s.error!.data).to.equal('0x'); + expectSameError(s, g); + }); + + it('a gas cap below the requirement fails identically to geth (-32000 allowance)', async () => { + const data = transferData(seiAdmin, ethers.parseEther('1')); + const [s, g] = await Promise.all([ + rawSei('eth_estimateGas', [{ from: seiAdmin, to: erc20Sei, data, gas: '0x5208' }]), + rawGeth('eth_estimateGas', [{ from: gethAdmin, to: erc20Geth, data, gas: '0x5208' }]), + ]); + expectJsonRpcError(s, -32000, /gas required exceeds allowance/); + expectSameError(s, g); + }); + + it('a malformed from address fails identically to geth (-32602, exact message)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_estimateGas', [{ from: '0xdead', to: BOB, value: '0x1' }]), + rawGeth('eth_estimateGas', [{ from: '0xdead', to: BOB, value: '0x1' }]), + ]); + expectJsonRpcError(s, -32602, /hex string has length 4, want 40 for common\.Address/); + expectSameError(s, g); + }); + + it('empty params fail identically to geth (-32602 missing required argument 0)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_estimateGas', []), + rawGeth('eth_estimateGas', []), + ]); + expectJsonRpcError(s, -32602, /missing value for required argument 0/); + expectSameError(s, g); + }); + + it('[divergence] insufficient funds: both -32000 with the same clause, different gas prefix', async () => { + const value = ethers.toQuantity(ethers.parseEther('1000000')); + const [s, g] = await Promise.all([ + rawSei('eth_estimateGas', [{ from: BOB, to: seiAdmin, value }]), + rawGeth('eth_estimateGas', [{ from: BOB, to: gethAdmin, value }]), + ]); + expect(s.error?.code, 'sei code').to.equal(-32000); + expect(g.error?.code, 'geth code').to.equal(-32000); + expect(s.error?.message).to.match(/insufficient funds for gas \* price \+ value/); + expect(g.error?.message).to.match(/insufficient funds for gas \* price \+ value/); + // The "failed with N gas" prefix encodes each node's block gas cap, which differs. + expect(s.error?.message).to.not.equal(g.error?.message); + }); + + it('[divergence] far-future block: both -32000 but different messages', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_estimateGas', [{ from: seiAdmin, to: BOB, value: '0x1' }, '0xffffffff']), + rawGeth('eth_estimateGas', [{ from: gethAdmin, to: BOB, value: '0x1' }, '0xffffffff']), + ]); + expect(s.error?.code, 'sei code').to.equal(-32000); + expect(g.error?.code, 'geth code').to.equal(-32000); + expect(s.error?.message).to.match(/not yet available/i); + expect(g.error?.message).to.match(/header not found/i); + expect(s.error?.message).to.not.equal(g.error?.message); + }); + }); + + describe('base fee increase doesnt change the gas estimates', () => { + const getBaseFee = async (): Promise => { + const blk = await sei.send('eth_getBlockByNumber', ['latest', false]); + return BigInt(blk.baseFeePerGas ?? '0x0'); + }; + + async function spamToRaiseBaseFee(): Promise<{ before: bigint; after: bigint }> { + const before = await getBaseFee(); + const GAS_LIMIT = 5_000_000n; + const ITERATIONS = 150n; + for (let round = 0; round < 8; round++) { + const fee = await sei.getFeeData(); + const baseNow = await getBaseFee(); + const tip = fee.maxPriorityFeePerGas ?? ethers.parseUnits('1', 'gwei'); + const maxFee = (baseNow === 0n ? ethers.parseUnits('10', 'gwei') : baseNow * 4n) + tip; + const sends: Promise[] = []; + for (let i = 0; i < spammers.length; i++) { + const s = spammers[i]; + if ((await s.balance()) < GAS_LIMIT * maxFee) continue; + const data = burnerIface.encodeFunctionData('burnGasIterations', [ + BigInt(round * 100 + i), + ITERATIONS, + ]); + sends.push( + s.wallet + .sendTransaction({ + to: gasBurner, + data, + gasLimit: GAS_LIMIT, + maxFeePerGas: maxFee, + maxPriorityFeePerGas: tip, + type: 2, + }) + .then(t => t.wait()) + .catch(() => null), + ); + } + if (sends.length === 0) break; + await Promise.all(sends); + if ((await getBaseFee()) > before) break; + } + return { before, after: await getBaseFee() }; + } + + it('gas estimates stay correct (and bound real usage) as the base fee rises', async function () { + const burnData = burnerIface.encodeFunctionData('burnGasIterations', [7n, 30n]); + const estimateBefore = await estimate(sei, { from: actor.address, to: gasBurner, data: burnData }); + + const { before, after } = await spamToRaiseBaseFee(); + if (after <= before) { + this.skip(); + } + expect(after > before, 'base fee should have risen').to.equal(true); + + // Gas is denominated in units; a fee-market move must not change the estimate. + const estimateAfter = await estimate(sei, { from: actor.address, to: gasBurner, data: burnData }); + expect(estimateAfter, 'gas units are independent of the base fee').to.equal(estimateBefore); + + const fee = await sei.getFeeData(); + const tx = await actor.wallet.sendTransaction({ + to: gasBurner, + data: burnData, + gasLimit: estimateAfter, + maxFeePerGas: fee.maxFeePerGas!, + maxPriorityFeePerGas: fee.maxPriorityFeePerGas!, + }); + const receipt = await tx.wait(); + expect(receipt!.status).to.equal(1); + expect(receipt!.gasUsed <= estimateAfter, 'estimate must still bound usage').to.equal(true); + }); + }); + + function authToRpc(a: ethers.Authorization): Record { + return { + chainId: ethers.toQuantity(a.chainId), + address: a.address, + nonce: ethers.toQuantity(a.nonce), + yParity: ethers.toQuantity(a.signature.yParity), + r: a.signature.r, + s: a.signature.s, + }; + } +}); diff --git a/integration_test/rpc_tests/eth/eth_estimateGasAfterCalls.spec.ts b/integration_test/rpc_tests/eth/eth_estimateGasAfterCalls.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_feeHistory.spec.ts b/integration_test/rpc_tests/eth/eth_feeHistory.spec.ts new file mode 100644 index 0000000000..a079e830cc --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_feeHistory.spec.ts @@ -0,0 +1,474 @@ +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import { bothProviders } from '../utils/providers'; +import { rawSei, rawGeth, expectJsonRpcError, JsonRpcEnvelope } from '../utils/rpc'; +import { readRuntimeState, RuntimeState } from '../utils/state'; +import { abiOf, deployContract } from '../utils/deploy'; +import { EvmAccount } from '../utils/wallet'; +import { HEX_QUANTITY } from '../utils/format'; +import { + Eip1559Params, + queryEip1559Params, + nextBaseFeeSei, + nextBaseFeeGeth, +} from '../utils/eip1559'; + +// eth_feeHistory parity against a local `geth --dev` reference. Every field returned +// (baseFeePerGas, gasUsedRatio, reward) is cross-checked against the underlying +// blocks, and the base-fee series is replayed through each chain's own fee-market +// formula after we deliberately raise the base fee with a gas burner. +describe('eth_feeHistory', function () { + this.timeout(240 * 1000); + + const { sei, geth } = bothProviders(); + const burnerIface = new ethers.Interface(abiOf('GasBurner.sol', 'RealGasBurner')); + + let runtime: RuntimeState; + let seiBurner: string; + let spammers: EvmAccount[]; + let seiParams: Eip1559Params | null; + + interface ParsedFeeHistory { + oldest: number; + baseFeePerGas: bigint[]; + gasUsedRatio: number[]; + reward?: bigint[][]; + } + + const feeHistory = ( + provider: ethers.JsonRpcProvider, + count: number, + newest: string, + percentiles: number[], + ) => provider.send('eth_feeHistory', [ethers.toQuantity(count), newest, percentiles]); + + function parse(raw: any): ParsedFeeHistory { + return { + oldest: Number(raw.oldestBlock), + baseFeePerGas: (raw.baseFeePerGas as string[]).map(BigInt), + gasUsedRatio: (raw.gasUsedRatio as number[]).map(Number), + reward: raw.reward + ? (raw.reward as string[][]).map(row => row.map(BigInt)) + : undefined, + }; + } + + async function blockInfo(provider: ethers.JsonRpcProvider, n: number) { + const b = await provider.send('eth_getBlockByNumber', [ethers.toQuantity(n), false]); + return { + gasUsed: BigInt(b.gasUsed), + gasLimit: BigInt(b.gasLimit), + baseFee: BigInt(b.baseFeePerGas ?? '0x0'), + }; + } + + /** + * Assert the whole envelope is internally consistent: array lengths, oldestBlock, + * every baseFeePerGas/gasUsedRatio entry against its block, ascending rewards, and + * the base-fee transition between each pair replayed through the chain's formula + * (exact on geth's integer math, within rounding tolerance on Sei's decimal math). + */ + async function verifySeries( + provider: ethers.JsonRpcProvider, + fh: ParsedFeeHistory, + newest: number, + percentiles: number[], + chain: 'sei' | 'geth', + ): Promise { + const count = fh.gasUsedRatio.length; + expect(fh.baseFeePerGas.length, 'baseFeePerGas is blockCount + 1').to.equal(count + 1); + expect(fh.oldest, 'oldestBlock = newest - count + 1').to.equal(newest - count + 1); + if (percentiles.length > 0) { + expect(fh.reward, 'reward present when percentiles requested').to.not.equal(undefined); + expect(fh.reward!.length, 'one reward row per block').to.equal(count); + } + + const head = await provider.getBlockNumber(); + // Sei reports gasUsedRatio quantized to 4 decimal places; geth is full precision. + const ratioTol = chain === 'sei' ? 1.01e-4 : 1e-9; + for (let i = 0; i < count; i++) { + const blk = await blockInfo(provider, fh.oldest + i); + + expect(fh.baseFeePerGas[i], `baseFeePerGas[${i}] equals block base fee`).to.equal( + blk.baseFee, + ); + const ratio = Number(blk.gasUsed) / Number(blk.gasLimit); + expect(fh.gasUsedRatio[i], `gasUsedRatio[${i}] equals gasUsed/gasLimit`).to.be.closeTo( + ratio, + ratioTol, + ); + + if (fh.reward) { + const row = fh.reward[i]; + expect(row.length, `reward[${i}] has one entry per percentile`).to.equal( + percentiles.length, + ); + for (let p = 1; p < row.length; p++) { + expect(row[p] >= row[p - 1], `reward[${i}] percentiles ascending`).to.equal(true); + } + } + + if (chain === 'geth') { + const predicted = nextBaseFeeGeth(fh.baseFeePerGas[i], blk.gasUsed, blk.gasLimit); + expect(fh.baseFeePerGas[i + 1], `geth base-fee transition ${i}`).to.equal(predicted); + } else if (seiParams) { + const predicted = nextBaseFeeSei( + Number(fh.baseFeePerGas[i]), + Number(blk.gasUsed), + seiParams, + ); + expect( + Number(fh.baseFeePerGas[i + 1]), + `sei base-fee transition ${i}`, + ).to.be.closeTo(predicted, 5); + } + } + + // The trailing element forecasts newest+1's base fee. A block's base fee depends + // only on its parent, so once newest+1 is mined the forecast must equal it exactly. + const forecastBlock = fh.oldest + count; + if (forecastBlock <= head) { + const nb = await blockInfo(provider, forecastBlock); + expect(fh.baseFeePerGas[count], 'forecast equals the real next block base fee').to.equal( + nb.baseFee, + ); + } + } + + function claimPool(count: number, salt: string): EvmAccount[] { + const pool = runtime.funded.pool; + let h = 0; + for (const ch of salt) h = (h * 31 + ch.charCodeAt(0)) >>> 0; + const start = h % pool.length; + return Array.from({ length: count }, (_, i) => + EvmAccount.fromPrivateKey(pool[(start + i) % pool.length].privateKey, sei), + ); + } + + before(async () => { + runtime = readRuntimeState(); + seiBurner = runtime.contracts.gasBurner; + spammers = claimPool(5, 'eth_feeHistory'); + seiParams = await queryEip1559Params(); + }); + + describe('schema / structure', () => { + it('returns well-formed, length-consistent arrays on Sei', async () => { + const newest = await sei.getBlockNumber(); + const percentiles = [5, 25, 50, 75, 95]; + const fh = parse(await feeHistory(sei, 5, ethers.toQuantity(newest), percentiles)); + await verifySeries(sei, fh, newest, percentiles, 'sei'); + }); + + it('returns well-formed, length-consistent arrays on geth', async () => { + const newest = await geth.getBlockNumber(); + const count = Math.min(newest, 4); + const percentiles = [10, 50, 90]; + const fh = parse(await feeHistory(geth, count, ethers.toQuantity(newest), percentiles)); + await verifySeries(geth, fh, newest, percentiles, 'geth'); + }); + + it('every base fee is a canonical quantity within the configured bounds (Sei)', async function () { + if (!seiParams) this.skip(); + const newest = await sei.getBlockNumber(); + const body = await rawSei('eth_feeHistory', ['0x5', ethers.toQuantity(newest), []]); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + for (const fee of body.result!.baseFeePerGas as string[]) { + expect(fee, 'canonical quantity').to.match(HEX_QUANTITY); + expect(Number(fee)).to.be.gte(seiParams!.minFeePerGas); + expect(Number(fee)).to.be.lte(seiParams!.maxFeePerGas); + } + }); + + it('[divergence] no percentiles: geth omits reward, Sei returns empty reward rows', async () => { + const [sNewest, gNewest] = await Promise.all([sei.getBlockNumber(), geth.getBlockNumber()]); + const [s, g] = await Promise.all([ + rawSei('eth_feeHistory', ['0x2', ethers.toQuantity(sNewest), []]), + rawGeth('eth_feeHistory', ['0x2', ethers.toQuantity(gNewest), []]), + ]); + expect(g.result.reward, 'geth omits reward entirely').to.equal(undefined); + expect(s.result.reward, 'sei returns a reward entry per block').to.be.an('array'); + (s.result.reward as unknown[][]).forEach(row => + expect(row, 'each Sei reward row is empty when no percentiles asked').to.deep.equal([]), + ); + expect(s.result.baseFeePerGas).to.be.an('array'); + expect(g.result.baseFeePerGas).to.be.an('array'); + }); + }); + + describe('base fee manipulation (Sei)', () => { + const getBaseFee = async (): Promise => + BigInt((await sei.send('eth_getBlockByNumber', ['latest', false])).baseFeePerGas ?? '0x0'); + + async function burnBurst(): Promise<{ before: bigint; minBlock: number; maxBlock: number }> { + const before = await getBaseFee(); + const GAS_LIMIT = 6_000_000n; + const ITERATIONS = 200n; + const tip = ethers.parseUnits('2', 'gwei'); + let minBlock = Number.MAX_SAFE_INTEGER; + let maxBlock = 0; + + for (let round = 0; round < 10; round++) { + const baseNow = await getBaseFee(); + const maxFee = baseNow * 4n + tip; + const sends: Promise[] = []; + for (let i = 0; i < spammers.length; i++) { + const s = spammers[i]; + if ((await s.balance()) < GAS_LIMIT * maxFee) continue; + const data = burnerIface.encodeFunctionData('burnGasIterations', [ + BigInt(round * 100 + i), + ITERATIONS, + ]); + sends.push( + s.wallet + .sendTransaction({ + to: seiBurner, + data, + gasLimit: GAS_LIMIT, + maxFeePerGas: maxFee, + maxPriorityFeePerGas: tip, + type: 2, + }) + .then(t => t.wait()) + .then(r => { + if (r) { + minBlock = Math.min(minBlock, r.blockNumber); + maxBlock = Math.max(maxBlock, r.blockNumber); + } + }) + .catch(() => undefined), + ); + } + if (sends.length === 0) break; + await Promise.all(sends); + } + return { before, minBlock, maxBlock }; + } + + it('drives the base fee up and every field replays through the fee-market formula', async function () { + if (!seiParams) this.skip(); + const { before, minBlock, maxBlock } = await burnBurst(); + if (maxBlock === 0) this.skip(); + + // Cover the whole burst plus one block on each side so the boundary + // transitions (rise into the burst, decay out of it) are included. + const newest = Math.min(maxBlock + 1, await sei.getBlockNumber()); + const count = Math.min(newest - minBlock + 2, 1024); + const percentiles = [10, 50, 90]; + const fh = parse(await feeHistory(sei, count, ethers.toQuantity(newest), percentiles)); + + await verifySeries(sei, fh, newest, percentiles, 'sei'); + + const peak = fh.baseFeePerGas.reduce((m, v) => (v > m ? v : m), 0n); + expect(peak > before, `base fee should rise above ${before}, peaked at ${peak}`).to.equal( + true, + ); + + // At least one block was pushed over target, so at least one transition rose. + const rose = fh.baseFeePerGas.some((v, i) => i > 0 && v > fh.baseFeePerGas[i - 1]); + expect(rose, 'at least one block raised the base fee').to.equal(true); + + // We paid a 2 gwei tip, so the top percentile of some burst block is non-zero. + const topRewards = fh.reward!.map(r => r[r.length - 1]); + expect( + topRewards.some(r => r > 0n), + 'a paid tip must surface in the reward percentiles', + ).to.equal(true); + }); + + it('a single over-target block reports gasUsedRatio above the target ratio', async function () { + if (!seiParams) this.skip(); + const data = burnerIface.encodeFunctionData('burnGasIterations', [777n, 200n]); + const tip = ethers.parseUnits('1', 'gwei'); + const baseNow = await getBaseFee(); + const tx = await spammers[0].wallet.sendTransaction({ + to: seiBurner, + data, + gasLimit: 6_000_000n, + maxFeePerGas: baseNow * 4n + tip, + maxPriorityFeePerGas: tip, + type: 2, + }); + const receipt = await tx.wait(); + const blk = await blockInfo(sei, receipt!.blockNumber); + const targetRatio = seiParams!.targetGasUsedPerBlock / Number(blk.gasLimit); + + const fh = parse( + await feeHistory(sei, 1, ethers.toQuantity(receipt!.blockNumber), []), + ); + const reportedRatio = fh.gasUsedRatio[0]; + expect(reportedRatio).to.be.closeTo(Number(blk.gasUsed) / Number(blk.gasLimit), 1.01e-4); + expect(reportedRatio > targetRatio, 'over-target block exceeds the target ratio').to.equal( + true, + ); + }); + }); + + describe('base fee manipulation (geth)', () => { + let gethBurner: ethers.Contract; + let gethSigner: EvmAccount; + let gethNonce: number; + const TIP = ethers.parseUnits('1', 'gwei'); + + before(async () => { + gethSigner = EvmAccount.fromPrivateKey(runtime.funded.gethAdmin.privateKey, geth); + const dep = await deployContract(gethSigner, 'GasBurner.sol', [], 'RealGasBurner'); + gethBurner = new ethers.Contract(dep.address, burnerIface, gethSigner.wallet); + // geth --dev instamines, so manage the nonce explicitly to avoid the + // pending-count lag racing successive heavy burns. + gethNonce = await gethSigner.nonce('latest'); + }); + + // Each heavy burn is its own block (one tx per dev block). Burn ~60% of the + // parent gas limit (over geth's 50% target so the next base fee rises) while + // capping the tx gas limit at 80% — comfortably under the block limit, which + // geth nudges +/-1/1024 per block, so the tx is always minable. + async function heavyGethBlock(salt: number): Promise { + const parent = await blockInfo(geth, await geth.getBlockNumber()); + const iterations = (parent.gasLimit * 60n) / 100n / 22_300n; + const tx = await gethBurner.burnGasIterations(salt, iterations, { + gasLimit: (parent.gasLimit * 80n) / 100n, + maxFeePerGas: parent.baseFee * 4n + TIP, + maxPriorityFeePerGas: TIP, + nonce: gethNonce++, + }); + const receipt = await tx.wait(1, 30_000); + expect(receipt!.status, 'heavy geth burn must succeed').to.equal(1); + return receipt!.blockNumber; + } + + it('raises the base fee monotonically and replays exactly through geth CalcBaseFee', async () => { + const blocks: number[] = []; + for (let i = 0; i < 4; i++) blocks.push(await heavyGethBlock(i)); + + const minBlock = blocks[0]; + const newest = blocks[blocks.length - 1]; + const count = newest - minBlock + 1; + const percentiles = [10, 50, 90]; + const fh = parse(await feeHistory(geth, count, ethers.toQuantity(newest), percentiles)); + + await verifySeries(geth, fh, newest, percentiles, 'geth'); + + // Each block was > 50% full, so every transition strictly increased the base fee. + for (let i = 1; i <= count; i++) { + expect( + fh.baseFeePerGas[i] > fh.baseFeePerGas[i - 1], + `geth base fee strictly rose at ${i}`, + ).to.equal(true); + } + // Each block was over the 50% target. + fh.gasUsedRatio.forEach((r, i) => + expect(r > 0.5, `geth block ${i} over 50% target (got ${r})`).to.equal(true), + ); + // A single tx per block, all paying the same tip, so every reward percentile is that tip. + fh.reward!.forEach((row, i) => + row.forEach((r, p) => + expect(r, `geth reward[${i}][${p}] equals the paid tip`).to.equal(TIP), + ), + ); + }); + }); + + describe('empty / null handling', () => { + it('blockCount 0 returns null arrays (Sei) and the geth divergence is documented', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_feeHistory', ['0x0', 'latest', []]), + rawGeth('eth_feeHistory', ['0x0', 'latest', []]), + ]); + expect(s.error, JSON.stringify(s.error)).to.equal(undefined); + expect(g.error, JSON.stringify(g.error)).to.equal(undefined); + expect(s.result.gasUsedRatio, 'sei nulls gasUsedRatio for empty range').to.equal(null); + expect(g.result.gasUsedRatio, 'geth nulls gasUsedRatio for empty range').to.equal(null); + // [divergence] Sei reports oldestBlock null; geth reports "0x0". + expect(s.result.oldestBlock).to.equal(null); + expect(g.result.oldestBlock).to.equal('0x0'); + }); + + it('an idle range still returns a zero-filled reward matrix, never null entries', async () => { + const newest = await sei.getBlockNumber(); + const percentiles = [25, 75]; + const fh = parse(await feeHistory(sei, 3, ethers.toQuantity(newest), percentiles)); + expect(fh.reward, 'reward present').to.not.equal(undefined); + fh.reward!.forEach(row => { + expect(row.length).to.equal(percentiles.length); + row.forEach(r => expect(r >= 0n).to.equal(true)); + }); + }); + + it('clamps an oversized blockCount to the available history without erroring (Sei)', async () => { + const newest = await sei.getBlockNumber(); + const body = await rawSei('eth_feeHistory', [ + '0xffff', + ethers.toQuantity(newest), + [], + ]); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + const ratios = body.result.gasUsedRatio as number[]; + expect(ratios.length > 0, 'returns some blocks').to.equal(true); + expect(ratios.length <= newest + 1, 'cannot exceed available history').to.equal(true); + }); + }); + + describe('wrong params / error handling', () => { + function expectSameError(s: JsonRpcEnvelope, g: JsonRpcEnvelope): void { + expect(g.error, `geth must error, got ${JSON.stringify(g.result)}`).to.not.equal(undefined); + expect(s.error, `sei must error, got ${JSON.stringify(s.result)}`).to.not.equal(undefined); + expect(s.error!.code, 'error.code parity').to.equal(g.error!.code); + expect(s.error!.message, 'error.message parity').to.equal(g.error!.message); + expect(s.error!.data, 'error.data parity').to.deep.equal(g.error!.data); + } + + it('missing percentiles argument fails identically (-32602, exact message)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_feeHistory', ['0x2', 'latest']), + rawGeth('eth_feeHistory', ['0x2', 'latest']), + ]); + expectJsonRpcError(s, -32602, /missing value for required argument 2/); + expectSameError(s, g); + }); + + it('empty params fail identically (-32602 missing required argument 0)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_feeHistory', []), + rawGeth('eth_feeHistory', []), + ]); + expectJsonRpcError(s, -32602, /missing value for required argument 0/); + expectSameError(s, g); + }); + + it('[divergence] unsorted percentiles: both -32000, different messages', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_feeHistory', ['0x2', 'latest', [50, 5]]), + rawGeth('eth_feeHistory', ['0x2', 'latest', [50, 5]]), + ]); + expect(s.error?.code, 'sei code').to.equal(-32000); + expect(g.error?.code, 'geth code').to.equal(-32000); + expect(s.error?.message).to.match(/ascending|invalid reward percentile/i); + expect(g.error?.message).to.match(/invalid reward percentile/i); + expect(s.error?.message).to.not.equal(g.error?.message); + }); + + it('[divergence] a percentile above 100 is rejected by both (-32000)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_feeHistory', ['0x2', 'latest', [150]]), + rawGeth('eth_feeHistory', ['0x2', 'latest', [150]]), + ]); + expect(s.error?.code, 'sei code').to.equal(-32000); + expect(g.error?.code, 'geth code').to.equal(-32000); + expect(s.error?.message).to.match(/percentile/i); + expect(g.error?.message).to.match(/percentile/i); + }); + + it('[divergence] a far-future newest block is rejected by both (-32000)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_feeHistory', ['0x2', '0xffffffff', [50]]), + rawGeth('eth_feeHistory', ['0x2', '0xffffffff', [50]]), + ]); + expect(s.error?.code, 'sei code').to.equal(-32000); + expect(g.error?.code, 'geth code').to.equal(-32000); + expect(s.error?.message).to.match(/not yet available|beyond/i); + expect(g.error?.message).to.match(/beyond head block/i); + expect(s.error?.message).to.not.equal(g.error?.message); + }); + }); +}); diff --git a/integration_test/rpc_tests/eth/eth_gasPrice.spec.ts b/integration_test/rpc_tests/eth/eth_gasPrice.spec.ts new file mode 100644 index 0000000000..36f3c29114 --- /dev/null +++ b/integration_test/rpc_tests/eth/eth_gasPrice.spec.ts @@ -0,0 +1,325 @@ +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import { bothProviders } from '../utils/providers'; +import { rawSei, rawGeth, expectJsonRpcError, JsonRpcEnvelope } from '../utils/rpc'; +import { readRuntimeState, RuntimeState } from '../utils/state'; +import { abiOf, deployContract } from '../utils/deploy'; +import { EvmAccount } from '../utils/wallet'; +import { HEX_QUANTITY } from '../utils/format'; +import { Eip1559Params, queryEip1559Params } from '../utils/eip1559'; +import { waitUntil } from '../utils/waitFor'; + +// eth_gasPrice parity against a local `geth --dev` reference. Sei and geth build the +// suggested gas price differently: geth returns baseFee + suggested tip, while Sei +// returns nextBaseFee * 1.1 when uncongested (or nextBaseFee + median reward when a +// block exceeds 80% of the gas limit). Both must track the base fee as it moves, so +// we drive the base fee up with a gas burner and assert the suggestion follows. +describe('eth_gasPrice', function () { + this.timeout(240 * 1000); + + const { sei, geth } = bothProviders(); + const burnerIface = new ethers.Interface(abiOf('GasBurner.sol', 'RealGasBurner')); + + let runtime: RuntimeState; + let seiBurner: string; + let spammers: EvmAccount[]; + let seiParams: Eip1559Params | null; + let floorBase: bigint; + let floorGasPrice: bigint; + + const seiGasPrice = async (): Promise => BigInt(await sei.send('eth_gasPrice', [])); + const gethGasPrice = async (): Promise => BigInt(await geth.send('eth_gasPrice', [])); + + async function blockInfo(provider: ethers.JsonRpcProvider, n: number | 'latest') { + const tag = typeof n === 'number' ? ethers.toQuantity(n) : n; + const b = await provider.send('eth_getBlockByNumber', [tag, false]); + return { + number: Number(b.number), + gasUsed: BigInt(b.gasUsed), + gasLimit: BigInt(b.gasLimit), + baseFee: BigInt(b.baseFeePerGas ?? '0x0'), + }; + } + + /** + * Read eth_gasPrice with the latest height pinned: only accept a reading where no + * new block landed across the call, so the returned price provably derives from + * GetNextBaseFeePerGas(B). Returns the price and that block height B. + */ + async function gasPriceAtStableBlock(): Promise<{ gasPrice: bigint; block: number }> { + for (let i = 0; i < 20; i++) { + const b1 = await sei.getBlockNumber(); + const gasPrice = await seiGasPrice(); + const b2 = await sei.getBlockNumber(); + if (b1 === b2) return { gasPrice, block: b1 }; + } + throw new Error('gasPriceAtStableBlock: block kept advancing across the gas price call'); + } + + /** + * Assert a Sei gas price reading tracks the base fee: uncongested it is exactly + * 1.1x the base fee of some block in the immediate neighbourhood of B (which block + * the node sampled for GetNextBaseFeePerGas can drift by one under active load); + * congested it at least covers the base fee. + */ + async function assertSeiGasPriceTracks(gasPrice: bigint, block: number): Promise { + await waitUntil(async () => ((await sei.getBlockNumber()) > block ? true : null), { + timeoutMs: 15_000, + label: 'block after sample', + }); + const head = await sei.getBlockNumber(); + const heights = [block - 1, block, block + 1, block + 2].filter(h => h >= 0 && h <= head); + const infos = await Promise.all(heights.map(h => blockInfo(sei, h))); + + if (infos.some(b => (b.baseFee * 110n) / 100n === gasPrice)) return; + + const congested = infos.some(b => b.gasUsed > (b.gasLimit * 80n) / 100n); + const minBase = infos.reduce((m, b) => (b.baseFee < m ? b.baseFee : m), infos[0].baseFee); + expect( + congested && gasPrice >= minBase, + `gasPrice ${gasPrice} is not 1.1x any base fee near block ${block} ` + + `(bases: ${infos.map(b => b.baseFee).join(', ')})`, + ).to.equal(true); + } + + function claimPool(count: number, salt: string): EvmAccount[] { + const pool = runtime.funded.pool; + let h = 0; + for (const ch of salt) h = (h * 31 + ch.charCodeAt(0)) >>> 0; + const start = h % pool.length; + return Array.from({ length: count }, (_, i) => + EvmAccount.fromPrivateKey(pool[(start + i) % pool.length].privateKey, sei), + ); + } + + before(async () => { + runtime = readRuntimeState(); + seiBurner = runtime.contracts.gasBurner; + spammers = claimPool(5, 'eth_gasPrice'); + seiParams = await queryEip1559Params(); + floorBase = seiParams ? BigInt(seiParams.minFeePerGas) : 1_000_000_000n; + floorGasPrice = (floorBase * 110n) / 100n; + }); + + describe('happy path / schema', () => { + it('returns a positive canonical quantity on Sei', async () => { + const body = await rawSei('eth_gasPrice', []); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result).to.match(HEX_QUANTITY); + expect(BigInt(body.result!) > 0n).to.equal(true); + }); + + it('returns a positive canonical quantity on geth', async () => { + const body = await rawGeth('eth_gasPrice', []); + expect(body.error, JSON.stringify(body.error)).to.equal(undefined); + expect(body.result).to.match(HEX_QUANTITY); + expect(BigInt(body.result!) > 0n).to.equal(true); + }); + + it('is at least the current base fee, so a tx priced at it is includable (both)', async () => { + const [sGas, sBlk, gGas, gBlk] = await Promise.all([ + seiGasPrice(), + blockInfo(sei, 'latest'), + gethGasPrice(), + blockInfo(geth, 'latest'), + ]); + expect(sGas >= sBlk.baseFee, `sei gasPrice ${sGas} < base ${sBlk.baseFee}`).to.equal(true); + expect(gGas >= gBlk.baseFee, `geth gasPrice ${gGas} < base ${gBlk.baseFee}`).to.equal(true); + }); + }); + + describe('relationship to base fee and priority fee', () => { + it('[Sei] an uncongested gas price is exactly the base fee plus the 10% buffer', async () => { + const { gasPrice, block } = await gasPriceAtStableBlock(); + await assertSeiGasPriceTracks(gasPrice, block); + }); + + it('[geth] the gas price equals the base fee plus the suggested priority fee (exact)', async () => { + const [gasPrice, tip, blk] = await Promise.all([ + gethGasPrice(), + BigInt(await geth.send('eth_maxPriorityFeePerGas', [])), + blockInfo(geth, 'latest'), + ]); + expect(gasPrice, 'geth gasPrice = baseFee + tip').to.equal(blk.baseFee + tip); + }); + + it('[Sei] maxPriorityFeePerGas defaults to 1 gwei while the chain is uncongested', async () => { + // Quiescent runs sit well under the 80% congestion threshold. + const tip = BigInt(await sei.send('eth_maxPriorityFeePerGas', [])); + expect(tip).to.equal(1_000_000_000n); + }); + + it('[divergence] Sei multiplies the base fee by 1.1; geth adds a flat tip', async () => { + const [sGas, sBlk, gGas, gTip, gBlk] = await Promise.all([ + seiGasPrice(), + blockInfo(sei, 'latest'), + gethGasPrice(), + BigInt(await geth.send('eth_maxPriorityFeePerGas', [])), + blockInfo(geth, 'latest'), + ]); + // geth's suggestion is purely additive. + expect(gGas - gBlk.baseFee, 'geth premium is the flat tip').to.equal(gTip); + // Sei's premium scales with the base fee (10%), not a flat 1 gwei tip. + expect(sGas, 'sei does not use base + 1gwei').to.not.equal(sBlk.baseFee + 1_000_000_000n); + }); + }); + + describe('reflects base fee increases (Sei)', () => { + async function burstAndSample(): Promise<{ + samples: { gasPrice: bigint; block: number }[]; + peakGasPrice: bigint; + peakBase: bigint; + }> { + const samples: { gasPrice: bigint; block: number }[] = []; + let peakGasPrice = 0n; + let peakBase = 0n; + const GAS_LIMIT = 6_000_000n; + const ITERATIONS = 200n; + const tip = ethers.parseUnits('2', 'gwei'); + + for (let round = 0; round < 10; round++) { + const baseNow = (await blockInfo(sei, 'latest')).baseFee; + const maxFee = baseNow * 4n + tip; + const sends: Promise[] = []; + for (let i = 0; i < spammers.length; i++) { + const s = spammers[i]; + if ((await s.balance()) < GAS_LIMIT * maxFee) continue; + const data = burnerIface.encodeFunctionData('burnGasIterations', [ + BigInt(round * 100 + i), + ITERATIONS, + ]); + sends.push( + s.wallet + .sendTransaction({ + to: seiBurner, + data, + gasLimit: GAS_LIMIT, + maxFeePerGas: maxFee, + maxPriorityFeePerGas: tip, + type: 2, + }) + .then(t => t.wait()) + .then(() => undefined) + .catch(() => undefined), + ); + } + if (sends.length === 0) break; + await Promise.all(sends); + + const sample = await gasPriceAtStableBlock(); + samples.push(sample); + const base = (await blockInfo(sei, sample.block)).baseFee; + if (sample.gasPrice > peakGasPrice) peakGasPrice = sample.gasPrice; + if (base > peakBase) peakBase = base; + } + return { samples, peakGasPrice, peakBase }; + } + + it('gas price rises with the base fee and keeps tracking nextBaseFee * 1.1', async function () { + if (!seiParams) this.skip(); + const { samples, peakGasPrice, peakBase } = await burstAndSample(); + // Skip when the environment cannot raise the base fee (e.g. the shared pool + // accounts have been drained by earlier runs) rather than fail spuriously. + if (samples.length === 0 || peakBase <= floorBase) this.skip(); + + expect( + peakGasPrice > floorGasPrice, + `gas price should rise above the idle ${floorGasPrice}`, + ).to.equal(true); + + // Every reading must track the live base fee through Sei's formula. + for (const s of samples) { + await assertSeiGasPriceTracks(s.gasPrice, s.block); + } + }); + + it('gas price decays back to the floor buffer once the load stops', async function () { + if (!seiParams) this.skip(); + const settled = await waitUntil( + async () => ((await seiGasPrice()) === floorGasPrice ? true : null), + { timeoutMs: 60_000, intervalMs: 500, label: 'gas price decays to floor' }, + ); + expect(settled).to.equal(true); + }); + }); + + describe('reflects base fee increases (geth)', () => { + let gethBurner: ethers.Contract; + let gethSigner: EvmAccount; + let gethNonce: number; + const TIP = ethers.parseUnits('1', 'gwei'); + + before(async () => { + gethSigner = EvmAccount.fromPrivateKey(runtime.funded.gethAdmin.privateKey, geth); + const dep = await deployContract(gethSigner, 'GasBurner.sol', [], 'RealGasBurner'); + gethBurner = new ethers.Contract(dep.address, burnerIface, gethSigner.wallet); + gethNonce = await gethSigner.nonce('latest'); + }); + + // Each heavy burn is its own dev block. Burn ~60% of the parent gas limit + // (over geth's 50% target so the base fee climbs) while capping the tx gas limit + // at 80% — comfortably under the block limit, which geth nudges +/-1/1024 each + // block, so the tx is always minable. + async function heavyGethBlock(salt: number): Promise { + const parent = await blockInfo(geth, 'latest'); + const iterations = (parent.gasLimit * 60n) / 100n / 22_300n; + const tx = await gethBurner.burnGasIterations(salt, iterations, { + gasLimit: (parent.gasLimit * 80n) / 100n, + maxFeePerGas: parent.baseFee * 4n + TIP, + maxPriorityFeePerGas: TIP, + nonce: gethNonce++, + }); + const receipt = await tx.wait(1, 30_000); + expect(receipt!.status, 'heavy geth burn must succeed').to.equal(1); + return receipt!.blockNumber; + } + + it('a run of heavy blocks raises the base fee and the gas price rises with it, still base + tip', async () => { + // A block's base fee is set by its parent, so the rise shows up across a run + // of consecutive over-target blocks rather than within the first one. + const blocks: number[] = []; + for (let i = 0; i < 4; i++) blocks.push(await heavyGethBlock(i)); + const first = await blockInfo(geth, blocks[0]); + const last = await blockInfo(geth, blocks[blocks.length - 1]); + expect(last.baseFee > first.baseFee, 'base fee climbed across the burst').to.equal(true); + + const [gasPrice, tip, head] = await Promise.all([ + gethGasPrice(), + BigInt(await geth.send('eth_maxPriorityFeePerGas', [])), + blockInfo(geth, 'latest'), + ]); + expect(gasPrice, 'gas price stays baseFee + tip').to.equal(head.baseFee + tip); + expect(gasPrice > first.baseFee + tip, 'gas price reflects the raised base fee').to.equal( + true, + ); + }); + }); + + describe('wrong params / error handling', () => { + function expectSameError(s: JsonRpcEnvelope, g: JsonRpcEnvelope): void { + expect(g.error, `geth must error, got ${JSON.stringify(g.result)}`).to.not.equal(undefined); + expect(s.error, `sei must error, got ${JSON.stringify(s.result)}`).to.not.equal(undefined); + expect(s.error!.code, 'error.code parity').to.equal(g.error!.code); + expect(s.error!.message, 'error.message parity').to.equal(g.error!.message); + expect(s.error!.data, 'error.data parity').to.deep.equal(g.error!.data); + } + + it('an extra positional argument fails identically (-32602, want at most 0)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_gasPrice', ['latest']), + rawGeth('eth_gasPrice', ['latest']), + ]); + expectJsonRpcError(s, -32602, /too many arguments, want at most 0/); + expectSameError(s, g); + }); + + it('an object argument fails identically (-32602, want at most 0)', async () => { + const [s, g] = await Promise.all([ + rawSei('eth_gasPrice', [{}]), + rawGeth('eth_gasPrice', [{}]), + ]); + expectJsonRpcError(s, -32602, /too many arguments, want at most 0/); + expectSameError(s, g); + }); + }); +}); diff --git a/integration_test/rpc_tests/eth/eth_getBalance.spec.ts b/integration_test/rpc_tests/eth/eth_getBalance.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getBlockByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockByHash.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getBlockByNumber.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockByNumber.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getBlockReceipts.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockReceipts.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByHash.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByNumber.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByNumber.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getCode.spec.ts b/integration_test/rpc_tests/eth/eth_getCode.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getFilterChanges.spec.ts b/integration_test/rpc_tests/eth/eth_getFilterChanges.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getFilterLogs.spec.ts b/integration_test/rpc_tests/eth/eth_getFilterLogs.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getLogs.spec.ts b/integration_test/rpc_tests/eth/eth_getLogs.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getProof.spec.ts b/integration_test/rpc_tests/eth/eth_getProof.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getStorageAt.spec.ts b/integration_test/rpc_tests/eth/eth_getStorageAt.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionByBlockHashAndIndex.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionByBlockHashAndIndex.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionByBlockNumberAndIndex.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionByBlockNumberAndIndex.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionByHash.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionCount.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionCount.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionErrorByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionErrorByHash.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionReceipt.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionReceipt.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_getVMError.spec.ts b/integration_test/rpc_tests/eth/eth_getVMError.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_maxPriorityFeePerGas.spec.ts b/integration_test/rpc_tests/eth/eth_maxPriorityFeePerGas.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_newBlockFilter.spec.ts b/integration_test/rpc_tests/eth/eth_newBlockFilter.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_newFilter.spec.ts b/integration_test/rpc_tests/eth/eth_newFilter.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_newPendingTransactionFilter.spec.ts b/integration_test/rpc_tests/eth/eth_newPendingTransactionFilter.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_sendRawTransaction.spec.ts b/integration_test/rpc_tests/eth/eth_sendRawTransaction.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_sendTransaction.spec.ts b/integration_test/rpc_tests/eth/eth_sendTransaction.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_sign.spec.ts b/integration_test/rpc_tests/eth/eth_sign.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_signTransaction.spec.ts b/integration_test/rpc_tests/eth/eth_signTransaction.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_subscribe.spec.ts b/integration_test/rpc_tests/eth/eth_subscribe.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_syncing.spec.ts b/integration_test/rpc_tests/eth/eth_syncing.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/eth/eth_uninstallFilter.spec.ts b/integration_test/rpc_tests/eth/eth_uninstallFilter.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/hardhat.config.ts b/integration_test/rpc_tests/hardhat.config.ts new file mode 100644 index 0000000000..e65fb7ded1 --- /dev/null +++ b/integration_test/rpc_tests/hardhat.config.ts @@ -0,0 +1,26 @@ +/** + * Compile-only Hardhat config for the rpc_tests module. Its sole job is to turn + * the Solidity sources under ./contracts into Hardhat artifacts under ./artifacts, + * which utils/deploy.ts loads at runtime (`npm run compile`). + * + * The separate ./hardhat/hardhat.config.ts is used only to spin up the optional + * mainnet fork reference node (`npm run rpc:fork`); keep the two configs apart. + */ +import { HardhatUserConfig } from 'hardhat/config'; +import '@nomicfoundation/hardhat-toolbox'; + +const config: HardhatUserConfig = { + solidity: { + version: '0.8.28', + settings: { + optimizer: { enabled: true, runs: 200 }, + }, + }, + paths: { + sources: 'contracts', + artifacts: 'artifacts', + cache: 'cache', + }, +}; + +export default config; diff --git a/integration_test/rpc_tests/hardhat/README.md b/integration_test/rpc_tests/hardhat/README.md new file mode 100644 index 0000000000..d788c71c37 --- /dev/null +++ b/integration_test/rpc_tests/hardhat/README.md @@ -0,0 +1,37 @@ +# Local Hardhat mainnet fork + +This config spins up a JSON-RPC node on `http://127.0.0.1:9546` that mirrors +Ethereum mainnet at the latest (or a pinned) block. It's the canonical Ethereum +reference for `tests/new_rpc_tests/` — we compare Sei's RPC behavior against it +instead of hitting an upstream Alchemy/Infura endpoint, which is flaky and rate +limited. + +## Quick start + +```bash +# In a dedicated terminal, leave this running for the duration of your test +# session. +yarn rpc:fork +``` + +Then in another terminal: + +```bash +yarn test:rpc +``` + +## Environment + +| Variable | Default | Purpose | +| ----------------------- | ---------------------------------------------------------------- | ------------------------------------------ | +| `ETH_MAINNET_UPSTREAM` | `https://eth-mainnet.g.alchemy.com/v2/Dmh5eMv-DYo4wvFHE2e3E` | RPC URL the fork pulls state from. | +| `ETH_MAINNET_FORK_BLOCK`| (unset → latest) | Pin to a specific block for determinism. | + +## Notes + +- `chainId` is `1`, matching mainnet, so `eth_chainId` and `net_version` + assertions against the fork agree with the upstream Ethereum semantics. +- Artifacts and cache live under `.artifacts/`, `.cache/` inside this folder so + they do not collide with the repository-level `artifacts/`. +- This fork is only an RPC reference. Sei deployments still happen on the local + Sei node — see `_start/00_bootstrap.spec.ts`. diff --git a/integration_test/rpc_tests/hardhat/hardhat.config.ts b/integration_test/rpc_tests/hardhat/hardhat.config.ts new file mode 100644 index 0000000000..57e49e612d --- /dev/null +++ b/integration_test/rpc_tests/hardhat/hardhat.config.ts @@ -0,0 +1,50 @@ +/** + * Standalone Hardhat config used solely to run a local mainnet fork as the + * Ethereum reference for the new_rpc_tests module. Kept separate from the repo's + * top-level hardhat.config.ts so spinning up the fork doesn't disturb existing + * deploy/test flows. + * + * Run with: + * npm run rpc:fork + * which expands to: + * hardhat --config hardhat/hardhat.config.ts node --port 9546 + * + * Required env (or use defaults): + * ETH_MAINNET_UPSTREAM - HTTP RPC URL we are forking from (Alchemy / Infura / etc.) + * ETH_MAINNET_FORK_BLOCK - optional pinned block, recommended for determinism + */ +import { HardhatUserConfig } from 'hardhat/config'; +import '@nomicfoundation/hardhat-toolbox'; + +const UPSTREAM = + process.env.ETH_MAINNET_UPSTREAM ?? + 'https://eth-mainnet.g.alchemy.com/v2/Dmh5eMv-DYo4wvFHE2e3E'; + +const FORK_BLOCK = process.env.ETH_MAINNET_FORK_BLOCK + ? Number(process.env.ETH_MAINNET_FORK_BLOCK) + : undefined; + +const config: HardhatUserConfig = { + solidity: '0.8.28', + networks: { + hardhat: { + chainId: 1, // pretend to be mainnet so eth_chainId tests align with the upstream + forking: { + url: UPSTREAM, + blockNumber: FORK_BLOCK, + }, + // Keep mining instant — RPC tests don't care about block production cadence here. + mining: { auto: true, interval: 0 }, + }, + }, + paths: { + // Hardhat resolves these relative to this config file's directory, so keep + // them simple. They land in tests/new_rpc_tests/hardhat/{.artifacts,.cache,sources} + // and stay isolated from the repo's top-level hardhat invocation. + artifacts: '.artifacts', + cache: '.cache', + sources: 'sources', + }, +}; + +export default config; diff --git a/integration_test/rpc_tests/net/net_version.spec.ts b/integration_test/rpc_tests/net/net_version.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/package-lock.json b/integration_test/rpc_tests/package-lock.json new file mode 100644 index 0000000000..a79f352666 --- /dev/null +++ b/integration_test/rpc_tests/package-lock.json @@ -0,0 +1,9368 @@ +{ + "name": "sei-rpc-tests", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sei-rpc-tests", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@cosmjs/amino": "^0.32.4", + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stargate": "^0.32.4", + "@cosmjs/tendermint-rpc": "^0.32.4", + "@sei-js/cosmos": "^1.0.6", + "cosmjs-types": "^0.9.0", + "ethers": "^6.14.0" + }, + "devDependencies": { + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@types/chai": "^4.3.16", + "@types/mocha": "^10.0.7", + "@types/node": "^22.5.0", + "chai": "^4.4.1", + "hardhat": "^2.22.10", + "mocha": "^10.7.3", + "mochawesome": "^7.1.3", + "mochawesome-merge": "^4.3.0", + "mochawesome-report-generator": "^6.2.0", + "tsx": "^4.19.0", + "typescript": "^5.5.4" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz", + "integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@confio/ics23": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@confio/ics23/-/ics23-0.6.8.tgz", + "integrity": "sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==", + "deprecated": "Unmaintained. The codebase for this package was moved to https://github.com/cosmos/ics23 but then the JS implementation was removed in https://github.com/cosmos/ics23/pull/353. Please consult the maintainers of https://github.com/cosmos for further assistance.", + "license": "Apache-2.0", + "dependencies": { + "@noble/hashes": "^1.0.0", + "protobufjs": "^6.8.8" + } + }, + "node_modules/@cosmjs/amino": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.32.4.tgz", + "integrity": "sha512-zKYOt6hPy8obIFtLie/xtygCkH9ZROiQ12UHfKsOkWaZfPQUvVbtgmu6R4Kn1tFLI/SRkw7eqhaogmW/3NYu/Q==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4" + } + }, + "node_modules/@cosmjs/crypto": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.32.4.tgz", + "integrity": "sha512-zicjGU051LF1V9v7bp8p7ovq+VyC91xlaHdsFOTo2oVry3KQikp8L/81RkXmUIT8FxMwdx1T7DmFwVQikcSDIw==", + "deprecated": "This uses elliptic for cryptographic operations, which contains several security-relevant bugs. To what degree this affects your application is something you need to carefully investigate. See https://github.com/cosmos/cosmjs/issues/1708 for further pointers. Starting with version 0.34.0 the cryptographic library has been replaced. However, private keys might still be at risk.", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers-sumo": "^0.7.11" + } + }, + "node_modules/@cosmjs/encoding": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.32.4.tgz", + "integrity": "sha512-tjvaEy6ZGxJchiizzTn7HVRiyTg1i4CObRRaTRPknm5EalE13SV+TCHq38gIDfyUeden4fCuaBVEdBR5+ti7Hw==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/json-rpc": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.32.4.tgz", + "integrity": "sha512-/jt4mBl7nYzfJ2J/VJ+r19c92mUKF0Lt0JxM3MXEJl7wlwW5haHAWtzRujHkyYMXOwIR+gBqT2S0vntXVBRyhQ==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.32.4", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/math": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.32.4.tgz", + "integrity": "sha512-++dqq2TJkoB8zsPVYCvrt88oJWsy1vMOuSOKcdlnXuOA/ASheTJuYy4+oZlTQ3Fr8eALDLGGPhJI02W2HyAQaw==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@cosmjs/proto-signing": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.32.4.tgz", + "integrity": "sha512-QdyQDbezvdRI4xxSlyM1rSVBO2st5sqtbEIl3IX03uJ7YiZIQHyv6vaHVf1V4mapusCqguiHJzm4N4gsFdLBbQ==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "^0.32.4", + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "cosmjs-types": "^0.9.0" + } + }, + "node_modules/@cosmjs/socket": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.32.4.tgz", + "integrity": "sha512-davcyYziBhkzfXQTu1l5NrpDYv0K9GekZCC9apBRvL1dvMc9F/ygM7iemHjUA+z8tJkxKxrt/YPjJ6XNHzLrkw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.32.4", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stargate": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.32.4.tgz", + "integrity": "sha512-usj08LxBSsPRq9sbpCeVdyLx2guEcOHfJS9mHGCLCXpdAPEIEQEtWLDpEUc0LEhWOx6+k/ChXTc5NpFkdrtGUQ==", + "license": "Apache-2.0", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stream": "^0.32.4", + "@cosmjs/tendermint-rpc": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "cosmjs-types": "^0.9.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stream": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.32.4.tgz", + "integrity": "sha512-Gih++NYHEiP+oyD4jNEUxU9antoC0pFSg+33Hpp0JlHwH0wXhtD3OOKnzSfDB7OIoEbrzLJUpEjOgpCp5Z+W3A==", + "license": "Apache-2.0", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/tendermint-rpc": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.32.4.tgz", + "integrity": "sha512-MWvUUno+4bCb/LmlMIErLypXxy7ckUuzEmpufYYYd9wgbdCXaTaO08SZzyFM5PI8UJ/0S2AmUrgWhldlbxO8mw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/json-rpc": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/socket": "^0.32.4", + "@cosmjs/stream": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "axios": "^1.6.0", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/utils": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.32.4.tgz", + "integrity": "sha512-D1Yc+Zy8oL/hkUkFUL/bwxvuDBzRGpc4cF7/SkdhxX4iHpSLgdOuTt1mhCh9+kl6NQREy9t7SYZ6xeW5gFe60w==", + "license": "Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/rlp": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", + "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", + "dev": true, + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/util": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-9.1.0.tgz", + "integrity": "sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/rlp": "^5.0.2", + "ethereum-cryptography": "^2.2.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, + "node_modules/@ethersproject/abi": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.8.0.tgz", + "integrity": "sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz", + "integrity": "sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/networks": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/web": "^5.8.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz", + "integrity": "sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.8.0.tgz", + "integrity": "sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/rlp": "^5.8.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.8.0.tgz", + "integrity": "sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.8.0.tgz", + "integrity": "sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/properties": "^5.8.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.8.0.tgz", + "integrity": "sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", + "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.8.0.tgz", + "integrity": "sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.8.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.8.0.tgz", + "integrity": "sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.8.0", + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/transactions": "^5.8.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.8.0.tgz", + "integrity": "sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.8.0.tgz", + "integrity": "sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/basex": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/pbkdf2": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/wordlists": "^5.8.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz", + "integrity": "sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hdnode": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/pbkdf2": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz", + "integrity": "sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", + "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/@ethersproject/networks": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.8.0.tgz", + "integrity": "sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz", + "integrity": "sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/sha2": "^5.8.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.8.0.tgz", + "integrity": "sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.8.0.tgz", + "integrity": "sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/base64": "^5.8.0", + "@ethersproject/basex": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/networks": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/rlp": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/web": "^5.8.0", + "bech32": "1.1.4", + "ws": "8.18.0" + } + }, + "node_modules/@ethersproject/providers/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@ethersproject/random": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.8.0.tgz", + "integrity": "sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.8.0.tgz", + "integrity": "sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.8.0.tgz", + "integrity": "sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.8.0.tgz", + "integrity": "sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "bn.js": "^5.2.1", + "elliptic": "6.6.1", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.8.0.tgz", + "integrity": "sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/strings": "^5.8.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.8.0.tgz", + "integrity": "sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.8.0.tgz", + "integrity": "sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/rlp": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.8.0.tgz", + "integrity": "sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.8.0.tgz", + "integrity": "sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/hdnode": "^5.8.0", + "@ethersproject/json-wallets": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/wordlists": "^5.8.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.8.0.tgz", + "integrity": "sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.8.0.tgz", + "integrity": "sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nomicfoundation/edr": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.12.0-next.23.tgz", + "integrity": "sha512-F2/6HZh8Q9RsgkOIkRrckldbhPjIZY7d4mT9LYuW68miwGQ5l7CkAgcz9fRRiurA0+YJhtsbx/EyrD9DmX9BOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.23", + "@nomicfoundation/edr-darwin-x64": "0.12.0-next.23", + "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.23", + "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.23", + "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.23", + "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.23", + "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.23" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.12.0-next.23.tgz", + "integrity": "sha512-Amh7mRoDzZyJJ4efqoePqdoZOzharmSOttZuJDlVE5yy07BoE8hL6ZRpa5fNYn0LCqn/KoWs8OHANWxhKDGhvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.12.0-next.23.tgz", + "integrity": "sha512-9wn489FIQm7m0UCD+HhktjWx6vskZzeZD9oDc2k9ZvbBzdXwPp5tiDqUBJ+eQpByAzCDfteAJwRn2lQCE0U+Iw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.12.0-next.23.tgz", + "integrity": "sha512-nlk5EejSzEUfEngv0Jkhqq3/wINIfF2ED9wAofc22w/V1DV99ASh9l3/e/MIHOQFecIZ9MDqt0Em9/oDyB1Uew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.12.0-next.23.tgz", + "integrity": "sha512-SJuPBp3Rc6vM92UtVTUxZQ/QlLhLfwTftt2XUiYohmGKB3RjGzpgduEFMCA0LEnucUckU6UHrJNFHiDm77C4PQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.12.0-next.23.tgz", + "integrity": "sha512-NU+Qs3u7Qt6t3bJFdmmjd5CsvgI2bPPzO31KifM2Ez96/jsXYho5debtTQnimlb5NAqiHTSlxjh/F8ROcptmeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.12.0-next.23.tgz", + "integrity": "sha512-F78fZA2h6/ssiCSZOovlgIu0dUeI7ItKPsDDF3UUlIibef052GCXmliMinC90jVPbrjUADMd1BUwjfI0Z8OllQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.12.0-next.23", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.12.0-next.23.tgz", + "integrity": "sha512-IfJZQJn7d/YyqhmguBIGoCKjE9dKjbu6V6iNEPApfwf5JyyjHYyyfkLU4rf7hygj57bfH4sl1jtQ6r8HnT62lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@nomicfoundation/hardhat-chai-matchers": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.1.2.tgz", + "integrity": "sha512-NlUlde/ycXw2bLzA2gWjjbxQaD9xIRbAF30nsoEprAWzH8dXEI1ILZUKZMyux9n9iygEXTzN0SDVjE6zWDZi9g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/chai-as-promised": "^7.1.3", + "chai-as-promised": "^7.1.1", + "deep-eql": "^4.0.1", + "ordinal": "^1.0.3" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.1.0", + "chai": "^4.2.0", + "ethers": "^6.14.0", + "hardhat": "^2.26.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ethers": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.1.3.tgz", + "integrity": "sha512-208JcDeVIl+7Wu3MhFUUtiA8TJ7r2Rn3Wr+lSx9PfsDTKkbsAsWPY6N6wQ4mtzDv0/pB9nIbJhkjoHe1EsgNsA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "ethers": "^6.14.0", + "hardhat": "^2.28.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition": { + "version": "0.15.16", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.16.tgz", + "integrity": "sha512-T0JTnuib7QcpsWkHCPLT7Z6F483EjTdcdjb1e00jqS9zTGCPqinPB66LLtR/duDLdvgoiCVS6K8WxTQkA/xR1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nomicfoundation/ignition-core": "^0.15.15", + "@nomicfoundation/ignition-ui": "^0.15.13", + "chalk": "^4.0.0", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "json5": "^2.2.3", + "prompts": "^2.4.2" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-verify": "^2.1.0", + "hardhat": "^2.26.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition-ethers": { + "version": "0.15.17", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition-ethers/-/hardhat-ignition-ethers-0.15.17.tgz", + "integrity": "sha512-io6Wrp1dUsJ94xEI3pw6qkPfhc9TFA+e6/+o16yQ8pvBTFMjgK5x8wIHKrrIHr9L3bkuTMtmDjyN4doqO2IqFQ==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.1.0", + "@nomicfoundation/hardhat-ignition": "^0.15.16", + "@nomicfoundation/ignition-core": "^0.15.15", + "ethers": "^6.14.0", + "hardhat": "^2.26.0" + } + }, + "node_modules/@nomicfoundation/hardhat-network-helpers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.1.2.tgz", + "integrity": "sha512-p7HaUVDbLj7ikFivQVNhnfMHUBgiHYMwQWvGn9AriieuopGOELIrwj2KjyM2a6z70zai5YKO264Vwz+3UFJZPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ethereumjs-util": "^7.1.4" + }, + "peerDependencies": { + "hardhat": "^2.26.0" + } + }, + "node_modules/@nomicfoundation/hardhat-toolbox": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-5.0.0.tgz", + "integrity": "sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=18.0.0", + "chai": "^4.2.0", + "ethers": "^6.4.0", + "hardhat": "^2.11.0", + "hardhat-gas-reporter": "^1.0.8", + "solidity-coverage": "^0.8.1", + "ts-node": ">=8.0.0", + "typechain": "^8.3.0", + "typescript": ">=4.5.0" + } + }, + "node_modules/@nomicfoundation/hardhat-verify": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.1.3.tgz", + "integrity": "sha512-danbGjPp2WBhLkJdQy9/ARM3WQIK+7vwzE0urNem1qZJjh9f54Kf5f1xuQv8DvqewUAkuPxVt/7q4Grz5WjqSg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "debug": "^4.1.1", + "lodash.clonedeep": "^4.5.0", + "picocolors": "^1.1.0", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.26.0" + } + }, + "node_modules/@nomicfoundation/ignition-core": { + "version": "0.15.15", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.15.tgz", + "integrity": "sha512-JdKFxYknTfOYtFXMN6iFJ1vALJPednuB+9p9OwGIRdoI6HYSh4ZBzyRURgyXtHFyaJ/SF9lBpsYV9/1zEpcYwg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/address": "5.6.1", + "@nomicfoundation/solidity-analyzer": "^0.1.1", + "cbor": "^9.0.0", + "debug": "^4.3.2", + "ethers": "^6.14.0", + "fs-extra": "^10.0.0", + "immer": "10.0.2", + "lodash": "4.17.21", + "ndjson": "2.0.0" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/@ethersproject/address": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", + "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.1" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@nomicfoundation/ignition-ui": { + "version": "0.15.13", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.13.tgz", + "integrity": "sha512-HbTszdN1iDHCkUS9hLeooqnLEW2U45FaqFwFEYT8nIno2prFZhG+n68JEERjmfFCB5u0WgbuJwk3CgLoqtSL7Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@nomicfoundation/solidity-analyzer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz", + "integrity": "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + }, + "optionalDependencies": { + "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", + "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz", + "integrity": "sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz", + "integrity": "sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz", + "integrity": "sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz", + "integrity": "sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz", + "integrity": "sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz", + "integrity": "sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz", + "integrity": "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", + "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "license": "BSD-3-Clause" + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@sei-js/cosmos": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@sei-js/cosmos/-/cosmos-1.0.6.tgz", + "integrity": "sha512-LMvLKQ35XI6bN9W1K0/uGEA4aDSSoSLSRcr/ALrS5JyjT9C9jw3sF1hpfQVLcTbfuhlvhDsf2jRukxwceuHzqQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.1.0", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stargate": "^0.32.4" + } + }, + "node_modules/@sentry/core": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", + "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/core/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/hub": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", + "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/minimal": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", + "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/node": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", + "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/core": "5.30.0", + "@sentry/hub": "5.30.0", + "@sentry/tracing": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/tracing": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", + "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/tracing/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@solidity-parser/parser": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", + "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@typechain/ethers-v6": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", + "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "ethers": "6.x", + "typechain": "^8.3.2", + "typescript": ">=4.7.0" + } + }, + "node_modules/@typechain/hardhat": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-9.1.0.tgz", + "integrity": "sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fs-extra": "^9.1.0" + }, + "peerDependencies": { + "@typechain/ethers-v6": "^0.5.1", + "ethers": "^6.1.0", + "hardhat": "^2.9.9", + "typechain": "^8.3.2" + } + }, + "node_modules/@typechain/hardhat/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai-as-promised": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/concat-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", + "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/form-data": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", + "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT" + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", + "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/secp256k1": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.7.tgz", + "integrity": "sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", + "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/bn.js": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "license": "MIT" + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai-as-promised": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", + "dev": true, + "license": "WTFPL", + "peer": true, + "dependencies": { + "check-error": "^1.0.2" + }, + "peerDependencies": { + "chai": ">= 2.1.2 < 6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "colors": "^1.1.2" + } + }, + "node_modules/cli-table3/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-table3/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true, + "license": "MIT" + }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/command-line-usage/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/command-line-usage/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/command-line-usage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/command-line-usage/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/cosmjs-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.9.0.tgz", + "integrity": "sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==", + "license": "Apache-2.0" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==", + "dev": true, + "peer": true + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/diff": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", + "dev": true, + "peer": true, + "dependencies": { + "heap": ">= 0.2.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eth-gas-reporter": { + "version": "0.2.27", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz", + "integrity": "sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@solidity-parser/parser": "^0.14.0", + "axios": "^1.5.1", + "cli-table3": "^0.5.0", + "colors": "1.4.0", + "ethereum-cryptography": "^1.0.3", + "ethers": "^5.7.2", + "fs-readdir-recursive": "^1.1.0", + "lodash": "^4.17.14", + "markdown-table": "^1.1.3", + "mocha": "^10.2.0", + "req-cwd": "^2.0.0", + "sha1": "^1.1.1", + "sync-request": "^6.0.0" + }, + "peerDependencies": { + "@codechecks/client": "^0.1.0" + }, + "peerDependenciesMeta": { + "@codechecks/client": { + "optional": true + } + } + }, + "node_modules/eth-gas-reporter/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/eth-gas-reporter/node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.8.0.tgz", + "integrity": "sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@ethersproject/abi": "5.8.0", + "@ethersproject/abstract-provider": "5.8.0", + "@ethersproject/abstract-signer": "5.8.0", + "@ethersproject/address": "5.8.0", + "@ethersproject/base64": "5.8.0", + "@ethersproject/basex": "5.8.0", + "@ethersproject/bignumber": "5.8.0", + "@ethersproject/bytes": "5.8.0", + "@ethersproject/constants": "5.8.0", + "@ethersproject/contracts": "5.8.0", + "@ethersproject/hash": "5.8.0", + "@ethersproject/hdnode": "5.8.0", + "@ethersproject/json-wallets": "5.8.0", + "@ethersproject/keccak256": "5.8.0", + "@ethersproject/logger": "5.8.0", + "@ethersproject/networks": "5.8.0", + "@ethersproject/pbkdf2": "5.8.0", + "@ethersproject/properties": "5.8.0", + "@ethersproject/providers": "5.8.0", + "@ethersproject/random": "5.8.0", + "@ethersproject/rlp": "5.8.0", + "@ethersproject/sha2": "5.8.0", + "@ethersproject/signing-key": "5.8.0", + "@ethersproject/solidity": "5.8.0", + "@ethersproject/strings": "5.8.0", + "@ethersproject/transactions": "5.8.0", + "@ethersproject/units": "5.8.0", + "@ethersproject/wallet": "5.8.0", + "@ethersproject/web": "5.8.0", + "@ethersproject/wordlists": "5.8.0" + } + }, + "node_modules/ethereum-bloom-filters": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz", + "integrity": "sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "^1.4.0" + } + }, + "node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "dev": true, + "license": "MPL-2.0", + "peer": true, + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethers": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz", + "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fp-ts": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", + "dev": true, + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fsu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==", + "dev": true, + "license": "MIT" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ghost-testrpc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", + "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "chalk": "^2.4.2", + "node-emoji": "^1.10.0" + }, + "bin": { + "testrpc-sc": "index.js" + } + }, + "node_modules/ghost-testrpc/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ghost-testrpc/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/ghost-testrpc/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ghost-testrpc/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/globby/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/globby/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globby/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hardhat": { + "version": "2.28.6", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.28.6.tgz", + "integrity": "sha512-zQze7qe+8ltwHvhX5NQ8sN1N37WWZGw8L63y+2XcPxGwAjc/SMF829z3NS6o1krX0sryhAsVBK/xrwUqlsot4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ethereumjs/util": "^9.1.0", + "@ethersproject/abi": "^5.1.2", + "@nomicfoundation/edr": "0.12.0-next.23", + "@nomicfoundation/solidity-analyzer": "^0.1.0", + "@sentry/node": "^5.18.1", + "adm-zip": "^0.4.16", + "aggregate-error": "^3.0.0", + "ansi-escapes": "^4.3.0", + "boxen": "^5.1.2", + "chokidar": "^4.0.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "ethereum-cryptography": "^1.0.3", + "find-up": "^5.0.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "immutable": "^4.0.0-rc.12", + "io-ts": "1.10.4", + "json-stream-stringify": "^3.1.4", + "keccak": "^3.0.2", + "lodash": "^4.17.11", + "micro-eth-signer": "^0.14.0", + "mnemonist": "^0.38.0", + "mocha": "^10.0.0", + "p-map": "^4.0.0", + "picocolors": "^1.1.0", + "raw-body": "^2.4.1", + "resolve": "1.17.0", + "semver": "^6.3.0", + "solc": "0.8.26", + "source-map-support": "^0.5.13", + "stacktrace-parser": "^0.1.10", + "tinyglobby": "^0.2.6", + "tsort": "0.0.1", + "undici": "^5.14.0", + "uuid": "^8.3.2", + "ws": "^7.4.6" + }, + "bin": { + "hardhat": "internal/cli/bootstrap.js" + }, + "peerDependencies": { + "ts-node": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/hardhat-gas-reporter": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", + "integrity": "sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "array-uniq": "1.0.3", + "eth-gas-reporter": "^0.2.25", + "sha1": "^1.1.1" + }, + "peerDependencies": { + "hardhat": "^2.0.2" + } + }, + "node_modules/hardhat/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/hardhat/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/hardhat/node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/hardhat/node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/hardhat/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, + "node_modules/hardhat/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/hardhat/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/hardhat/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/hash-base/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hash-base/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/hash-base/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/hash-base/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/http-basic": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", + "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", + "http-response-object": "^3.0.1", + "parse-cache-control": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-response-object": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^10.0.3" + } + }, + "node_modules/http-response-object/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.8.tgz", + "integrity": "sha512-d/Ld9aLbKpNwyl0KiM2CT1WYvkitQ1TSvmRtkcV8FKStiDoA7Slzgjmb/1G2yhKM1p0XeNOieaTbFZmU1d3Xuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/io-ts": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", + "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fp-ts": "^1.0.0" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/json-stream-stringify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", + "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=7.10.1" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonschema": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", + "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libsodium-sumo": { + "version": "0.7.16", + "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.16.tgz", + "integrity": "sha512-x6atrz2AdXCJg6G709x9W9TTJRI6/0NcL5dD0l5GGVqNE48UJmDsjO4RUWYTeyXXUpg+NXZ2SHECaZnFRYzwGA==", + "license": "ISC" + }, + "node_modules/libsodium-wrappers-sumo": { + "version": "0.7.16", + "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.16.tgz", + "integrity": "sha512-gR0JEFPeN3831lB9+ogooQk0KH4K5LSMIO5Prd5Q5XYR2wHFtZfPg0eP7t1oJIWq+UIzlU4WVeBxZ97mt28tXw==", + "license": "ISC", + "dependencies": { + "libsodium-sumo": "^0.7.16" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micro-eth-signer": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz", + "integrity": "sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "micro-packed": "~0.7.2" + } + }, + "node_modules/micro-eth-signer/node_modules/@noble/curves": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.2" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/micro-eth-signer/node_modules/@noble/hashes": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/micro-ftch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", + "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/micro-packed": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.3.tgz", + "integrity": "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mnemonist": { + "version": "0.38.5", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", + "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "obliterator": "^2.0.0" + } + }, + "node_modules/mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/mocha/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mochawesome": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.4.tgz", + "integrity": "sha512-fucGSh8643QkSvNRFOaJ3+kfjF0FhA/YtvDncnRAG0A4oCtAzHIFkt/+SgsWil1uwoeT+Nu5fsAnrKkFtnPcZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "diff": "^5.0.0", + "json-stringify-safe": "^5.0.1", + "lodash.isempty": "^4.4.0", + "lodash.isfunction": "^3.0.9", + "lodash.isobject": "^3.0.2", + "lodash.isstring": "^4.0.1", + "mochawesome-report-generator": "^6.3.0", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "mocha": ">=7" + } + }, + "node_modules/mochawesome-merge": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.4.1.tgz", + "integrity": "sha512-QCzsXrfH5ewf4coUGvrAOZSpRSl9Vg39eqL2SpKKGkUw390f18hx9C90BNWTA4f/teD2nA0Inb1yxYPpok2gvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^7.0.1", + "glob": "^7.1.6", + "yargs": "^15.3.1" + }, + "bin": { + "mochawesome-merge": "bin/mochawesome-merge.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mochawesome-merge/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/mochawesome-merge/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mochawesome-merge/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/mochawesome-merge/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mochawesome-merge/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/mochawesome-merge/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mochawesome-merge/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/mochawesome-merge/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mochawesome-merge/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mochawesome-merge/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/mochawesome-merge/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/mochawesome-merge/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mochawesome-report-generator": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.3.2.tgz", + "integrity": "sha512-iB6iyOUMyMr8XOUYTNfrqYuZQLZka3K/Gr2GPc6CHPe7t2ZhxxfcoVkpMLOtyDKnWbY1zgu1/7VNRsigrvKnOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "dateformat": "^4.5.1", + "escape-html": "^1.0.3", + "fs-extra": "^10.0.0", + "fsu": "^1.1.1", + "lodash.isfunction": "^3.0.9", + "opener": "^1.5.2", + "prop-types": "^15.7.2", + "tcomb": "^3.2.17", + "tcomb-validation": "^3.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "marge": "bin/cli.js" + } + }, + "node_modules/mochawesome-report-generator/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mochawesome-report-generator/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mochawesome-report-generator/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "ndjson": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "dev": true, + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/obliterator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", + "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", + "dev": true, + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ordinal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", + "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", + "dev": true, + "peer": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.6.tgz", + "integrity": "sha512-BT6eelPB1EyGHo8pC0o9Bl6k6SYVhKO1jEbd3lcTrtr7XHdjP8BW1YpfCV3G9Kwkxgattk+S5q2/RvuttCsS1g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/protobufjs": { + "version": "6.11.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.6.tgz", + "integrity": "sha512-k8BHqgPBOtrlougZZqF2uUk5Z7bN8f0wj+3e8M3hvtSv0NBAz4VBy5f6R5Nxq/l+i7mRFTgNZb2trxqTpHNY/A==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/readonly-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", + "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==", + "license": "Apache-2.0" + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "peer": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/recursive-readdir/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/recursive-readdir/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/req-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", + "integrity": "sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "req-from": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", + "integrity": "sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rlp": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", + "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "dev": true, + "license": "MPL-2.0", + "peer": true, + "dependencies": { + "bn.js": "^5.2.0" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sc-istanbul": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", + "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/sc-istanbul/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/sc-istanbul/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/sc-istanbul/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sc-istanbul/node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sc-istanbul/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sc-istanbul/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/sc-istanbul/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/secp256k1/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "peer": true, + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shelljs/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/shelljs/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/solc": { + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", + "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solc.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/solidity-coverage": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.17.tgz", + "integrity": "sha512-5P8vnB6qVX9tt1MfuONtCTEaEGO/O4WuEidPHIAJjx4sktHHKhO3rFvnE0q8L30nWJPTrcqGQMT7jpE29B2qow==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.0.9", + "@solidity-parser/parser": "^0.20.1", + "chalk": "^2.4.2", + "death": "^1.1.0", + "difflib": "^0.2.4", + "fs-extra": "^8.1.0", + "ghost-testrpc": "^0.0.2", + "global-modules": "^2.0.0", + "globby": "^10.0.1", + "jsonschema": "^1.2.4", + "lodash": "^4.17.21", + "mocha": "^10.2.0", + "node-emoji": "^1.10.0", + "pify": "^4.0.1", + "recursive-readdir": "^2.2.2", + "sc-istanbul": "^0.4.5", + "semver": "^7.3.4", + "shelljs": "^0.8.3", + "web3-utils": "^1.3.6" + }, + "bin": { + "solidity-coverage": "plugins/bin.js" + }, + "peerDependencies": { + "hardhat": "^2.11.0" + } + }, + "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.20.2.tgz", + "integrity": "sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/solidity-coverage/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/solidity-coverage/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/solidity-coverage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/solidity-coverage/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/solidity-coverage/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/solidity-coverage/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solidity-coverage/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/stacktrace-parser": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", + "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", + "dev": true, + "license": "WTFPL OR MIT", + "peer": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/symbol-observable": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", + "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/sync-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", + "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "http-response-object": "^3.0.1", + "sync-rpc": "^1.2.1", + "then-request": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sync-rpc": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", + "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "get-port": "^3.1.0" + } + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table-layout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", + "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tcomb": { + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tcomb-validation": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tcomb": "^3.0.0" + } + }, + "node_modules/then-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", + "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/concat-stream": "^1.6.0", + "@types/form-data": "0.0.33", + "@types/node": "^8.0.0", + "@types/qs": "^6.2.31", + "caseless": "~0.12.0", + "concat-stream": "^1.6.0", + "form-data": "^2.2.0", + "http-basic": "^8.1.1", + "http-response-object": "^3.0.1", + "promise": "^8.0.0", + "qs": "^6.4.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/then-request/node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/then-request/node_modules/form-data": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-command-line-args": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", + "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "string-format": "^2.0.0" + }, + "bin": { + "write-markdown": "dist/write-markdown.js" + } + }, + "node_modules/ts-essentials": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", + "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "typescript": ">=3.7.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, + "node_modules/tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tsx": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.3.tgz", + "integrity": "sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typechain": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", + "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prettier": "^2.1.1", + "debug": "^4.3.1", + "fs-extra": "^7.0.0", + "glob": "7.1.7", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "mkdirp": "^1.0.4", + "prettier": "^2.3.1", + "ts-command-line-args": "^2.2.0", + "ts-essentials": "^7.0.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + }, + "peerDependencies": { + "typescript": ">=4.3.0" + } + }, + "node_modules/typechain/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/typechain/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/typechain/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typechain/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/typechain/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typechain/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typechain/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/web3-utils": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", + "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", + "dev": true, + "license": "LGPL-3.0", + "peer": true, + "dependencies": { + "@ethereumjs/util": "^8.1.0", + "bn.js": "^5.2.1", + "ethereum-bloom-filters": "^1.0.6", + "ethereum-cryptography": "^2.1.2", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-utils/node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "dev": true, + "license": "MPL-2.0", + "peer": true, + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/web3-utils/node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "dev": true, + "license": "MPL-2.0", + "peer": true, + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/web3-utils/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.21.tgz", + "integrity": "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/wordwrapjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", + "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "reduce-flatten": "^2.0.0", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xstream": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", + "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", + "license": "MIT", + "dependencies": { + "globalthis": "^1.0.1", + "symbol-observable": "^2.0.3" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/integration_test/rpc_tests/package.json b/integration_test/rpc_tests/package.json new file mode 100644 index 0000000000..e92b56dae0 --- /dev/null +++ b/integration_test/rpc_tests/package.json @@ -0,0 +1,43 @@ +{ + "name": "sei-rpc-tests", + "version": "1.0.0", + "private": true, + "description": "Self-contained suite that verifies Sei's EVM JSON-RPC against a local geth reference node.", + "license": "MIT", + "scripts": { + "compile": "hardhat compile", + "rpc:geth": "geth --dev --http --http.addr 127.0.0.1 --http.port 9547 --http.api eth,net,web3,debug,txpool --dev.period 0", + "rpc:fork": "hardhat --config hardhat/hardhat.config.ts node --port 9546", + "rpc:bootstrap": "mocha --config .mocharc.bootstrap.json", + "rpc:run": "bash scripts/run-parallel.sh", + "rpc:run:serial": "mocha --config .mocharc.run.json", + "test:rpc": "npm run rpc:bootstrap && npm run rpc:run", + "report:merge": "mochawesome-merge \"reports/new_rpc/*.json\" > reports/merged.json && marge reports/merged.json -o reports/merged -f rpc-tests --reportTitle \"Sei RPC Tests\" --charts", + "test:rpc:full": "bash scripts/run-full.sh" + }, + "dependencies": { + "@cosmjs/amino": "^0.32.4", + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stargate": "^0.32.4", + "@cosmjs/tendermint-rpc": "^0.32.4", + "@sei-js/cosmos": "^1.0.6", + "cosmjs-types": "^0.9.0", + "ethers": "^6.14.0" + }, + "devDependencies": { + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@types/chai": "^4.3.16", + "@types/mocha": "^10.0.7", + "@types/node": "^22.5.0", + "chai": "^4.4.1", + "hardhat": "^2.22.10", + "mocha": "^10.7.3", + "mochawesome": "^7.1.3", + "mochawesome-merge": "^4.3.0", + "mochawesome-report-generator": "^6.2.0", + "tsx": "^4.19.0", + "typescript": "^5.5.4" + } +} diff --git a/integration_test/rpc_tests/runtime/.gitkeep b/integration_test/rpc_tests/runtime/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration_test/rpc_tests/scripts/run-full.sh b/integration_test/rpc_tests/scripts/run-full.sh new file mode 100755 index 0000000000..4c399ef22f --- /dev/null +++ b/integration_test/rpc_tests/scripts/run-full.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash +# +# One-shot runner for the Sei EVM JSON-RPC test suite. +# +# 1. Starts the local 4-node Sei docker cluster (make docker-cluster-start). +# 2. Starts the geth --dev reference node (npm run rpc:geth). +# 3. Runs the suite (bootstrap + parallel run) producing mochawesome JSON. +# 4. Merges the per-phase JSON into a single combined mochawesome HTML report. +# +# The geth node we start is always torn down on exit. The docker cluster is left +# running by default (set STOP_CLUSTER=true to tear it down too); a subsequent run +# is still safe because `docker-cluster-start` stops any existing cluster first. +# +# Env knobs: +# CLUSTER_TIMEOUT seconds to wait for the cluster to come up (default 900) +# GETH_TIMEOUT seconds to wait for geth to listen on :9547 (default 120) +# SEI_TIMEOUT seconds to wait for Sei EVM RPC on :8545 (default 300) +# STOP_CLUSTER "true" to run docker-cluster-stop on exit (default false) +set -uo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +RPC_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_ROOT="$(cd "$RPC_DIR/../.." && pwd)" + +GETH_PORT=9547 +SEI_EVM_RPC_URL="${SEI_EVM_RPC:-http://localhost:8545}" +GETH_RPC_URL="${RPC_ETH_GETH:-http://127.0.0.1:${GETH_PORT}}" +CLUSTER_TIMEOUT="${CLUSTER_TIMEOUT:-900}" +GETH_TIMEOUT="${GETH_TIMEOUT:-120}" +SEI_TIMEOUT="${SEI_TIMEOUT:-300}" +STOP_CLUSTER="${STOP_CLUSTER:-false}" + +REPORT_DIR="$RPC_DIR/reports/new_rpc" +GETH_LOG="$RPC_DIR/reports/geth.log" +GETH_PID="" + +log() { printf '\n\033[1;36m==> %s\033[0m\n' "$*"; } +warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*"; } +die() { printf '\033[1;31m[error]\033[0m %s\n' "$*" >&2; exit 1; } + +cleanup() { + local code=$? + log "Cleaning up" + if [ -n "$GETH_PID" ] && kill -0 "$GETH_PID" 2>/dev/null; then + kill "$GETH_PID" 2>/dev/null || true + fi + # Make sure nothing is left bound to the geth port. + local stray + stray="$(lsof -ti tcp:${GETH_PORT} 2>/dev/null || true)" + [ -n "$stray" ] && kill $stray 2>/dev/null || true + if [ "$STOP_CLUSTER" = "true" ]; then + log "Stopping docker cluster" + ( cd "$REPO_ROOT" && make docker-cluster-stop ) || warn "docker-cluster-stop failed" + fi + exit $code +} +trap cleanup EXIT INT TERM + +# Read a single eth_blockNumber (decimal) from an EVM RPC, or empty on failure. +eth_block_number() { + local url="$1" hex + hex="$(curl -s -m 3 -X POST -H 'content-type: application/json' \ + --data '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}' \ + "$url" 2>/dev/null | sed -n 's/.*"result":"\(0x[0-9a-fA-F]*\)".*/\1/p')" + [ -n "$hex" ] && printf '%d' "$hex" 2>/dev/null || true +} + +# Poll an EVM JSON-RPC endpoint until it answers eth_chainId or times out. +wait_for_rpc() { + local url="$1" name="$2" timeout="$3" elapsed=0 + log "Waiting for $name at $url (timeout ${timeout}s)" + while [ "$elapsed" -lt "$timeout" ]; do + if curl -s -m 3 -X POST -H 'content-type: application/json' \ + --data '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}' \ + "$url" 2>/dev/null | grep -q '"result"'; then + log "$name is up (after ${elapsed}s)" + return 0 + fi + sleep 2; elapsed=$((elapsed + 2)) + done + return 1 +} + +wait_for_block_production() { + local url="$1" name="$2" timeout="$3" elapsed=0 first second + log "Waiting for $name to produce blocks (timeout ${timeout}s)" + while [ "$elapsed" -lt "$timeout" ]; do + first="$(eth_block_number "$url")" + if [ -n "$first" ] && [ "$first" -gt 0 ] 2>/dev/null; then + sleep 3 + second="$(eth_block_number "$url")" + if [ -n "$second" ] && [ "$second" -gt "$first" ] 2>/dev/null; then + log "$name is minting blocks (height $first -> $second, after ${elapsed}s)" + return 0 + fi + elapsed=$((elapsed + 3)) + fi + sleep 2; elapsed=$((elapsed + 2)) + done + return 1 +} + +# Wait for the cluster's launch.complete sentinel (>=4 nodes ready). +wait_for_cluster() { + local sentinel="$REPO_ROOT/build/generated/launch.complete" elapsed=0 + log "Waiting for Sei cluster readiness ($sentinel, timeout ${CLUSTER_TIMEOUT}s)" + while [ "$elapsed" -lt "$CLUSTER_TIMEOUT" ]; do + if [ -f "$sentinel" ] && [ "$(wc -l < "$sentinel" 2>/dev/null || echo 0)" -ge 4 ]; then + log "All 4 nodes reported ready (after ${elapsed}s)" + return 0 + fi + sleep 5; elapsed=$((elapsed + 5)) + done + return 1 +} + +command -v geth >/dev/null 2>&1 || die "geth not found on PATH; install go-ethereum to run the reference node." +command -v curl >/dev/null 2>&1 || die "curl is required." + +mkdir -p "$REPORT_DIR" + +# --- 1. Start the Sei docker cluster (detached) --------------------------------- +log "Starting Sei docker cluster (DOCKER_DETACH=true make docker-cluster-start)" +( cd "$REPO_ROOT" && DOCKER_DETACH=true make docker-cluster-start ) \ + || die "make docker-cluster-start failed" + +wait_for_cluster || die "Sei cluster did not become ready within ${CLUSTER_TIMEOUT}s" +wait_for_rpc "$SEI_EVM_RPC_URL" "Sei EVM RPC" "$SEI_TIMEOUT" \ + || die "Sei EVM RPC at $SEI_EVM_RPC_URL never came up" +# The cluster sentinel only means the nodes booted; the bootstrap's funding + +# association txs need the chain to actually be committing blocks, so gate on that. +wait_for_block_production "$SEI_EVM_RPC_URL" "Sei chain" "$SEI_TIMEOUT" \ + || die "Sei chain at $SEI_EVM_RPC_URL is up but not producing blocks within ${SEI_TIMEOUT}s" + +# --- 2. Start the geth --dev reference node ------------------------------------- +log "Starting geth reference node (npm run rpc:geth) -> $GETH_LOG" +( cd "$RPC_DIR" && npm run --silent rpc:geth ) > "$GETH_LOG" 2>&1 & +GETH_PID=$! + +wait_for_rpc "$GETH_RPC_URL" "geth reference" "$GETH_TIMEOUT" \ + || { warn "geth log tail:"; tail -n 20 "$GETH_LOG" || true; die "geth never came up on $GETH_RPC_URL"; } + +# --- 3. Run the suite (don't abort on test failures; we still want a report) ----- +cd "$RPC_DIR" +log "Running bootstrap (npm run rpc:bootstrap)" +npm run rpc:bootstrap; BOOT_CODE=$? + +log "Running parallel suite (npm run rpc:run)" +npm run rpc:run; RUN_CODE=$? + +# --- 4. Merge mochawesome reports into one combined HTML ------------------------ +# mochawesome-merge wants a single glob (multiple explicit file args only reads the +# first). We glob the per-phase JSON in $REPORT_DIR and write the merged output to +# $RPC_DIR/reports so a re-run's glob never re-ingests its own merged.json. +log "Merging mochawesome reports" +if ls "$REPORT_DIR"/*.json >/dev/null 2>&1; then + npx mochawesome-merge "$REPORT_DIR/*.json" > "$RPC_DIR/reports/merged.json" \ + && npx marge "$RPC_DIR/reports/merged.json" -o "$RPC_DIR/reports/merged" \ + -f rpc-tests --reportTitle "Sei RPC Tests" --charts \ + && log "Combined report: $RPC_DIR/reports/merged/rpc-tests.html" +else + warn "No mochawesome JSON found to merge (did the suite produce any reports?)" +fi + +# --- Result --------------------------------------------------------------------- +if [ "$BOOT_CODE" -ne 0 ] || [ "$RUN_CODE" -ne 0 ]; then + warn "Test run finished with failures (bootstrap=$BOOT_CODE, run=$RUN_CODE)" + exit 1 +fi +log "All RPC tests passed" diff --git a/integration_test/rpc_tests/scripts/run-parallel.sh b/integration_test/rpc_tests/scripts/run-parallel.sh new file mode 100755 index 0000000000..bf90ab86a0 --- /dev/null +++ b/integration_test/rpc_tests/scripts/run-parallel.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# Parallel test runner that still produces a valid mochawesome report. +# +# mocha's built-in `--parallel` mode is incompatible with mochawesome: the single +# main-process reporter can't consolidate worker results and emits a corrupt +# `results: [false]`. So instead of mocha-level parallelism we shard the spec files +# into N buckets and run one mocha PROCESS per bucket concurrently. Each process +# writes its own well-formed mochawesome JSON (run-.json); report:merge then +# globs them together. This is the same "one JSON per process" model that makes +# mochawesome merging reliable for Cypress. +# +# Env: +# RPC_JOBS number of concurrent mocha processes (default 8) +set -uo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +RPC_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$RPC_DIR" + +JOBS="${RPC_JOBS:-8}" +REPORT_DIR="reports/new_rpc" +mkdir -p "$REPORT_DIR" + +# Same set the old .mocharc.run.json spec globs covered. +shopt -s nullglob +specs=( debug/*.spec.ts echo/*.spec.ts eth/*.spec.ts net/*.spec.ts web3/*.spec.ts ) +if [ "${#specs[@]}" -eq 0 ]; then + echo "run-parallel: no spec files found under $RPC_DIR" >&2 + exit 1 +fi + +# Clear previous run shards/logs (but keep bootstrap.json from the bootstrap phase). +rm -f "$REPORT_DIR"/run-*.json "$REPORT_DIR"/run.json "$REPORT_DIR"/run-*.log + +# Prefer the locally-installed mocha to avoid npx resolution overhead per process. +MOCHA_BIN="$RPC_DIR/node_modules/.bin/mocha" +[ -x "$MOCHA_BIN" ] || MOCHA_BIN="npx mocha" + +# Round-robin the specs into JOBS buckets so load (esp. the eth/ specs) spreads out. +declare -a buckets +for i in "${!specs[@]}"; do + b=$(( i % JOBS )) + buckets[$b]="${buckets[$b]:-} ${specs[$i]}" +done + +echo "==> Running ${#specs[@]} spec files across up to $JOBS parallel mocha processes" + +pids=() +bucket_ids=() +for b in "${!buckets[@]}"; do + files="${buckets[$b]}" + [ -z "${files// /}" ] && continue + # shellcheck disable=SC2086 -- spec paths/bin are controlled and contain no spaces. + $MOCHA_BIN --require tsx --timeout 600000 --exit \ + --reporter mochawesome \ + --reporter-options "reportDir=$REPORT_DIR,reportFilename=run-$b,html=false,json=true,overwrite=true" \ + $files \ + > "$REPORT_DIR/run-$b.log" 2>&1 & + pids+=($!) + bucket_ids+=("$b") +done + +fails=0 +for idx in "${!pids[@]}"; do + if ! wait "${pids[$idx]}"; then + fails=$((fails + 1)) + echo "==> bucket ${bucket_ids[$idx]} reported failures (see $REPORT_DIR/run-${bucket_ids[$idx]}.log)" + fi +done + +# Surface a combined tail so failures are visible in the runner output. +if [ "$fails" -ne 0 ]; then + echo "==> $fails/${#pids[@]} buckets had failing tests" +fi + +exit "$fails" diff --git a/integration_test/rpc_tests/tsconfig.json b/integration_test/rpc_tests/tsconfig.json new file mode 100644 index 0000000000..5a25d244ed --- /dev/null +++ b/integration_test/rpc_tests/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "CommonJS", + "moduleResolution": "Node", + "lib": ["ES2022"], + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "types": ["node", "mocha", "chai"] + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "hardhat/.artifacts", "hardhat/.cache", "artifacts", "cache"] +} diff --git a/integration_test/rpc_tests/utils/auth7702.ts b/integration_test/rpc_tests/utils/auth7702.ts new file mode 100644 index 0000000000..f10503fe07 --- /dev/null +++ b/integration_test/rpc_tests/utils/auth7702.ts @@ -0,0 +1,73 @@ +import { ethers } from 'ethers'; +import { EvmAccount } from './wallet'; + +/** + * Helpers for EIP-7702 SetCode (type-4) transactions, kept self-contained so the + * new_rpc_tests module does not depend on shared/ or the chain_tests pectra utils. + */ + +/** Minimal ABI for the SimpleAccount7702 delegation target (executeBatch only). */ +export const SIMPLE_ACCOUNT_ABI = [ + { + inputs: [ + { + components: [ + { internalType: 'address', name: 'target', type: 'address' }, + { internalType: 'uint256', name: 'value', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + internalType: 'struct BaseAccount.Call[]', + name: 'calls', + type: 'tuple[]', + }, + ], + name: 'executeBatch', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const; + +/** The 0xef0100-prefixed delegation designator geth/Sei store as an EOA's code. */ +export function delegationDesignator(implementationAddress: string): string { + return '0xef0100' + implementationAddress.replace(/^0x/, '').toLowerCase(); +} + +/** + * Sign a self-authorization delegating `account` to `implementationAddress`. For a + * self-sponsored type-4 tx the authorization nonce is the account's current nonce + * + 1, because the outer tx consumes the current nonce first. + */ +export async function selfAuthorize( + account: EvmAccount, + implementationAddress: string, +): Promise { + const provider = account.wallet.provider!; + const [{ chainId }, latest] = await Promise.all([ + provider.getNetwork(), + provider.getTransactionCount(account.address, 'latest'), + ]); + return account.wallet.authorize({ + address: implementationAddress, + chainId, + nonce: latest + 1, + }); +} + +/** Broadcast a type-4 tx that installs the delegation designator on `account` itself. */ +export async function setCodeForEOA( + account: EvmAccount, + authorizationList: ethers.Authorization[], +): Promise { + const provider = account.wallet.provider!; + const fee = await provider.getFeeData(); + const tx = await account.wallet.sendTransaction({ + to: account.address, + data: '0x', + maxFeePerGas: fee.maxFeePerGas!, + maxPriorityFeePerGas: fee.maxPriorityFeePerGas!, + authorizationList, + type: 4, + }); + return tx.wait(); +} diff --git a/integration_test/rpc_tests/utils/cosmos.ts b/integration_test/rpc_tests/utils/cosmos.ts new file mode 100644 index 0000000000..2bdf5709d4 --- /dev/null +++ b/integration_test/rpc_tests/utils/cosmos.ts @@ -0,0 +1,28 @@ +import { QueryClient, setupBankExtension, BankExtension } from '@cosmjs/stargate'; +import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; +import { QueryBalanceRequest, QueryBalanceResponse } from 'cosmjs-types/cosmos/bank/v1beta1/query'; +import { Endpoints } from '../config/endpoints'; + +let clientPromise: Promise | undefined; + +async function bankClient(): Promise { + if (!clientPromise) { + clientPromise = (async () => { + const tm = await Tendermint34Client.connect(Endpoints.sei.cosmosRpc); + return QueryClient.withExtensions(tm, setupBankExtension); + })(); + } + return clientPromise; +} + +export async function bankBalanceUsei(seiAddress: string, height?: number): Promise { + const qc = await bankClient(); + if (height === undefined) { + const coin = await qc.bank.balance(seiAddress, 'usei'); + return BigInt(coin.amount); + } + const request = QueryBalanceRequest.encode({ address: seiAddress, denom: 'usei' }).finish(); + const { value } = await qc.queryAbci('/cosmos.bank.v1beta1.Query/Balance', request, height); + const { balance } = QueryBalanceResponse.decode(value); + return balance ? BigInt(balance.amount) : 0n; +} diff --git a/integration_test/rpc_tests/utils/deploy.ts b/integration_test/rpc_tests/utils/deploy.ts new file mode 100644 index 0000000000..7d3f5c2479 --- /dev/null +++ b/integration_test/rpc_tests/utils/deploy.ts @@ -0,0 +1,76 @@ +import { ethers, Contract, ContractFactory } from 'ethers'; +import path from 'node:path'; +import fs from 'node:fs'; +import { EvmAccount } from './wallet'; + +/** + * Minimal artifact loader that reads Hardhat-style JSON artifacts from this + * module's own `artifacts/contracts/.sol/.json` tree, produced by + * `npm run compile` (see ./contracts and ../hardhat.config.ts). We deliberately + * read these via fs at runtime rather than via `import ... from '...'` so the + * loader works regardless of which directory the spec lives in, and so the suite + * stays self-contained — it never reaches outside this folder. + */ +const ARTIFACTS_ROOT = path.resolve(__dirname, '..', 'artifacts', 'contracts'); + +interface HardhatArtifact { + contractName: string; + abi: any[]; + bytecode: string; +} + +function loadArtifact(solFile: string, contractName?: string): HardhatArtifact { + const name = contractName ?? solFile.replace(/\.sol$/, ''); + const artifactPath = path.join(ARTIFACTS_ROOT, solFile, `${name}.json`); + if (!fs.existsSync(artifactPath)) { + throw new Error( + `loadArtifact: ${artifactPath} not found. Run \`npm run compile\` first.`, + ); + } + return JSON.parse(fs.readFileSync(artifactPath, 'utf-8')) as HardhatArtifact; +} + +/** + * Deploy any artifact-backed contract. Returns the deployed contract instance + * plus the deploy receipt so callers can record `blockNumber`. + */ +export async function deployContract( + deployer: EvmAccount, + solFile: string, + args: unknown[] = [], + contractName?: string, +): Promise<{ contract: Contract; address: string; receipt: ethers.TransactionReceipt }> { + const artifact = loadArtifact(solFile, contractName); + const factory = new ContractFactory(artifact.abi, artifact.bytecode, deployer.wallet); + const contract = await factory.deploy(...args); + const tx = contract.deploymentTransaction(); + if (!tx) throw new Error(`deployContract(${solFile}): no deployment transaction returned`); + const receipt = await tx.wait(); + if (!receipt) throw new Error(`deployContract(${solFile}): deploy tx did not confirm`); + const address = await contract.getAddress(); + return { contract: contract as Contract, address, receipt }; +} + +/** + * Convenience wrapper for the canonical ERC20 used across the RPC suite. + * Constructor: `constructor(address initialOwner)` — see contracts/TestERC20.sol. + */ +export async function deployTestErc20( + deployer: EvmAccount, + initialOwner = deployer.address, +) { + return deployContract(deployer, 'TestERC20.sol', [initialOwner], 'TestERC20'); +} + +/** + * Returns the parsed ABI for a known artifact. Use this when you only need to + * encode/decode calldata against an already-deployed address. + */ +export function abiOf(solFile: string, contractName?: string): any[] { + return loadArtifact(solFile, contractName).abi; +} + +/** Returns the creation bytecode for a known artifact (for deploy-gas estimation). */ +export function bytecodeOf(solFile: string, contractName?: string): string { + return loadArtifact(solFile, contractName).bytecode; +} diff --git a/integration_test/rpc_tests/utils/eip1559.ts b/integration_test/rpc_tests/utils/eip1559.ts new file mode 100644 index 0000000000..1d4d5e7f4e --- /dev/null +++ b/integration_test/rpc_tests/utils/eip1559.ts @@ -0,0 +1,99 @@ +import util from 'node:util'; + +const exec = util.promisify(require('node:child_process').exec); + +const DOCKER_NODE = 'sei-node-0'; +const SEID_ENV = 'export PATH=$PATH:/root/go/bin:/root/.foundry/bin'; + +/** EIP-1559 fee-market parameters as the chain applies them. */ +export interface Eip1559Params { + blockGasLimit: number; + targetGasUsedPerBlock: number; + maxUpwardAdjustment: number; + maxDownwardAdjustment: number; + minFeePerGas: number; + maxFeePerGas: number; +} + +/** + * Read the live EIP-1559 params from the in-container `seid`. Returns null when no + * local docker devnet is reachable so callers can degrade to structural-only checks + * instead of failing on a hosted/remote Sei endpoint. + */ +export async function queryEip1559Params(): Promise { + try { + const param = async (key: string): Promise => { + const { stdout } = await exec( + `docker exec ${DOCKER_NODE} /bin/bash -c '${SEID_ENV} && seid query params subspace evm ${key} --output json'`, + ); + return JSON.parse(stdout).value.replace(/"/g, ''); + }; + const { stdout: blockParams } = await exec( + `docker exec ${DOCKER_NODE} /bin/bash -c '${SEID_ENV} && seid query params blockparams --output json'`, + ); + const [minFee, maxFee, upward, downward, target] = await Promise.all([ + param('KeyMinFeePerGas'), + param('KeyMaximumFeePerGas'), + param('KeyMaxDynamicBaseFeeUpwardAdjustment'), + param('KeyMaxDynamicBaseFeeDownwardAdjustment'), + param('KeyTargetGasUsedPerBlock'), + ]); + return { + blockGasLimit: Number(JSON.parse(blockParams).max_gas), + targetGasUsedPerBlock: Number(target), + maxUpwardAdjustment: parseFloat(upward), + maxDownwardAdjustment: parseFloat(downward), + minFeePerGas: parseFloat(minFee), + maxFeePerGas: parseFloat(maxFee), + }; + } catch { + return null; + } +} + +/** + * Sei's dynamic base fee for the next block. Sei does not use geth's 1/8 rule: it + * nudges by up to `maxUpwardAdjustment` when a block is over `targetGasUsedPerBlock` + * (scaled by how full the block is relative to the gas limit) and down by + * `maxDownwardAdjustment` when under target (scaled by how empty it is), then clamps + * to [minFeePerGas, maxFeePerGas]. Mirrors x/evm's CalculateNextBaseFee. + */ +export function nextBaseFeeSei( + prevBaseFee: number, + blockGasUsed: number, + p: Eip1559Params, +): number { + let next: number; + if (blockGasUsed > p.targetGasUsedPerBlock) { + const fullness = (blockGasUsed - p.targetGasUsedPerBlock) / (p.blockGasLimit - p.targetGasUsedPerBlock); + next = prevBaseFee * (1 + p.maxUpwardAdjustment * fullness); + } else { + const emptiness = (p.targetGasUsedPerBlock - blockGasUsed) / p.targetGasUsedPerBlock; + next = prevBaseFee * (1 - p.maxDownwardAdjustment * emptiness); + } + next = Math.floor(next); + if (next < p.minFeePerGas) return p.minFeePerGas; + if (next > p.maxFeePerGas) return p.maxFeePerGas; + return next; +} + +const GETH_ELASTICITY = 2n; +const GETH_BASE_FEE_CHANGE_DENOMINATOR = 8n; + +/** + * go-ethereum's London CalcBaseFee (all integer arithmetic): target = gasLimit/2, + * base fee moves by at most 1/8 toward fullness each block, with a minimum delta of + * 1 wei when over target. Exact, so feeHistory's predicted next base fee can be + * matched byte-for-byte. + */ +export function nextBaseFeeGeth(prevBaseFee: bigint, gasUsed: bigint, gasLimit: bigint): bigint { + const target = gasLimit / GETH_ELASTICITY; + if (gasUsed === target) return prevBaseFee; + if (gasUsed > target) { + const delta = (prevBaseFee * (gasUsed - target)) / target / GETH_BASE_FEE_CHANGE_DENOMINATOR; + return prevBaseFee + (delta > 0n ? delta : 1n); + } + const delta = (prevBaseFee * (target - gasUsed)) / target / GETH_BASE_FEE_CHANGE_DENOMINATOR; + const next = prevBaseFee - delta; + return next > 0n ? next : 0n; +} diff --git a/integration_test/rpc_tests/utils/format.ts b/integration_test/rpc_tests/utils/format.ts new file mode 100644 index 0000000000..97a8581aeb --- /dev/null +++ b/integration_test/rpc_tests/utils/format.ts @@ -0,0 +1,31 @@ +/** + * Shared format matchers for JSON-RPC response validation. + * + * These encode the canonical Ethereum JSON-RPC encodings (QUANTITY, DATA, address) + * so individual specs can assert "this is a well-formed X" without re-deriving the + * regex each time. Keep them strict — a loose matcher hides real schema regressions. + */ + +/** + * Canonical QUANTITY: 0x-prefixed, lower-case hex, no leading zeros (except "0x0"). + * Per the Ethereum JSON-RPC spec, quantities must be minimally encoded. + */ +export const HEX_QUANTITY = /^0x(0|[1-9a-f][0-9a-f]*)$/; + +/** 20-byte address, 0x-prefixed. Case-insensitive (covers checksummed + lowercase). */ +export const ADDRESS = /^0x[0-9a-fA-F]{40}$/; + +/** Lower-cased 20-byte address (some endpoints return non-checksummed addresses). */ +export const ADDRESS_LOWER = /^0x[0-9a-f]{40}$/; + +/** Arbitrary 0x-prefixed byte string with an even number of nibbles. */ +export const HEX_DATA = /^0x([0-9a-fA-F]{2})*$/; + +export const isHexQuantity = (v: unknown): v is string => + typeof v === 'string' && HEX_QUANTITY.test(v); + +export const isAddress = (v: unknown): v is string => + typeof v === 'string' && ADDRESS.test(v); + +export const isHexData = (v: unknown): v is string => + typeof v === 'string' && HEX_DATA.test(v); diff --git a/integration_test/rpc_tests/utils/funding.ts b/integration_test/rpc_tests/utils/funding.ts new file mode 100644 index 0000000000..67d64e127b --- /dev/null +++ b/integration_test/rpc_tests/utils/funding.ts @@ -0,0 +1,74 @@ +import { ethers } from 'ethers'; +import { EvmAccount } from './wallet'; + +/** + * Send native sei (in wei) from `from` to `to` and wait for inclusion. + * Used by the bootstrap to seed fresh EVM accounts. + * + * Returns the receipt so callers can record the block number it landed in. + */ +export async function fundEvm( + from: EvmAccount, + to: string, + amountWei: bigint, +): Promise { + const tx = await from.wallet.sendTransaction({ to, value: amountWei }); + const receipt = await tx.wait(); + if (!receipt) { + throw new Error(`fundEvm: transaction ${tx.hash} did not confirm`); + } + return receipt; +} + +/** + * Fund a recipient from an account the node itself holds unlocked, letting the + * node sign (`eth_sendTransaction`) rather than a local key. + * + * This is how we seed a deployer on `geth --dev`: the pre-funded developer account + * lives in the node's keyring (auto-unlocked) and is regenerated on every restart, + * so we never have its private key client-side. We send from it via the node, wait + * for the (insta-mined) receipt, and hand the funded recipient a key we *do* control + * for subsequent local-signed deploys. + */ +export async function fundFromUnlocked( + provider: ethers.JsonRpcProvider, + from: string, + to: string, + amountWei: bigint, +): Promise { + const hash: string = await provider.send('eth_sendTransaction', [ + // toQuantity gives the minimal hex encoding geth's hexutil.Big requires. + // toBeHex pads to whole bytes and can emit a leading zero ("0x056b…"), + // which geth rejects as "hex number with leading zero digits". + { from, to, value: ethers.toQuantity(amountWei) }, + ]); + const receipt = await provider.waitForTransaction(hash); + if (!receipt) { + throw new Error(`fundFromUnlocked: transaction ${hash} did not confirm`); + } + return receipt; +} + +/** + * Fund many recipients in parallel from a single funder. We do this one nonce at + * a time but submit broadcast concurrently — Sei's mempool accepts gapless nonces + * from the same sender, so this is the fastest correct pattern. + */ +export async function fundManyEvm( + from: EvmAccount, + recipients: string[], + amountWei: bigint, +): Promise { + if (recipients.length === 0) return []; + const startNonce = await from.nonce('pending'); + const txs = await Promise.all( + recipients.map((to, i) => + from.wallet.sendTransaction({ to, value: amountWei, nonce: startNonce + i }), + ), + ); + const receipts = await Promise.all(txs.map(t => t.wait())); + receipts.forEach((r, i) => { + if (!r) throw new Error(`fundManyEvm: tx ${txs[i].hash} did not confirm`); + }); + return receipts as ethers.TransactionReceipt[]; +} diff --git a/integration_test/rpc_tests/utils/providers.ts b/integration_test/rpc_tests/utils/providers.ts new file mode 100644 index 0000000000..794a2e2159 --- /dev/null +++ b/integration_test/rpc_tests/utils/providers.ts @@ -0,0 +1,67 @@ +import { ethers } from 'ethers'; +import { Endpoints } from '../config/endpoints'; + +const POLLING_INTERVAL_MS = Number(process.env.RPC_POLLING_INTERVAL_MS ?? 100); + +const makeProvider = (url: string): ethers.JsonRpcProvider => + new ethers.JsonRpcProvider(url, undefined, { + batchMaxCount: 1, // RPC tests assert per-request behavior; batching would mask it. + staticNetwork: true, + pollingInterval: POLLING_INTERVAL_MS, + }); + +let seiProvider: ethers.JsonRpcProvider | undefined; +let gethProvider: ethers.JsonRpcProvider | undefined; +let forkProvider: ethers.JsonRpcProvider | undefined; + +export function seiRpc(): ethers.JsonRpcProvider { + if (!seiProvider) seiProvider = makeProvider(Endpoints.sei.evmRpc); + return seiProvider; +} + +/** Primary Ethereum reference: local geth --dev. */ +export function gethRpc(): ethers.JsonRpcProvider { + if (!gethProvider) gethProvider = makeProvider(Endpoints.eth.geth); + return gethProvider; +} + +/** Optional secondary reference: anvil/Hardhat mainnet fork. */ +export function forkRpc(): ethers.JsonRpcProvider { + if (!forkProvider) forkProvider = makeProvider(Endpoints.eth.fork); + return forkProvider; +} + +/** + * Sei + the primary geth reference. Most parity specs want exactly these two. + * `eth` aliases the geth provider so existing specs keep working after the + * fork→geth reference switch. + */ +export function bothProviders(): { + sei: ethers.JsonRpcProvider; + geth: ethers.JsonRpcProvider; + eth: ethers.JsonRpcProvider; +} { + const sei = seiRpc(); + const geth = gethRpc(); + return { sei, geth, eth: geth }; +} + +export async function isReachable(url: string, timeoutMs = 2_500): Promise { + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), timeoutMs); + try { + const res = await fetch(url, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_chainId', params: [] }), + signal: controller.signal, + }); + if (!res.ok) return false; + const body = (await res.json()) as { result?: string }; + return typeof body.result === 'string'; + } catch { + return false; + } finally { + clearTimeout(timer); + } +} diff --git a/integration_test/rpc_tests/utils/rpc.ts b/integration_test/rpc_tests/utils/rpc.ts new file mode 100644 index 0000000000..67788720fc --- /dev/null +++ b/integration_test/rpc_tests/utils/rpc.ts @@ -0,0 +1,110 @@ +import { Endpoints } from '../config/endpoints'; + +export interface JsonRpcError { + code: number; + message: string; + data?: unknown; +} + +export interface JsonRpcEnvelope { + jsonrpc: '2.0'; + id: number | string | null; + result?: T; + error?: JsonRpcError; +} + +/** + * Raw JSON-RPC POST that bypasses ethers' client-side validation. + * + * Ethers v6 normalises addresses, hexlifies `data`, and re-wraps non-array `params` + * into an array inside JsonRpcProvider.send. For negative tests that send + * deliberately malformed payloads, we need the bytes to reach the node untouched so + * we can verify the *node's* validation, not the client's. Returns the raw envelope. + */ +export async function rawJsonRpc( + url: string, + method: string, + params: unknown, + id: number | string = 1, +): Promise> { + const res = await fetch(url, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ jsonrpc: '2.0', id, method, params }), + }); + return res.json() as Promise>; +} + +export const rawSei = (method: string, params: unknown) => + rawJsonRpc(Endpoints.sei.evmRpc, method, params); + +/** Raw POST to the primary geth reference. */ +export const rawGeth = (method: string, params: unknown) => + rawJsonRpc(Endpoints.eth.geth, method, params); + +/** Raw POST to the optional anvil/Hardhat fork. */ +export const rawFork = (method: string, params: unknown) => + rawJsonRpc(Endpoints.eth.fork, method, params); + +/** Raw POST to a keyless node (hosted RPC) — used to observe the empty-account case. */ +export const rawAccountless = (method: string, params: unknown) => + rawJsonRpc(Endpoints.accountless, method, params); + +/** Back-compat alias: `eth` reference is now geth. */ +export const rawEth = rawGeth; + +/** + * Resolve a promise expected to throw an ethers RPC error and return the underlying + * JSON-RPC envelope. We unwrap both `e.info.error` (ethers v6 default) and `e.error` + * (older shapes) so tests do not have to know which shape they got. + * + * Throws if the promise resolved successfully, or if the thrown error does not + * carry an RPC envelope — both of those are test-author bugs, not test failures. + */ +export async function captureRpcError(promise: Promise): Promise { + try { + await promise; + } catch (e: any) { + const env = e?.info?.error ?? e?.error; + if (env && typeof env.code === 'number') { + return env as JsonRpcError; + } + throw new Error( + `captureRpcError: thrown error did not carry an RPC envelope: ${e?.message ?? e}`, + ); + } + throw new Error('captureRpcError: expected promise to reject but it resolved'); +} + +/** + * Assert that a raw JSON-RPC envelope carries an error matching `code` and + * (optionally) `messagePattern`. Returns the error for further inspection. + * + * Throws a descriptive Error (not a chai assertion) so the failure message includes + * the whole envelope — useful when a node returns an error shaped differently than + * expected. Use this for raw-transport negative tests where you POST malformed + * payloads directly. + */ +export function expectJsonRpcError( + envelope: JsonRpcEnvelope, + code: number, + messagePattern?: RegExp, +): JsonRpcError { + const err = envelope.error; + if (!err) { + throw new Error( + `expectJsonRpcError: expected an error but got result: ${JSON.stringify(envelope.result)}`, + ); + } + if (err.code !== code) { + throw new Error( + `expectJsonRpcError: expected code ${code} but got ${err.code} (message: ${err.message})`, + ); + } + if (messagePattern && !messagePattern.test(err.message)) { + throw new Error( + `expectJsonRpcError: message ${JSON.stringify(err.message)} did not match ${messagePattern}`, + ); + } + return err; +} diff --git a/integration_test/rpc_tests/utils/seiAdmin.ts b/integration_test/rpc_tests/utils/seiAdmin.ts new file mode 100644 index 0000000000..7267775d94 --- /dev/null +++ b/integration_test/rpc_tests/utils/seiAdmin.ts @@ -0,0 +1,128 @@ +import util from 'node:util'; +import { ethers } from 'ethers'; +import { DirectSecp256k1HdWallet, Registry } from '@cosmjs/proto-signing'; +import { stringToPath } from '@cosmjs/crypto'; +import { SigningStargateClient, defaultRegistryTypes } from '@cosmjs/stargate'; +import { coins } from '@cosmjs/amino'; +import { seiProtoRegistry, Encoder } from '@sei-js/cosmos/encoding'; +import { Endpoints } from '../config/endpoints'; +import { waitUntil } from './waitFor'; +import { bankBalanceUsei } from './cosmos'; + +const exec = util.promisify(require('node:child_process').exec); + +// Sei keys use cosmos coin type 118; the EVM key derives from the same path, so a +// single mnemonic yields a matching (sei, 0x) address pair. +const SEI_HD_PATH = "m/44'/118'/0'/0/0"; +const DOCKER_NODE = 'sei-node-0'; +const DOCKER_KEY_PASSWORD = '12345678'; +// 10^12 usei == 10^6 SEI. Matches shared/Funder.fundAdminOnSei. +const DEFAULT_FUND_USEI = '1000000000000'; +const SEID_ENV = 'export PATH=$PATH:/root/go/bin:/root/.foundry/bin'; + +/** bech32 `sei1…` address for a mnemonic (cosmos coin type 118). */ +export async function seiAddressFromMnemonic(mnemonic: string): Promise { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'sei', + hdPaths: [stringToPath(SEI_HD_PATH)], + }); + const [account] = await wallet.getAccounts(); + return account.address; +} + +/** True when a local `sei-node-0` docker container is running. */ +export async function isSeiDocker(): Promise { + try { + const { stdout } = await exec( + `docker ps --filter 'name=${DOCKER_NODE}' --format '{{.Names}}'`, + ); + return stdout.includes(DOCKER_NODE); + } catch { + return false; + } +} + +async function bankSendFromContainerAdmin(toSeiAddress: string, amountUsei: string): Promise { + const { stdout } = await exec( + `docker exec ${DOCKER_NODE} /bin/bash -c '${SEID_ENV} && printf "${DOCKER_KEY_PASSWORD}\\n" | seid keys show admin -a'`, + ); + const containerAdmin = stdout.trimEnd(); + await exec( + `docker exec ${DOCKER_NODE} /bin/bash -c '${SEID_ENV} && printf "${DOCKER_KEY_PASSWORD}\\n" | seid tx bank send ${containerAdmin} ${toSeiAddress} ${amountUsei}usei --fees 24500usei -y'`, + ); +} + + +/** + * Broadcast MsgAssociate so the account's pubkey lands on-chain. Until an account is + * associated, Sei cannot map its cosmos balance to its EVM address and + * eth_getBalance returns 0. Tolerates an already-associated account. + */ +async function associate(mnemonic: string, seiAddress: string): Promise { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'sei', + hdPaths: [stringToPath(SEI_HD_PATH)], + }); + const registry = new Registry([...seiProtoRegistry, ...defaultRegistryTypes]); + const client = await SigningStargateClient.connectWithSigner(Endpoints.sei.cosmosRpc, wallet, { + registry, + }); + const msg = { + typeUrl: `/${Encoder.evm.MsgAssociate.$type}`, + value: Encoder.evm.MsgAssociate.fromPartial({ + sender: seiAddress, + custom_message: 'new_rpc_tests bootstrap', + }), + }; + const fee = { amount: coins(21000, 'usei'), gas: '200000' }; + try { + await client.signAndBroadcast(seiAddress, [msg], fee, 'associate'); + } catch (e: any) { + // An already-associated account rejects a second association; that's fine — + // the final balance check below is the real gate. + if (!/already|associated/i.test(e?.message ?? '')) throw e; + } finally { + client.disconnect(); + } +} + +/** + * Mirror of UserFactory.fundAdminOnSei: give the admin a spendable EVM balance on a + * local Sei docker devnet. Funding alone is not enough — Sei only exposes an EVM + * balance once the account is associated — so we bank-send usei to the admin's + * cosmos address from the in-container `admin` key, then broadcast MsgAssociate. + * + * Idempotent: returns early when the admin already has an EVM balance. Throws when + * no local docker devnet is running, since the admin then cannot be funded + * automatically (point at a pre-funded admin via SEI_ADMIN_MNEMONIC instead). + */ +export async function fundAdminOnSei( + adminEvmAddress: string, + mnemonic: string, + provider: ethers.JsonRpcProvider, + amountUsei = DEFAULT_FUND_USEI, +): Promise { + if ((await provider.getBalance(adminEvmAddress)) > 0n) return; + + if (!(await isSeiDocker())) { + throw new Error( + `fundAdminOnSei: admin ${adminEvmAddress} has no EVM balance and no local ` + + `${DOCKER_NODE} container is running to fund it. Start the cluster ` + + '(cd sei-chain && make docker-cluster-start) or set SEI_ADMIN_MNEMONIC to a ' + + 'pre-funded account.', + ); + } + + const seiAddress = await seiAddressFromMnemonic(mnemonic); + await bankSendFromContainerAdmin(seiAddress, amountUsei); + // Wait for the bank send to land so association has gas to spend. + await waitUntil(async () => ((await bankBalanceUsei(seiAddress)) > 0n ? true : null), { + timeoutMs: 30_000, + label: 'admin sei bank balance', + }); + await associate(mnemonic, seiAddress); + await waitUntil( + async () => ((await provider.getBalance(adminEvmAddress)) > 0n ? true : null), + { timeoutMs: 30_000, label: 'admin evm balance after association' }, + ); +} diff --git a/integration_test/rpc_tests/utils/state.ts b/integration_test/rpc_tests/utils/state.ts new file mode 100644 index 0000000000..78679771b4 --- /dev/null +++ b/integration_test/rpc_tests/utils/state.ts @@ -0,0 +1,83 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { RuntimeStatePath } from '../config/endpoints'; + +/** + * Runtime state captured once by _start/00_bootstrap.spec.ts and read by every + * other spec file. Keeping the contract here means a missing field is a TypeScript + * error in the spec, not a runtime undefined. + * + * Add a field when you need a new precomputed value across specs — never write + * back to this file from a non-bootstrap spec, or parallel workers will race. + */ +export interface RuntimeState { + /** ISO timestamp when the state was written. */ + bootstrappedAt: string; + + /** Chain IDs as integers. */ + chainIds: { + sei: number; + eth: number; + }; + + /** Block numbers captured at well-defined points in the bootstrap. */ + blocks: { + /** Sei block just before any contracts were deployed. */ + seiBeforeDeploy: number; + /** Sei block in which TestERC20 was deployed. */ + seiErc20Deploy: number; + /** Sei block just after the bootstrap finished. */ + seiAfterDeploy: number; + /** geth reference head when the bootstrap ran. */ + ethAtBootstrap: number; + /** geth block in which the mirrored TestERC20 was deployed. */ + ethErc20Deploy: number; + }; + + /** Deployed contract addresses, one per reference chain. */ + contracts: { + /** TestERC20 on Sei. */ + erc20: string; + /** The same TestERC20 deployed on the geth reference, for parity tests. */ + erc20Geth: string; + /** SimpleAccount7702 delegation target on Sei (used by EIP-7702 specs). */ + simpleAccount7702: string; + /** RealGasBurner on Sei: lets specs burn arbitrary gas to move the base fee. */ + gasBurner: string; + }; + + /** EVM addresses pre-funded with a small balance, ready for use by tests. */ + funded: { + admin: string; + /** + * Deployer/owner of the geth-side TestERC20. Funded from geth's unlocked dev + * account; this key is controlled client-side so specs can sign geth txs. + */ + gethAdmin: { address: string; privateKey: string }; + /** Pool of fresh accounts the bootstrap funded but has not transacted from. */ + pool: { address: string; privateKey: string }[]; + }; +} + +const stateAbsPath = (): string => path.resolve(process.cwd(), RuntimeStatePath); + +export function writeRuntimeState(state: RuntimeState): void { + const abs = stateAbsPath(); + fs.mkdirSync(path.dirname(abs), { recursive: true }); + fs.writeFileSync(abs, JSON.stringify(state, null, 2), 'utf-8'); +} + +let cached: RuntimeState | undefined; + +export function readRuntimeState(): RuntimeState { + if (cached) return cached; + const abs = stateAbsPath(); + if (!fs.existsSync(abs)) { + throw new Error( + `readRuntimeState: ${abs} not found. ` + + 'Run `yarn rpc:bootstrap` (or `yarn test:rpc`) before running spec files individually.', + ); + } + cached = JSON.parse(fs.readFileSync(abs, 'utf-8')) as RuntimeState; + return cached; +} diff --git a/integration_test/rpc_tests/utils/testHelpers.ts b/integration_test/rpc_tests/utils/testHelpers.ts new file mode 100644 index 0000000000..85e31d9c77 --- /dev/null +++ b/integration_test/rpc_tests/utils/testHelpers.ts @@ -0,0 +1,62 @@ +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import { EvmAccount } from './wallet'; +import { RuntimeState } from './state'; +import { JsonRpcEnvelope } from './rpc'; + +/** + * Assert two JSON-RPC envelopes carry byte-identical errors (code, message and data). + * Used by the parity specs to prove Sei and the geth reference fail the exact same way. + */ +export function expectSameError(s: JsonRpcEnvelope, g: JsonRpcEnvelope): void { + expect(g.error, `geth must error, got result ${JSON.stringify(g.result)}`).to.not.equal( + undefined, + ); + expect(s.error, `sei must error, got result ${JSON.stringify(s.result)}`).to.not.equal( + undefined, + ); + expect(s.error!.code, 'error.code parity').to.equal(g.error!.code); + expect(s.error!.message, 'error.message parity').to.equal(g.error!.message); + expect(s.error!.data, 'error.data parity').to.deep.equal(g.error!.data); +} + +/** + * Deterministically claim `count` accounts from the pre-funded pool, offset by a hash + * of `salt` so different specs tend to take disjoint slices and avoid serialising on a + * shared nonce. Accounts are returned connected to `provider`. + */ +export function claimPool( + runtime: RuntimeState, + provider: ethers.JsonRpcProvider, + count: number, + salt: string, +): EvmAccount[] { + const pool = runtime.funded.pool; + let h = 0; + for (const ch of salt) h = (h * 31 + ch.charCodeAt(0)) >>> 0; + const start = h % pool.length; + return Array.from({ length: count }, (_, i) => + EvmAccount.fromPrivateKey(pool[(start + i) % pool.length].privateKey, provider), + ); +} + +/** Left-pad a uint into its canonical 32-byte ABI word. */ +export const encodeUint = (value: bigint): string => + ethers.zeroPadValue(ethers.toBeHex(value), 32); + +/** Calldata encoders and result decoders bound to a specific ERC20 ABI. */ +export class Erc20Calldata { + constructor(private readonly iface: ethers.Interface) {} + + balanceOf(holder: string): string { + return this.iface.encodeFunctionData('balanceOf', [holder]); + } + + transfer(to: string, amount: bigint): string { + return this.iface.encodeFunctionData('transfer', [to, amount]); + } + + decodeBalance(hex: string): bigint { + return this.iface.decodeFunctionResult('balanceOf', hex)[0] as bigint; + } +} diff --git a/integration_test/rpc_tests/utils/waitFor.ts b/integration_test/rpc_tests/utils/waitFor.ts new file mode 100644 index 0000000000..6a8c2d3846 --- /dev/null +++ b/integration_test/rpc_tests/utils/waitFor.ts @@ -0,0 +1,31 @@ +export const sleep = (ms: number): Promise => + new Promise(resolve => setTimeout(resolve, ms)); + +/** + * Poll `fn` until it returns truthy or the timeout elapses. Returns the truthy value + * or throws. Intended for "wait for the next Sei block to land", "wait until the + * Hardhat fork is reachable", etc. — short, deterministic guards, not retries. + */ +export async function waitUntil( + fn: () => Promise, + opts: { timeoutMs: number; intervalMs?: number; label?: string } = { timeoutMs: 30_000 }, +): Promise { + const interval = opts.intervalMs ?? 250; + const deadline = Date.now() + opts.timeoutMs; + let lastError: unknown; + while (Date.now() < deadline) { + try { + const result = await fn(); + if (result !== undefined && result !== null && result !== false) { + return result as T; + } + } catch (e) { + lastError = e; + } + await sleep(interval); + } + throw new Error( + `waitUntil(${opts.label ?? 'condition'}) timed out after ${opts.timeoutMs}ms` + + (lastError ? `: ${(lastError as Error)?.message ?? lastError}` : ''), + ); +} diff --git a/integration_test/rpc_tests/utils/wallet.ts b/integration_test/rpc_tests/utils/wallet.ts new file mode 100644 index 0000000000..c1f96adb7d --- /dev/null +++ b/integration_test/rpc_tests/utils/wallet.ts @@ -0,0 +1,37 @@ +import { ethers, HDNodeWallet, Wallet } from 'ethers'; +import { seiRpc } from './providers'; + +const HD_PATH = "m/44'/118'/0'/0/0"; + +export class EvmAccount { + readonly wallet: HDNodeWallet | Wallet; + readonly address: string; + + private constructor(wallet: HDNodeWallet | Wallet) { + this.wallet = wallet; + this.address = wallet.address; + } + + static fromMnemonic(mnemonic: string, provider = seiRpc()): EvmAccount { + const wallet = ethers.HDNodeWallet.fromPhrase(mnemonic, '', HD_PATH).connect(provider); + return new EvmAccount(wallet); + } + + static fromPrivateKey(privateKey: string, provider = seiRpc()): EvmAccount { + const wallet = new ethers.Wallet(privateKey, provider); + return new EvmAccount(wallet); + } + + static random(provider = seiRpc()): EvmAccount { + const wallet = ethers.Wallet.createRandom().connect(provider); + return new EvmAccount(wallet); + } + + nonce(blockTag: ethers.BlockTag = 'latest'): Promise { + return this.wallet.provider!.getTransactionCount(this.address, blockTag); + } + + balance(blockTag: ethers.BlockTag = 'latest'): Promise { + return this.wallet.provider!.getBalance(this.address, blockTag); + } +} diff --git a/integration_test/rpc_tests/web3/web3_clientVersion.spec.ts b/integration_test/rpc_tests/web3/web3_clientVersion.spec.ts new file mode 100644 index 0000000000..e69de29bb2 From 65fb5b64450378987ada2ec4a7d783edc569b22f Mon Sep 17 00:00:00 2001 From: kollegian Date: Fri, 29 May 2026 17:47:44 +0300 Subject: [PATCH 2/4] chore: remove empty specs for now --- integration_test/rpc_tests/debug/debug_getRawBlock.spec.ts | 0 integration_test/rpc_tests/debug/debug_getRawHeader.spec.ts | 0 integration_test/rpc_tests/debug/debug_getRawReceipts.spec.ts | 0 .../rpc_tests/debug/debug_getRawTransaction.spec.ts | 0 .../rpc_tests/debug/debug_traceBlockByHash.spec.ts | 0 .../rpc_tests/debug/debug_traceBlockByNumber.spec.ts | 0 integration_test/rpc_tests/debug/debug_traceCall.spec.ts | 0 .../rpc_tests/debug/debug_traceStateAccess.spec.ts | 0 .../rpc_tests/debug/debug_traceTransaction.spec.ts | 0 .../rpc_tests/debug/debug_traceTransactionProfile.spec.ts | 0 integration_test/rpc_tests/echo/echo_echo.spec.ts | 0 integration_test/rpc_tests/eth/eth_createAccessList.spec.ts | 0 .../rpc_tests/eth/eth_estimateGasAfterCalls.spec.ts | 0 integration_test/rpc_tests/eth/eth_getBalance.spec.ts | 0 integration_test/rpc_tests/eth/eth_getBlockByHash.spec.ts | 0 integration_test/rpc_tests/eth/eth_getBlockByNumber.spec.ts | 0 integration_test/rpc_tests/eth/eth_getBlockReceipts.spec.ts | 0 .../rpc_tests/eth/eth_getBlockTransactionCountByHash.spec.ts | 0 .../eth/eth_getBlockTransactionCountByNumber.spec.ts | 0 integration_test/rpc_tests/eth/eth_getCode.spec.ts | 0 integration_test/rpc_tests/eth/eth_getFilterChanges.spec.ts | 0 integration_test/rpc_tests/eth/eth_getFilterLogs.spec.ts | 0 integration_test/rpc_tests/eth/eth_getLogs.spec.ts | 0 integration_test/rpc_tests/eth/eth_getProof.spec.ts | 0 integration_test/rpc_tests/eth/eth_getStorageAt.spec.ts | 0 .../eth/eth_getTransactionByBlockHashAndIndex.spec.ts | 0 .../eth/eth_getTransactionByBlockNumberAndIndex.spec.ts | 0 .../rpc_tests/eth/eth_getTransactionByHash.spec.ts | 0 .../rpc_tests/eth/eth_getTransactionCount.spec.ts | 0 .../rpc_tests/eth/eth_getTransactionErrorByHash.spec.ts | 0 .../rpc_tests/eth/eth_getTransactionReceipt.spec.ts | 0 integration_test/rpc_tests/eth/eth_getVMError.spec.ts | 0 .../rpc_tests/eth/eth_maxPriorityFeePerGas.spec.ts | 0 integration_test/rpc_tests/eth/eth_newBlockFilter.spec.ts | 0 integration_test/rpc_tests/eth/eth_newFilter.spec.ts | 0 .../rpc_tests/eth/eth_newPendingTransactionFilter.spec.ts | 0 integration_test/rpc_tests/eth/eth_sendRawTransaction.spec.ts | 0 integration_test/rpc_tests/eth/eth_sendTransaction.spec.ts | 0 integration_test/rpc_tests/eth/eth_sign.spec.ts | 0 integration_test/rpc_tests/eth/eth_signTransaction.spec.ts | 0 integration_test/rpc_tests/eth/eth_subscribe.spec.ts | 0 integration_test/rpc_tests/eth/eth_syncing.spec.ts | 0 integration_test/rpc_tests/eth/eth_uninstallFilter.spec.ts | 0 integration_test/rpc_tests/net/net_version.spec.ts | 0 integration_test/rpc_tests/scripts/run-parallel.sh | 4 ++-- integration_test/rpc_tests/web3/web3_clientVersion.spec.ts | 0 46 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 integration_test/rpc_tests/debug/debug_getRawBlock.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_getRawHeader.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_getRawReceipts.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_getRawTransaction.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_traceBlockByHash.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_traceBlockByNumber.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_traceCall.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_traceStateAccess.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_traceTransaction.spec.ts delete mode 100644 integration_test/rpc_tests/debug/debug_traceTransactionProfile.spec.ts delete mode 100644 integration_test/rpc_tests/echo/echo_echo.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_createAccessList.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_estimateGasAfterCalls.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getBalance.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getBlockByHash.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getBlockByNumber.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getBlockReceipts.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getBlockTransactionCountByHash.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getBlockTransactionCountByNumber.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getCode.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getFilterChanges.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getFilterLogs.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getLogs.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getProof.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getStorageAt.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getTransactionByBlockHashAndIndex.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getTransactionByBlockNumberAndIndex.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getTransactionByHash.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getTransactionCount.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getTransactionErrorByHash.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getTransactionReceipt.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_getVMError.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_maxPriorityFeePerGas.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_newBlockFilter.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_newFilter.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_newPendingTransactionFilter.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_sendRawTransaction.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_sendTransaction.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_sign.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_signTransaction.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_subscribe.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_syncing.spec.ts delete mode 100644 integration_test/rpc_tests/eth/eth_uninstallFilter.spec.ts delete mode 100644 integration_test/rpc_tests/net/net_version.spec.ts delete mode 100644 integration_test/rpc_tests/web3/web3_clientVersion.spec.ts diff --git a/integration_test/rpc_tests/debug/debug_getRawBlock.spec.ts b/integration_test/rpc_tests/debug/debug_getRawBlock.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_getRawHeader.spec.ts b/integration_test/rpc_tests/debug/debug_getRawHeader.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_getRawReceipts.spec.ts b/integration_test/rpc_tests/debug/debug_getRawReceipts.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_getRawTransaction.spec.ts b/integration_test/rpc_tests/debug/debug_getRawTransaction.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_traceBlockByHash.spec.ts b/integration_test/rpc_tests/debug/debug_traceBlockByHash.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_traceBlockByNumber.spec.ts b/integration_test/rpc_tests/debug/debug_traceBlockByNumber.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_traceCall.spec.ts b/integration_test/rpc_tests/debug/debug_traceCall.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_traceStateAccess.spec.ts b/integration_test/rpc_tests/debug/debug_traceStateAccess.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_traceTransaction.spec.ts b/integration_test/rpc_tests/debug/debug_traceTransaction.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/debug/debug_traceTransactionProfile.spec.ts b/integration_test/rpc_tests/debug/debug_traceTransactionProfile.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/echo/echo_echo.spec.ts b/integration_test/rpc_tests/echo/echo_echo.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_createAccessList.spec.ts b/integration_test/rpc_tests/eth/eth_createAccessList.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_estimateGasAfterCalls.spec.ts b/integration_test/rpc_tests/eth/eth_estimateGasAfterCalls.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getBalance.spec.ts b/integration_test/rpc_tests/eth/eth_getBalance.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getBlockByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockByHash.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getBlockByNumber.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockByNumber.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getBlockReceipts.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockReceipts.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByHash.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByNumber.spec.ts b/integration_test/rpc_tests/eth/eth_getBlockTransactionCountByNumber.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getCode.spec.ts b/integration_test/rpc_tests/eth/eth_getCode.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getFilterChanges.spec.ts b/integration_test/rpc_tests/eth/eth_getFilterChanges.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getFilterLogs.spec.ts b/integration_test/rpc_tests/eth/eth_getFilterLogs.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getLogs.spec.ts b/integration_test/rpc_tests/eth/eth_getLogs.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getProof.spec.ts b/integration_test/rpc_tests/eth/eth_getProof.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getStorageAt.spec.ts b/integration_test/rpc_tests/eth/eth_getStorageAt.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionByBlockHashAndIndex.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionByBlockHashAndIndex.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionByBlockNumberAndIndex.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionByBlockNumberAndIndex.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionByHash.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionCount.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionCount.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionErrorByHash.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionErrorByHash.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getTransactionReceipt.spec.ts b/integration_test/rpc_tests/eth/eth_getTransactionReceipt.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_getVMError.spec.ts b/integration_test/rpc_tests/eth/eth_getVMError.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_maxPriorityFeePerGas.spec.ts b/integration_test/rpc_tests/eth/eth_maxPriorityFeePerGas.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_newBlockFilter.spec.ts b/integration_test/rpc_tests/eth/eth_newBlockFilter.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_newFilter.spec.ts b/integration_test/rpc_tests/eth/eth_newFilter.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_newPendingTransactionFilter.spec.ts b/integration_test/rpc_tests/eth/eth_newPendingTransactionFilter.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_sendRawTransaction.spec.ts b/integration_test/rpc_tests/eth/eth_sendRawTransaction.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_sendTransaction.spec.ts b/integration_test/rpc_tests/eth/eth_sendTransaction.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_sign.spec.ts b/integration_test/rpc_tests/eth/eth_sign.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_signTransaction.spec.ts b/integration_test/rpc_tests/eth/eth_signTransaction.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_subscribe.spec.ts b/integration_test/rpc_tests/eth/eth_subscribe.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_syncing.spec.ts b/integration_test/rpc_tests/eth/eth_syncing.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/eth/eth_uninstallFilter.spec.ts b/integration_test/rpc_tests/eth/eth_uninstallFilter.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/net/net_version.spec.ts b/integration_test/rpc_tests/net/net_version.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/integration_test/rpc_tests/scripts/run-parallel.sh b/integration_test/rpc_tests/scripts/run-parallel.sh index bf90ab86a0..13c693a852 100755 --- a/integration_test/rpc_tests/scripts/run-parallel.sh +++ b/integration_test/rpc_tests/scripts/run-parallel.sh @@ -22,9 +22,9 @@ JOBS="${RPC_JOBS:-8}" REPORT_DIR="reports/new_rpc" mkdir -p "$REPORT_DIR" -# Same set the old .mocharc.run.json spec globs covered. +# All non-bootstrap spec files (currently only eth/; add dirs here as they grow). shopt -s nullglob -specs=( debug/*.spec.ts echo/*.spec.ts eth/*.spec.ts net/*.spec.ts web3/*.spec.ts ) +specs=( debug/*.spec.ts echo/*.spec.ts eth/*.spec.ts net/*.spec.ts sei/*.spec.ts sei2/*.spec.ts txpool/*.spec.ts web3/*.spec.ts ) if [ "${#specs[@]}" -eq 0 ]; then echo "run-parallel: no spec files found under $RPC_DIR" >&2 exit 1 diff --git a/integration_test/rpc_tests/web3/web3_clientVersion.spec.ts b/integration_test/rpc_tests/web3/web3_clientVersion.spec.ts deleted file mode 100644 index e69de29bb2..0000000000 From f1a394fcc2f323e4d1e464433fdb22debe5a13e2 Mon Sep 17 00:00:00 2001 From: kollegian Date: Fri, 29 May 2026 17:49:11 +0300 Subject: [PATCH 3/4] chore: update Readme --- integration_test/rpc_tests/.mocharc.run.json | 9 ++------- integration_test/rpc_tests/README.md | 16 +++++++--------- .../rpc_tests/scripts/run-parallel.sh | 13 +++++++++++-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/integration_test/rpc_tests/.mocharc.run.json b/integration_test/rpc_tests/.mocharc.run.json index 589dd344ae..33ec5d9665 100644 --- a/integration_test/rpc_tests/.mocharc.run.json +++ b/integration_test/rpc_tests/.mocharc.run.json @@ -10,11 +10,6 @@ "json=true", "overwrite=true" ], - "spec": [ - "debug/*.spec.ts", - "echo/*.spec.ts", - "eth/*.spec.ts", - "net/*.spec.ts", - "web3/*.spec.ts" - ] + "spec": ["**/*.spec.ts"], + "ignore": ["_start/*.spec.ts", "node_modules/**"] } diff --git a/integration_test/rpc_tests/README.md b/integration_test/rpc_tests/README.md index cc5de5d898..8c686179f5 100644 --- a/integration_test/rpc_tests/README.md +++ b/integration_test/rpc_tests/README.md @@ -17,7 +17,8 @@ npm run compile # compiles ./contracts -> ./artifacts (TestERC20, RealGasBurn ## What this suite proves -For every JSON-RPC method we care about, the spec file in `eth/`, , `debug/`, etc. answers one or more of: +For every JSON-RPC method we care about, the spec file in `eth/` (and future +namespace dirs like `debug/`, `sei/`, etc.) answers one or more of: - **Happy path.** The method returns the expected value/shape for valid input. - **Schema parity.** The response shape on Sei matches geth for the same call. @@ -65,9 +66,12 @@ integration_test/rpc_tests/ ├── runtime/ # gitignored, holds runtime.json ├── _start/ │ └── 00_bootstrap.spec.ts # one-time setup -└── eth/ sei/ sei2/ debug/ ... # the actual specs +└── eth/ # the actual specs (one dir per RPC namespace) ``` +New RPC namespaces just need their own directory of `*.spec.ts` files (e.g. +`debug/`, `sei/`, `txpool/`); the runner picks up any `*/*.spec.ts` automatically. + ## One-shot runner (recommended) ```bash @@ -207,10 +211,4 @@ Rules of the road for new specs: 5. **geth is the error/schema source of truth.** Assert Sei matches `rawGeth` exactly for shared methods. The anvil fork (`rawFork`) is only for real-data shape sanity checks, never exact error parity. Sei-only methods (`sei_*`) - have no reference — just assert the Sei behavior. - -## Pending migration - -Empty placeholder spec files (`*.spec.ts` with no content) under `debug/`, -`echo/`, `net/`, and `web3/` are stubs waiting to be filled in. They are safe to -run (mocha just registers nothing) but assert nothing yet. + have no reference — just assert the Sei behavior. \ No newline at end of file diff --git a/integration_test/rpc_tests/scripts/run-parallel.sh b/integration_test/rpc_tests/scripts/run-parallel.sh index 13c693a852..05baebcd13 100755 --- a/integration_test/rpc_tests/scripts/run-parallel.sh +++ b/integration_test/rpc_tests/scripts/run-parallel.sh @@ -22,9 +22,18 @@ JOBS="${RPC_JOBS:-8}" REPORT_DIR="reports/new_rpc" mkdir -p "$REPORT_DIR" -# All non-bootstrap spec files (currently only eth/; add dirs here as they grow). +# Every spec file in a namespace dir (one level deep, e.g. eth/, debug/, sei/...) +# except the sequential bootstrap under _start/. Directory-agnostic so new RPC +# namespace folders are picked up automatically. A plain one-level glob keeps this +# portable to macOS's default bash 3.2 (which lacks `globstar`). shopt -s nullglob -specs=( debug/*.spec.ts echo/*.spec.ts eth/*.spec.ts net/*.spec.ts sei/*.spec.ts sei2/*.spec.ts txpool/*.spec.ts web3/*.spec.ts ) +specs=() +for f in */*.spec.ts; do + case "$f" in + _start/*|node_modules/*) continue ;; + esac + specs+=("$f") +done if [ "${#specs[@]}" -eq 0 ]; then echo "run-parallel: no spec files found under $RPC_DIR" >&2 exit 1 From 2a9e78ad3ed814ccd5230a57cc7ef6a041828bb3 Mon Sep 17 00:00:00 2001 From: kollegian Date: Fri, 29 May 2026 18:02:32 +0300 Subject: [PATCH 4/4] chore: address cursor comments --- integration_test/rpc_tests/README.md | 2 +- integration_test/rpc_tests/config/endpoints.ts | 10 ---------- integration_test/rpc_tests/hardhat/README.md | 8 ++++---- integration_test/rpc_tests/hardhat/hardhat.config.ts | 11 ++++++++--- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/integration_test/rpc_tests/README.md b/integration_test/rpc_tests/README.md index 8c686179f5..6e5c657345 100644 --- a/integration_test/rpc_tests/README.md +++ b/integration_test/rpc_tests/README.md @@ -150,7 +150,7 @@ npx mocha --require tsx eth/eth_blockNumber.spec.ts | `SEI_REST` | `http://localhost:1317` | | `RPC_ETH_GETH` | `http://127.0.0.1:9547` (geth --dev, primary) | | `RPC_ETH_FORK` | `http://127.0.0.1:9546` (anvil/Hardhat, optional) | -| `ETH_MAINNET_UPSTREAM` | Alchemy mainnet URL (used only by `yarn rpc:fork`) | +| `ETH_MAINNET_UPSTREAM` | required for `npm run rpc:fork` (no default — bring your own mainnet RPC URL) | | `ETH_MAINNET_FORK_BLOCK`| unset (latest) | | `SEI_ADMIN_MNEMONIC` | local devnet admin (in `endpoints.ts`) | | `RPC_POLLING_INTERVAL_MS`| `100` (Sei blocks are ~400ms; ethers default 4s is too slow) | diff --git a/integration_test/rpc_tests/config/endpoints.ts b/integration_test/rpc_tests/config/endpoints.ts index 5abee0c1d3..55056d1431 100644 --- a/integration_test/rpc_tests/config/endpoints.ts +++ b/integration_test/rpc_tests/config/endpoints.ts @@ -3,11 +3,6 @@ const env = (key: string, fallback: string): string => { return v && v.length > 0 ? v : fallback; }; -const envOptional = (key: string): string | undefined => { - const v = process.env[key]; - return v && v.length > 0 ? v : undefined; -}; - export const Endpoints = { sei: { evmRpc: env('SEI_EVM_RPC', 'http://localhost:8545'), @@ -17,11 +12,6 @@ export const Endpoints = { eth: { geth: env('RPC_ETH_GETH', 'http://127.0.0.1:9547'), fork: env('RPC_ETH_FORK', 'http://127.0.0.1:9546'), - upstream: env( - 'ETH_MAINNET_UPSTREAM', - 'https://eth-mainnet.g.alchemy.com/v2/Dmh5eMv-DYo4wvFHE2e3E', - ), - forkBlock: envOptional('ETH_MAINNET_FORK_BLOCK'), }, accountless: env('RPC_ACCOUNTLESS', 'https://evm-rpc.sei-apis.com'), } as const; diff --git a/integration_test/rpc_tests/hardhat/README.md b/integration_test/rpc_tests/hardhat/README.md index d788c71c37..cc51cdba30 100644 --- a/integration_test/rpc_tests/hardhat/README.md +++ b/integration_test/rpc_tests/hardhat/README.md @@ -22,10 +22,10 @@ yarn test:rpc ## Environment -| Variable | Default | Purpose | -| ----------------------- | ---------------------------------------------------------------- | ------------------------------------------ | -| `ETH_MAINNET_UPSTREAM` | `https://eth-mainnet.g.alchemy.com/v2/Dmh5eMv-DYo4wvFHE2e3E` | RPC URL the fork pulls state from. | -| `ETH_MAINNET_FORK_BLOCK`| (unset → latest) | Pin to a specific block for determinism. | +| Variable | Default | Purpose | +| ----------------------- | ------------------------ | ------------------------------------------------------------ | +| `ETH_MAINNET_UPSTREAM` | (required, no default) | Mainnet RPC URL the fork pulls state from. Provide your own. | +| `ETH_MAINNET_FORK_BLOCK`| (unset → latest) | Pin to a specific block for determinism. | ## Notes diff --git a/integration_test/rpc_tests/hardhat/hardhat.config.ts b/integration_test/rpc_tests/hardhat/hardhat.config.ts index 57e49e612d..0908d46e63 100644 --- a/integration_test/rpc_tests/hardhat/hardhat.config.ts +++ b/integration_test/rpc_tests/hardhat/hardhat.config.ts @@ -16,9 +16,14 @@ import { HardhatUserConfig } from 'hardhat/config'; import '@nomicfoundation/hardhat-toolbox'; -const UPSTREAM = - process.env.ETH_MAINNET_UPSTREAM ?? - 'https://eth-mainnet.g.alchemy.com/v2/Dmh5eMv-DYo4wvFHE2e3E'; +const UPSTREAM = process.env.ETH_MAINNET_UPSTREAM; +if (!UPSTREAM) { + throw new Error( + 'ETH_MAINNET_UPSTREAM is not set. The mainnet fork (npm run rpc:fork) needs an ' + + 'Ethereum mainnet RPC URL to fork from, e.g.\n' + + ' ETH_MAINNET_UPSTREAM="https://eth-mainnet.g.alchemy.com/v2/" npm run rpc:fork', + ); +} const FORK_BLOCK = process.env.ETH_MAINNET_FORK_BLOCK ? Number(process.env.ETH_MAINNET_FORK_BLOCK)