diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..3265e9d7 --- /dev/null +++ b/.babelrc @@ -0,0 +1,7 @@ +{ + "presets": [ + ["@babel/preset-env", { "targets": { "node": "current" } }], + "@babel/preset-typescript" + ] + } + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 723df2c4..0a3e28bc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ config.js dist/ .idea/ .DS_Store +.test/ \ No newline at end of file diff --git a/README.md b/README.md index 59ce70f6..df3ba6fb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ +

+ Shardeum Logo +

+ +

+

Shardeum is an EVM based autoscaling blockchain

+

+ # Overview The Shardeum JSON-RPC Server enables developers to interact with the Shardeum blockchain network. It allows dapps to post request, retrieve information, and other related operations, using JSON-RPC over HTTP. Additionally, the Shardeum JSON-RPC Server comes with an added REST API for debugging and monitoring purposes. @@ -29,15 +37,15 @@ docker compose logs -f docker compose down ``` -# Developer Environment Setup +## Developer Environment Setup For end users, such as exchanges and large decentralized applications (dApps), seeking to deploy their own RPC server, it is recommended to run the Shardeum JSON-RPC server using Docker. It ensures all dependencies are installed and the server is running in a consistent environment. For developers who want to contribute to this project, running the server from source is recommended. You can use `npm` for installing the server locally. -## Requirements +### Requirements If you are using `Docker`, in order to run the Shardeum JSON-RPC server, you must have the [Docker](https://docs.docker.com/get-docker/) daemon installed. -## Installing project source code +### Installing project source code Let’s install the project source code, switch to `dev` branch and follow the below instructions: @@ -86,7 +94,42 @@ port: 8080 The RPC URL for using Metamask with Remix IDE and for running scripts is (default: ) -If you are contributing to this project, use Shardeum server to create the network from within the [validator repo](https://gitlab.com/shardus/archive/archive-server). You can find more details [here](https://github.com/shardeum/shardeum) +If you are contributing to this project, use Shardeum server to create the network. You can find more details [here](https://github.com/shardeum/shardeum) + +## Running Tests + +There are two ways to set up the testing environment for the JSON RPC Server: Manual setup and using a Bash script. + +### Setting Up the Test Environment Manually + +Follow these steps to set up your local environment for testing: + +1. Run the Shardeum network locally (find instructions in the [Shardeum Readme.md](https://github.com/shardeum/shardeum/blob/dev/README.md) file). +2. Once your network is running, visit `localhost:4000/cycleinfo/1` to see your network's details. +3. Wait until the network enters processing mode, which happens when the active nodes in the network equals the minimum amount of nodes required (usually around cycle counter 12-14). +4. Once the network is in processing mode, start the JSON RPC server with `npm run start`. +5. Open a new terminal tab and run the tests with `npm run test` to see the test results. + +### Using the Bash Script + +The Bash script simplifies the process of setting up the test environment. It's particularly useful if you haven't already configured the Shardeum network and the JSON RPC server locally, though it can also be used if you have. The script will manage both situations and execute the tests for you. + +To run the script: + +1. Clone and set up the JSON RPC Server locally. +2. Navigate to the root of the project: `cd json-rpc-server`. +3. Execute the script: + - Run `npm local:test ~/root/path/to/your/shardeum/project` - If you already have the Shardeum repo installed locally. + - Run `npm local:test` - If you'd prefer the script to set one up for you. + - The script will creat a test environment path `/.test` and set up the Shardeum network there. +4. It will then start a network of 10 nodes along with the JSON RPC server, and finally run the test suite. +5. Tests involving transactions on the network will fail if your local network has fewer than 5 active nodes. + To address this, you can increase the wait time in the script to more than 10 minutes. + This will give the network sufficient time to reach processing mode with at least 5 active nodes. + +A test account with a hardcoded private key is provided in the tests, ensuring that your tests should pass without any extra configuration. + +> For detailed information about the tests, check the test document in the `src/__tests__/integration/TEST.md` file and the individual test files located in `src/__tests__`. Each test file contains specific tests for different parts of the JSON-RPC methods. ## Cleanup @@ -104,7 +147,7 @@ make clean This will remove all docker images created by the server during the build process. -# DEBUG Endpoints +## DEBUG Endpoints These api are protected preventing general public to wiping out debug data to authenticate use `/authenticate/:passphrase`. `passphrase` is set in `config.ts` config file or within the system env variable. @@ -127,6 +170,10 @@ GET `/cleanStatTable` this endpoint trigger purging of table that store interfac GET `/cleanTxTable` this endpoint trigger purging of table that store transaction logging -# Contributing +## Contributing Contributions are very welcome! Everyone interacting in our codebases, issue trackers, and any other form of communication, including chat rooms and mailing lists, is expected to follow our [code of conduct](CODE_OF_CONDUCT.md) so we can all enjoy the effort we put into this project. + +## Community + +For chatting with others using Shardeum: [Join the Shardeum Discord Server](https://discord.com/invite/shardeum) diff --git a/TEST.md b/TEST.md new file mode 100644 index 00000000..5ebbc980 --- /dev/null +++ b/TEST.md @@ -0,0 +1,57 @@ +# Shardeum Automated Testing Documentation + +## Overview + +This documentation covers the setup and execution of automated tests for JSON-RPC methods in the Shardeum JSON RPC Server. The goal is to ensure that Shardeum's implementation adheres to expected behaviors in handling blockchain transactions via JSON-RPC. + +## Goals + +- Test all JSON-RPC functions to ensure that they perform as expected. +- Verify the Shardus network connectivity and functionality. +- Ensure proper transaction handling and balance updates. + +## Test Script Overview + +The test script is designed to prepare an environment that is suitable for running the JSON RPC tests. Here is a breakdown of its functionality: + +1. **Environment Preparation**: + + - Checks for and uses NVM (Node Version Manager). + - Installs Node.js v18.16.1 if not present. + - Installs Rust if missing (version 1.74.1). + - Installs necessary build tools (build-essential on Linux, gcc on macOS). + +2. **Repository Management**: + + - Uses an existing Shardeum project if specified, otherwise it clones a fresh copy from the Shardeum repository. + - Applies a debug patch for 10-node setup. + +3. **Dependency Installation**: + + - Runs `npm ci` to install all project dependencies. + - Installs the Shardus CLI tool and the Shardus Archiver if not found. + +4. **Network Initialization**: + - Starts a Shardus network with 10 nodes. + - Waits for 4 minutes to allow network stabilization. + - Runs the tests + +### Test Execution + +Once the environment is set up, the tests are executed using Jest. These tests primarily interact with the `extendedServer` instance defined in the `server.ts` file. It handles JSON-RPC requests and performs the blockchain operations in the tests. Each test file imports its own instance of the RPC server and executes against it. + +Each RPC call has its own test file in the `src/__tests__` directory. Each file contains multiple test cases covering different aspects and edge cases for each RPC method. + +### Test Accounts + +The script uses an account in the Shardeum genesis file that starts off with a balance of `200,000,000 Ether` to send 0.01 Ether to the receiving address each time the transaction test executes. The test sends this transaction and then verifies that the receiving account's balance has increased by at least this amount. + +### Run Tests + +The tests typically run automatically through the test script, however, you can run the tests manually by executing the `npm test` command in the JSON RPC Server project. [More on how to run tests here ](https://github.com/shardeum/json-rpc-server/blob/localtest/README.md#running-tests). + +## Expand the Test Suite + +- **Add New Tests**: New tests can be added by creating new test files under the `src/__tests__` directory. Each new file should mimic the structure of existing tests, initializing its setup, defining the RPC calls, and tearing down after tests. +- **Modifying Existing Tests**: To modify existing tests, locate the relevant test file and add or adjust test cases as needed. Be mindful of potential side effects on other tests due to shared state or network conditions. +- **Enhancing Test Coverage**: Increase coverage by adding more scenarios and edge cases, particularly focusing on error handling and failure modes. diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..810c0546 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,21 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/__tests__/**/*.test.ts'], + moduleNameMapper: { + '^@/(.*)$': '/src/$1' + }, + testTimeout: 20000, + collectCoverage: true, + coverageDirectory: 'coverage', + coverageReporters: ['text', 'lcov'], + coveragePathIgnorePatterns: [ + "/node_modules/", + "/dist/", + "/src/server.js" + ], + transform: { + "^.+\\.(ts|tsx)$": "ts-jest", + }, + }; + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 85467cd1..5a579319 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "cookie-parser": "1.4.6", "cors": "2.8.5", "eth-rpc-errors": "4.0.3", + "ethereumjs-tx": "^2.1.2", "ethereumjs-util": "7.1.3", "execa": "^5.1.1", "express": "4.17.2", @@ -37,21 +38,30 @@ "ws": "8.13.0" }, "devDependencies": { + "@babel/core": "^7.24.8", + "@babel/preset-env": "^7.24.8", + "@babel/preset-typescript": "^7.24.7", "@types/better-sqlite3": "7.5.0", "@types/cookie-parser": "1.4.3", "@types/cors": "2.8.13", "@types/express": "4.17.15", "@types/hapi__sntp": "^3.1.4", + "@types/jest": "^29.5.12", "@types/jsonwebtoken": "8.5.9", "@types/node": "^18.16.1", + "@types/supertest": "^6.0.2", "@types/ws": "8.5.4", "@typescript-eslint/eslint-plugin": "5.46.1", "@typescript-eslint/parser": "5.60.1", + "babel-jest": "^29.7.0", "eslint-config-prettier": "8.5.0", "eslint-plugin-no-unsanitized": "4.0.2", "eslint-plugin-security": "1.5.0", "eslint-plugin-xss": "0.1.12", - "nodemon": "2.0.22" + "jest": "^29.7.0", + "nodemon": "2.0.22", + "supertest": "7.0.0", + "ts-jest": "29.2.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -67,6 +77,29 @@ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", @@ -75,22 +108,265 @@ "@babel/highlight": "^7.10.4" } }, + "node_modules/@babel/compat-data": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", + "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", + "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.9", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-module-transforms": "^7.24.9", + "@babel/helpers": "^7.24.8", + "@babel/parser": "^7.24.8", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", + "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", + "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", + "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", + "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.8" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -160,137 +436,416 @@ "node": ">=4" } }, - "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==", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "engines": { - "node": ">= 4" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ethereumjs/common": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", - "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.5" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ethereumjs/common/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==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": 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" + "@babel/helper-plugin-utils": "^7.12.13" }, - "engines": { - "node": ">=10.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", - "bin": { - "rlp": "bin/rlp.cjs" + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ethereumjs/tx": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.4.0.tgz", - "integrity": "sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "dependencies": { - "@ethereumjs/common": "^2.6.0", - "ethereumjs-util": "^7.1.3" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ethereumjs/util": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-9.0.2.tgz", - "integrity": "sha512-dasKCj6Vb5spVPnNmRDFHmbfBySvokE440F0RDroPLzO4Mb4hyDqeoOMUxlbLz/BscK2pOpWUendGA+AOvGpNQ==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, "dependencies": { - "@ethereumjs/rlp": "^5.0.2", - "ethereum-cryptography": "^2.1.3" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "c-kzg": "^2.1.2" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", - "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "dependencies": { - "@noble/curves": "1.3.0", - "@noble/hashes": "1.3.3", - "@scure/bip32": "1.3.3", - "@scure/bip39": "1.2.2" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", + "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.8", + "@babel/types": "^7.24.8", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "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==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "dependencies": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/common/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==", + "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/@ethereumjs/rlp": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", + "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/tx": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.4.0.tgz", + "integrity": "sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==", + "dependencies": { + "@ethereumjs/common": "^2.6.0", + "ethereumjs-util": "^7.1.3" + } + }, + "node_modules/@ethereumjs/util": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-9.0.2.tgz", + "integrity": "sha512-dasKCj6Vb5spVPnNmRDFHmbfBySvokE440F0RDroPLzO4Mb4hyDqeoOMUxlbLz/BscK2pOpWUendGA+AOvGpNQ==", + "dependencies": { + "@ethereumjs/rlp": "^5.0.2", + "ethereum-cryptography": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } + } + }, + "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "dependencies": { + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" } }, "node_modules/@ethersproject/bytes": { @@ -383,32 +938,420 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "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==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@noble/curves": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", - "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "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==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", "dependencies": { "@noble/hashes": "1.3.3" }, @@ -719,6 +1662,12 @@ "resolved": "https://registry.npmjs.org/@shardus/types/-/types-1.2.8.tgz", "integrity": "sha512-QCCHm15dmEFkH+TUMUNMT/iCGCsjOR8z6/5AZasG7Gsu9CTL85V4L+Ny/SGjKzM9sdi1Vz8XARy96r+slUZBOg==" }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -730,6 +1679,24 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -771,6 +1738,47 @@ "resolved": "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-7.2.5.tgz", "integrity": "sha512-/2B0nQF4UdupuxeKTJA2+Rj1D+uDemo6P4kMwKCpbfpnzeVaWSELTsAw4Lxn3VJD6APtRrZOCuYo+4nHUQfTfg==" }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, "node_modules/@types/better-sqlite3": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.5.0.tgz", @@ -826,6 +1834,12 @@ "@types/express": "*" } }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true + }, "node_modules/@types/cors": { "version": "2.8.13", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", @@ -858,6 +1872,15 @@ "@types/send": "*" } }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/hapi__sntp": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/hapi__sntp/-/hapi__sntp-3.1.4.tgz", @@ -875,6 +1898,40 @@ "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", "dev": true }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", @@ -917,6 +1974,12 @@ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==" }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -997,6 +2060,33 @@ "@types/node": "*" } }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/superagent": { + "version": "8.1.7", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", + "integrity": "sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==", + "dev": true, + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", + "dev": true, + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, "node_modules/@types/ws": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", @@ -1006,6 +2096,21 @@ "@types/node": "*" } }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.46.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz", @@ -1512,9 +2617,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { "debug": "^4.3.4" }, @@ -1651,6 +2756,12 @@ "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 + }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -1721,15 +2832,122 @@ "proxy-from-env": "^1.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==" - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.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==" + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", "dependencies": { "safe-buffer": "^5.0.1" } @@ -1899,6 +3117,50 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", @@ -1917,6 +3179,15 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -2063,6 +3334,26 @@ "node": ">=8" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2078,6 +3369,15 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -2119,6 +3419,21 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -2128,6 +3443,12 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -2170,6 +3491,20 @@ "node": ">= 10" } }, + "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, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -2181,6 +3516,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2213,6 +3564,15 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2273,6 +3633,12 @@ "emitter-listener": "^1.1.1" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", @@ -2298,6 +3664,12 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -2346,6 +3718,27 @@ "sha.js": "^2.4.8" } }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2467,6 +3860,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -2480,6 +3887,15 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", @@ -2584,6 +4000,25 @@ "node": ">=8" } }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -2592,6 +4027,15 @@ "node": ">=0.3.1" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -2627,6 +4071,27 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.827", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==", + "dev": true + }, "node_modules/elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -2654,6 +4119,18 @@ "shimmer": "^1.2.0" } }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2667,6 +4144,16 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "peer": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/encoding-down": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", @@ -2681,6 +4168,19 @@ "node": ">=6" } }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -2751,6 +4251,15 @@ "es6-promise": "^4.0.3" } }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3217,6 +4726,49 @@ "setimmediate": "^1.0.5" } }, + "node_modules/ethereumjs-common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", + "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==", + "deprecated": "New package name format for new versions: @ethereumjs/common. Please update." + }, + "node_modules/ethereumjs-tx": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", + "deprecated": "New package name format for new versions: @ethereumjs/tx. Please update.", + "dependencies": { + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-tx/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ethereumjs-tx/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/ethereumjs-tx/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, "node_modules/ethereumjs-util": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz", @@ -3232,6 +4784,19 @@ "node": ">=10.0.0" } }, + "node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, "node_modules/eventemitter2": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", @@ -3273,6 +4838,15 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -3281,6 +4855,22 @@ "node": ">=6" } }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/express": { "version": "4.17.2", "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", @@ -3478,10 +5068,19 @@ "reusify": "^1.0.4" } }, - "node_modules/fclone": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", - "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" }, "node_modules/figures": { "version": "3.2.0", @@ -3521,6 +5120,36 @@ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3631,6 +5260,20 @@ "node": ">= 6" } }, + "node_modules/formidable": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", + "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3696,6 +5339,24 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "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, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -3714,6 +5375,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -4141,6 +5811,15 @@ "node": ">= 0.4" } }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -4162,6 +5841,12 @@ "node": ">=10" } }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", @@ -4300,6 +5985,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4363,6 +6067,23 @@ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -4396,193 +6117,918 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dependencies": { - "binary-extensions": "^2.0.0" + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dependencies": { + "has": "^1.0.3" + }, + "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==", + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "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==", + "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==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "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==", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", + "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jayson": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.6.5.tgz", + "integrity": "sha512-wmOjX+eQcnCDyPF4KORomaIj9wj3h0B5VEbeD0+2VHfTfErB+h1zpR7oBkgCZp36AFjp3+a4CLz6U72BYpFHAw==", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/express-serve-static-core": "^4.17.9", + "@types/lodash": "^4.14.159", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "lodash": "^4.17.20", + "uuid": "^3.4.0", + "ws": "^7.4.5" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/jayson/node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/jayson/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "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/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/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, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/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, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/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, + "dependencies": { + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, "engines": { - "node": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, "dependencies": { - "which-typed-array": "^1.1.14" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "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==", - "peerDependencies": { - "ws": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jayson": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.6.5.tgz", - "integrity": "sha512-wmOjX+eQcnCDyPF4KORomaIj9wj3h0B5VEbeD0+2VHfTfErB+h1zpR7oBkgCZp36AFjp3+a4CLz6U72BYpFHAw==", + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "dependencies": { - "@types/connect": "^3.4.33", - "@types/express-serve-static-core": "^4.17.9", - "@types/lodash": "^4.14.159", - "@types/node": "^12.12.54", - "@types/ws": "^7.4.4", - "commander": "^2.20.3", - "delay": "^5.0.0", - "es6-promisify": "^5.0.0", - "eyes": "^0.1.8", - "isomorphic-ws": "^4.0.1", - "json-stringify-safe": "^5.0.1", - "JSONStream": "^1.3.5", - "lodash": "^4.17.20", - "uuid": "^3.4.0", - "ws": "^7.4.5" - }, - "bin": { - "jayson": "bin/jayson.js" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jayson/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" - }, - "node_modules/jayson/node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "node_modules/jest-worker/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, "dependencies": { - "@types/node": "*" - } - }, - "node_modules/jayson/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "engines": { - "node": ">=8.3.0" + "has-flag": "^4.0.0" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/js-git": { @@ -4613,6 +7059,23 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4744,6 +7207,15 @@ "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, + "engines": { + "node": ">=6" + } + }, "node_modules/lazy": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", @@ -4858,6 +7330,15 @@ "node": ">=6" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4891,6 +7372,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4933,11 +7420,35 @@ "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", "integrity": "sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==" }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "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==" }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -5341,6 +7852,18 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, "node_modules/nodemon": { "version": "2.0.22", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", @@ -5718,6 +8241,11 @@ "node": ">=0.12" } }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -5734,10 +8262,31 @@ "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", "integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==", "dependencies": { - "safe-buffer": "^5.2.1" + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, "node_modules/pm2": { @@ -5946,6 +8495,32 @@ "node": ">=6.0.0" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5962,6 +8537,19 @@ "read": "^1.0.4" } }, + "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, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -6033,6 +8621,22 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", @@ -6129,6 +8733,12 @@ "node": ">=0.10.0" } }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, "node_modules/read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -6258,6 +8868,15 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "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, + "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", @@ -6309,6 +8928,27 @@ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -6317,6 +8957,15 @@ "node": ">=4" } }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -6735,6 +9384,12 @@ "node": ">=8.10.0" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6769,36 +9424,31 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, "node_modules/socks-proxy-agent": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.1.tgz", - "integrity": "sha512-59EjPbbgg8U3x62hhKOFVAmySQUcfRQ4C7Q/D5sEHnZTQRrQlNKINks44DMR1gwXp0p4LaVIeccX2KHTTcHVqQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "dependencies": { - "agent-base": "^7.0.1", + "agent-base": "^7.1.1", "debug": "^4.3.4", - "socks": "^2.7.1" + "socks": "^2.8.3" }, "engines": { "node": ">= 14" } }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" - }, "node_modules/sodium-native": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-3.3.0.tgz", @@ -6858,6 +9508,27 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -6874,6 +9545,19 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6898,6 +9582,15 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -6906,6 +9599,18 @@ "node": ">=6" } }, + "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==", + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -6928,6 +9633,51 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", + "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -7037,6 +9787,20 @@ "node": ">=6" } }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -7058,6 +9822,21 @@ "node": ">=0.6.0" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=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", @@ -7102,6 +9881,63 @@ "node": ">=8" } }, + "node_modules/ts-jest": { + "version": "29.2.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.2.tgz", + "integrity": "sha512-sSW7OooaKT34AAngP6k1VS669a0HdLxkQZnlC7T76sckGCokXFnvJ3yRlQZGRTAoV5K19HfSgCiSwWOSIfcYlg==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "ejs": "^3.0.0", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/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, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -7202,6 +10038,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -7267,6 +10112,36 @@ "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -7319,6 +10194,30 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -7358,6 +10257,15 @@ "lodash": "^4.17.14" } }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/web3": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/web3/-/web3-4.8.0.tgz", @@ -7795,6 +10703,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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, + "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", @@ -7839,6 +10764,15 @@ "node": ">=0.4" } }, + "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, + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -7857,6 +10791,24 @@ "yaml2json": "bin/yaml2json" } }, + "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, + "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/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", @@ -7865,6 +10817,15 @@ "node": ">=10" } }, + "node_modules/yargs/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, + "engines": { + "node": ">=12" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -7873,6 +10834,18 @@ "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "3.23.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.4.tgz", diff --git a/package.json b/package.json index 5f5fa631..23391d5b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "JSON RPC server for Shardeum", "main": "src/server.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "bash run_tests.sh", "start": "npm run compile && node dist/src/server.js", "dev": "nodemon", "compile": "tsc -p .", @@ -12,7 +12,8 @@ "lint": "eslint './src/**/*.ts'", "lint-windows": "eslint ./src/**/*.ts", "update-docker-dev": "docker build -t registry.gitlab.com/shardeum/json-rpc-server:dev . --push", - "format-check": "prettier --check './src/**/*.ts'" + "format-check": "prettier --check './src/**/*.ts'", + "coverage": "jest --coverage --detectOpenHandles --forceExit --silent" }, "author": "thantsintoe", "license": "ISC", @@ -31,6 +32,7 @@ "cookie-parser": "1.4.6", "cors": "2.8.5", "eth-rpc-errors": "4.0.3", + "ethereumjs-tx": "2.1.2", "ethereumjs-util": "7.1.3", "execa": "^5.1.1", "express": "4.17.2", @@ -50,8 +52,10 @@ "@types/cors": "2.8.13", "@types/express": "4.17.15", "@types/hapi__sntp": "^3.1.4", + "@types/jest": "29.5.12", "@types/jsonwebtoken": "8.5.9", "@types/node": "^18.16.1", + "@types/supertest": "6.0.2", "@types/ws": "8.5.4", "@typescript-eslint/eslint-plugin": "5.46.1", "@typescript-eslint/parser": "5.60.1", @@ -59,7 +63,10 @@ "eslint-plugin-no-unsanitized": "4.0.2", "eslint-plugin-security": "1.5.0", "eslint-plugin-xss": "0.1.12", - "nodemon": "2.0.22" + "jest": "29.7.0", + "nodemon": "2.0.22", + "supertest": "7.0.0", + "ts-jest": "29.2.2" }, "overrides": { "semver": "7.5.3", diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 00000000..f1c96edc --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +export NVM_DIR="${XDG_CONFIG_HOME:-${HOME}/.nvm}" + +if [ ! -f "$NVM_DIR/nvm.sh" ]; then + echo "Please install nvm before running this script as Shardeum requires a specific version of node and npm." + exit 1 +fi + +# Load nvm +source "$NVM_DIR/nvm.sh" + +# Define your local repository path +REPO_PATH="${1:-/path/to/your/local/shardeum/repo}" +REPO_NAME="shardeum" + +# Check if the directory exists +if [ -d "$REPO_PATH" ]; then + echo "Repository path exists: $REPO_PATH" + pushd "$REPO_PATH" +else + echo "No existing Shardeum installation found, cloning the repository..." + if [ ! -d .test ]; then + mkdir .test + fi + pushd .test + if [ -d $REPO_NAME ]; then + rm -rf $REPO_NAME + fi + git clone https://github.com/shardeum/shardeum.git || { echo "Failed to clone shardeum repository"; exit 1; } + pushd "$REPO_NAME" +fi + +# Check Node.js version +if ! node --version | grep -q "v18"; then + echo "Node.js v18 not found, installing and selecting via nvm..." + nvm install 18.16.1 && nvm use 18.16.1 || { echo "Failed to install/select Node.js v18.16.1"; exit 1; } +fi + +# Ensure Rust is installed +if ! command -v rustc &> /dev/null; then + echo "Rust missing, installing..." + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source $HOME/.cargo/env + rustup toolchain install 1.74.1 + rustup default 1.74.1 +else + echo -n "Rust detected, version: " + rustc --version +fi + +# Install build essentials based on OS +install_linux() { + sudo apt-get update && sudo apt-get install -y build-essential +} + +install_macos() { + if ! command -v brew &> /dev/null; then + echo "Homebrew is not installed, please install it before running this script." + exit 1 + fi + brew update + brew install gcc +} + +case "$OSTYPE" in + linux-gnu*) install_linux ;; + darwin*) install_macos ;; + *) echo "Unsupported OS: $OSTYPE"; exit 1 ;; +esac + +# Install project dependencies and apply debug patch +echo "Installing Shardeum project dependencies..." +npm ci + +git apply debug-10-nodes.patch || { echo "Failed to apply patch"; exit 1; } + +# Build the project +npm run prepare + +# Install shardus and archiver globally if not already installed +command -v shardus &> /dev/null || npm install -g shardus @shardus/archiver + +# Start the shardus network +shardus start 10 || { echo "Failed to start shardus network"; exit 1; } +echo "Started 10 nodes with shardus" + +# Wait for archivers in the network to initialize +echo "Waiting for 4 minutes to allow the network to stabilize..." +sleep 240 + +# Return to the original directory using popd +popd || { echo "Failed to return to parent directory"; exit 1; } + + +npm run test || { echo "Test suite failed"; exit 1; } +echo "Test suite completed." + +# Stop the shardus network +shardus stop & shardus clean & rm -rf .test || { echo "Failed to stop shardus network"; exit 1; } \ No newline at end of file diff --git a/src/__tests__/integration/eth_accounts.test.ts b/src/__tests__/integration/eth_accounts.test.ts new file mode 100644 index 00000000..0adc5d22 --- /dev/null +++ b/src/__tests__/integration/eth_accounts.test.ts @@ -0,0 +1,85 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_accounts', () => { + describe('eth_accounts', () => { + it('should return an array of eth accounts', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_accounts', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toBeInstanceOf(Array); + expect(response.body.result).toContain('0x407d73d8a49eeb85d32cf465507dd71d507100c1'); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 2, + method: 'eth_accounts', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_accounts', + params: [] + }); + + expect(response.status).toBe(204); + }); + + it('should return a successful response if params property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 4, + method: 'eth_accounts' + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toBeInstanceOf(Array); + expect(response.body.result).toContain('0x407d73d8a49eeb85d32cf465507dd71d507100c1'); + }); + + it('should return a correct response if id property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 'six', // id should be a number + method: 'eth_accounts', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe('six'); + expect(response.body.result).toBeInstanceOf(Array); + expect(response.body.result).toContain('0x407d73d8a49eeb85d32cf465507dd71d507100c1'); + }); + }); +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_blockNumber.test.ts b/src/__tests__/integration/eth_blockNumber.test.ts new file mode 100644 index 00000000..cb775fb7 --- /dev/null +++ b/src/__tests__/integration/eth_blockNumber.test.ts @@ -0,0 +1,139 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_blockNumber', () => { + describe('eth_blockNumber', () => { + it('should return the block number', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_blockNumber', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 2, + method: 'eth_blockNumber', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_blockNumber', + params: [] + }); + + expect(response.status).toBe(204); + }); + + it('should return an error if method property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 3, + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should not return an error if params property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 4, + method: 'eth_blockNumber' + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if jsonrpc version is invalid', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: 'invalid_version', + id: 5, + method: 'eth_blockNumber', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return a correct response if id property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 'six', // id should be a number + method: 'eth_blockNumber', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe('six'); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + + it('should return an error if params property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 8, + method: 'eth_blockNumber', + params: 'invalid_params' // params should be an array + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + }); +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_chainId.test.ts b/src/__tests__/integration/eth_chainId.test.ts new file mode 100644 index 00000000..3e129393 --- /dev/null +++ b/src/__tests__/integration/eth_chainId.test.ts @@ -0,0 +1,135 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_chainId', () => { + describe('eth_chainId', () => { + it('should return the chain ID of the current network', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_chainId', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('result'); + expect(response.body.result).toMatch(/0x[0-9a-fA-F]+/); + }); + + it('should return a valid chain ID', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 2, + method: 'eth_chainId', + params: [] + }); + + expect(response.status).toBe(200); + const chainId = parseInt(response.body.result, 16); + expect(chainId).toBeGreaterThan(0); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 3, + method: 'eth_chainId', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_chainId', + params: [] + }); + + expect(response.status).toBe(204); + }); + + it('should not return an error if params property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 5, + method: 'eth_chainId' + }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('result'); + expect(response.body.result).toMatch(/0x[0-9a-fA-F]+/); + }); + + it('should return an error if jsonrpc version is invalid', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: 'invalid_version', + id: 6, + method: 'eth_chainId', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return a correct response if id property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 'seven', // id should be a number + method: 'eth_chainId', + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe('seven'); + expect(response.body.result).toMatch(/0x[0-9a-fA-F]+/); + }); + + it('should return an error if method property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 8, + method: 123, // method should be a string + params: [] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + }); +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_estimateGas.test.ts b/src/__tests__/integration/eth_estimateGas.test.ts new file mode 100644 index 00000000..1fa7c080 --- /dev/null +++ b/src/__tests__/integration/eth_estimateGas.test.ts @@ -0,0 +1,22 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_estimateGas', () => { + it('should return the estimated gas', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_estimateGas", + params: [{ to: "0x8469448199bdc8d5956a61643baadbf3e6930fec" }], + id: 1, + jsonrpc: "2.0" + } + ); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + }); +}); diff --git a/src/__tests__/integration/eth_gasPrice.test.ts b/src/__tests__/integration/eth_gasPrice.test.ts new file mode 100644 index 00000000..19eade99 --- /dev/null +++ b/src/__tests__/integration/eth_gasPrice.test.ts @@ -0,0 +1,143 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - Missing/Invalid Properties', () => { + describe('eth_gasPrice', () => { + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 1, + method: 'eth_gasPrice', + params: [] + }); + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return an error if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_gasPrice', + params: [] + }); + expect(response.statusCode).toBe(204); + }); + + it('should return an error if method property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + params: [] + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return correct response if params property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_gasPrice' + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(1); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if jsonrpc version is invalid', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '1.0', + id: 1, + method: 'eth_gasPrice', + params: [] + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return correct result if id property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 'invalid_id', // id should be a number + method: 'eth_gasPrice', + params: [] + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe('invalid_id'); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if method property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 123, // method should be a string + params: [] + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return an error if params property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_gasPrice', + params: 'invalid_params' // params should be an array + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + }); +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_getBalance.test.ts b/src/__tests__/integration/eth_getBalance.test.ts new file mode 100644 index 00000000..fde8bd86 --- /dev/null +++ b/src/__tests__/integration/eth_getBalance.test.ts @@ -0,0 +1,177 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - Missing/Invalid Properties', () => { + describe('eth_getBalance', () => { + it('should return the correct balance for a valid address', async () => { + const address = '0x4a372F3F5cFa12Ce491106BDD82735764ea29D62'; + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBalance", + params: [address, "latest"], + id: 1, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return zero if the address has no transactions', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getBalance', + params: ['0x5f752C078d8fE70d77C644F05f3e29d9F073776c', 'latest'], + id: 1, + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBe('0x0'); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 1, + method: 'eth_getBalance', + params: ['0x4a372F3F5cFa12Ce491106BDD82735764ea29D62', 'latest'] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getBalance', + params: ['0x4a372F3F5cFa12Ce491106BDD82735764ea29D62', 'latest'] + }); + + expect(response.status).toBe(204); + }); + + it('should return an error if method property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + params: ['0x4a372F3F5cFa12Ce491106BDD82735764ea29D62', 'latest'] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return error if params property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_getBalance' + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(1); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32602); + expect(response.body.error.message).toBe('Invalid params: non-array args'); + + }); + + it('should return an error if jsonrpc version is invalid', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: 'invalid_version', + id: 1, + method: 'eth_getBalance', + params: ['0x4a372F3F5cFa12Ce491106BDD82735764ea29D62', 'latest'] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return a correct response if id property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 'one', // id should be a number + method: 'eth_getBalance', + params: ['0x4a372F3F5cFa12Ce491106BDD82735764ea29D62', 'latest'] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe('one') + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if method property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 123, // method should be a string + params: ['0x4a372F3F5cFa12Ce491106BDD82735764ea29D62', 'latest'] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return an error if params property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_getBalance', + params: 'invalid_params' // params should be an array + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + }); +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_getBlockByHash.test.ts b/src/__tests__/integration/eth_getBlockByHash.test.ts new file mode 100644 index 00000000..c2da8adf --- /dev/null +++ b/src/__tests__/integration/eth_getBlockByHash.test.ts @@ -0,0 +1,46 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getBlockByHash', () => { + it('should return the block details by hash with transaction details set to false', async () => { + // Step 1: Get the latest block to retrieve its hash + const latestBlockResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByNumber", + params: ["latest"], + id: 1, + jsonrpc: "2.0" + }); + + expect(latestBlockResponse.status).toBe(200); + expect(latestBlockResponse.body.result).toBeDefined(); + const latestBlockHash = latestBlockResponse.body.result.hash; + expect(latestBlockHash).toMatch(/^0x[0-9a-fA-F]+$/); + + // Step 2: Get block details by hash using the retrieved hash + const blockByHashResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByHash", + params: [latestBlockHash, false], + id: 2, + jsonrpc: "2.0" + }); + + expect(blockByHashResponse.status).toBe(200); + expect(blockByHashResponse.body.result).toBeDefined(); + + // Check that the block hash matches the one we used + expect(blockByHashResponse.body.result).toHaveProperty('hash', latestBlockHash); + + // Check that the transactions array is present + expect(blockByHashResponse.body.result).toHaveProperty('transactions'); + // When transaction_detail_flag is false, transactions should be an array of transaction hashes + if (blockByHashResponse.body.result.transactions.length > 0) { + expect(blockByHashResponse.body.result.transactions[0]).toMatch(/^0x[0-9a-fA-F]+$/); // Check if it is a transaction hash + } + }); + }); +}); diff --git a/src/__tests__/integration/eth_getBlockByNumber.test.ts b/src/__tests__/integration/eth_getBlockByNumber.test.ts new file mode 100644 index 00000000..b740b407 --- /dev/null +++ b/src/__tests__/integration/eth_getBlockByNumber.test.ts @@ -0,0 +1,28 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getBlockByNumber', () => { + it('should return the block details by number with transaction details set to false', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByNumber", + params: ["latest", false], + id: 1, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + // Check the block number + expect(response.body.result).toHaveProperty('number'); + // Check that the transactions array is present + expect(response.body.result).toHaveProperty('transactions'); + // When transaction_detail_flag is false, transactions should be an array of transaction hashes + if (response.body.result.transactions.length > 0) { + expect(response.body.result.transactions[0]).toMatch(/^0x[0-9a-fA-F]+$/); // Check if it is a transaction hash + } + }); + }); +}); diff --git a/src/__tests__/integration/eth_getCode.test.ts b/src/__tests__/integration/eth_getCode.test.ts new file mode 100644 index 00000000..348741a4 --- /dev/null +++ b/src/__tests__/integration/eth_getCode.test.ts @@ -0,0 +1,53 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_getCode', () => { + const testAddress = '0x6d1f44b11eb29b8bcbb4f7e15be7e4ebdd0a9cc5'; + + it('should return the code at the given address for the latest block', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_getCode', + params: [testAddress, 'latest'] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(1); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]*$/); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 1, + method: 'eth_getCode', + params: [testAddress, 'latest'] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getCode', + params: [testAddress, 'latest'] + }); + + expect(response.status).toBe(204); + }); +}); diff --git a/src/__tests__/integration/eth_getFilterChanges.test.ts b/src/__tests__/integration/eth_getFilterChanges.test.ts new file mode 100644 index 00000000..9b8d8c28 --- /dev/null +++ b/src/__tests__/integration/eth_getFilterChanges.test.ts @@ -0,0 +1,34 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getFilterChanges', () => { + it('should return changes for the given filter ID', async () => { + // First, create a new filter to get a filter ID + const newFilterResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_newFilter", + params: [{}], // No specific parameters, using default behavior + id: 1, + jsonrpc: "2.0" + }); + + const filterId = newFilterResponse.body.result; + + // Now get filter changes using the filter ID + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_getFilterChanges", + params: [filterId], + id: 2, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toBeInstanceOf(Array); // Should return an array of changes + }); + }); +}); diff --git a/src/__tests__/integration/eth_getFilterLogs.test.ts b/src/__tests__/integration/eth_getFilterLogs.test.ts new file mode 100644 index 00000000..d60e1787 --- /dev/null +++ b/src/__tests__/integration/eth_getFilterLogs.test.ts @@ -0,0 +1,75 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_getFilterLogs', () => { + describe('eth_getFilterLogs', () => { + it('should return logs for the given filter ID', async () => { + // Step 1: Create a filter to get its ID + const filterResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_newFilter", + params: [{ + fromBlock: "0x1", + toBlock: "latest", + address: "0x8469448199bdc8d5956a61643baadbf3e6930fec", + topics: [] + }], + id: 1, + jsonrpc: "2.0" + }); + + expect(filterResponse.status).toBe(200); + expect(filterResponse.body.result).toBeDefined(); + const filterId = filterResponse.body.result; + + // Step 2: Use the filter ID to get logs + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_getFilterLogs", + params: [filterId], + id: 1, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toBeInstanceOf(Array); // Should return an array of logs + }); + + it('should return no logs if there are no matching logs', async () => { + const filterResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_newFilter", + params: [{ + fromBlock: "0x1", + toBlock: "latest", + address: "0x0000000000000000000000000000000000000000", // Address with no logs + topics: [] + }], + id: 4, + jsonrpc: "2.0" + }); + + expect(filterResponse.status).toBe(200); + expect(filterResponse.body.result).toBeDefined(); + const filterId = filterResponse.body.result; + + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_getFilterLogs", + params: [filterId], + id: 5, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toBeInstanceOf(Array); // Should return an array of logs + expect(response.body.result.length).toBe(0); // No logs should be returned + }); + }); +}); diff --git a/src/__tests__/integration/eth_getLogs.test.ts b/src/__tests__/integration/eth_getLogs.test.ts new file mode 100644 index 00000000..8dbe83e5 --- /dev/null +++ b/src/__tests__/integration/eth_getLogs.test.ts @@ -0,0 +1,26 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getLogs', () => { + it('should return logs for the given filter options', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_getLogs", + params: [{ + fromBlock: "0x1", + toBlock: "latest", + address: "0x8469448199bdc8d5956a61643baadbf3e6930fec", + topics: [] + }], + id: 1, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toBeInstanceOf(Array); // Should return an array of logs + }); + }); +}); diff --git a/src/__tests__/integration/eth_getStorageAt.test.ts b/src/__tests__/integration/eth_getStorageAt.test.ts new file mode 100644 index 00000000..0cf7b605 --- /dev/null +++ b/src/__tests__/integration/eth_getStorageAt.test.ts @@ -0,0 +1,103 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_getStorageAt', () => { + describe('eth_getStorageAt', () => { + it('should return the storage value at a given position', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_getStorageAt', + params: [ + '0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', + '0x1', + 'latest' + ] + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.result).toBe('0x'); + }); + + it('should return an error if address property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 2, + method: 'eth_getStorageAt', + params: [ + '', + '0x1', + 'latest' + ] + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 2, + method: 'eth_getStorageAt', + params: [ + '0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', + '0x1', + 'latest' + ] + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getStorageAt', + params: [ + '0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', + '0x1', + 'latest' + ] + }); + + expect(response.statusCode).toBe(204); + }); + + it('should return an error if params property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 4, + method: 'eth_getStorageAt' + }); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(4); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32602); + expect(response.body.error.message).toBe('Invalid params: non-array args'); + }); + + }); +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_getTransactionByBlockHashAndIndex.test.ts b/src/__tests__/integration/eth_getTransactionByBlockHashAndIndex.test.ts new file mode 100644 index 00000000..ee50627c --- /dev/null +++ b/src/__tests__/integration/eth_getTransactionByBlockHashAndIndex.test.ts @@ -0,0 +1,64 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getTransactionByBlockHashAndIndex', () => { + it('should return the transaction details by block hash and transaction index', async () => { + // Step 1: Get the latest block to retrieve its hash and transactions + const latestBlockResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByNumber", + params: ["latest", false], + id: 1, + jsonrpc: "2.0" + }); + + expect(latestBlockResponse.status).toBe(200); + expect(latestBlockResponse.body.result).toBeDefined(); + const latestBlock = latestBlockResponse.body.result; + const latestBlockHash = latestBlock.hash; + const transactions = latestBlock.transactions; + + expect(latestBlockHash).toMatch(/^0x[0-9a-fA-F]+$/); + + // Ensure there are transactions in the latest block + if (transactions.length > 0) { + const transactionIndex = 0; // Index of the first transaction + + // Step 2: Get transaction details by block hash and transaction index + const transactionByHashAndIndexResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getTransactionByBlockHashAndIndex", + params: [ + latestBlockHash, // Block hash in hexadecimal + `0x${transactionIndex.toString(16)}` // Transaction index in hexadecimal + ], + id: 2, + jsonrpc: "2.0" + }); + + expect(transactionByHashAndIndexResponse.status).toBe(200); + expect(transactionByHashAndIndexResponse.body.result).toBeDefined(); + const transaction = transactionByHashAndIndexResponse.body.result; + + // Check that the transaction hash matches the one in the block's transaction array + expect(transaction.hash).toBe(transactions[transactionIndex]); + + // Additional checks for transaction properties + expect(transaction).toHaveProperty('blockHash', latestBlockHash); + expect(transaction).toHaveProperty('blockNumber'); + expect(transaction.blockNumber).toMatch(/^0x[0-9a-fA-F]+$/); + expect(transaction).toHaveProperty('from'); + expect(transaction.from).toMatch(/^0x[0-9a-fA-F]{40}$/); + expect(transaction).toHaveProperty('to'); + if (transaction.to) { + expect(transaction.to).toMatch(/^0x[0-9a-fA-F]{40}$/); + } + expect(transaction).toHaveProperty('value'); + expect(transaction.value).toMatch(/^0x[0-9a-fA-F]+$/); + } + }); + }); +}); diff --git a/src/__tests__/integration/eth_getTransactionByBlockNumberAndIndex.test.ts b/src/__tests__/integration/eth_getTransactionByBlockNumberAndIndex.test.ts new file mode 100644 index 00000000..92976cb0 --- /dev/null +++ b/src/__tests__/integration/eth_getTransactionByBlockNumberAndIndex.test.ts @@ -0,0 +1,66 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getTransactionByBlockNumberAndIndex', () => { + it('should return the transaction details by block number and transaction index', async () => { + // Step 1: Get the latest block to retrieve its transactions + const latestBlockResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByNumber", + params: [ + "latest", // Block number in hexadecimal + false + ], + id: 1, + jsonrpc: "2.0" + }); + + expect(latestBlockResponse.status).toBe(200); + expect(latestBlockResponse.body.result).toBeDefined(); + const latestBlock = latestBlockResponse.body.result; + const blockNumber = latestBlock.number; + const transactions = latestBlock.transactions; + + expect(blockNumber).toMatch(/^0x[0-9a-fA-F]+$/); + + // Ensure there are transactions in the latest block + if (transactions.length > 0) { + const transactionIndex = 0; // Index of the first transaction + + // Step 2: Get transaction details by block number and transaction index + const transactionByNumberAndIndexResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getTransactionByBlockNumberAndIndex", + params: [ + blockNumber, // Block number in hexadecimal + `0x${transactionIndex.toString(16)}` // Transaction index in hexadecimal + ], + id: 2, + jsonrpc: "2.0" + }); + + expect(transactionByNumberAndIndexResponse.status).toBe(200); + expect(transactionByNumberAndIndexResponse.body.result).toBeDefined(); + const transaction = transactionByNumberAndIndexResponse.body.result; + + // Check that the transaction hash matches the one in the block's transaction array + expect(transaction.hash).toBe(transactions[transactionIndex]); + + // Additional checks for transaction properties + expect(transaction).toHaveProperty('blockHash', latestBlock.hash); + expect(transaction).toHaveProperty('blockNumber', blockNumber); + expect(transaction).toHaveProperty('from'); + expect(transaction.from).toMatch(/^0x[0-9a-fA-F]{40}$/); + expect(transaction).toHaveProperty('to'); + if (transaction.to) { + expect(transaction.to).toMatch(/^0x[0-9a-fA-F]{40}$/); + } + expect(transaction).toHaveProperty('value'); + expect(transaction.value).toMatch(/^0x[0-9a-fA-F]+$/); + } + }); + }); +}); diff --git a/src/__tests__/integration/eth_getTransactionByHash.test.ts b/src/__tests__/integration/eth_getTransactionByHash.test.ts new file mode 100644 index 00000000..6d43a259 --- /dev/null +++ b/src/__tests__/integration/eth_getTransactionByHash.test.ts @@ -0,0 +1,60 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getTransactionByHash', () => { + it('should return the transaction details by transaction hash', async () => { + // Step 1: Get the latest block to retrieve its transactions + const latestBlockResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByNumber", + params: [ + "latest", // Block number in hexadecimal + false + ], + id: 1, + jsonrpc: "2.0" + }); + + expect(latestBlockResponse.status).toBe(200); + expect(latestBlockResponse.body.result).toBeDefined(); + const latestBlock = latestBlockResponse.body.result; + const transactions = latestBlock.transactions; + + // Ensure there are transactions in the latest block + if (transactions.length > 0) { + const transactionHash = transactions[0]; // Get the hash of the first transaction + + // Step 2: Get transaction details by transaction hash + const transactionByHashResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getTransactionByHash", + params: [transactionHash], + id: 2, + jsonrpc: "2.0" + }); + + expect(transactionByHashResponse.status).toBe(200); + expect(transactionByHashResponse.body.result).toBeDefined(); + const transaction = transactionByHashResponse.body.result; + + // Check that the transaction hash matches + expect(transaction.hash).toBe(transactionHash); + + // Additional checks for transaction properties + expect(transaction).toHaveProperty('blockHash', latestBlock.hash); + expect(transaction).toHaveProperty('blockNumber', latestBlock.number); + expect(transaction).toHaveProperty('from'); + expect(transaction.from).toMatch(/^0x[0-9a-fA-F]{40}$/); + expect(transaction).toHaveProperty('to'); + if (transaction.to) { + expect(transaction.to).toMatch(/^0x[0-9a-fA-F]{40}$/); + } + expect(transaction).toHaveProperty('value'); + expect(transaction.value).toMatch(/^0x[0-9a-fA-F]+$/); + } + }); + }); +}); diff --git a/src/__tests__/integration/eth_getTransactionCount.test.ts b/src/__tests__/integration/eth_getTransactionCount.test.ts new file mode 100644 index 00000000..aff749df --- /dev/null +++ b/src/__tests__/integration/eth_getTransactionCount.test.ts @@ -0,0 +1,163 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('POST / eth_getTransactionCount', () => { + it('should return the transaction count for a given address at the latest block', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getTransactionCount', + params: ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest'], + id: 1, + }); + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('result'); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return zero if the address has no transactions', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getTransactionCount', + params: ['0x5f752C078d8fE70d77C644F05f3e29d9F073776c', 'latest'], + id: 2, + }); + expect(response.status).toBe(200); + expect(response.body.result).toBe('0x0'); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + method: 'eth_getTransactionCount', + params: ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest'], + id: 3, + }); + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getTransactionCount', + params: ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest'] + }); + expect(response.status).toBe(204); + }); + + it('should return an error if method property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 4, + params: ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest'] + }); + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return an error if params property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 5, + method: 'eth_getTransactionCount' + }); + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(5); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32602); + expect(response.body.error.message).toBe('Invalid params: non-array args'); + }); + + it('should return an error if jsonrpc version is invalid', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: 'invalid_version', + id: 6, + method: 'eth_getTransactionCount', + params: ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest'] + }); + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return a correct response if id property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 'one', // id should be a number + method: 'eth_getTransactionCount', + params: ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest'] + }); + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe('one'); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if method property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 7, + method: 123, // method should be a string + params: ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest'] + }); + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return an error if params property is of invalid type', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 8, + method: 'eth_getTransactionCount', + params: 'invalid_params' // params should be an array + }); + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_getTransactionReceipt.test.ts b/src/__tests__/integration/eth_getTransactionReceipt.test.ts new file mode 100644 index 00000000..a74135d4 --- /dev/null +++ b/src/__tests__/integration/eth_getTransactionReceipt.test.ts @@ -0,0 +1,123 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; +const { Transaction } = require('ethereumjs-tx'); + +// Helper function to make JSON-RPC calls +async function jsonRpcRequest(method: any, params: any) { + try { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: method, + params: params + }); + return response.body; + } catch (error) { + console.error(`Error in JSON-RPC request: ${error}`); + throw error; + } +} + +describe('JSON-RPC Methods - eth_getTransactionReceipt', () => { + describe('eth_getTransactionReceipt', () => { + it('should perform a transaction return the transaction receipt', async () => { + // Step 1: Get the nonce + const nonceResult = await jsonRpcRequest('eth_getTransactionCount', ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest']); + const nonce = nonceResult.result; + console.log(`Nonce: ${nonce}`); + + // Step 2: Create the transaction object + const txParams = { + nonce: nonce, + gasPrice: '0x09184e72a000', // 20 Gwei + gasLimit: '0x5208', // 21000 + to: '0xC5223533feB845fD28717A7813a72af4df5F2751', + value: '0x2386f26fc10000', // 0.01 Ether in hex + data: '0x', // Empty data field + chainId: 8082, + }; + + // Step 3: Create a new transaction and sign it + const tx = new Transaction(txParams); + const senderPrivateKey = Buffer.from('226dfdb1f49f8d4dcc6b8bdc533d3ea0fbb56f37cd7e9e1ddc986ae77b36abc0', 'hex'); + tx.sign(senderPrivateKey); + + // Step 4: Serialize the transaction + const serializedTx = tx.serialize(); + const rawTx = '0x' + serializedTx.toString('hex'); + console.log(`Raw Transaction: ${rawTx}`); + + // Step 5: Send the signed transaction + const sendResponse = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_sendRawTransaction', + params: [rawTx] + }); + + expect(sendResponse.status).toBe(200); + expect(sendResponse.body).toHaveProperty('result'); + const transactionHash = sendResponse.body.result; + console.log('Transaction hash:', transactionHash); + + // Step 6: Get the transaction receipt + const receiptResponse = await jsonRpcRequest('eth_getTransactionReceipt', [transactionHash]); + expect(receiptResponse).toHaveProperty('result'); + const receipt = receiptResponse.result; + expect(receipt).toBeDefined(); + + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 2, + method: 'eth_sendTransaction', + params: [ + { + from: '0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', + to: '0xC5223533feB845fD28717A7813a72af4df5F2751', + gas: '0x5208', + gasPrice: '0x09184e72a000', + value: '0x2386f26fc10000', + data: '0x' + } + ] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_sendTransaction', + params: [ + { + from: '0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', + to: '0xC5223533feB845fD28717A7813a72af4df5F2751', + gas: '0x5208', + gasPrice: '0x09184e72a000', + value: '0x2386f26fc10000', + data: '0x' + } + ] + }); + + expect(response.status).toBe(204); + }); + }); +}); diff --git a/src/__tests__/integration/eth_getUncleByBlockHashAndIndex.test.ts b/src/__tests__/integration/eth_getUncleByBlockHashAndIndex.test.ts new file mode 100644 index 00000000..c1b57532 --- /dev/null +++ b/src/__tests__/integration/eth_getUncleByBlockHashAndIndex.test.ts @@ -0,0 +1,57 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getUncleByBlockHashAndIndex', () => { + it('should return the uncle block details by block hash and uncle index', async () => { + // Step 1: Get the latest block to retrieve its hash + const latestBlockResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByNumber", + params: [ + "latest", // Block number in hexadecimal + false + ], + id: 1, + jsonrpc: "2.0" + }); + + expect(latestBlockResponse.status).toBe(200); + expect(latestBlockResponse.body.result).toBeDefined(); + const latestBlock = latestBlockResponse.body.result; + const latestBlockHash = latestBlock.hash; + + expect(latestBlockHash).toMatch(/^0x[0-9a-fA-F]+$/); + + // Step 2: Check if the block has uncles + if (latestBlock.uncles.length > 0) { + const uncleIndex = 0; // Index of the first uncle + + // Step 3: Get uncle details by block hash and uncle index + const uncleByHashAndIndexResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getUncleByBlockHashAndIndex", + params: [ + latestBlockHash, // Block hash in hexadecimal + `0x${uncleIndex.toString(16)}` // Uncle index in hexadecimal + ], + id: 3, + jsonrpc: "2.0" + }); + + expect(uncleByHashAndIndexResponse.status).toBe(200); + expect(uncleByHashAndIndexResponse.body.result).toBeDefined(); + const uncle = uncleByHashAndIndexResponse.body.result; + + // Additional checks for uncle properties + expect(uncle).toHaveProperty('number'); + expect(uncle.number).toMatch(/^0x[0-9a-fA-F]+$/); + expect(uncle).toHaveProperty('hash'); + expect(uncle.hash).toMatch(/^0x[0-9a-fA-F]+$/); + expect(uncle).toHaveProperty('parentHash', latestBlockHash); + } + }); + }); +}); diff --git a/src/__tests__/integration/eth_getUncleByBlockNumberAndIndex.test.ts b/src/__tests__/integration/eth_getUncleByBlockNumberAndIndex.test.ts new file mode 100644 index 00000000..2da355a1 --- /dev/null +++ b/src/__tests__/integration/eth_getUncleByBlockNumberAndIndex.test.ts @@ -0,0 +1,57 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_getUncleByBlockNumberAndIndex', () => { + it('should return the uncle block details by block number and uncle index', async () => { + // Step 1: Get the latest block to retrieve its number + const latestBlockResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getBlockByNumber", + params: [ + "latest", // Block number in hexadecimal + false + ], + id: 1, + jsonrpc: "2.0" + }); + + expect(latestBlockResponse.status).toBe(200); + expect(latestBlockResponse.body.result).toBeDefined(); + const latestBlock = latestBlockResponse.body.result; + const blockNumber = latestBlock.number; + + expect(blockNumber).toMatch(/^0x[0-9a-fA-F]+$/); + + // Step 2: Check if the block has uncles + if (latestBlock.uncles.length > 0) { + const uncleIndex = 0; // Index of the first uncle + + // Step 3: Get uncle details by block number and uncle index + const uncleByNumberAndIndexResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_getUncleByBlockNumberAndIndex", + params: [ + blockNumber, // Block number in hexadecimal + `0x${uncleIndex.toString(16)}` // Uncle index in hexadecimal + ], + id: 4, + jsonrpc: "2.0" + }); + + expect(uncleByNumberAndIndexResponse.status).toBe(200); + expect(uncleByNumberAndIndexResponse.body.result).toBeDefined(); + const uncle = uncleByNumberAndIndexResponse.body.result; + + // Additional checks for uncle properties + expect(uncle).toHaveProperty('number'); + expect(uncle.number).toMatch(/^0x[0-9a-fA-F]+$/); + expect(uncle).toHaveProperty('hash'); + expect(uncle.hash).toMatch(/^0x[0-9a-fA-F]+$/); + expect(uncle).toHaveProperty('parentHash', latestBlock.hash); + } + }); + }); +}); diff --git a/src/__tests__/integration/eth_getUncleCountByBlockHash.test.ts b/src/__tests__/integration/eth_getUncleCountByBlockHash.test.ts new file mode 100644 index 00000000..a1c3fec5 --- /dev/null +++ b/src/__tests__/integration/eth_getUncleCountByBlockHash.test.ts @@ -0,0 +1,67 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_getUncleCountByBlockHash', () => { + let blockHash: any; + + // Fetch a block hash before running the tests + beforeAll(async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_getBlockByNumber', + params: ['latest', false] + }); + + blockHash = response.body.result.hash; + }); + + it('should return the number of uncles for a valid block hash', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_getUncleCountByBlockHash', + params: [blockHash] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(1); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 1, + method: 'eth_getUncleCountByBlockHash', + params: [blockHash] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getUncleCountByBlockHash', + params: [blockHash] + }); + + expect(response.status).toBe(204); + }); +}); diff --git a/src/__tests__/integration/eth_getUncleCountByBlockNumber.test.ts b/src/__tests__/integration/eth_getUncleCountByBlockNumber.test.ts new file mode 100644 index 00000000..75efcd57 --- /dev/null +++ b/src/__tests__/integration/eth_getUncleCountByBlockNumber.test.ts @@ -0,0 +1,68 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_getUncleCountByBlockNumber', () => { + let blockNumber: any; + + // Fetch the latest block number before running the tests + beforeAll(async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_blockNumber', + params: [] + }); + + blockNumber = response.body.result; + }); + + it('should return the number of uncles for a valid block number', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_getUncleCountByBlockNumber', + params: [blockNumber] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(1); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 1, + method: 'eth_getUncleCountByBlockNumber', + params: [blockNumber] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_getUncleCountByBlockNumber', + params: [blockNumber] + }); + + expect(response.status).toBe(204); + }); + +}); diff --git a/src/__tests__/integration/eth_newBlockFilter.test.ts b/src/__tests__/integration/eth_newBlockFilter.test.ts new file mode 100644 index 00000000..46c197f8 --- /dev/null +++ b/src/__tests__/integration/eth_newBlockFilter.test.ts @@ -0,0 +1,22 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_newBlockFilter', () => { + it('should create a new block filter and return a filter ID', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_newBlockFilter", + // No specific parameters, using default behavior + params: [], + id: 1, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); // Check if it is a valid filter ID + }); + }); +}); diff --git a/src/__tests__/integration/eth_newFilter.test.ts b/src/__tests__/integration/eth_newFilter.test.ts new file mode 100644 index 00000000..867b5581 --- /dev/null +++ b/src/__tests__/integration/eth_newFilter.test.ts @@ -0,0 +1,21 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_newFilter', () => { + it('should create a new filter and return a filter ID', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_newFilter", + params: [{}], // No specific parameters, using default behavior + id: 1, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); // Check if it is a valid filter ID + }); + }); +}); diff --git a/src/__tests__/integration/eth_newPendingTransactionFilter.test.ts b/src/__tests__/integration/eth_newPendingTransactionFilter.test.ts new file mode 100644 index 00000000..ddcdcff3 --- /dev/null +++ b/src/__tests__/integration/eth_newPendingTransactionFilter.test.ts @@ -0,0 +1,22 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_newPendingTransactionFilter', () => { + it('should create a new pending transaction filter and return a filter ID', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_newPendingTransactionFilter", + // No specific parameters, using default behavior + params: [], + id: 1, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); // Check if it is a valid filter ID + }); + }); +}); diff --git a/src/__tests__/integration/eth_sendRawTransaction.test.ts b/src/__tests__/integration/eth_sendRawTransaction.test.ts new file mode 100644 index 00000000..08046147 --- /dev/null +++ b/src/__tests__/integration/eth_sendRawTransaction.test.ts @@ -0,0 +1,66 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; +const { Transaction } = require('ethereumjs-tx'); + +// Helper function to make JSON-RPC calls +async function jsonRpcRequest(method: any, params: any) { + try { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: method, + params: params + }); + return response.body; + } catch (error) { + console.error(`Error in JSON-RPC request: ${error}`); + throw error; + } +} + +describe('JSON-RPC Methods - eth_sendRawTransaction', () => { + describe('eth_sendRawTransaction', () => { + it('should send a raw transaction and return the transaction hash', async () => { + // Step 1: Get the nonce + const nonceResult = await jsonRpcRequest('eth_getTransactionCount', ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest']); + const nonce = nonceResult.result; + + // Step 2: Create the transaction object + const txParams = { + nonce: nonce, + gasPrice: '0x09184e72a000', // 20 Gwei + gasLimit: '0x5208', // 21000 + to: '0xC5223533feB845fD28717A7813a72af4df5F2751', + value: '0x2386f26fc10000', // 0.01 Ether in hex + data: '0x', // Empty data field + chainId: 8082, + }; + + // Step 3: Create a new transaction and sign it + const tx = new Transaction(txParams); + const senderPrivateKey = Buffer.from('226dfdb1f49f8d4dcc6b8bdc533d3ea0fbb56f37cd7e9e1ddc986ae77b36abc0', 'hex'); + tx.sign(senderPrivateKey); + + // Step 4: Serialize the transaction + const serializedTx = tx.serialize(); + const rawTx = '0x' + serializedTx.toString('hex'); + console.log(`Raw Transaction: ${rawTx}`); + + // Step 5: Send the signed transaction + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_sendRawTransaction', + params: [rawTx] + }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('result'); + }); + }); + +}); diff --git a/src/__tests__/integration/eth_sendTransaction.test.ts b/src/__tests__/integration/eth_sendTransaction.test.ts new file mode 100644 index 00000000..02a29933 --- /dev/null +++ b/src/__tests__/integration/eth_sendTransaction.test.ts @@ -0,0 +1,120 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; +const { Transaction } = require('ethereumjs-tx'); + +// Helper function to make JSON-RPC calls +async function jsonRpcRequest(method: any, params: any) { + try { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: method, + params: params + }); + return response.body; + } catch (error) { + console.error(`Error in JSON-RPC request: ${error}`); + throw error; + } +} + +describe('JSON-RPC Methods - eth_sendTransaction', () => { + describe('eth_sendTransaction', () => { + it('should send a transaction and return the transaction hash', async () => { + // Step 1: Get the nonce + const nonceResult = await jsonRpcRequest('eth_getTransactionCount', ['0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', 'latest']); + const nonce = nonceResult.result; + + // Step 2: Create the transaction object + const now = Math.floor(Date.now() / 1000); + const txParams = { + nonce: nonce, + gasPrice: '0x09184e72a000', // 20 Gwei + gasLimit: '0x5208', // 21000 + to: '0xC5223533feB845fD28717A7813a72af4df5F2751', + value: '0x2386f26fc10000', // 0.01 Ether in hex + data: '0x', // Empty data field + chainId: 8082, + timestamp: now + }; + + // Step 3: Create a new transaction and sign it + const tx = new Transaction(txParams); + const senderPrivateKey = Buffer.from('226dfdb1f49f8d4dcc6b8bdc533d3ea0fbb56f37cd7e9e1ddc986ae77b36abc0', 'hex'); + tx.sign(senderPrivateKey); + + // Step 4: Serialize the transaction + const serializedTx = tx.serialize(); + const rawTx = '0x' + serializedTx.toString('hex'); + + // Step 5: Send the signed transaction + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + id: 1, + method: 'eth_sendRawTransaction', + params: [rawTx] + }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('result'); + + // Step 6: Verify the balance of the receiving account + const balanceResponse = await jsonRpcRequest('eth_getBalance', ['0xC5223533feB845fD28717A7813a72af4df5F2751', 'latest']); + const balance = balanceResponse.result; + expect(parseInt(balance, 16)).toBeGreaterThanOrEqual(parseInt('0x2386f26fc10000', 16)); + }); + + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 2, + method: 'eth_sendTransaction', + params: [ + { + from: '0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', + to: '0xC5223533feB845fD28717A7813a72af4df5F2751', + gas: '0x5208', + gasPrice: '0x09184e72a000', + value: '0x2386f26fc10000', + data: '0x' + } + ] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_sendTransaction', + params: [ + { + from: '0x1923A1Eb8e4dA49604aFfd34De1B478580cf8698', + to: '0xC5223533feB845fD28717A7813a72af4df5F2751', + gas: '0x5208', + gasPrice: '0x09184e72a000', + value: '0x2386f26fc10000', + data: '0x' + } + ] + }); + + expect(response.status).toBe(204); + }); + }); + +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_signTransaction.test.ts b/src/__tests__/integration/eth_signTransaction.test.ts new file mode 100644 index 00000000..aa10fcc8 --- /dev/null +++ b/src/__tests__/integration/eth_signTransaction.test.ts @@ -0,0 +1,74 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods - eth_signTransaction', () => { + it('should sign a transaction and return the signed data', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_signTransaction', + params: [ + { + from: '0xa4c0aadcce9c04fe8b833279b0198d4ae29d76a7', + to: '0x510e84aa16ab92752451a2763352681624c75ebe', + gas: '0x76c0', + gasPrice: '0x9184e72a000', + value: '0x9184e72a', + data: '0x0', + }, + ], + id: 1, + }); + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('result'); + expect(response.body.result).toMatch(/^0x[0-9a-fA-F]+$/); + }); + it('should return no response if id property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + jsonrpc: '2.0', + method: 'eth_signTransaction', + params: [ + { + from: '0xa4c0aadcce9c04fe8b833279b0198d4ae29d76a7', + to: '0x510e84aa16ab92752451a2763352681624c75ebe', + gas: '0x76c0', + gasPrice: '0x9184e72a000', + value: '0x9184e72a', + data: '0x0', + }, + ] + }); + + expect(response.status).toBe(204); + }); + it('should return an error if jsonrpc property is missing', async () => { + const response = await request(extendedServer) + .post('/') + .send({ + id: 2, + method: 'eth_signTransaction', + params: [ + { + from: '0xa4c0aadcce9c04fe8b833279b0198d4ae29d76a7', + to: '0x510e84aa16ab92752451a2763352681624c75ebe', + gas: '0x76c0', + gasPrice: '0x9184e72a000', + value: '0x9184e72a', + data: '0x0', + }, + ] + }); + + expect(response.status).toBe(200); + expect(response.body).toBeDefined(); + expect(response.body.jsonrpc).toBe('2.0'); + expect(response.body.id).toBe(null); + expect(response.body.error).toBeDefined(); + expect(response.body.error.code).toBe(-32600); + expect(response.body.error.message).toBe('Invalid request'); + }); + +}); \ No newline at end of file diff --git a/src/__tests__/integration/eth_uninstallFilter.test.ts b/src/__tests__/integration/eth_uninstallFilter.test.ts new file mode 100644 index 00000000..28810a62 --- /dev/null +++ b/src/__tests__/integration/eth_uninstallFilter.test.ts @@ -0,0 +1,34 @@ +import request from 'supertest'; +import { extendedServer } from '../../server'; + +describe('JSON-RPC Methods', () => { + describe('eth_uninstallFilter', () => { + it('should uninstall a filter by filter ID', async () => { + // First, create a new filter to get a filter ID + const newFilterResponse = await request(extendedServer) + .post('/') + .send({ + method: "eth_newFilter", + params: [{}], // No specific parameters, using default behavior + id: 1, + jsonrpc: "2.0" + }); + + const filterId = newFilterResponse.body.result; + + // Now uninstall the filter using the filter ID + const response = await request(extendedServer) + .post('/') + .send({ + method: "eth_uninstallFilter", + params: [filterId], + id: 2, + jsonrpc: "2.0" + }); + + expect(response.status).toBe(200); + expect(response.body.result).toBeDefined(); + expect(response.body.result).toBe(true); // Should return true if filter was successfully uninstalled + }); + }); +}); diff --git a/src/api.ts b/src/api.ts index 4e12c042..41a719cf 100755 --- a/src/api.ts +++ b/src/api.ts @@ -3822,4 +3822,4 @@ export const methods = { // subscription failed, will not be tracking it } }, -} +} \ No newline at end of file diff --git a/src/external/ServiceValidator.ts b/src/external/ServiceValidator.ts index b2e2c233..6fe9d766 100644 --- a/src/external/ServiceValidator.ts +++ b/src/external/ServiceValidator.ts @@ -42,6 +42,7 @@ class ServiceValidator extends BaseExternal { } } + async getAccount(address: string, blockNumberHex?: string): Promise { if (!CONFIG.serviceValidatorSourcing.enabled) return null if (verbose) console.log(`ServiceValidator: getAccount call for address: ${address}`) @@ -233,4 +234,4 @@ class ServiceValidator extends BaseExternal { } } -export const serviceValidator = new ServiceValidator(CONFIG.serviceValidatorSourcing.serviceValidatorUrl) +export const serviceValidator = new ServiceValidator(CONFIG.serviceValidatorSourcing.serviceValidatorUrl) \ No newline at end of file diff --git a/src/logger.ts b/src/logger.ts index ce5c264b..33e5ebce 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -40,28 +40,27 @@ export const debug_info = { export async function saveInterfaceStat(): Promise { console.log(apiPerfLogData) - try { + // eslint-disable-next-line prefer-const + let { api_name, tfinal, timestamp, nodeUrl, success, reason, hash } = apiPerfLogData[0] + // nodeUrl = nodeUrl ? nodeUrl : new URL(nodeUrl as string).hostname + let placeholders = `NULL, '${api_name}', '${tfinal}','${timestamp}', '${nodeUrl}', '${success}', '${reason}', '${hash}'` + let sql = 'INSERT INTO interface_stats VALUES (' + placeholders + ')' + for (let i = 1; i < apiPerfLogData.length; i++) { // eslint-disable-next-line prefer-const - let { api_name, tfinal, timestamp, nodeUrl, success, reason, hash } = apiPerfLogData[0] + let { api_name, tfinal, timestamp, nodeUrl, success, reason, hash } = apiPerfLogData[i] // eslint-disable-line security/detect-object-injection + // nodeUrl = nodeUrl ? nodeUrl : new URL(nodeUrl as string).hostname - let placeholders = `NULL, '${api_name}', '${tfinal}','${timestamp}', '${nodeUrl}', '${success}', '${reason}', '${hash}'` - let sql = 'INSERT INTO interface_stats VALUES (' + placeholders + ')' - for (let i = 1; i < apiPerfLogData.length; i++) { - // eslint-disable-next-line prefer-const - let { api_name, tfinal, timestamp, nodeUrl, success, reason, hash } = apiPerfLogData[i] // eslint-disable-line security/detect-object-injection + placeholders = `NULL, '${api_name}', '${tfinal}','${timestamp}', '${nodeUrl}', '${success}', '${reason}', '${hash}'` + sql = sql + `, (${placeholders})` + } - // nodeUrl = nodeUrl ? nodeUrl : new URL(nodeUrl as string).hostname - placeholders = `NULL, '${api_name}', '${tfinal}','${timestamp}', '${nodeUrl}', '${success}', '${reason}', '${hash}'` - sql = sql + `, (${placeholders})` - } + apiPerfLogData = [] + try { await db.exec(sql) } catch (e) { console.log(e) } - - apiPerfLogData = [] - apiPerfLogTicket = {} } export function setupLogEvents(): void { diff --git a/src/server.ts b/src/server.ts index 9cdad9a7..6794c082 100644 --- a/src/server.ts +++ b/src/server.ts @@ -199,6 +199,22 @@ app.use(injectIP) app.use(rejectSubscription) app.use(server.middleware()) +export const startServer = () => { + if (process.env.NODE_ENV !== 'test') { + extendedServer.listen(port, function () { + console.log(`JSON RPC Server listening on port ${port} and chainId is ${chainId}.`) + setupDatabase() + setupLogEvents() + setupSubscriptionEventHandlers() + setupEvmLogProviderConnectionStream() + }) + } +} + +export const stopServer = (callback?: () => void) => { + extendedServer.close(callback) +} + setupArchiverDiscovery({ customConfigPath: 'archiverConfig.json', }).then(() => { @@ -214,12 +230,8 @@ setupArchiverDiscovery({ setInterval(checkArchiverHealth, 60000) setInterval(cleanBadNodes, 60000) setInterval(updateEdgeNodeConfig, 60000 * 5) - extendedServer.listen(port, function () { - console.log(`JSON RPC Server listening on port ${port} and chainId is ${chainId}.`) - setupDatabase() - setupLogEvents() - setupSubscriptionEventHandlers() - setupEvmLogProviderConnectionStream() - }) + startServer() }) }) + +export { extendedServer, app, server }