diff --git a/.dockerignore b/.dockerignore index 20b25939ec..3b54c5b8c4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,2 @@ -**/dist/ \ No newline at end of file +**/dist/ +**.env diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8ce206c849..54b4193537 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -17,4 +17,3 @@ - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. -- [ ] Code has been formatted via `zk fmt` and `zk lint`. diff --git a/.github/workflows/app-deploy-feature-branch.yml b/.github/workflows/app-deploy-feature-branch.yml index 5b862b4edd..e7bc4fca09 100644 --- a/.github/workflows/app-deploy-feature-branch.yml +++ b/.github/workflows/app-deploy-feature-branch.yml @@ -66,13 +66,14 @@ jobs: mainnet: needs: build - name: Feature Env, Mainnet+ + name: Feature on Mainnet + Sepolia uses: ./.github/workflows/app-e2e.yml secrets: inherit permissions: - contents: read + contents: write with: targetUrl: ${{ needs.build.outputs.dappUrl }} + testnet_network_value_for_e2e: "/?network=sepolia" default_network_value_for_e2e: "/?network=mainnet" publish_to_allure: true - environmentTags: "and not @stagingEnv" + environmentTags: "and not @productionEnv" diff --git a/.github/workflows/app-deploy-preview.yml b/.github/workflows/app-deploy-preview.yml index de279372f8..b2208e0662 100644 --- a/.github/workflows/app-deploy-preview.yml +++ b/.github/workflows/app-deploy-preview.yml @@ -63,14 +63,14 @@ jobs: mainnet: needs: deploy - name: Staging Env, Mainnet+ + name: Staging on Mainnet + Sepolia uses: ./.github/workflows/app-e2e.yml secrets: inherit permissions: - contents: read + contents: write with: targetUrl: ${{ needs.deploy.outputs.dappUrl }} + testnet_network_value_for_e2e: "/?network=sepolia" default_network_value_for_e2e: "/?network=mainnet" publish_to_allure: true environmentTags: "and not @featureEnv" - \ No newline at end of file diff --git a/.github/workflows/app-e2e.yml b/.github/workflows/app-e2e.yml index 5ca7ad825d..0803e7976d 100644 --- a/.github/workflows/app-e2e.yml +++ b/.github/workflows/app-e2e.yml @@ -19,6 +19,10 @@ on: type: string default: '/?network=mainnet' required: true + testnet_network_value_for_e2e: + type: string + default: '/?network=sepolia' + required: true publish_to_allure: #Here we define the variable that can be overwritten by caller workflow type: boolean description: "Publish test results to allure" @@ -58,7 +62,7 @@ jobs: name: '${{ matrix.tags }}' container: image: mcr.microsoft.com/playwright:v1.27.0-focal - options: --user root + options: --user 1001 steps: - uses: actions/checkout@v3 with: @@ -69,7 +73,7 @@ jobs: with: node-version: '18' cache: 'npm' - + - name: Cache node modules id: cache-nodemodules uses: actions/cache@v3 @@ -104,33 +108,27 @@ jobs: echo "Run tests" if [ "${{ matrix.tags }}" = "@testnetSmokeSuite" ]; then echo "Run in testnetSmokeSuite only" - E2ENETWORK='/?network=goerli' npx cucumber-js --tags "${{ matrix.tags }} ${{ inputs.environmentTags }} and not @mainnet" + E2ENETWORK='${{ inputs.testnet_network_value_for_e2e }}' npx cucumber-js --tags "${{ matrix.tags }} ${{ inputs.environmentTags }} and not @mainnet" else echo "Run in mainnet" E2ENETWORK='${{ inputs.default_network_value_for_e2e }}' npx cucumber-js --tags "${{ matrix.tags }} ${{ inputs.environmentTags }} and not @testnet" fi - - name: Reset tags quotes + - name: Save artifacts to Git if: always() - run: | - echo "MATRIX_TAG_WITHOUT_QUOTES=$(echo ${{ matrix.tags }} | sed -e 's/@//g' )" >> $GITHUB_ENV + uses: actions/upload-artifact@v3 + with: + name: allure-results + path: packages/app/allure-results - - name: Create launch ID + - name: Upload test results to Allure reporter if: always() env: - ALLURE_LAUNCH_NAME: "#${{ github.run_number }} ${{ env.MATRIX_TAG_WITHOUT_QUOTES }}" - ALLURE_LAUNCH_TAGS: "${{ env.ALLURE_BASIC_TAGS }}, ${{ env.MATRIX_TAG_WITHOUT_QUOTES }}" ALLURE_TOKEN: ${{ secrets.ALLURE_TOKEN }} run: | - echo "ALLURE_LAUNCH_ID=$(./allurectl launch create --launch-name '${{ env.ALLURE_LAUNCH_NAME }}' --no-header --format ID | tail -n1)" >> $GITHUB_ENV - - - name: Upload tests to the Allure proj - if: always() && inputs.publish_to_allure == true - env: - ALLURE_TOKEN: ${{ secrets.ALLURE_TOKEN }} - run: | - ./allurectl upload allure-results --launch-id ${{ env.ALLURE_LAUNCH_ID }} - ./allurectl launch close ${{ env.ALLURE_LAUNCH_ID }} + ./allurectl upload allure-results + echo "*Public report link: https://raw.githack.com/matter-labs/block-explorer/gh-pages/${{ github.run_number }}/index.html" + echo "*Public report link will be available when the 'Allure Report' job will be succesfully executed." - if: failure() name: Save artifacts @@ -140,18 +138,53 @@ jobs: path: packages/app/tests/e2e/artifacts/* publish: - name: Publish Allure link to GIT + name: Allure Report runs-on: ubuntu-latest permissions: - contents: read + contents: write needs: e2e if: always() steps: + - uses: actions/checkout@v3 + + - uses: actions/download-artifact@v2 + with: + name: allure-results + path: packages/app/allure-results + + - name: Get Allure history + uses: actions/checkout@v3 + if: always() + continue-on-error: true + with: + ref: gh-pages + path: gh-pages + + - name: Allure Report action from marketplace + uses: simple-elf/allure-report-action@v1.7 + if: always() + id: allure-report + with: + allure_results: packages/app/allure-results + gh_pages: gh-pages + allure_report: allure-report + allure_history: allure-history + keep_reports: 10 + + - name: Deploy report to Github Pages + if: always() + uses: peaceiris/actions-gh-pages@v2 + env: + PERSONAL_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PUBLISH_BRANCH: gh-pages + PUBLISH_DIR: allure-history + - name: Prepare a link run: | echo "BASE64_SEARCH_REQUEST=$(echo '${{ env.ALLURE_SEARCH_REQUEST }}' | base64)" >> $GITHUB_ENV - name: Publish Allure link to GIT Summary run: | - LINK="${{ vars.ALLURE_ENDPOINT }}project/${{ vars.ALLURE_PROJECT_ID }}/launches?search=${{ env.BASE64_SEARCH_REQUEST }}" - echo "Allure [e2e tests]($LINK) :rocket: in git run #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY + LINK1="${{ vars.ALLURE_ENDPOINT }}project/${{ vars.ALLURE_PROJECT_ID }}/launches?search=${{ env.BASE64_SEARCH_REQUEST }}" + LINK2="https://raw.githack.com/matter-labs/block-explorer/gh-pages/${{ github.run_number }}/index.html" + echo "Allure [Private]($LINK1) and [Public]($LINK2) links:rocket: in git run #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/integration-tests-api.yml b/.github/workflows/integration-tests-api.yml new file mode 100644 index 0000000000..f191349d4c --- /dev/null +++ b/.github/workflows/integration-tests-api.yml @@ -0,0 +1,61 @@ +name: Integration test - API +on: pull_request + +jobs: + runTests: + timeout-minutes: 30 + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + checks: write + strategy: + matrix: + node-version: ['lts/*'] # 18.17.1 or lts/* + test-pattern: + - accounts.test.ts + - addresses.test.ts + - batches.test.ts + - blocks.test.ts + - contracts.test.ts + - logs.test.ts + - stats.test.ts + - tokens.test.ts + - transactions.test.ts + name: 'API test set: ${{ matrix.test-pattern}} / Node: ${{ matrix.node-version}}' + steps: + - name: Checkout with Submodule + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: npm + + - name: Install dependencies + run: | + npm ci --no-audit + npx playwright install --with-deps chromium + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USER }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Start docker containers + run: | + docker-compose -f "docker-compose.yaml" up -d --build + - name: List running containers + run: docker ps + + - name: API tests run (parallel) + run: | + cd packages/integration-tests + npx jest --verbose --testPathPattern=${{ matrix.test-pattern }} + - name: Stop containers + if: always() + run: | + docker-compose -f "docker-compose.yaml" down diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c9060f634..8415c96558 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -111,6 +111,34 @@ jobs: file: packages/worker/Dockerfile no-cache: true + - name: Build and push Docker image for Data Fetcher + uses: docker/build-push-action@v4 + with: + push: true + tags: | + "matterlabs/block-explorer-data-fetcher:latest" + "matterlabs/block-explorer-data-fetcher:v${{ needs.createReleaseVersion.outputs.releaseVersion }}" + "matterlabs/block-explorer-data-fetcher:${{ steps.setVersionForFlux.outputs.imageTag }}" + "us-docker.pkg.dev/matterlabs-infra/matterlabs-docker/block-explorer-data-fetcher:latest" + "us-docker.pkg.dev/matterlabs-infra/matterlabs-docker/block-explorer-data-fetcher:v${{ needs.createReleaseVersion.outputs.releaseVersion }}" + "us-docker.pkg.dev/matterlabs-infra/matterlabs-docker/block-explorer-data-fetcher:${{ steps.setVersionForFlux.outputs.imageTag }}" + file: packages/data-fetcher/Dockerfile + no-cache: true + + - name: Build and push Docker image for App + uses: docker/build-push-action@v4 + with: + push: true + tags: | + "matterlabs/block-explorer-app:latest" + "matterlabs/block-explorer-app:v${{ needs.createReleaseVersion.outputs.releaseVersion }}" + "matterlabs/block-explorer-app:${{ steps.setVersionForFlux.outputs.imageTag }}" + "us-docker.pkg.dev/matterlabs-infra/matterlabs-docker/block-explorer-app:latest" + "us-docker.pkg.dev/matterlabs-infra/matterlabs-docker/block-explorer-app:v${{ needs.createReleaseVersion.outputs.releaseVersion }}" + "us-docker.pkg.dev/matterlabs-infra/matterlabs-docker/block-explorer-app:${{ steps.setVersionForFlux.outputs.imageTag }}" + file: packages/app/Dockerfile + no-cache: true + deployFrontendToStaging: name: Deploy Block Explorer frontend to staging runs-on: ubuntu-latest diff --git a/.github/workflows/validate-pr.yml b/.github/workflows/validate-pr.yml index 539a8e0679..a837a4a49e 100644 --- a/.github/workflows/validate-pr.yml +++ b/.github/workflows/validate-pr.yml @@ -66,6 +66,7 @@ jobs: packages/app/junit.xml packages/api/junit.xml packages/worker/junit.xml + packages/data-fetcher/junit.xml check_run_annotations: all tests, skipped tests report_individual_runs: "true" check_name: Unit Test Results diff --git a/.gitignore b/.gitignore index 71a95711fa..dd8c346732 100644 --- a/.gitignore +++ b/.gitignore @@ -17,10 +17,17 @@ volumes cypress/videos/ cypress/screenshots/ tests/e2e/reports/ -tests/e2e/artifacts/ +**/tests/e2e/artifacts/ +**/playbook/artifacts-zk/ +**/playbook/artifacts/ +**/playbook/buffer/ +**/playbook/cache-zk/ +**/playbook/cache/ # Logs logs +!/packages/worker/test/logs/ +!/packages/data-fetcher/test/logs/ *.log npm-debug.log* yarn-debug.log* @@ -53,12 +60,7 @@ lerna-debug.log* !.vscode/extensions.json # Allure -#Allure results and artifacts -**/allure-results/ -**/e2e/artifacts/ -**/playbook/artifacts* -**/playbook/cache* -**/buffer/*.txt +**allure-results/ # App hyperchain config hyperchain.config.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..c359855985 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib", + "editor.tabSize": 2 +} diff --git a/README.md b/README.md index b97bf0db76..5fa1535b62 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,9 @@

Online blockchain browser for viewing and analyzing zkSync Era blockchain.

## 📌 Overview -This repository is a monorepo consisting of 3 packages: -- [Worker](./packages/worker) - an indexer service for [zkSync Era](https://zksync.io) blockchain data. The purpose of the service is to read the data from the blockchain in real time, transform it and fill in it's database with the data in a way that makes it easy to be queried by the [API](./packages/api) service. +This repository is a monorepo consisting of 4 packages: +- [Worker](./packages/worker) - an indexer service for [zkSync Era](https://zksync.io) blockchain data. The purpose of the service is to read blockchain data in real time, transform it and fill in it's database with the data in a way that makes it easy to be queried by the [API](./packages/api) service. +- [Data Fetcher](./packages/data-fetcher) - a service that exposes and implements an HTTP endpoint to retrieve aggregated data for a certain block / range of blocks from the blockchain. This endpoint is called by the [Worker](./packages/worker) service. - [API](./packages/api) - a service providing Web API for retrieving structured [zkSync Era](https://zksync.io) blockchain data collected by [Worker](./packages/worker). It connects to the Worker's database to be able to query the collected data. - [App](./packages/app) - a front-end app providing an easy-to-use interface for users to view and inspect transactions, blocks, contracts and more. It makes requests to the [API](./packages/api) to get the data and presents it in a way that's easy to read and understand. @@ -22,10 +23,14 @@ flowchart subgraph explorer[Block explorer] Database[("Block explorer DB
(PostgreSQL)")] Worker(Worker service) + Data-Fetcher(Data Fetcher service) API(API service) App(App) - + + Worker-."Request aggregated data (HTTP)".->Data-Fetcher + Data-Fetcher-."Request data (HTTP)".->Blockchain Worker-.Save processed data.->Database + API-.Query data.->Database App-."Request data (HTTP)".->API App-."Request data (HTTP)".->Blockchain @@ -34,7 +39,7 @@ flowchart Worker-."Request data (HTTP)".->Blockchain ``` -[Worker](./packages/worker) service is responsible for getting data from blockchain using [zkSync Era JSON-RPC API](https://era.zksync.io/docs/api/api.html), processing it and saving into the database. [API](./packages/api) service is connected to the same database where it gets the data from to handle API requests. It performs only read requests to the database. The front-end [App](./packages/app) makes HTTP calls to the Block Explorer [API](./packages/api) to get blockchain data and to the [zkSync Era JSON-RPC API](https://era.zksync.io/docs/api/api.html) for reading contracts, performing transactions etc. +[Worker](./packages/worker) service retrieves aggregated data from the [Data Fetcher](./packages/data-fetcher) via HTTP and also directly from the blockchain using [zkSync Era JSON-RPC API](https://era.zksync.io/docs/api/api.html), processes it and saves into the database. [API](./packages/api) service is connected to the same database where it gets the data from to handle API requests. It performs only read requests to the database. The front-end [App](./packages/app) makes HTTP calls to the Block Explorer [API](./packages/api) to get blockchain data and to the [zkSync Era JSON-RPC API](https://era.zksync.io/docs/api/api.html) for reading contracts, performing transactions etc. ## 🚀 Features @@ -52,20 +57,20 @@ flowchart ## 🛠 Installation ```bash -$ npm install +npm install ``` ## ⚙️ Setting up env variables ### Manually set up env variables -Make sure you have set up all the necessary env variables. Follow [Setting up env variables for Worker](./packages/worker#setting-up-env-variables) and [Setting up env variables for API](./packages/api#setting-up-env-variables) for instructions. For the [App](./packages/app) package you might want to edit environment config, see [Environment configs](./packages/app#environment-configs). +Make sure you have set up all the necessary env variables. Follow setting up env variables instructions for [Worker](./packages/worker#setting-up-env-variables), [Data Fetcher](./packages/data-fetcher#setting-up-env-variables) and [API](./packages/api#setting-up-env-variables). For the [App](./packages/app) package you might want to edit environment config, see [Environment configs](./packages/app#environment-configs). ### Build env variables based on your [zksync-era](https://github.com/matter-labs/zksync-era) local repo setup Make sure you have [zksync-era](https://github.com/matter-labs/zksync-era) repo set up locally. You must have your environment variables files present in the [zksync-era](https://github.com/matter-labs/zksync-era) repo at `/etc/env/*.env` for the build envs script to work. -The following script sets `.env` files for [Worker](./packages/worker) and [API](./packages/api) packages as well as environment configuration file for [App](./packages/app) package based on your local [zksync-era](https://github.com/matter-labs/zksync-era) repo setup. +The following script sets `.env` files for [Worker](./packages/worker), [Data Fetcher](./packages/data-fetcher) and [API](./packages/api) packages as well as environment configuration file for [App](./packages/app) package based on your local [zksync-era](https://github.com/matter-labs/zksync-era) repo setup. ```bash -$ npm run hyperchain:configure +npm run hyperchain:configure ``` You can review and edit generated files if you need to change any settings. @@ -74,18 +79,18 @@ You can review and edit generated files if you need to change any settings. Before running the solution, make sure you have a database server up and running, you have created a database and set up all the required environment variables. To create a database run the following command: ```bash -$ npm run db:create +npm run db:create ``` -To run all the packages (`Worker`, `API` and front-end `App`) in `development` mode run the following command from the root directory. +To run all the packages (`Worker`, `Data Fetcher`, `API` and front-end `App`) in `development` mode run the following command from the root directory. ```bash -$ npm run dev +npm run dev ``` For `production` mode run: ```bash -$ npm run build -$ npm run start +npm run build +npm run start ``` Each component can also be started individually. Follow individual packages `README` for details. @@ -93,7 +98,7 @@ Each component can also be started individually. Follow individual packages `REA ## 🐳 Running in Docker There is a docker compose configuration that allows you to run Block Explorer and all its dependencies in docker. Just run the following command to spin up the whole environment: ``` -docker-compose up +docker compose up ``` It will run local Ethereum node, ZkSync Era, Postgres DB and all Block Explorer services. @@ -102,20 +107,20 @@ To get block-explorer connected to your ZK Stack Hyperchain you need to set up a ## 🔍 Verify Block Explorer is up and running -To verify front-end `App` is running open http://localhost:3010 in your browser. `API` should be available at http://localhost:3020. `Worker` - http://localhost:3001. +To verify front-end `App` is running open http://localhost:3010 in your browser. `API` should be available at http://localhost:3020, `Worker` at http://localhost:3001 and `Data Fetcher` at http://localhost:3040. ## 🕵️‍♂️ Testing Run unit tests for all packages: ```bash -$ npm run test +npm run test ``` Run e2e tests for all packages: ```bash -$ npm run test:e2e +npm run test:e2e ``` Run tests for a specific package: ```bash -$ npm run test -w {package} +npm run test -w {package} ``` For more details on testing please check individual packages `README`. @@ -131,7 +136,9 @@ zkSync Era Block Explorer is distributed under the terms of either at your option. ## 🔗 Production links -- Testnet API: https://block-explorer-api.testnets.zksync.dev +- Testnet Goerli API: https://block-explorer-api.testnets.zksync.dev +- Testnet Sepolia API: https://block-explorer-api.sepolia.zksync.dev - Mainnet API: https://block-explorer-api.mainnet.zksync.io -- Testnet App: https://goerli.explorer.zksync.io +- Testnet Goerli App: https://goerli.explorer.zksync.io +- Testnet Sepolia App: https://sepolia.explorer.zksync.io - Mainnet App: https://explorer.zksync.io diff --git a/docker-compose-cli.yaml b/docker-compose-cli.yaml new file mode 100644 index 0000000000..a8f29e8478 --- /dev/null +++ b/docker-compose-cli.yaml @@ -0,0 +1,75 @@ +services: + app: + platform: linux/amd64 + image: "matterlabs/block-explorer-app:${VERSION}" + ports: + - '3010:3010' + depends_on: + - api + restart: unless-stopped + + worker: + platform: linux/amd64 + image: "matterlabs/block-explorer-worker:${VERSION}" + environment: + - PORT=3001 + - LOG_LEVEL=verbose + - NODE_ENV=development + - DATABASE_HOST=postgres + - DATABASE_USER=postgres + - DATABASE_PASSWORD=postgres + - DATABASE_NAME=block-explorer + - BLOCKCHAIN_RPC_URL=http://host.docker.internal:${RPC_PORT} + - DATA_FETCHER_URL=http://data-fetcher:3040 + - BATCHES_PROCESSING_POLLING_INTERVAL=1000 + restart: unless-stopped + extra_hosts: + - "host.docker.internal:host-gateway" + + data-fetcher: + platform: linux/amd64 + image: "matterlabs/block-explorer-data-fetcher:${VERSION}" + environment: + - PORT=3040 + - LOG_LEVEL=verbose + - NODE_ENV=development + - BLOCKCHAIN_RPC_URL=http://host.docker.internal:${RPC_PORT} + ports: + - '3040:3040' + restart: unless-stopped + extra_hosts: + - "host.docker.internal:host-gateway" + + api: + platform: linux/amd64 + image: "matterlabs/block-explorer-api:${VERSION}" + environment: + - PORT=3020 + - METRICS_PORT=3005 + - LOG_LEVEL=verbose + - NODE_ENV=development + - DATABASE_URL=postgres://postgres:postgres@postgres:5432/block-explorer + ports: + - '3020:3020' + depends_on: + - worker + restart: unless-stopped + + postgres: + image: "postgres:14" + logging: + driver: none + volumes: + - postgres:/var/lib/postgresql/data + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U postgres" ] + interval: 5s + timeout: 5s + retries: 5 + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=block-explorer + +volumes: + postgres: \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 0c32b27bd3..59eeb73f9a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,10 +1,8 @@ -name: block-explorer services: app: build: context: . dockerfile: ./packages/app/Dockerfile - command: npm run --prefix packages/app dev -- --host ports: - '3010:3010' depends_on: @@ -15,26 +13,33 @@ services: build: context: . dockerfile: ./packages/worker/Dockerfile - target: development-stage - command: npm run --prefix packages/worker dev:debug environment: - PORT=3001 - LOG_LEVEL=verbose - - NODE_ENV=development - DATABASE_HOST=postgres - DATABASE_USER=postgres - DATABASE_PASSWORD=postgres - DATABASE_NAME=block-explorer - BLOCKCHAIN_RPC_URL=http://zksync:3050 + - DATA_FETCHER_URL=http://data-fetcher:3040 - BATCHES_PROCESSING_POLLING_INTERVAL=1000 ports: - '3001:3001' - - '9229:9229' - - '9230:9230' - volumes: - - ./packages/worker:/usr/src/app/packages/worker - - /usr/src/app/packages/worker/node_modules - - ./node_modules:/usr/src/worker/node_modules:ro + depends_on: + zksync: + condition: service_healthy + restart: unless-stopped + + data-fetcher: + build: + context: . + dockerfile: ./packages/data-fetcher/Dockerfile + environment: + - PORT=3040 + - LOG_LEVEL=verbose + - BLOCKCHAIN_RPC_URL=http://zksync:3050 + ports: + - '3040:3040' depends_on: zksync: condition: service_healthy @@ -44,23 +49,14 @@ services: build: context: . dockerfile: ./packages/api/Dockerfile - target: development-stage - command: npm run --prefix packages/api dev:debug environment: - PORT=3020 - METRICS_PORT=3005 - LOG_LEVEL=verbose - - NODE_ENV=development - DATABASE_URL=postgres://postgres:postgres@postgres:5432/block-explorer ports: - '3020:3020' - '3005:3005' - - '9231:9229' - - '9232:9230' - volumes: - - ./packages/api:/usr/src/app/packages/api - - /usr/src/app/packages/api/node_modules - - ./node_modules:/usr/src/api/node_modules:ro depends_on: - worker restart: unless-stopped @@ -117,11 +113,11 @@ services: test: "curl -H \"Content-Type: application/json\" -X POST --data '{\"jsonrpc\":\"2.0\",\"method\":\"web3_clientVersion\",\"params\":[],\"id\":67}' 127.0.0.1:3050 || exit 1" interval: 5s timeout: 5s - retries: 120 + retries: 300 restart: unless-stopped volumes: geth: postgres: zksync-config: - zksync-data: \ No newline at end of file + zksync-data: diff --git a/package-lock.json b/package-lock.json index 92a8b1b3b1..be64827c1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -218,9 +218,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", "engines": { "node": ">=6.9.0" } @@ -348,9 +348,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", - "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -562,12 +562,12 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", - "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", + "@babel/traverse": "^7.23.2", "@babel/types": "^7.23.0" }, "engines": { @@ -648,9 +648,9 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.0.tgz", - "integrity": "sha512-kYsT+f5ARWF6AdFmqoEEp+hpqxEB8vGmRWfw2aj78M2vTwS2uHW91EF58iFm1Z9U8Y/RrLu2XKJn46P9ca1b0w==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.2.tgz", + "integrity": "sha512-eR0gJQc830fJVGz37oKLvt9W9uUIQSAovUl0e9sJ3YeO09dlcoBVYD3CLrjCj4qHdXmfiyTyFt8yeQYSN5fxLg==", "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.22.15", @@ -939,7 +939,6 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1091,14 +1090,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz", - "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -1947,12 +1946,12 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.20.tgz", - "integrity": "sha512-11MY04gGC4kSzlPHRfvVkNAZhUxOvm7DCJ37hPDnUENwe06npjIRAfInEMTGSb4LZK5ZgDFkv5hw0lGebHeTyg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.2.tgz", + "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.20", + "@babel/compat-data": "^7.23.2", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", @@ -1978,15 +1977,15 @@ "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.22.5", - "@babel/plugin-transform-async-generator-functions": "^7.22.15", + "@babel/plugin-transform-async-generator-functions": "^7.23.2", "@babel/plugin-transform-async-to-generator": "^7.22.5", "@babel/plugin-transform-block-scoped-functions": "^7.22.5", - "@babel/plugin-transform-block-scoping": "^7.22.15", + "@babel/plugin-transform-block-scoping": "^7.23.0", "@babel/plugin-transform-class-properties": "^7.22.5", "@babel/plugin-transform-class-static-block": "^7.22.11", "@babel/plugin-transform-classes": "^7.22.15", "@babel/plugin-transform-computed-properties": "^7.22.5", - "@babel/plugin-transform-destructuring": "^7.22.15", + "@babel/plugin-transform-destructuring": "^7.23.0", "@babel/plugin-transform-dotall-regex": "^7.22.5", "@babel/plugin-transform-duplicate-keys": "^7.22.5", "@babel/plugin-transform-dynamic-import": "^7.22.11", @@ -1998,9 +1997,9 @@ "@babel/plugin-transform-literals": "^7.22.5", "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", "@babel/plugin-transform-member-expression-literals": "^7.22.5", - "@babel/plugin-transform-modules-amd": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.22.15", - "@babel/plugin-transform-modules-systemjs": "^7.22.11", + "@babel/plugin-transform-modules-amd": "^7.23.0", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-modules-systemjs": "^7.23.0", "@babel/plugin-transform-modules-umd": "^7.22.5", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", "@babel/plugin-transform-new-target": "^7.22.5", @@ -2009,7 +2008,7 @@ "@babel/plugin-transform-object-rest-spread": "^7.22.15", "@babel/plugin-transform-object-super": "^7.22.5", "@babel/plugin-transform-optional-catch-binding": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.22.15", + "@babel/plugin-transform-optional-chaining": "^7.23.0", "@babel/plugin-transform-parameters": "^7.22.15", "@babel/plugin-transform-private-methods": "^7.22.5", "@babel/plugin-transform-private-property-in-object": "^7.22.11", @@ -2026,10 +2025,10 @@ "@babel/plugin-transform-unicode-regex": "^7.22.5", "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", "@babel/preset-modules": "0.1.6-no-external-plugins", - "@babel/types": "^7.22.19", - "babel-plugin-polyfill-corejs2": "^0.4.5", - "babel-plugin-polyfill-corejs3": "^0.8.3", - "babel-plugin-polyfill-regenerator": "^0.5.2", + "@babel/types": "^7.23.0", + "babel-plugin-polyfill-corejs2": "^0.4.6", + "babel-plugin-polyfill-corejs3": "^0.8.5", + "babel-plugin-polyfill-regenerator": "^0.5.3", "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, @@ -2041,13 +2040,13 @@ } }, "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.4.tgz", - "integrity": "sha512-9l//BZZsPR+5XjyJMPtZSK4jv0BsTO1zDac2GC6ygx9WLGlcsnRd1Co0B2zT5fF5Ic6BZy+9m3HNZ3QcOeDKfg==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", + "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.2", - "core-js-compat": "^3.32.2" + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.33.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -2105,9 +2104,9 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.0.tgz", - "integrity": "sha512-6P6VVa/NM/VlAYj5s2Aq/gdVg8FSENCg3wlZ6Qau9AcPaoF5LbN1nyGlR9DTRIw9PpxI94e+ReydsJHcjwAweg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz", + "integrity": "sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2149,9 +2148,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", - "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2178,9 +2177,9 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dependencies": { "@babel/code-frame": "^7.22.13", "@babel/generator": "^7.23.0", @@ -2273,21 +2272,23 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, "engines": { "node": ">=0.1.90" } }, "node_modules/@commitlint/cli": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.7.2.tgz", - "integrity": "sha512-t3N7TZq7lOeqTOyEgfGcaltHqEJf7YDlPg75MldeVPPyz14jZq/+mbGF9tueDLFX8R6RwdymrN6D+U5XwZ8Iwg==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.8.1.tgz", + "integrity": "sha512-ay+WbzQesE0Rv4EQKfNbSMiJJ12KdKTDzIt0tcK4k11FdsWmtwP0Kp1NWMOUswfIWo6Eb7p7Ln721Nx9FLNBjg==", "dev": true, "dependencies": { - "@commitlint/format": "^17.4.4", - "@commitlint/lint": "^17.7.0", - "@commitlint/load": "^17.7.2", - "@commitlint/read": "^17.5.1", - "@commitlint/types": "^17.4.4", + "@commitlint/format": "^17.8.1", + "@commitlint/lint": "^17.8.1", + "@commitlint/load": "^17.8.1", + "@commitlint/read": "^17.8.1", + "@commitlint/types": "^17.8.1", "execa": "^5.0.0", "lodash.isfunction": "^3.0.9", "resolve-from": "5.0.0", @@ -2302,9 +2303,9 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.7.0.tgz", - "integrity": "sha512-iicqh2o6et+9kWaqsQiEYZzfLbtoWv9uZl8kbI8EGfnc0HeGafQBF7AJ0ylN9D/2kj6txltsdyQs8+2fTMwWEw==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.8.1.tgz", + "integrity": "sha512-NxCOHx1kgneig3VLauWJcDWS40DVjg7nKOpBEEK9E5fjJpQqLCilcnKkIIjdBH98kEO1q3NpE5NSrZ2kl/QGJg==", "dev": true, "dependencies": { "conventional-changelog-conventionalcommits": "^6.1.0" @@ -2314,12 +2315,12 @@ } }, "node_modules/@commitlint/config-validator": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.6.7.tgz", - "integrity": "sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.8.1.tgz", + "integrity": "sha512-UUgUC+sNiiMwkyiuIFR7JG2cfd9t/7MV8VB4TZ+q02ZFkHoduUS4tJGsCBWvBOGD9Btev6IecPMvlWUfJorkEA==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^17.8.1", "ajv": "^8.11.0" }, "engines": { @@ -2327,12 +2328,12 @@ } }, "node_modules/@commitlint/ensure": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.6.7.tgz", - "integrity": "sha512-mfDJOd1/O/eIb/h4qwXzUxkmskXDL9vNPnZ4AKYKiZALz4vHzwMxBSYtyL2mUIDeU9DRSpEUins8SeKtFkYHSw==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.8.1.tgz", + "integrity": "sha512-xjafwKxid8s1K23NFpL8JNo6JnY/ysetKo8kegVM7c8vs+kWLP8VrQq+NbhgVlmCojhEDbzQKp4eRXSjVOGsow==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^17.8.1", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", @@ -2344,21 +2345,21 @@ } }, "node_modules/@commitlint/execute-rule": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", - "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.8.1.tgz", + "integrity": "sha512-JHVupQeSdNI6xzA9SqMF+p/JjrHTcrJdI02PwesQIDCIGUrv04hicJgCcws5nzaoZbROapPs0s6zeVHoxpMwFQ==", "dev": true, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/format": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.4.tgz", - "integrity": "sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.8.1.tgz", + "integrity": "sha512-f3oMTyZ84M9ht7fb93wbCKmWxO5/kKSbwuYvS867duVomoOsgrgljkGGIztmT/srZnaiGbaK8+Wf8Ik2tSr5eg==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^17.8.1", "chalk": "^4.1.0" }, "engines": { @@ -2409,12 +2410,12 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.7.0.tgz", - "integrity": "sha512-043rA7m45tyEfW7Zv2vZHF++176MLHH9h70fnPoYlB1slKBeKl8BwNIlnPg4xBdRBVNPaCqvXxWswx2GR4c9Hw==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.8.1.tgz", + "integrity": "sha512-UshMi4Ltb4ZlNn4F7WtSEugFDZmctzFpmbqvpyxD3la510J+PLcnyhf9chs7EryaRFJMdAKwsEKfNK0jL/QM4g==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^17.8.1", "semver": "7.5.4" }, "engines": { @@ -2455,30 +2456,30 @@ "dev": true }, "node_modules/@commitlint/lint": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.7.0.tgz", - "integrity": "sha512-TCQihm7/uszA5z1Ux1vw+Nf3yHTgicus/+9HiUQk+kRSQawByxZNESeQoX9ujfVd3r4Sa+3fn0JQAguG4xvvbA==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.8.1.tgz", + "integrity": "sha512-aQUlwIR1/VMv2D4GXSk7PfL5hIaFSfy6hSHV94O8Y27T5q+DlDEgd/cZ4KmVI+MWKzFfCTiTuWqjfRSfdRllCA==", "dev": true, "dependencies": { - "@commitlint/is-ignored": "^17.7.0", - "@commitlint/parse": "^17.7.0", - "@commitlint/rules": "^17.7.0", - "@commitlint/types": "^17.4.4" + "@commitlint/is-ignored": "^17.8.1", + "@commitlint/parse": "^17.8.1", + "@commitlint/rules": "^17.8.1", + "@commitlint/types": "^17.8.1" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/load": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.7.2.tgz", - "integrity": "sha512-XA7WTnsjHZ4YH6ZYsrnxgLdXzriwMMq+utZUET6spbOEEIPBCDLdOQXS26P+v3TTO4hUHOEhzUquaBv3jbBixw==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.8.1.tgz", + "integrity": "sha512-iF4CL7KDFstP1kpVUkT8K2Wl17h2yx9VaR1ztTc8vzByWWcbO/WaKwxsnCOqow9tVAlzPfo1ywk9m2oJ9ucMqA==", "dev": true, "dependencies": { - "@commitlint/config-validator": "^17.6.7", - "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.6.7", - "@commitlint/types": "^17.4.4", + "@commitlint/config-validator": "^17.8.1", + "@commitlint/execute-rule": "^17.8.1", + "@commitlint/resolve-extends": "^17.8.1", + "@commitlint/types": "^17.8.1", "@types/node": "20.5.1", "chalk": "^4.1.0", "cosmiconfig": "^8.0.0", @@ -2488,7 +2489,7 @@ "lodash.uniq": "^4.5.0", "resolve-from": "^5.0.0", "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.0.0" + "typescript": "^4.6.4 || ^5.2.2" }, "engines": { "node": ">=v14" @@ -2598,21 +2599,21 @@ } }, "node_modules/@commitlint/message": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.4.2.tgz", - "integrity": "sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.8.1.tgz", + "integrity": "sha512-6bYL1GUQsD6bLhTH3QQty8pVFoETfFQlMn2Nzmz3AOLqRVfNNtXBaSY0dhZ0dM6A2MEq4+2d7L/2LP8TjqGRkA==", "dev": true, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/parse": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.7.0.tgz", - "integrity": "sha512-dIvFNUMCUHqq5Abv80mIEjLVfw8QNuA4DS7OWip4pcK/3h5wggmjVnlwGCDvDChkw2TjK1K6O+tAEV78oxjxag==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.8.1.tgz", + "integrity": "sha512-/wLUickTo0rNpQgWwLPavTm7WbwkZoBy3X8PpkUmlSmQJyWQTj0m6bDjiykMaDt41qcUbfeFfaCvXfiR4EGnfw==", "dev": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^17.8.1", "conventional-changelog-angular": "^6.0.0", "conventional-commits-parser": "^4.0.0" }, @@ -2621,13 +2622,13 @@ } }, "node_modules/@commitlint/read": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.5.1.tgz", - "integrity": "sha512-7IhfvEvB//p9aYW09YVclHbdf1u7g7QhxeYW9ZHSO8Huzp8Rz7m05aCO1mFG7G8M+7yfFnXB5xOmG18brqQIBg==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.8.1.tgz", + "integrity": "sha512-Fd55Oaz9irzBESPCdMd8vWWgxsW3OWR99wOntBDHgf9h7Y6OOHjWEdS9Xzen1GFndqgyoaFplQS5y7KZe0kO2w==", "dev": true, "dependencies": { - "@commitlint/top-level": "^17.4.0", - "@commitlint/types": "^17.4.4", + "@commitlint/top-level": "^17.8.1", + "@commitlint/types": "^17.8.1", "fs-extra": "^11.0.0", "git-raw-commits": "^2.0.11", "minimist": "^1.2.6" @@ -2637,13 +2638,13 @@ } }, "node_modules/@commitlint/resolve-extends": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.6.7.tgz", - "integrity": "sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.8.1.tgz", + "integrity": "sha512-W/ryRoQ0TSVXqJrx5SGkaYuAaE/BUontL1j1HsKckvM6e5ZaG0M9126zcwL6peKSuIetJi7E87PRQF8O86EW0Q==", "dev": true, "dependencies": { - "@commitlint/config-validator": "^17.6.7", - "@commitlint/types": "^17.4.4", + "@commitlint/config-validator": "^17.8.1", + "@commitlint/types": "^17.8.1", "import-fresh": "^3.0.0", "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0", @@ -2654,15 +2655,15 @@ } }, "node_modules/@commitlint/rules": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.7.0.tgz", - "integrity": "sha512-J3qTh0+ilUE5folSaoK91ByOb8XeQjiGcdIdiB/8UT1/Rd1itKo0ju/eQVGyFzgTMYt8HrDJnGTmNWwcMR1rmA==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.8.1.tgz", + "integrity": "sha512-2b7OdVbN7MTAt9U0vKOYKCDsOvESVXxQmrvuVUZ0rGFMCrCPJWWP1GJ7f0lAypbDAhaGb8zqtdOr47192LBrIA==", "dev": true, "dependencies": { - "@commitlint/ensure": "^17.6.7", - "@commitlint/message": "^17.4.2", - "@commitlint/to-lines": "^17.4.0", - "@commitlint/types": "^17.4.4", + "@commitlint/ensure": "^17.8.1", + "@commitlint/message": "^17.8.1", + "@commitlint/to-lines": "^17.8.1", + "@commitlint/types": "^17.8.1", "execa": "^5.0.0" }, "engines": { @@ -2670,18 +2671,18 @@ } }, "node_modules/@commitlint/to-lines": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.4.0.tgz", - "integrity": "sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.8.1.tgz", + "integrity": "sha512-LE0jb8CuR/mj6xJyrIk8VLz03OEzXFgLdivBytoooKO5xLt5yalc8Ma5guTWobw998sbR3ogDd+2jed03CFmJA==", "dev": true, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/top-level": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.4.0.tgz", - "integrity": "sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.8.1.tgz", + "integrity": "sha512-l6+Z6rrNf5p333SHfEte6r+WkOxGlWK4bLuZKbtf/2TXRN+qhrvn1XE63VhD8Oe9oIHQ7F7W1nG2k/TJFhx2yA==", "dev": true, "dependencies": { "find-up": "^5.0.0" @@ -2691,9 +2692,9 @@ } }, "node_modules/@commitlint/types": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", - "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.8.1.tgz", + "integrity": "sha512-PXDQXkAmiMEG162Bqdh9ChML/GJZo6vU+7F03ALKDK8zYc6SuAr47LjG7hGYRqUOz+WK0dU7bQ0xzuqFMdxzeQ==", "dev": true, "dependencies": { "chalk": "^4.1.0" @@ -3239,9 +3240,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -4014,9 +4015,9 @@ } }, "node_modules/@faker-js/faker": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.1.0.tgz", - "integrity": "sha512-38DT60rumHfBYynif3lmtxMqMqmsOQIxQgEuPZxCk2yUYN0eqWpTACgxi0VpidvsJB8CRxCpvP7B3anK85FjtQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.2.0.tgz", + "integrity": "sha512-VacmzZqVxdWdf9y64lDOMZNDMM/FQdtM9IsaOPKOm2suYwEatb8VkdHqOzXcDnZbk7YDE2BmsJmy/2Hmkn563g==", "dev": true, "funding": [ { @@ -4080,12 +4081,12 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -4107,9 +4108,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@hutson/parse-repository-url": { @@ -4382,19 +4383,19 @@ } }, "node_modules/@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dependencies": { - "@jest/types": "^28.1.3", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/console/node_modules/ansi-styles": { @@ -4426,6 +4427,70 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@jest/console/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==", + "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/console/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/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==", + "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/@jest/console/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/@jest/console/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4438,42 +4503,41 @@ } }, "node_modules/@jest/core": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", - "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dependencies": { - "@jest/console": "^28.1.3", - "@jest/reporters": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", + "@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": "^28.1.3", - "jest-config": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-resolve-dependencies": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "jest-watcher": "^28.1.3", + "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": "^28.1.3", - "rimraf": "^3.0.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -4484,14 +4548,6 @@ } } }, - "node_modules/@jest/core/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/core/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4521,18 +4577,52 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/@jest/core/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==", + "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/core/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/core/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core/node_modules/react-is": { @@ -4552,35 +4642,36 @@ } }, "node_modules/@jest/environment": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.3.tgz", - "integrity": "sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dependencies": { - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^28.1.3" + "jest-mock": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dependencies": { - "expect": "^28.1.3", - "jest-snapshot": "^28.1.3" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", + "dev": true, "dependencies": { "jest-get-type": "^28.0.2" }, @@ -4588,46 +4679,303 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/@jest/expect/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==", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/expect/node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/expect/node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "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/@jest/expect/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==", + "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/expect/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==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/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==", + "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/expect/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==", + "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/expect/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/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==", + "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/@jest/expect/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@jest/expect/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/fake-timers": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.3.tgz", - "integrity": "sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==", + "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==", "dependencies": { - "@jest/types": "^28.1.3", - "@sinonjs/fake-timers": "^9.1.2", + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^28.1.3", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/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==", + "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/fake-timers/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/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==", + "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/@jest/fake-timers/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@jest/fake-timers/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/@jest/globals": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.3.tgz", - "integrity": "sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/expect": "^28.1.3", - "@jest/types": "^28.1.3" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", - "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@jridgewell/trace-mapping": "^0.3.13", + "@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", @@ -4635,21 +4983,20 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.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": "^28.1.3", - "jest-util": "^28.1.3", - "jest-worker": "^28.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", - "terminal-link": "^2.0.0", "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -4689,6 +5036,70 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@jest/reporters/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==", + "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/reporters/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/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==", + "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/@jest/reporters/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/@jest/reporters/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4701,80 +5112,80 @@ } }, "node_modules/@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dependencies": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "28.1.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", - "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.13", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dependencies": { - "@jest/console": "^28.1.3", - "@jest/types": "^28.1.3", + "@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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz", - "integrity": "sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dependencies": { - "@jest/test-result": "^28.1.3", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", - "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^28.1.3", - "@jridgewell/trace-mapping": "^0.3.13", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.3", + "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.1" + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform/node_modules/ansi-styles": { @@ -4806,6 +5217,27 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@jest/transform/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==" + }, + "node_modules/@jest/transform/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/transform/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4818,11 +5250,11 @@ } }, "node_modules/@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dependencies": { - "@jest/schemas": "^28.1.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -4830,7 +5262,7 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types/node_modules/ansi-styles": { @@ -4917,18 +5349,18 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@lerna/child-process": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-7.3.0.tgz", - "integrity": "sha512-rA+fGUo2j/LEq6w1w8s6oVikLbJTWoIDVpYMc7bUCtwDOUuZKMQiRtjmpavY3fTm7ltu42f4AKflc2A70K4wvA==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-7.4.1.tgz", + "integrity": "sha512-Bx1cRCZcVcWoz+atDQc4CSVzGuEgGJPOpIAXjQbBEA2cX5nqIBWdbye8eHu31En/F03aH9BhpNEJghs6wy4iTg==", "dev": true, "dependencies": { "chalk": "^4.1.0", @@ -4936,7 +5368,7 @@ "strong-log-transformer": "^2.1.0" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">=16.0.0" } }, "node_modules/@lerna/child-process/node_modules/ansi-styles": { @@ -4983,12 +5415,12 @@ } }, "node_modules/@lerna/create": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-7.3.0.tgz", - "integrity": "sha512-fjgiKjg9VXwQ4ZKKsrXICEKRiC3yo6+FprR0mc55uz0s5e9xupoSGLobUTTBdE7ncNB3ibqml8dfaAn/+ESajQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@lerna/create/-/create-7.4.1.tgz", + "integrity": "sha512-zPO9GyWceRimtMD+j+aQ8xJgNPYn/Q/SzHf4wYN+4Rj5nrFKMyX+Et7FbWgUNpj0dRgyCCKBDYmTB7xQVVq4gQ==", "dev": true, "dependencies": { - "@lerna/child-process": "7.3.0", + "@lerna/child-process": "7.4.1", "@npmcli/run-script": "6.0.2", "@nx/devkit": ">=16.5.1 < 17", "@octokit/plugin-enterprise-rest": "6.0.1", @@ -5055,7 +5487,7 @@ "yargs-parser": "20.2.4" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">=16.0.0" } }, "node_modules/@lerna/create/node_modules/ansi-styles": { @@ -5139,6 +5571,12 @@ } } }, + "node_modules/@lerna/create/node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, "node_modules/@lerna/create/node_modules/execa": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", @@ -5603,14 +6041,6 @@ "integrity": "sha512-JW7nHREPqEtjBWz3EfxLarkmJBD8vi7Kx/1AQ6eBZnz12eHc1VkOyrc6mpR5ogTf0dOUNXFAfZut+cDe2dn4kQ==", "dev": true }, - "node_modules/@matterlabs/token-library": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@matterlabs/token-library/-/token-library-2.9.0.tgz", - "integrity": "sha512-Xkp0n0NdmG5UqHMRtY6BJSWbfTgv8OjhkWYuaevhwjb8+0uv3GpJC++2webB0jdebDVQBFUiwcC+Er7E49sryQ==", - "dependencies": { - "ohmyfetch": "^0.4.21" - } - }, "node_modules/@matterlabs/zksync-contracts": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/@matterlabs/zksync-contracts/-/zksync-contracts-0.6.1.tgz", @@ -5790,9 +6220,9 @@ } }, "node_modules/@metamask/object-multiplex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-1.2.0.tgz", - "integrity": "sha512-hksV602d3NWE2Q30Mf2Np1WfVKaGqfJRy9vpHAmelbaD0OkDt06/0KQkRR6UVYdMbTbkuEu8xN5JDUU80inGwQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-1.3.0.tgz", + "integrity": "sha512-czcQeVYdSNtabd+NcYQnrM69MciiJyd1qvKH8WM2Id3C0ZiUUX5Xa/MK+/VUk633DBhVOwdNzAKIQ33lGyA+eQ==", "dependencies": { "end-of-stream": "^1.4.4", "once": "^1.4.0", @@ -6613,7 +7043,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -6730,7 +7159,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -6781,7 +7209,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -6862,7 +7289,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7013,7 +7439,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7122,7 +7547,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7215,7 +7639,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7293,7 +7716,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7341,7 +7763,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -8601,9 +9022,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.9.0.tgz", - "integrity": "sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz", + "integrity": "sha512-Lm+fYpMfZoEucJ7cMxgt4dYt8jLfbpwRCzAjm9UgSLOkmlqo9gupxt6YX3DY0Fk155NT9l17d/ydi+964uS9Lw==", "dev": true, "engines": { "node": ">=14.0.0" @@ -8907,32 +9328,30 @@ } }, "node_modules/@sentry-internal/tracing": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.73.0.tgz", - "integrity": "sha512-ig3WL/Nqp8nRQ52P205NaypGKNfIl/G+cIqge9xPW6zfRb5kJdM1YParw9GSJ1SPjEZBkBORGAML0on5H2FILw==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.75.1.tgz", + "integrity": "sha512-nynV+7iVcF8k3CqhvI2K7iA8h4ovJhgYHKnXR8RDDevQOqNG2AEX9+hjCj9fZM4MhKHYFqf1od2oO9lTr38kwg==", "dev": true, "dependencies": { - "@sentry/core": "7.73.0", - "@sentry/types": "7.73.0", - "@sentry/utils": "7.73.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry/core": "7.75.1", + "@sentry/types": "7.75.1", + "@sentry/utils": "7.75.1" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/browser": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.73.0.tgz", - "integrity": "sha512-e301hUixcJ5+HNKCJwajFF5smF4opXEFSclyWsJuFNufv5J/1C1SDhbwG2JjBt5zzdSoKWJKT1ewR6vpICyoDw==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.75.1.tgz", + "integrity": "sha512-0+jPfPA5P9HVYYRQraDokGCY2NiMknSfz11dggClK4VmjvG+hOXiEyf73SFVwLFnv/hwrkWySjoIrVCX65xXQA==", "dev": true, "dependencies": { - "@sentry-internal/tracing": "7.73.0", - "@sentry/core": "7.73.0", - "@sentry/replay": "7.73.0", - "@sentry/types": "7.73.0", - "@sentry/utils": "7.73.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry-internal/tracing": "7.75.1", + "@sentry/core": "7.75.1", + "@sentry/replay": "7.75.1", + "@sentry/types": "7.75.1", + "@sentry/utils": "7.75.1" }, "engines": { "node": ">=8" @@ -9012,14 +9431,13 @@ } }, "node_modules/@sentry/core": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.73.0.tgz", - "integrity": "sha512-9FEz4Gq848LOgVN2OxJGYuQqxv7cIVw69VlAzWHEm3njt8mjvlTq+7UiFsGRo84+59V2FQuHxzA7vVjl90WfSg==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.75.1.tgz", + "integrity": "sha512-Kw4KyKBxbxbh8OKO0S11Tm0gWP+6AaXXYrsq3hp8H338l/wOmIzyckmCbUrc/XJeoRqaFLJbdcCrcUEDZUvsVQ==", "dev": true, "dependencies": { - "@sentry/types": "7.73.0", - "@sentry/utils": "7.73.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry/types": "7.75.1", + "@sentry/utils": "7.75.1" }, "engines": { "node": ">=8" @@ -9097,19 +9515,16 @@ "dev": true }, "node_modules/@sentry/node": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.73.0.tgz", - "integrity": "sha512-i50bRfmgkRRx0XXUbg9jGD/RuznDJxJXc4rBILhoJuhl+BjRIaoXA3ayplfJn8JLZxsNh75uJaCq4IUK70SORw==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.75.1.tgz", + "integrity": "sha512-E174NbP3j7OIqQQYPtpMGz1FfL/KE5PeGnhoACyMIk0D5MGB7Ia7Y9+nYfHB7+EOJPV2Ob6BYlhemX/MxPrYWg==", "dev": true, "dependencies": { - "@sentry-internal/tracing": "7.73.0", - "@sentry/core": "7.73.0", - "@sentry/types": "7.73.0", - "@sentry/utils": "7.73.0", - "cookie": "^0.5.0", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry-internal/tracing": "7.75.1", + "@sentry/core": "7.75.1", + "@sentry/types": "7.75.1", + "@sentry/utils": "7.75.1", + "https-proxy-agent": "^5.0.0" }, "engines": { "node": ">=8" @@ -9141,48 +9556,48 @@ } }, "node_modules/@sentry/replay": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.73.0.tgz", - "integrity": "sha512-a8IC9SowBisLYD2IdLkXzx7gN4iVwHDJhQvLp2B8ARs1PyPjJ7gCxSMHeGrYp94V0gOXtorNYkrxvuX8ayPROA==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.75.1.tgz", + "integrity": "sha512-MKQTDWNYs9QXCJ+irGX5gu8Kxdk/Ds5puhILy8+DnCoXgXuPFRMGob1Sxt8qXmbQmcGeogsx221MNTselsRS6g==", "dev": true, "dependencies": { - "@sentry/core": "7.73.0", - "@sentry/types": "7.73.0", - "@sentry/utils": "7.73.0" + "@sentry-internal/tracing": "7.75.1", + "@sentry/core": "7.75.1", + "@sentry/types": "7.75.1", + "@sentry/utils": "7.75.1" }, "engines": { "node": ">=12" } }, "node_modules/@sentry/tracing": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.73.0.tgz", - "integrity": "sha512-LOQR6Hkc8ZoflCXWtMlxTbCBEwv0MSOr3vesnRsmlFG8TW1YUIneU+wKnVxToWAZ8fq+6ubclnuIUKHfqTk/Tg==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.75.1.tgz", + "integrity": "sha512-hy8MQB9TAYdvuO6O6Lotmi/xMkhseM5E3ecY6yjgkbQwzjJV+dBBW4xsCXowMQQQ1qN+E/n95p/gUPvbfe2mgQ==", "dev": true, "dependencies": { - "@sentry-internal/tracing": "7.73.0" + "@sentry-internal/tracing": "7.75.1" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/types": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.73.0.tgz", - "integrity": "sha512-/v8++bly8jW7r4cP2wswYiiVpn7eLLcqwnfPUMeCQze4zj3F3nTRIKc9BGHzU0V+fhHa3RwRC2ksqTGq1oJMDg==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.75.1.tgz", + "integrity": "sha512-km+ygqgMDaFfTrbQwdhrptFqx0Oq15jZABqIoIpbaOCkCAMm+tyCqrFS8dTfaq5wpCktqWOy2qU/DOpppO99Cg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.73.0.tgz", - "integrity": "sha512-h3ZK/qpf4k76FhJV9uiSbvMz3V/0Ovy94C+5/9UgPMVCJXFmVsdw8n/dwANJ7LupVPfYP23xFGgebDMFlK1/2w==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.75.1.tgz", + "integrity": "sha512-QzW2eRjY20epD//9/tQ0FTNwdAL6XZi+LyJNUQIeK3NMnc5NgHrgpxId87gmFq8cNx47utH1Blub8RuMbKqiwQ==", "dev": true, "dependencies": { - "@sentry/types": "7.73.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry/types": "7.75.1" }, "engines": { "node": ">=8" @@ -9201,16 +9616,15 @@ } }, "node_modules/@sentry/vue": { - "version": "7.73.0", - "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-7.73.0.tgz", - "integrity": "sha512-BTZVvY4PTLqqIbLbwBr0fbMQsUalV+BSm1JbCx2cy4IX/Rcf5YQUdkv1CvUMvI4yZKYTINMamyT/8XCCPljl6A==", + "version": "7.75.1", + "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-7.75.1.tgz", + "integrity": "sha512-GUasSjHOU5Ge4bseuS5Hv35nirGVOT72TjKy0f8e29Oom9gveHTkeOVHIfs2gHT4cmGqzdsON+Dk4vSfG6PSBg==", "dev": true, "dependencies": { - "@sentry/browser": "7.73.0", - "@sentry/core": "7.73.0", - "@sentry/types": "7.73.0", - "@sentry/utils": "7.73.0", - "tslib": "^2.4.1 || ^1.9.3" + "@sentry/browser": "7.75.1", + "@sentry/core": "7.75.1", + "@sentry/types": "7.75.1", + "@sentry/utils": "7.75.1" }, "engines": { "node": ">=8" @@ -9289,24 +9703,24 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "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==", "dependencies": { - "@sinonjs/commons": "^1.7.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sqltools/formatter": { @@ -9827,9 +10241,9 @@ } }, "node_modules/@storybook/addon-essentials/node_modules/@types/yargs": { - "version": "15.0.16", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.16.tgz", - "integrity": "sha512-2FeD5qezW3FvLpZ0JpfuaEWepgNLl9b2gQYiz/ce0NhoB1W/D+VZu98phITXkADYerfr/jb7JcDcVhITsc9bwg==", + "version": "15.0.17", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.17.tgz", + "integrity": "sha512-cj53I8GUcWJIgWVTSVe2L7NJAB5XWGdsoMosVvUgv1jEnMbAcsbaCzt1coUcyi8Sda5PgTWAooG8jNyDTD+CWA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -18025,15 +18439,15 @@ } }, "node_modules/@types/aria-query": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.2.tgz", - "integrity": "sha512-PHKZuMN+K5qgKIWhBodXzQslTo5P+K/6LqeKXS6O/4liIDdZqaX5RXrCK++LAw+y/nptN48YmUMFiQHRSWYwtQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.3.tgz", + "integrity": "sha512-0Z6Tr7wjKJIk4OUEjVUQMtyunLDy339vcMaj38Kpj6jM2OE1p3S4kXExKZ7a3uXQAPCoy3sbrP1wibDKaf39oA==", "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", - "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -18043,43 +18457,43 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", - "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", - "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", - "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/bn.js": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.2.tgz", - "integrity": "sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", + "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", "dev": true, "dependencies": { "@types/connect": "*", @@ -18087,15 +18501,15 @@ } }, "node_modules/@types/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==", + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz", + "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==", "dev": true }, "node_modules/@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz", + "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==", "dev": true, "dependencies": { "@types/chai": "*" @@ -18111,62 +18525,62 @@ } }, "node_modules/@types/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-GwXanrvq/tBHJtudbl1lSy9Ybt7KS9+rA+YY3bcuIIM+d6jSHUr+5yjO83gtiRpuaPiBccwFjSnAK2qSrIPA7w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.2.tgz", + "integrity": "sha512-KGRIgCxwcgazts4MXRCikPbIMzBpjfdgEZSy8TRHU/gtg+f9sOfHdtK8unPfxIoBtyd2aTTwINVLSNENlC8U8A==", "dev": true, "dependencies": { "@types/color-name": "*" } }, "node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.2.tgz", + "integrity": "sha512-JWO/ZyxTKk0bLuOhAavGjnwLR73rUE7qzACnU7gMeyA/gdrSHm2xJwqNPipw2MtaZUaqQ2UG/q7pP6AQiZ8mqw==", "dev": true }, "node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-LZ8SD3LpNmLMDLkG2oCBjZg+ETnx6XdCjydUE0HwojDmnDfDUnhMKKbtth1TZh+hzcqb03azrYWoXLS8sMXdqg==", "dev": true }, "node_modules/@types/eslint": { - "version": "8.44.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", - "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", + "version": "8.44.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", + "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "node_modules/@types/eslint-scope": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz", - "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", + "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "node_modules/@types/estree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" }, "node_modules/@types/express": { - "version": "4.17.18", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz", - "integrity": "sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", + "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -18176,9 +18590,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -18188,17 +18602,17 @@ } }, "node_modules/@types/filesystem": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.33.tgz", - "integrity": "sha512-2KedRPzwu2K528vFkoXnnWdsG0MtUwPjuA7pRy4vKxlxHEe8qUDZibYHXJKZZr2Cl/ELdCWYqyb/MKwsUuzBWw==", + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.34.tgz", + "integrity": "sha512-La4bGrgck8/rosDUA1DJJP8hrFcKq0BV6JaaVlNnOo1rJdJDcft3//slEbAmsWNUJwXRCc0DXpeO40yuATlexw==", "dependencies": { "@types/filewriter": "*" } }, "node_modules/@types/filewriter": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.30.tgz", - "integrity": "sha512-lB98tui0uxc7erbj0serZfJlHKLNJHwBltPnbmO1WRpL5T325GOHRiQfr2E29V2q+S1brDO63Fpdt6vb3bES9Q==" + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.31.tgz", + "integrity": "sha512-12df1utOvPC80+UaVoOO1d81X8pa5MefHNS+gWX9R2ucSESpMz9K5QwlTWDGKASrzCpSFwj7NPYh+nTsolgEGA==" }, "node_modules/@types/glob": { "version": "8.1.0", @@ -18211,22 +18625,22 @@ } }, "node_modules/@types/graceful-fs": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", - "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/har-format": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.13.tgz", - "integrity": "sha512-PwBsCBD3lDODn4xpje3Y1di0aDJp4Ww7aSfMRVw6ysnxD4I7Wmq2mBkSKaDtN403hqH5sp6c9xQUvFYY3+lkBg==" + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.14.tgz", + "integrity": "sha512-pEmBAoccWvO6XbSI8A7KvIDGEoKtlLWtdqVCKoVBcCDSFvR4Ijd7zGLu7MWGEqk2r8D54uWlMRt+VZuSrfFMzQ==" }, "node_modules/@types/hast": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.6.tgz", - "integrity": "sha512-47rJE80oqPmFdVDCD7IheXBrVdwuBgsYwoczFvKmwfo2Mzsnt+V9OONsYauFmICb6lQPpCuXYJWejBNs4pDJRg==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.7.tgz", + "integrity": "sha512-EVLigw5zInURhzfXUM65eixfadfsHKomGKUakToXo84t8gGIJuTcD2xooM2See7GyQ7DRtYjhCHnSUQez8JaLw==", "dev": true, "dependencies": { "@types/unist": "^2" @@ -18239,34 +18653,34 @@ "dev": true }, "node_modules/@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", "dev": true }, "node_modules/@types/is-function": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.1.tgz", - "integrity": "sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-Je5TaQzK7H06pt4e88WsjXwRC64EkmxsdqirUI+4GPVMjhs68Dmm8hr+yqf8tmpYlfR6zPlsJC5xs14dlVUehw==", "dev": true }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==" }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", "dependencies": { "@types/istanbul-lib-report": "*" } @@ -18281,6 +18695,24 @@ "pretty-format": "^28.0.0" } }, + "node_modules/@types/jest/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@types/jest/node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, "node_modules/@types/jest/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -18323,9 +18755,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==" + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -18334,9 +18766,9 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.199", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", - "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", + "version": "4.14.200", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", + "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==", "dev": true }, "node_modules/@types/lru-cache": { @@ -18346,18 +18778,18 @@ "dev": true }, "node_modules/@types/mdast": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.13.tgz", - "integrity": "sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==", + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.14.tgz", + "integrity": "sha512-gVZ04PGgw1qLZKsnWnyFv4ORnaJ+DXLdHTVSFbU8yX6xZ34Bjg4Q32yPkmveUP1yItXReKfB0Aknlh/3zxTKAw==", "dev": true, "dependencies": { "@types/unist": "^2" } }, "node_modules/@types/mime": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", - "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", + "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", "dev": true }, "node_modules/@types/minimatch": { @@ -18367,9 +18799,9 @@ "dev": true }, "node_modules/@types/minimist": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.3.tgz", - "integrity": "sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.4.tgz", + "integrity": "sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ==", "dev": true }, "node_modules/@types/node": { @@ -18378,9 +18810,9 @@ "integrity": "sha512-/4QOuy3ZpV7Ya1GTRz5CYSz3DgkKpyUptXuQ5PPce7uuyJAOR7r9FhkmxJfvcNUXyklbC63a+YvB3jxy7s9ngw==" }, "node_modules/@types/node-fetch": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz", - "integrity": "sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg==", "dev": true, "dependencies": { "@types/node": "*", @@ -18388,28 +18820,31 @@ } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.3.tgz", + "integrity": "sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg==", "dev": true }, "node_modules/@types/npmlog": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", - "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", - "dev": true + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.5.tgz", + "integrity": "sha512-Fl3TEbwPoR7V1z6CMJ18whXOUkOYqF5eCkGKTir2VuevdLYUmcwj9mQdvXzuY0oagZBbsy0J7df41jn+ZcwGRA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/overlayscrollbars": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@types/overlayscrollbars/-/overlayscrollbars-1.12.2.tgz", - "integrity": "sha512-WBKnlpWYaWExCEB+obYtcXlwrlcsSWoMGfXPm5v4q60543Hjaqx0711kyV8wbsw2xB3G9X/NcCTcAA2O6PEyaw==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@types/overlayscrollbars/-/overlayscrollbars-1.12.3.tgz", + "integrity": "sha512-XjQakOYnk+lM3JXhQR2Zg61f/p7KTpm10mXuQ9o6eOQkGuaZ3NcHDkTo1aHm1MZOzFyzbvwMsqq2e/0rPK4gEw==", "dev": true }, "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz", + "integrity": "sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==", + "devOptional": true }, "node_modules/@types/parse5": { "version": "7.0.0", @@ -18422,23 +18857,18 @@ } }, "node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", "dev": true, "dependencies": { "@types/node": "*" } }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" - }, "node_modules/@types/pretty-hrtime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz", - "integrity": "sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz", + "integrity": "sha512-vyv9knII8XeW8TnXDcGH7HqG6FeR56ESN6ExM34d/U8Zvs3xuG34euV6CVyB7KEYI7Ts4lQM8b4NL72e7UadnA==", "dev": true }, "node_modules/@types/prismjs": { @@ -18448,27 +18878,27 @@ "dev": true }, "node_modules/@types/prop-types": { - "version": "15.7.8", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.8.tgz", - "integrity": "sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==", + "version": "15.7.9", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", + "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", "dev": true }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz", - "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", "dev": true }, "node_modules/@types/react": { - "version": "18.2.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.27.tgz", - "integrity": "sha512-Wfv7B7FZiR2r3MIqbAlXoY1+tXm4bOqfz4oRr+nyXdBqapDBZ0l/IGcSlAfvxIHEEJjkPU0MYAc/BlFPOcrgLw==", + "version": "18.2.33", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", + "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -18502,30 +18932,30 @@ } }, "node_modules/@types/scheduler": { - "version": "0.16.4", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.4.tgz", - "integrity": "sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==", + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", + "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", "dev": true }, "node_modules/@types/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-oN0PFsYxDZnX/qSJ5S5OwaEDTYfekhvaM5vqui2bu1AA39pKofmgL104Q29KiOXizXS2yLjSzc5YdTyMKdcy4A==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", + "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", "dev": true }, "node_modules/@types/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", - "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", + "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -18533,9 +18963,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", - "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -18544,20 +18974,20 @@ } }, "node_modules/@types/source-list-map": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.3.tgz", - "integrity": "sha512-I9R/7fUjzUOyDy6AFkehCK711wWoAXEaBi80AfjZt1lIkbe6AcXKd3ckQc3liMvQExWvfOeh/8CtKzrfUFN5gA==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.4.tgz", + "integrity": "sha512-Kdfm7Sk5VX8dFW7Vbp18+fmAatBewzBILa1raHYxrGEFXT0jNl9x3LWfuW7bTbjEKFNey9Dfkj/UzT6z/NvRlg==", "dev": true }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", + "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==" }, "node_modules/@types/superagent": { - "version": "4.1.19", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.19.tgz", - "integrity": "sha512-McM1mlc7PBZpCaw0fw/36uFqo0YeA6m8JqoyE4OfqXsZCIg0hPP2xdE6FM7r6fdprDZHlJwDpydUj1R++93hCA==", + "version": "4.1.20", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.20.tgz", + "integrity": "sha512-GfpwJgYSr3yO+nArFkmyqv3i0vZavyEG5xPd/o95RwpKYpsOKJYI5XLdxLpdRbZI3YiGKKdIOFIf/jlP7A0Jxg==", "dev": true, "dependencies": { "@types/cookiejar": "*", @@ -18565,35 +18995,35 @@ } }, "node_modules/@types/supertest": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.14.tgz", - "integrity": "sha512-Q900DeeHNFF3ZYYepf/EyJfZDA2JrnWLaSQ0YNV7+2GTo8IlJzauEnDGhya+hauncpBYTYGpVHwGdssJeAQ7eA==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.15.tgz", + "integrity": "sha512-jUCZZ/TMcpGzoSaed9Gjr8HCf3HehExdibyw3OHHEL1als1KmyzcOZZH4MjbObI8TkWsEr7bc7gsW0WTDni+qQ==", "dev": true, "dependencies": { "@types/superagent": "*" } }, "node_modules/@types/tapable": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.9.tgz", - "integrity": "sha512-fOHIwZua0sRltqWzODGUM6b4ffZrf/vzGUmNXdR+4DzuJP42PMbM5dLKcdzlYvv8bMJ3GALOzkk1q7cDm2zPyA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.10.tgz", + "integrity": "sha512-q8F20SdXG5fdVJQ5yxsVlH+f+oekP42QeHv4s5KlrxTMT0eopXn7ol1rhxMcksf8ph7XNv811iVDE2hOpUvEPg==", "dev": true }, "node_modules/@types/tough-cookie": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.3.tgz", - "integrity": "sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.4.tgz", + "integrity": "sha512-95Sfz4nvMAb0Nl9DTxN3j64adfwfbBPEYq14VN7zT5J5O2M9V6iZMIIQU1U+pJyl9agHYHNCqhCXgyEtIRRa5A==", "dev": true }, "node_modules/@types/triple-beam": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.3.tgz", - "integrity": "sha512-6tOUG+nVHn0cJbVp25JFayS5UE6+xlbcNF9Lo9mU7U0zk3zeUShZied4YEQZjy1JBF043FSkdXw8YkUJuVtB5g==" + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.4.tgz", + "integrity": "sha512-HlJjF3wxV4R2VQkFpKe0YqJLilYNgtRtsqqZtby7RkVsSs+i+vbyzjtUwpFEdUCKcrGzCiEJE7F/0mKjh0sunA==" }, "node_modules/@types/uglify-js": { - "version": "3.17.2", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.2.tgz", - "integrity": "sha512-9SjrHO54LINgC/6Ehr81NjAxAYvwEZqjUHLjJYvC4Nmr9jbLQCIZbWSvl4vXQkkmR1UAuaKDycau3O1kWGFyXQ==", + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.3.tgz", + "integrity": "sha512-ToldSfJ6wxO21cakcz63oFD1GjqQbKzhZCD57eH7zWuYT5UEZvfUoqvrjX5d+jB9g4a/sFO0n6QSVzzn5sMsjg==", "dev": true, "dependencies": { "source-map": "^0.6.1" @@ -18609,9 +19039,9 @@ } }, "node_modules/@types/unist": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.8.tgz", - "integrity": "sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.9.tgz", + "integrity": "sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ==", "dev": true }, "node_modules/@types/uuid": { @@ -18621,9 +19051,9 @@ "dev": true }, "node_modules/@types/validator": { - "version": "13.11.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.2.tgz", - "integrity": "sha512-nIKVVQKT6kGKysnNt+xLobr+pFJNssJRi2s034wgWeFBUx01fI8BeHTW2TcRp7VcFu9QCYG8IlChTuovcm0oKQ==" + "version": "13.11.5", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.5.tgz", + "integrity": "sha512-xW4qsT4UIYILu+7ZrBnfQdBYniZrMLYYK3wN9M/NdeIHgBN5pZI2/8Q7UfdWIcr5RLJv/OGENsx91JIpUUoC7Q==" }, "node_modules/@types/web-bluetooth": { "version": "0.0.14", @@ -18631,9 +19061,9 @@ "integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==" }, "node_modules/@types/webpack": { - "version": "4.41.34", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.34.tgz", - "integrity": "sha512-CN2aOGrR3zbMc2v+cKqzaClYP1ldkpPOgtdNvgX+RmlWCSWxHxpzz6WSCVQZRkF8D60ROlkRzAoEpgjWQ+bd2g==", + "version": "4.41.35", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.35.tgz", + "integrity": "sha512-XRC6HLGHtNfN8/xWeu1YUQV1GSE+28q8lSqvcJ+0xt/zW9Wmn4j9pCSvaXPyRlCKrl5OuqECQNEJUy2vo8oWqg==", "dev": true, "dependencies": { "@types/node": "*", @@ -18645,15 +19075,15 @@ } }, "node_modules/@types/webpack-env": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.2.tgz", - "integrity": "sha512-BFqcTHHTrrI8EBmIzNAmLPP3IqtEG9J1IPFWbPeS/F0/TGNmo0pI5svOa7JbMF9vSCXQCvJWT2gxLJNVuf9blw==", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.3.tgz", + "integrity": "sha512-v4CH6FLBCftYGFAswDhzFLjKgucXsOkIf5Mzl8ZZhEtC6oye9whFInNPKszNB9AvX7JEZMtpXxWctih6addP+Q==", "dev": true }, "node_modules/@types/webpack-sources": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.1.tgz", - "integrity": "sha512-iLC3Fsx62ejm3ST3PQ8vBMC54Rb3EoCprZjeJGI5q+9QjfDLGt9jeg/k245qz1G9AQnORGk0vqPicJFPT1QODQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.2.tgz", + "integrity": "sha512-acCzhuVe+UJy8abiSFQWXELhhNMZjQjQKpLNEi1pKGgKXZj0ul614ATcx4kkhunPost6Xw+aCq8y8cn1/WwAiA==", "dev": true, "dependencies": { "@types/node": "*", @@ -18671,17 +19101,17 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.28", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz", - "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==", + "version": "17.0.29", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", + "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==" + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", + "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", @@ -19084,59 +19514,71 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", - "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.7.tgz", + "integrity": "sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==", "dev": true, "dependencies": { - "@babel/parser": "^7.21.3", - "@vue/shared": "3.3.4", + "@babel/parser": "^7.23.0", + "@vue/shared": "3.3.7", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", - "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.7.tgz", + "integrity": "sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==", "dev": true, "dependencies": { - "@vue/compiler-core": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-core": "3.3.7", + "@vue/shared": "3.3.7" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz", - "integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.7.tgz", + "integrity": "sha512-7pfldWy/J75U/ZyYIXRVqvLRw3vmfxDo2YLMwVtWVNew8Sm8d6wodM+OYFq4ll/UxfqVr0XKiVwti32PCrruAw==", "dev": true, "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.4", - "@vue/compiler-dom": "3.3.4", - "@vue/compiler-ssr": "3.3.4", - "@vue/reactivity-transform": "3.3.4", - "@vue/shared": "3.3.4", + "@babel/parser": "^7.23.0", + "@vue/compiler-core": "3.3.7", + "@vue/compiler-dom": "3.3.7", + "@vue/compiler-ssr": "3.3.7", + "@vue/reactivity-transform": "3.3.7", + "@vue/shared": "3.3.7", "estree-walker": "^2.0.2", - "magic-string": "^0.30.0", - "postcss": "^8.1.10", + "magic-string": "^0.30.5", + "postcss": "^8.4.31", "source-map-js": "^1.0.2" } }, + "node_modules/@vue/compiler-sfc/node_modules/magic-string": { + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@vue/compiler-ssr": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz", - "integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.7.tgz", + "integrity": "sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg==", "dev": true, "dependencies": { - "@vue/compiler-dom": "3.3.4", - "@vue/shared": "3.3.4" + "@vue/compiler-dom": "3.3.7", + "@vue/shared": "3.3.7" } }, "node_modules/@vue/devtools-api": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz", - "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.1.tgz", + "integrity": "sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==" }, "node_modules/@vue/eslint-config-prettier": { "version": "7.1.0", @@ -19179,16 +19621,28 @@ } }, "node_modules/@vue/reactivity-transform": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz", - "integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.7.tgz", + "integrity": "sha512-APhRmLVbgE1VPGtoLQoWBJEaQk4V8JUsqrQihImVqKT+8U6Qi3t5ATcg4Y9wGAPb3kIhetpufyZ1RhwbZCIdDA==", "dev": true, "dependencies": { - "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.4", - "@vue/shared": "3.3.4", + "@babel/parser": "^7.23.0", + "@vue/compiler-core": "3.3.7", + "@vue/shared": "3.3.7", "estree-walker": "^2.0.2", - "magic-string": "^0.30.0" + "magic-string": "^0.30.5" + } + }, + "node_modules/@vue/reactivity-transform/node_modules/magic-string": { + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" } }, "node_modules/@vue/reactivity/node_modules/@vue/shared": { @@ -19280,9 +19734,9 @@ } }, "node_modules/@vue/shared": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", - "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.7.tgz", + "integrity": "sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg==", "dev": true }, "node_modules/@vue/test-utils": { @@ -20830,20 +21284,20 @@ } }, "node_modules/babel-jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz", - "integrity": "sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dependencies": { - "@jest/transform": "^28.1.3", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^28.1.3", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" @@ -21115,10 +21569,25 @@ "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==", + "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": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", - "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", + "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==", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -21126,14 +21595,14 @@ "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dev": true, + "devOptional": true, "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", @@ -21145,13 +21614,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", - "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.2", + "@babel/helper-define-polyfill-provider": "^0.4.3", "semver": "^6.3.1" }, "peerDependencies": { @@ -21191,12 +21660,12 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", - "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.2" + "@babel/helper-define-polyfill-provider": "^0.4.3" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -21231,15 +21700,15 @@ } }, "node_modules/babel-preset-jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz", - "integrity": "sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==", + "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==", "dependencies": { - "babel-plugin-jest-hoist": "^28.1.3", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -21687,20 +22156,23 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", "dev": true, "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.4", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 4" } }, "node_modules/browserify-sign/node_modules/readable-stream": { @@ -22204,12 +22676,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -22286,9 +22759,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001546", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", - "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==", + "version": "1.0.30001554", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz", + "integrity": "sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==", "funding": [ { "type": "opencollective", @@ -23957,9 +24430,9 @@ } }, "node_modules/core-js": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.0.tgz", - "integrity": "sha512-HoZr92+ZjFEKar5HS6MC776gYslNOKHt75mEBKWKnPeFDpZ6nH5OeF3S6HFT1mUAUZKrzkez05VboaX8myjSuw==", + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.1.tgz", + "integrity": "sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q==", "dev": true, "hasInstallScript": true, "funding": { @@ -23968,9 +24441,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.0.tgz", - "integrity": "sha512-0w4LcLXsVEuNkIqwjjf9rjCoPhK8uqA4tMRh4Ge26vfLtUutshn+aRJU21I9LCJlh2QQHfisNToLjw1XEJLTWw==", + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", + "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==", "dev": true, "dependencies": { "browserslist": "^4.22.1" @@ -23981,9 +24454,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.33.0.tgz", - "integrity": "sha512-FKSIDtJnds/YFIEaZ4HszRX7hkxGpNKM7FC9aJ9WLJbSd3lD4vOltFuVIBLR8asSx9frkTSqL0dw90SKQxgKrg==", + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.33.1.tgz", + "integrity": "sha512-wCXGbLjnsP10PlK/thHSQlOLlLKNEkaWbTzVvHHZ79fZNeN1gUmw2gBlpItxPv/pvqldevEXFh/d5stdNvl6EQ==", "dev": true, "hasInstallScript": true, "funding": { @@ -24012,7 +24485,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, + "devOptional": true, "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -24445,7 +24918,6 @@ "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", @@ -24462,1186 +24934,349 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/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, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "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" + "color-convert": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/create-jest/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, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/create-jest/node_modules/@jest/expect": { + "node_modules/create-jest/node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/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, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "jest-get-type": "^29.6.3" + "has-flag": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/create-jest/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, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "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" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/create-jest/node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/create-jest/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==", + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/create-jest/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==", + "node_modules/css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/create-jest/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==", + "node_modules/css-loader/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "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": ">=6" } }, - "node_modules/create-jest/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==", + "node_modules/css-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/css-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/create-jest/node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/css-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "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": ">=0.10.0" } }, - "node_modules/create-jest/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==", + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "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" + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/create-jest/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/create-jest/node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, - "dependencies": { - "type-detect": "4.0.8" + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/create-jest/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==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" } }, - "node_modules/create-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "cssom": "~0.3.6" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/create-jest/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==", + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, + "node_modules/cyclist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", + "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", + "dev": true + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "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": ">=8" } }, - "node_modules/create-jest/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==", + "node_modules/data-fetcher": { + "resolved": "packages/data-fetcher", + "link": true + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", "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" + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/create-jest/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==", + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/create-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "node_modules/date-fns": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", "engines": { - "node": ">=10" + "node": ">=0.11" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/date-fns" } }, - "node_modules/create-jest/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/create-jest/node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" }, "peerDependenciesMeta": { - "babel-plugin-macros": { + "supports-color": { "optional": true } } }, - "node_modules/create-jest/node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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/create-jest/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/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/create-jest/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/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": { - "@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/create-jest/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/create-jest/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/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": { - "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/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/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/create-jest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/create-jest/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/create-jest/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/create-jest/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/create-jest/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/create-jest/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/create-jest/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/create-jest/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": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/create-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/create-jest/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/css-loader/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/css-loader/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/css-loader/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/css-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" - }, - "node_modules/cyclist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", - "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", - "dev": true - }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/date-fns": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", - "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "dependencies": { "decamelize": "^1.1.0", @@ -25679,9 +25314,17 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deep-eql": { "version": "4.1.3", @@ -25775,10 +25418,9 @@ } }, "node_modules/define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", "dependencies": { "get-intrinsic": "^1.2.1", "gopd": "^1.0.1", @@ -26003,6 +25645,7 @@ "version": "28.1.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } @@ -26321,9 +25964,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.545", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.545.tgz", - "integrity": "sha512-G1HKumUw+y5yxMjewGfKz0XrqG6O+Tb4zrlC/Vs1+9riRXBuFlO0hOEXP3xeI+ltlJkbVUuLkYdmjHYH6Jkiow==" + "version": "1.4.567", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz", + "integrity": "sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==" }, "node_modules/element-resize-detector": { "version": "1.2.4", @@ -26354,9 +25997,9 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "engines": { "node": ">=12" }, @@ -26648,26 +26291,26 @@ } }, "node_modules/es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "arraybuffer.prototype.slice": "^1.0.2", "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", + "hasown": "^2.0.0", "internal-slot": "^1.0.5", "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", @@ -26677,7 +26320,7 @@ "is-string": "^1.0.7", "is-typed-array": "^1.1.12", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.5.1", @@ -26691,7 +26334,7 @@ "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -26732,26 +26375,26 @@ "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==" }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -27316,26 +26959,26 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", + "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", + "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", "semver": "^6.3.1", "tsconfig-paths": "^3.14.2" }, @@ -27855,7 +27498,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -28175,6 +27817,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", + "dev": true, "dependencies": { "@jest/expect-utils": "^28.1.3", "jest-get-type": "^28.0.2", @@ -28894,9 +28537,9 @@ "dev": true }, "node_modules/flow-parser": { - "version": "0.218.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.218.0.tgz", - "integrity": "sha512-mk4e7UK4P/W3tjrJyto6oxPuCjwvRMyzBh72hTl8T0dOcTzkP0M2JJHpncgyhKphMFi9pnjwHfc8e0oe4Uk3LA==", + "version": "0.219.5", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.219.5.tgz", + "integrity": "sha512-lHx/cl2XjopBx/ma9RYhG7FGj2JLKacoBwtI3leOp8AwRDPGwu6bzJoaCMfIl/sq14KdtY5MGzd5q6nKfGzcuQ==", "dev": true, "engines": { "node": ">=0.4.0" @@ -29192,9 +28835,9 @@ "dev": true }, "node_modules/fraction.js": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", - "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, "engines": { "node": "*" @@ -29318,9 +28961,12 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.6", @@ -29410,14 +29056,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -29831,7 +29477,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -29890,9 +29535,9 @@ } }, "node_modules/hardhat": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.18.0.tgz", - "integrity": "sha512-Com3SPFgk6v73LlE3rypuh32DYxOWvNbVBm5xfPUEzGVEW54Fcc4j3Uq7j6COj7S8Jc27uNihLFsveHYM0YJkQ==", + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.19.1.tgz", + "integrity": "sha512-bsWa63g1GB78ZyMN08WLhFElLPA+J+pShuKD1BFO2+88g3l+BL3R07vj9deIi9dMbssxgE714Gof1dBEDGqnCw==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", @@ -30256,14 +29901,6 @@ } } }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-ansi": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-4.0.1.tgz", @@ -30318,12 +29955,11 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -30513,6 +30149,17 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hast-to-hyperscript": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", @@ -31082,7 +30729,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, + "devOptional": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -31098,7 +30745,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=4" } @@ -31405,13 +31052,13 @@ "link": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -31485,15 +31132,15 @@ } }, "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, "node_modules/is-alphabetical": { @@ -31643,26 +31290,26 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", "dev": true, "dependencies": { - "kind-of": "^6.0.0" + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/is-date-object": { @@ -32281,20 +31928,50 @@ } }, "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==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "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" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, + "node_modules/istanbul-lib-instrument/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", @@ -32515,20 +32192,20 @@ } }, "node_modules/jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", - "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", + "version": "29.2.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.2.1.tgz", + "integrity": "sha512-K0N+7rx+fv3Us3KhuwRSJt55MMpZPs9Q3WSO/spRZSnsalX8yEYOTQ1PiSN7OvqzoRX4JEUXCbOJRlP4n8m5LA==", "dependencies": { - "@jest/core": "^28.1.3", - "@jest/types": "^28.1.3", + "@jest/core": "^29.2.1", + "@jest/types": "^29.2.1", "import-local": "^3.0.2", - "jest-cli": "^28.1.3" + "jest-cli": "^29.2.1" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -32540,52 +32217,102 @@ } }, "node_modules/jest-changed-files": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", - "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", + "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==", "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-changed-files/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/jest-circus": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", - "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", + "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==", "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/expect": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", + "@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": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^28.1.3", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", + "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": "^28.1.3", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-circus/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/chalk": { @@ -32617,18 +32344,96 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-circus/node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/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==", + "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-circus/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==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/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==", + "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-circus/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==", + "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-circus/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-circus/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus/node_modules/react-is": { @@ -32648,28 +32453,27 @@ } }, "node_modules/jest-cli": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", - "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dependencies": { - "@jest/core": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", + "@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", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "prompts": "^2.0.1", + "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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -32709,6 +32513,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-cli/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-cli/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -32721,35 +32541,35 @@ } }, "node_modules/jest-config": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", - "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.1.3", - "@jest/types": "^28.1.3", - "babel-jest": "^28.1.3", + "@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": "^28.1.3", - "jest-environment-node": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", + "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": "^28.1.3", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@types/node": "*", @@ -32764,14 +32584,6 @@ } } }, - "node_modules/jest-config/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/jest-config/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -32801,18 +32613,41 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-config/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==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-config/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-config/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-config/node_modules/react-is": { @@ -32835,6 +32670,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^28.1.1", @@ -32845,10 +32681,29 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/jest-diff/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-diff/node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, "node_modules/jest-diff/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -32857,6 +32712,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -32872,6 +32728,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -32886,6 +32743,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -32899,12 +32757,14 @@ "node_modules/jest-diff/node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "node_modules/jest-diff/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -32913,37 +32773,29 @@ } }, "node_modules/jest-docblock": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", - "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dependencies": { "detect-newline": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", - "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", + "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==", "dependencies": { - "@jest/types": "^28.1.3", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.1.3", - "pretty-format": "^28.1.3" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-each/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each/node_modules/chalk": { @@ -32975,18 +32827,41 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-each/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==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-each/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each/node_modules/react-is": { @@ -33006,51 +32881,164 @@ } }, "node_modules/jest-environment-node": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", - "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-environment-node/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-environment-node/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/jest-get-type": { "version": "28.0.2", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-haste-map": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", - "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dependencies": { - "@jest/types": "^28.1.3", + "@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": "^28.0.2", - "jest-util": "^28.1.3", - "jest-worker": "^28.1.3", + "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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-haste-map/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-haste-map/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-haste-map/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "engines": { + "node": ">=8" } }, "node_modules/jest-junit": { @@ -33078,37 +33066,36 @@ } }, "node_modules/jest-leak-detector": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", - "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", + "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==", "dependencies": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-leak-detector/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/jest-leak-detector/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==", "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-leak-detector/node_modules/react-is": { @@ -33120,6 +33107,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "jest-diff": "^28.1.3", @@ -33130,10 +33118,29 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/jest-matcher-utils/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, "node_modules/jest-matcher-utils/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -33142,6 +33149,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -33157,6 +33165,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -33171,6 +33180,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -33184,12 +33194,14 @@ "node_modules/jest-matcher-utils/node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "node_modules/jest-matcher-utils/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -33201,6 +33213,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^28.1.3", @@ -33216,10 +33229,46 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/jest-message-util/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, "node_modules/jest-message-util/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -33228,6 +33277,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -33243,6 +33293,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -33257,6 +33308,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, "dependencies": { "@jest/schemas": "^28.1.3", "ansi-regex": "^5.0.1", @@ -33270,12 +33322,14 @@ "node_modules/jest-message-util/node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "node_modules/jest-message-util/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -33284,15 +33338,16 @@ } }, "node_modules/jest-mock": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", - "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock-extended": { @@ -33307,6 +33362,62 @@ "typescript": "^3.0.0 || ^4.0.0 || ^5.0.0" } }, + "node_modules/jest-mock/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-mock/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-mock/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", @@ -33324,42 +33435,42 @@ } }, "node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", - "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", + "resolve.exports": "^2.0.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve-dependencies": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", - "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", + "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==", "dependencies": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.3" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve/node_modules/ansi-styles": { @@ -33391,6 +33502,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-resolve/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-resolve/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -33403,34 +33530,34 @@ } }, "node_modules/jest-runner": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", - "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dependencies": { - "@jest/console": "^28.1.3", - "@jest/environment": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", + "@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.10.2", + "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-leak-detector": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-resolve": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-util": "^28.1.3", - "jest-watcher": "^28.1.3", - "jest-worker": "^28.1.3", + "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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner/node_modules/ansi-styles": { @@ -33462,6 +33589,70 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-runner/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==", + "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-runner/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/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==", + "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/jest-runner/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/jest-runner/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -33491,35 +33682,35 @@ } }, "node_modules/jest-runtime": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", - "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", - "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/globals": "^28.1.3", - "@jest/source-map": "^28.1.2", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "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", - "execa": "^5.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-mock": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", + "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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime/node_modules/ansi-styles": { @@ -33551,6 +33742,70 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-runtime/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==", + "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-runtime/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/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==", + "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/jest-runtime/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/jest-runtime/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -33576,44 +33831,44 @@ } }, "node_modules/jest-snapshot": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", - "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "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/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", + "@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": "^28.1.3", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.1.3", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", + "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": "^28.1.3", - "semver": "^7.3.5" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/jest-snapshot/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==", + "dependencies": { + "jest-get-type": "^29.6.3" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/chalk": { @@ -33645,6 +33900,100 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-snapshot/node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "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/jest-snapshot/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==", + "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-snapshot/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==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/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==", + "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-snapshot/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==", + "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-snapshot/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-snapshot/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -33657,17 +34006,16 @@ } }, "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/react-is": { @@ -33709,6 +34057,7 @@ "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, "dependencies": { "@jest/types": "^28.1.3", "@types/node": "*", @@ -33721,10 +34070,46 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/jest-util/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-util/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-util/node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, "node_modules/jest-util/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -33739,6 +34124,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -33754,6 +34140,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -33762,27 +34149,19 @@ } }, "node_modules/jest-validate": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", - "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dependencies": { - "@jest/types": "^28.1.3", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^28.1.3" + "pretty-format": "^29.7.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-validate/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate/node_modules/chalk": { @@ -33814,18 +34193,25 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/jest-validate/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==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-validate/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate/node_modules/react-is": { @@ -33845,21 +34231,21 @@ } }, "node_modules/jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dependencies": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-watcher/node_modules/ansi-styles": { @@ -33891,6 +34277,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/jest-watcher/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-watcher/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -33903,16 +34305,73 @@ } }, "node_modules/jest-worker": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", - "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dependencies": { "@types/node": "*", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-worker/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-worker/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/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==", + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jiti": { @@ -34628,13 +35087,13 @@ "dev": true }, "node_modules/lerna": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-7.3.0.tgz", - "integrity": "sha512-Dt8TH+J+c9+3MhTYcm5OxnNzXb87WG7GPNj3kidjYJjJY7KxIMDNU37qBTYRWA1h3wAeNKBplXVQYUPkGcYgkQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-7.4.1.tgz", + "integrity": "sha512-c6sOO0dlJU689vStIsko+zjRdn2fJOWH8aNjePLNv2AubAdABKqfrDCpE2H/Q7+O80Duo68ZQtWYkUUk7hRWDw==", "dev": true, "dependencies": { - "@lerna/child-process": "7.3.0", - "@lerna/create": "7.3.0", + "@lerna/child-process": "7.4.1", + "@lerna/create": "7.4.1", "@npmcli/run-script": "6.0.2", "@nx/devkit": ">=16.5.1 < 17", "@octokit/plugin-enterprise-rest": "6.0.1", @@ -34713,27 +35172,9 @@ "lerna": "dist/cli.js" }, "engines": { - "node": "^14.17.0 || >=16.0.0" - } - }, - "node_modules/lerna/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": ">=16.0.0" } }, - "node_modules/lerna/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/lerna/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -34815,6 +35256,12 @@ } } }, + "node_modules/lerna/node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, "node_modules/lerna/node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -35532,9 +35979,9 @@ "dev": true }, "node_modules/libphonenumber-js": { - "version": "1.10.47", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.47.tgz", - "integrity": "sha512-b4t7VQDV29xx/ni+58yl9KWPGjnDLDXCeCTLrD4V8vDpObXZRZBrg7uX/HWZ7YXiJKqdBDGgc+barUUTNB6Slw==" + "version": "1.10.48", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.48.tgz", + "integrity": "sha512-Vvcgt4+o8+puIBJZLdMshPYx9nRN3/kTT7HPtOyfYrSQuN9PGBF1KUv0g07fjNzt4E4GuA7FnsLb+WeAMzyRQg==" }, "node_modules/lilconfig": { "version": "2.1.0", @@ -35933,9 +36380,9 @@ } }, "node_modules/locter/node_modules/destr": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.1.tgz", - "integrity": "sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.2.tgz", + "integrity": "sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==", "dev": true }, "node_modules/locter/node_modules/foreground-child": { @@ -36332,16 +36779,27 @@ } }, "node_modules/logform": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", - "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", "dependencies": { - "@colors/colors": "1.5.0", + "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" } }, "node_modules/loose-envify": { @@ -36357,12 +36815,12 @@ } }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "node_modules/lower-case": { @@ -37901,13 +38359,12 @@ } }, "node_modules/nock": { - "version": "13.3.3", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.3.tgz", - "integrity": "sha512-z+KUlILy9SK/RjpeXDiDUEAq4T94ADPHE3qaRkf66mpEhzc/ytOMm3Bwdrbq6k1tMWkbdujiKim3G2tfQARuJw==", + "version": "13.3.6", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.6.tgz", + "integrity": "sha512-lT6YuktKroUFM+27mubf2uqQZVy2Jf+pfGzuh9N6VwdHlFoZqvi4zyxFTVR1w/ChPqGY6yxGehHp6C3wqCASCw==", "dependencies": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.21", "propagate": "^2.0.0" }, "engines": { @@ -41379,24 +41836,6 @@ } } }, - "node_modules/nx/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/nx/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/nx/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -41728,9 +42167,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -42545,7 +42984,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, + "devOptional": true, "dependencies": { "callsites": "^3.0.0" }, @@ -42763,7 +43202,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -43283,9 +43722,9 @@ } }, "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", + "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", "dev": true, "engines": { "node": ">= 14" @@ -43934,9 +44373,9 @@ } }, "node_modules/property-expr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", - "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", "dev": true }, "node_modules/property-information": { @@ -44194,7 +44633,6 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", - "dev": true, "funding": [ { "type": "individual", @@ -44606,12 +45044,12 @@ } }, "node_modules/react-router": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.16.0.tgz", - "integrity": "sha512-VT4Mmc4jj5YyjpOi5jOf0I+TYzGpvzERy4ckNSvSh2RArv8LLoCxlsZ2D+tc7zgjxcY34oTz2hZaeX5RVprKqA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.17.0.tgz", + "integrity": "sha512-YJR3OTJzi3zhqeJYADHANCGPUu9J+6fT5GLv82UWRGSxu6oJYCKVmxUcaBQuGm9udpWmPsvpme/CdHumqgsoaA==", "dev": true, "dependencies": { - "@remix-run/router": "1.9.0" + "@remix-run/router": "1.10.0" }, "engines": { "node": ">=14.0.0" @@ -44621,13 +45059,13 @@ } }, "node_modules/react-router-dom": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.16.0.tgz", - "integrity": "sha512-aTfBLv3mk/gaKLxgRDUPbPw+s4Y/O+ma3rEN1u8EgEpLpPe6gNjIsWt9rxushMHHMb7mSwxRGdGlGdvmFsyPIg==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.17.0.tgz", + "integrity": "sha512-qWHkkbXQX+6li0COUUPKAUkxjNNqPJuiBd27dVwQGDNsuFBdMbrS6UZ0CLYc4CsbdLYTckn4oB4tGDuPZpPhaQ==", "dev": true, "dependencies": { - "@remix-run/router": "1.9.0", - "react-router": "6.16.0" + "@remix-run/router": "1.10.0", + "react-router": "6.17.0" }, "engines": { "node": ">=14.0.0" @@ -45571,9 +46009,9 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -45655,9 +46093,9 @@ "dev": true }, "node_modules/resolve.exports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "engines": { "node": ">=10" } @@ -46222,9 +46660,9 @@ } }, "node_modules/sass": { - "version": "1.69.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.0.tgz", - "integrity": "sha512-l3bbFpfTOGgQZCLU/gvm1lbsQ5mC/WnLz3djL2v4WCJBDrWm58PO+jgngcGRNnKUh6wSsdm50YaovTqskZ0xDQ==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz", + "integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==", "devOptional": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -46483,18 +46921,18 @@ } }, "node_modules/semantic-release/node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.2.tgz", + "integrity": "sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==", "dev": true }, "node_modules/semantic-release/node_modules/@octokit/plugin-paginate-rest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", - "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.1.tgz", + "integrity": "sha512-e48ypUbfVWWXHyWsjVHdYFMLSdVaWJkAF5Tg9yfO92ltqd3JmuxWLlmwA5B1n9niSy7qsjBWPbEvREyCXqBQkA==", "dev": true, "dependencies": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.1.0" }, "engines": { "node": ">= 18" @@ -46521,9 +46959,9 @@ } }, "node_modules/semantic-release/node_modules/@octokit/plugin-throttling": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.0.0.tgz", - "integrity": "sha512-OkMbHYUidj81q92YRkPzWmwXkEtsI3KOcSkNm763aqUOh9IEplyX05XjKAdZFANAvaYH0Q4JBZwu4h2VnPVXZA==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.1.2.tgz", + "integrity": "sha512-oFba+ioR6HGb0fgqxMta7Kpk/MdffUTuUxNY856l1nXPvh7Qggp8w4AksRx1SDA8SGd+4cbrpkY4k1J/Xz8nZQ==", "dev": true, "dependencies": { "@octokit/types": "^12.0.0", @@ -46537,9 +46975,9 @@ } }, "node_modules/semantic-release/node_modules/@octokit/request": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.3.tgz", - "integrity": "sha512-iUvXP4QmysS8kyE/a4AGwR0A+tHDVxgW6TmPd2ci8/Xc8KjlBtTKSDpZlUT5Y4S4Nu+eM8LvbOYjVAp/sz3Gpg==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.4.tgz", + "integrity": "sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==", "dev": true, "dependencies": { "@octokit/endpoint": "^9.0.0", @@ -46567,12 +47005,12 @@ } }, "node_modules/semantic-release/node_modules/@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.1.1.tgz", + "integrity": "sha512-qnJTldJ1NyGT5MTsCg/Zi+y2IFHZ1Jo5+njNCjJ9FcainV7LjuHgmB697kA0g4MjZeDAJsM3B45iqCVsCLVFZg==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^19.0.2" } }, "node_modules/semantic-release/node_modules/@semantic-release/commit-analyzer": { @@ -50602,9 +51040,9 @@ } }, "node_modules/semantic-release/node_modules/type-fest": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.4.0.tgz", - "integrity": "sha512-HT3RRs7sTfY22KuPQJkD/XjbTbxgP2Je5HPt6H6JEGvcjHd5Lqru75EbrP3tb4FYjNJ+DjLp+MNQTFQU0mhXNw==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.6.0.tgz", + "integrity": "sha512-rLjWJzQFOq4xw7MgJrCZ6T1jIOvvYElXT12r+y0CC6u67hegDHaxcPqb2fZHOGlqxugGQPNB1EnTezjBetkwkw==", "dev": true, "engines": { "node": ">=16" @@ -50846,6 +51284,20 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-function-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", @@ -52518,6 +52970,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -52530,6 +52983,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -52593,9 +53047,9 @@ "dev": true }, "node_modules/tailwindcss": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", - "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.5.tgz", + "integrity": "sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==", "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -52603,10 +53057,10 @@ "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.18.2", + "jiti": "^1.19.1", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", @@ -52841,25 +53295,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terser": { - "version": "5.21.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.21.0.tgz", - "integrity": "sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", + "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -53343,14 +53782,14 @@ "dev": true }, "node_modules/ts-jest": { - "version": "28.0.8", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", - "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", + "version": "29.0.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", + "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==", "dev": true, "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^28.0.0", + "jest-util": "^29.0.0", "json5": "^2.2.1", "lodash.memoize": "4.x", "make-error": "1.x", @@ -53361,13 +53800,13 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^28.0.0", - "babel-jest": "^28.0.0", - "jest": "^28.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", "typescript": ">=4.3" }, "peerDependenciesMeta": { @@ -53393,42 +53832,11 @@ "jest-resolve": "^29.5.0" } }, - "node_modules/ts-jest-resolver/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==", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/ts-jest-resolver/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==", - "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/ts-jest-resolver/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==" - }, - "node_modules/ts-jest-resolver/node_modules/ansi-styles": { + "node_modules/ts-jest/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -53439,10 +53847,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ts-jest-resolver/node_modules/chalk": { + "node_modules/ts-jest/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -53454,69 +53863,11 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ts-jest-resolver/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==", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/ts-jest-resolver/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==", - "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/ts-jest-resolver/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==", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/ts-jest-resolver/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==", - "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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/ts-jest-resolver/node_modules/jest-util": { + "node_modules/ts-jest/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": "*", @@ -53529,98 +53880,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ts-jest-resolver/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==", - "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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/ts-jest-resolver/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==", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/ts-jest-resolver/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==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/ts-jest-resolver/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==", - "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/ts-jest-resolver/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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-jest-resolver/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, - "node_modules/ts-jest-resolver/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==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest-resolver/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ts-jest/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -53648,6 +53907,18 @@ "node": ">=10" } }, + "node_modules/ts-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ts-jest/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -54453,9 +54724,9 @@ } }, "node_modules/undici": { - "version": "5.25.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.25.4.tgz", - "integrity": "sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==", + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.0.tgz", + "integrity": "sha512-l3ydWhlhOJzMVOYkymLykcRRXqbUaQriERtR70B9LzNkZ4bX52Fc8wbTDneMiwo8T+AemZXvXaTx+9o5ROxrXg==", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -56191,9 +56462,9 @@ } }, "node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -56529,13 +56800,13 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.4", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" @@ -56651,16 +56922,16 @@ } }, "node_modules/winston-transport": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", - "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz", + "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==", "dependencies": { "logform": "^2.3.2", "readable-stream": "^3.6.0", "triple-beam": "^1.3.0" }, "engines": { - "node": ">= 6.4.0" + "node": ">= 12.0.0" } }, "node_modules/winston-transport/node_modules/readable-stream": { @@ -56962,7 +57233,7 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 6" } @@ -57125,12 +57396,12 @@ "@typescript-eslint/parser": "^5.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", - "jest": "28.1.3", + "jest": "29.2.1", "jest-junit": "^14.0.1", "lint-staged": "^13.0.3", "source-map-support": "^0.5.20", "supertest": "^6.1.3", - "ts-jest": "28.0.8", + "ts-jest": "29.0.3", "ts-loader": "^9.2.3", "ts-node": "^10.0.0", "tsconfig-paths": "4.1.0" @@ -57290,7 +57561,6 @@ "license": "MIT", "dependencies": { "@matterlabs/composables": "1.1.7", - "@matterlabs/token-library": "2.9.0", "@vueuse/components": "8.9.2", "@vueuse/core": "8.9.2", "date-fns": "2.28.0", @@ -57550,15 +57820,15 @@ } }, "packages/app/node_modules/@types/node": { - "version": "16.18.58", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.58.tgz", - "integrity": "sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA==", + "version": "16.18.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.59.tgz", + "integrity": "sha512-PJ1w2cNeKUEdey4LiPra0ZuxZFOGvetswE8qHRriV/sUkL5Al4tTmPV9D2+Y/TPIxTHHgxTfRjZVKWhPw/ORhQ==", "dev": true }, "packages/app/node_modules/@types/yargs": { - "version": "15.0.16", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.16.tgz", - "integrity": "sha512-2FeD5qezW3FvLpZ0JpfuaEWepgNLl9b2gQYiz/ce0NhoB1W/D+VZu98phITXkADYerfr/jb7JcDcVhITsc9bwg==", + "version": "15.0.17", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.17.tgz", + "integrity": "sha512-cj53I8GUcWJIgWVTSVe2L7NJAB5XWGdsoMosVvUgv1jEnMbAcsbaCzt1coUcyi8Sda5PgTWAooG8jNyDTD+CWA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -57724,107 +57994,306 @@ "node": ">=10.13.0" } }, - "packages/app/node_modules/prettier-plugin-tailwindcss": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.8.tgz", - "integrity": "sha512-KgPcEnJeIijlMjsA6WwYgRs5rh3/q76oInqtMXBA/EMcamrcYJpyhtRhyX1ayT9hnHlHTuO8sIifHF10WuSDKg==", - "dev": true, + "packages/app/node_modules/prettier-plugin-tailwindcss": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.8.tgz", + "integrity": "sha512-KgPcEnJeIijlMjsA6WwYgRs5rh3/q76oInqtMXBA/EMcamrcYJpyhtRhyX1ayT9hnHlHTuO8sIifHF10WuSDKg==", + "dev": true, + "engines": { + "node": ">=12.17.0" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@shufo/prettier-plugin-blade": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "prettier": ">=2.2.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*", + "prettier-plugin-twig-melody": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@shufo/prettier-plugin-blade": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "prettier-plugin-twig-melody": { + "optional": true + } + } + }, + "packages/app/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/app/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "packages/app/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "packages/data-fetcher": { + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@nestjs/common": "^9.0.0", + "@nestjs/config": "^2.2.0", + "@nestjs/core": "^9.0.0", + "@nestjs/platform-express": "^9.0.0", + "@nestjs/terminus": "^9.1.2", + "@willsoto/nestjs-prometheus": "^4.7.0", + "ethers": "^5.7.1", + "nest-winston": "^1.7.0", + "prom-client": "^14.1.0", + "reflect-metadata": "^0.1.13", + "rimraf": "^3.0.2", + "rxjs": "^7.2.0", + "winston": "^3.8.2", + "zksync-web3": "0.15.4" + }, + "devDependencies": { + "@nestjs/cli": "^9.0.0", + "@nestjs/schematics": "^9.0.0", + "@nestjs/testing": "^9.0.0", + "@types/express": "^4.17.13", + "@types/jest": "28.1.8", + "@types/supertest": "^2.0.11", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0", + "jest": "29.2.1", + "jest-junit": "^14.0.1", + "jest-mock-extended": "^3.0.1", + "lint-staged": "^13.0.3", + "source-map-support": "^0.5.20", + "supertest": "^6.1.3", + "ts-jest": "29.0.3", + "ts-loader": "^9.2.3", + "ts-node": "^10.0.0", + "tsconfig-paths": "4.1.0" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=9.0.0" + } + }, + "packages/data-fetcher/node_modules/@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "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/logger": "^5.7.0" + } + }, + "packages/data-fetcher/node_modules/@ethersproject/providers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", + "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "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/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "packages/data-fetcher/node_modules/@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "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/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "packages/data-fetcher/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "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/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "packages/data-fetcher/node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "engines": { - "node": ">=12.17.0" + "node": ">=8.3.0" }, "peerDependencies": { - "@ianvs/prettier-plugin-sort-imports": "*", - "@prettier/plugin-pug": "*", - "@shopify/prettier-plugin-liquid": "*", - "@shufo/prettier-plugin-blade": "*", - "@trivago/prettier-plugin-sort-imports": "*", - "prettier": ">=2.2.0", - "prettier-plugin-astro": "*", - "prettier-plugin-css-order": "*", - "prettier-plugin-import-sort": "*", - "prettier-plugin-jsdoc": "*", - "prettier-plugin-organize-attributes": "*", - "prettier-plugin-organize-imports": "*", - "prettier-plugin-style-order": "*", - "prettier-plugin-svelte": "*", - "prettier-plugin-twig-melody": "*" + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { - "@ianvs/prettier-plugin-sort-imports": { - "optional": true - }, - "@prettier/plugin-pug": { - "optional": true - }, - "@shopify/prettier-plugin-liquid": { - "optional": true - }, - "@shufo/prettier-plugin-blade": { - "optional": true - }, - "@trivago/prettier-plugin-sort-imports": { - "optional": true - }, - "prettier-plugin-astro": { - "optional": true - }, - "prettier-plugin-css-order": { - "optional": true - }, - "prettier-plugin-import-sort": { - "optional": true - }, - "prettier-plugin-jsdoc": { - "optional": true - }, - "prettier-plugin-organize-attributes": { - "optional": true - }, - "prettier-plugin-organize-imports": { - "optional": true - }, - "prettier-plugin-style-order": { - "optional": true - }, - "prettier-plugin-svelte": { + "bufferutil": { "optional": true }, - "prettier-plugin-twig-melody": { + "utf-8-validate": { "optional": true } } }, - "packages/app/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/app/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "packages/app/node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "packages/data-fetcher/node_modules/zksync-web3": { + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/zksync-web3/-/zksync-web3-0.15.4.tgz", + "integrity": "sha512-6CEpRBbF4nGwRYSF3KvPGqg2aNJFYTl8AR+cejBnC2Uyu1v3NYSkmkXXVuMGupJ7HIQR1aTqFEDsUFPyO/bL0Q==", + "deprecated": "This package has been deprecated in favor of zksync-ethers@5.0.0", + "peerDependencies": { + "ethers": "^5.7.0" } }, "packages/integration-tests": { @@ -57939,143 +58408,6 @@ "@ethersproject/strings": "^5.7.0" } }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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 - } - } - }, - "packages/integration-tests/node_modules/@jest/core/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 - } - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, "packages/integration-tests/node_modules/@jest/expect-utils": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", @@ -58088,180 +58420,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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 - } - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, "packages/integration-tests/node_modules/@matterlabs/hardhat-zksync-deploy": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-0.6.5.tgz", @@ -58281,119 +58439,43 @@ "packages/integration-tests/node_modules/@matterlabs/hardhat-zksync-deploy/node_modules/@matterlabs/hardhat-zksync-solc": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-0.4.2.tgz", - "integrity": "sha512-6NFWPSZiOAoo7wNuhMg4ztj7mMEH+tLrx09WuCbcURrHPijj/KxYNsJD6Uw5lapKr7G8H7SQISGid1/MTXVmXQ==", - "dev": true, - "dependencies": { - "@nomiclabs/hardhat-docker": "^2.0.0", - "chalk": "4.1.2", - "dockerode": "^3.3.4", - "fs-extra": "^11.1.1", - "proper-lockfile": "^4.1.2", - "semver": "^7.5.1" - }, - "peerDependencies": { - "hardhat": "^2.14.0" - } - }, - "packages/integration-tests/node_modules/@playwright/test": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz", - "integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==", - "dev": true, - "dependencies": { - "playwright": "1.38.1" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=16" - } - }, - "packages/integration-tests/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 - }, - "packages/integration-tests/node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/node_modules/@types/jest": { - "version": "29.5.5", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", - "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "packages/integration-tests/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" + "integrity": "sha512-6NFWPSZiOAoo7wNuhMg4ztj7mMEH+tLrx09WuCbcURrHPijj/KxYNsJD6Uw5lapKr7G8H7SQISGid1/MTXVmXQ==", + "dev": true, + "dependencies": { + "@nomiclabs/hardhat-docker": "^2.0.0", + "chalk": "4.1.2", + "dockerode": "^3.3.4", + "fs-extra": "^11.1.1", + "proper-lockfile": "^4.1.2", + "semver": "^7.5.1" }, "peerDependencies": { - "@babel/core": "^7.8.0" + "hardhat": "^2.14.0" } }, - "packages/integration-tests/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==", + "packages/integration-tests/node_modules/@playwright/test": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.0.tgz", + "integrity": "sha512-PdW+kn4eV99iP5gxWNSDQCbhMaDVej+RXL5xr6t04nbKLCBwYtA046t7ofoczHOm8u6c+45hpDKQVZqtqwkeQg==", "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" + "playwright": "1.40.0" + }, + "bin": { + "playwright": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=16" } }, - "packages/integration-tests/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==", + "packages/integration-tests/node_modules/@types/jest": { + "version": "29.5.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", + "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", "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" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "packages/integration-tests/node_modules/chalk": { @@ -58427,26 +58509,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "packages/integration-tests/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 - }, - "packages/integration-tests/node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, "packages/integration-tests/node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -58456,18 +58518,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "packages/integration-tests/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" - } - }, "packages/integration-tests/node_modules/ethers": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", @@ -58546,22 +58596,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "packages/integration-tests/node_modules/istanbul-lib-instrument": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", - "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": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, "packages/integration-tests/node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -58588,129 +58622,6 @@ } } }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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 - } - } - }, - "packages/integration-tests/node_modules/jest-cli/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 - } - } - }, "packages/integration-tests/node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -58726,51 +58637,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, "packages/integration-tests/node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -58780,44 +58646,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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" - } - }, "packages/integration-tests/node_modules/jest-matcher-utils": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", @@ -58853,158 +58681,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "packages/integration-tests/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/integration-tests/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/integration-tests/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": { - "@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" - } - }, - "packages/integration-tests/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" - } - }, - "packages/integration-tests/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "packages/integration-tests/node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -59022,72 +58698,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "packages/integration-tests/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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/integration-tests/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": { - "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/integration-tests/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/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/integration-tests/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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "packages/integration-tests/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -59101,12 +58711,12 @@ } }, "packages/integration-tests/node_modules/playwright": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz", - "integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", + "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", "dev": true, "dependencies": { - "playwright-core": "1.38.1" + "playwright-core": "1.40.0" }, "bin": { "playwright": "cli.js" @@ -59119,9 +58729,9 @@ } }, "packages/integration-tests/node_modules/playwright-core": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz", - "integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", + "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -59150,15 +58760,6 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "packages/integration-tests/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" - } - }, "packages/integration-tests/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -59174,25 +58775,6 @@ "node": ">=10" } }, - "packages/integration-tests/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/integration-tests/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": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "packages/integration-tests/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -59276,9 +58858,9 @@ "dev": true }, "packages/integration-tests/node_modules/zksync-web3": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/zksync-web3/-/zksync-web3-0.14.3.tgz", - "integrity": "sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ==", + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/zksync-web3/-/zksync-web3-0.14.4.tgz", + "integrity": "sha512-kYehMD/S6Uhe1g434UnaMN+sBr9nQm23Ywn0EUP5BfQCsbjcr3ORuS68PosZw8xUTu3pac7G6YMSnNHk+fwzvg==", "dev": true, "peerDependencies": { "ethers": "^5.7.0" @@ -59288,6 +58870,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { + "@nestjs/axios": "^3.0.0", "@nestjs/common": "^9.0.0", "@nestjs/config": "^2.2.0", "@nestjs/core": "^9.0.0", @@ -59296,6 +58879,7 @@ "@nestjs/terminus": "^9.1.2", "@nestjs/typeorm": "^9.0.1", "@willsoto/nestjs-prometheus": "^4.7.0", + "axios": "^1.4.0", "ethers": "^5.7.1", "nest-winston": "^1.7.0", "pg": "^8.8.0", @@ -59318,13 +58902,13 @@ "@typescript-eslint/parser": "^5.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", - "jest": "28.1.3", + "jest": "29.2.1", "jest-junit": "^14.0.1", "jest-mock-extended": "^3.0.1", "lint-staged": "^13.0.3", "source-map-support": "^0.5.20", "supertest": "^6.1.3", - "ts-jest": "28.0.8", + "ts-jest": "29.0.3", "ts-loader": "^9.2.3", "ts-node": "^10.0.0", "tsconfig-paths": "4.1.0", diff --git a/packages/api/.env.example b/packages/api/.env.example index eeaf301412..ed85f208b3 100644 --- a/packages/api/.env.example +++ b/packages/api/.env.example @@ -6,8 +6,11 @@ METRICS_PORT=3005 COLLECT_DB_CONNECTION_POOL_METRICS_INTERVAL=10000 PORT=3020 LOG_LEVEL=debug -LIMITED_PAGINATION_MAX_ITEMS=100000 +LIMITED_PAGINATION_MAX_ITEMS=10000 +API_LIMITED_PAGINATION_MAX_ITEMS=1000 DISABLE_API_SCHEMA_DOCS=false +DISABLE_BFF_API_SCHEMA_DOCS=false DISABLE_EXTERNAL_API=false DATABASE_STATEMENT_TIMEOUT_MS=90000 CONTRACT_VERIFICATION_API_URL=http://127.0.0.1:3070 +NETWORK_NAME=testnet-goerli diff --git a/packages/api/.env.test b/packages/api/.env.test index 3566e2364e..d4d855e2d6 100644 --- a/packages/api/.env.test +++ b/packages/api/.env.test @@ -2,4 +2,5 @@ DATABASE_URL='postgres://postgres:postgres@localhost:5432/block-explorer-e2e' METRICS_PORT=3005 PORT=3007 LIMITED_PAGINATION_MAX_ITEMS=15 +API_LIMITED_PAGINATION_MAX_ITEMS=15 CONTRACT_VERIFICATION_API_URL=http://verification.api diff --git a/packages/api/Dockerfile b/packages/api/Dockerfile index 2dc91c236d..55c750f00a 100644 --- a/packages/api/Dockerfile +++ b/packages/api/Dockerfile @@ -38,5 +38,6 @@ ENV METRICS_PORT $METRICS_PORT EXPOSE $PORT $METRICS_PORT 9229 9230 USER node +WORKDIR /usr/src/app/packages/api -CMD [ "node", "packages/api/dist/main.js" ] +CMD [ "node", "dist/main.js" ] diff --git a/packages/api/nest-cli.json b/packages/api/nest-cli.json index 256648114a..db78c9f4be 100644 --- a/packages/api/nest-cli.json +++ b/packages/api/nest-cli.json @@ -1,5 +1,10 @@ { "$schema": "https://json.schemastore.org/nest-cli", "collection": "@nestjs/schematics", - "sourceRoot": "src" -} + "sourceRoot": "src", + "compilerOptions": { + "assets": [ + "config/docs/constants.*.json" + ] + } +} \ No newline at end of file diff --git a/packages/api/package.json b/packages/api/package.json index 1d8e79915f..60db3155d0 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -62,12 +62,12 @@ "@typescript-eslint/parser": "^5.0.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", - "jest": "28.1.3", + "jest": "29.2.1", "jest-junit": "^14.0.1", "lint-staged": "^13.0.3", "source-map-support": "^0.5.20", "supertest": "^6.1.3", - "ts-jest": "28.0.8", + "ts-jest": "29.0.3", "ts-loader": "^9.2.3", "ts-node": "^10.0.0", "tsconfig-paths": "4.1.0" diff --git a/packages/api/src/address/address.controller.spec.ts b/packages/api/src/address/address.controller.spec.ts index fb040b44b9..e215f6c378 100644 --- a/packages/api/src/address/address.controller.spec.ts +++ b/packages/api/src/address/address.controller.spec.ts @@ -7,8 +7,6 @@ import { BalanceService } from "../balance/balance.service"; import { BlockService } from "../block/block.service"; import { LogService } from "../log/log.service"; import { TransactionService } from "../transaction/transaction.service"; -import { TransactionReceiptService } from "../transaction/transactionReceipt.service"; -import { TransactionReceipt } from "../transaction/entities/transactionReceipt.entity"; import { Log } from "../log/log.entity"; import { Token } from "../token/token.entity"; import { PagingOptionsWithMaxItemsLimitDto } from "../common/dtos"; @@ -28,7 +26,6 @@ describe("AddressController", () => { let logServiceMock: LogService; let balanceServiceMock: BalanceService; let transactionServiceMock: TransactionService; - let transactionReceiptServiceMock: TransactionReceiptService; let transferServiceMock: TransferService; const blockchainAddress = "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; const normalizedAddress = "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF"; @@ -38,7 +35,6 @@ describe("AddressController", () => { serviceMock = mock(); blockServiceMock = mock(); transactionServiceMock = mock(); - transactionReceiptServiceMock = mock(); logServiceMock = mock(); balanceServiceMock = mock(); transferServiceMock = mock(); @@ -58,10 +54,6 @@ describe("AddressController", () => { provide: TransactionService, useValue: transactionServiceMock, }, - { - provide: TransactionReceiptService, - useValue: transactionReceiptServiceMock, - }, { provide: LogService, useValue: logServiceMock, @@ -104,9 +96,8 @@ describe("AddressController", () => { describe("when contract address exists", () => { const transactionHash = "transactionHash"; - const transactionFrom = "transactionFrom"; + const creatorAddress = "creatorAddress"; const totalTxCount = 20; - let transactionReceipt; const addressBalances = { balances: { "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF": { @@ -128,21 +119,13 @@ describe("AddressController", () => { bytecode: "0x123", createdInBlockNumber: 30, creatorTxHash: transactionHash, - creatorAddress: transactionFrom, + creatorAddress, }; - transactionReceipt = mock({ from: transactionFrom }); (serviceMock.findOne as jest.Mock).mockResolvedValue(addressRecord); - (transactionReceiptServiceMock.findOne as jest.Mock).mockResolvedValue(transactionReceipt); (transactionServiceMock.count as jest.Mock).mockResolvedValue(totalTxCount); (balanceServiceMock.getBalances as jest.Mock).mockResolvedValue(addressBalances); }); - it("queries creatorAddress value from transaction receipt", async () => { - await controller.getAddress(blockchainAddress); - expect(transactionReceiptServiceMock.findOne).toHaveBeenCalledTimes(1); - expect(transactionReceiptServiceMock.findOne).toHaveBeenCalledWith(transactionHash, ["from"]); - }); - it("queries totalTransactions value from transaction receipt repo with formatted contractAddress", async () => { await controller.getAddress(blockchainAddress); expect(transactionServiceMock.count).toHaveBeenCalledTimes(1); diff --git a/packages/api/src/address/address.controller.ts b/packages/api/src/address/address.controller.ts index 5c1498c089..70f18a078c 100644 --- a/packages/api/src/address/address.controller.ts +++ b/packages/api/src/address/address.controller.ts @@ -1,5 +1,13 @@ import { Controller, Get, Param, Query } from "@nestjs/common"; -import { ApiTags, ApiParam, ApiOkResponse, ApiBadRequestResponse, ApiExtraModels, refs } from "@nestjs/swagger"; +import { + ApiTags, + ApiParam, + ApiOkResponse, + ApiBadRequestResponse, + ApiExtraModels, + refs, + ApiExcludeController, +} from "@nestjs/swagger"; import { Pagination } from "nestjs-typeorm-paginate"; import { utils } from "ethers"; import { PagingOptionsWithMaxItemsLimitDto, ListFiltersDto } from "../common/dtos"; @@ -8,7 +16,6 @@ import { formatHexAddress, buildDateFilter } from "../common/utils"; import { AddressService } from "./address.service"; import { BlockService } from "../block/block.service"; import { TransactionService } from "../transaction/transaction.service"; -import { TransactionReceiptService } from "../transaction/transactionReceipt.service"; import { BalanceService } from "../balance/balance.service"; import { AddressType, ContractDto, AccountDto, TokenAddressDto } from "./dtos"; import { LogDto } from "../log/log.dto"; @@ -16,17 +23,19 @@ import { LogService } from "../log/log.service"; import { ParseAddressPipe, ADDRESS_REGEX_PATTERN } from "../common/pipes/parseAddress.pipe"; import { TransferService } from "../transfer/transfer.service"; import { TransferDto } from "../transfer/transfer.dto"; +import { swagger } from "../config/featureFlags"; +import { constants } from "../config/docs"; const entityName = "address"; -@ApiTags(entityName) +@ApiTags("Address BFF") +@ApiExcludeController(!swagger.bffEnabled) @Controller(entityName) export class AddressController { constructor( private readonly addressService: AddressService, private readonly blockService: BlockService, private readonly transactionService: TransactionService, - private readonly transactionReceiptService: TransactionReceiptService, private readonly logService: LogService, private readonly balanceService: BalanceService, private readonly transferService: TransferService @@ -36,7 +45,7 @@ export class AddressController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.address, description: "Valid hex address", }) @ApiExtraModels(AccountDto, ContractDto) @@ -55,11 +64,7 @@ export class AddressController { ]); if (addressRecord?.bytecode.length > 2) { - const [txReceipt, totalTransactions] = await Promise.all([ - this.transactionReceiptService.findOne(addressRecord.creatorTxHash, ["from"]), - this.transactionService.count({ "from|to": formatHexAddress(address) }), - ]); - + const totalTransactions = await this.transactionService.count({ "from|to": formatHexAddress(address) }); return { type: AddressType.Contract, ...addressRecord, @@ -68,7 +73,7 @@ export class AddressController { createdInBlockNumber: addressRecord.createdInBlockNumber, creatorTxHash: addressRecord.creatorTxHash, totalTransactions, - creatorAddress: txReceipt.from, + creatorAddress: addressRecord.creatorAddress, }; } @@ -102,7 +107,7 @@ export class AddressController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.contractAddressWithLogs, description: "Valid hex address", }) @ApiListPageOkResponse(LogDto, { description: "Successfully returned address logs" }) @@ -126,7 +131,7 @@ export class AddressController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.address, description: "Valid hex address", }) @ApiListPageOkResponse(TransferDto, { description: "Successfully returned address transfers" }) diff --git a/packages/api/src/address/dtos/baseAddress.dto.ts b/packages/api/src/address/dtos/baseAddress.dto.ts index bc78059e9f..cc93fa4604 100644 --- a/packages/api/src/address/dtos/baseAddress.dto.ts +++ b/packages/api/src/address/dtos/baseAddress.dto.ts @@ -50,6 +50,9 @@ export class BaseAddressDto { symbol: "symbol", name: "Token name", decimals: 18, + usdPrice: 1.0001, + liquidity: 1000000, + iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", }, }, "0xD754fF5e8A6f257E162F72578A4Bb0493C0681d9": { @@ -60,6 +63,9 @@ export class BaseAddressDto { symbol: "symbol 2", name: "Token name 2", decimals: 18, + usdPrice: 1.0001, + liquidity: 1000000, + iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", }, }, }, diff --git a/packages/api/src/api/account/account.controller.spec.ts b/packages/api/src/api/account/account.controller.spec.ts index 921bf8e54e..f5b2f14c6e 100644 --- a/packages/api/src/api/account/account.controller.spec.ts +++ b/packages/api/src/api/account/account.controller.spec.ts @@ -3,6 +3,7 @@ import { mock } from "jest-mock-extended"; import { BadRequestException, Logger } from "@nestjs/common"; import { L2_ETH_TOKEN_ADDRESS } from "../../common/constants"; import { BlockService } from "../../block/block.service"; +import { BlockDetails } from "../../block/blockDetails.entity"; import { TransactionService } from "../../transaction/transaction.service"; import { BalanceService } from "../../balance/balance.service"; import { TransactionStatus } from "../../transaction/entities/transaction.entity"; @@ -49,6 +50,7 @@ describe("AccountController", () => { cumulativeGasUsed: "1200000", gasUsed: "900000", }, + type: 255, }, }; @@ -91,6 +93,7 @@ describe("AccountController", () => { cumulativeGasUsed: "1200000", gasUsed: "900000", }, + type: 255, }, } as Transfer; @@ -104,6 +107,7 @@ describe("AccountController", () => { beforeEach(async () => { blockServiceMock = mock({ getLastBlockNumber: jest.fn().mockResolvedValue(100), + findMany: jest.fn().mockResolvedValue([]), }); transactionServiceMock = mock({ findByAddress: jest.fn().mockResolvedValue([]), @@ -244,6 +248,7 @@ describe("AccountController", () => { transactionIndex: "10", txreceipt_status: "1", value: "1000000", + type: "255", }, ], }); @@ -329,6 +334,7 @@ describe("AccountController", () => { traceId: "0", type: "call", value: "1000000", + transactionType: "255", }, ], }); @@ -434,6 +440,7 @@ describe("AccountController", () => { tokenSymbol: "TKN", transactionIndex: "10", value: "1000000", + transactionType: "255", }, ], }); @@ -540,6 +547,7 @@ describe("AccountController", () => { tokenSymbol: "TKN", transactionIndex: "10", value: "1000000", + transactionType: "255", }, ], }); @@ -603,4 +611,41 @@ describe("AccountController", () => { expect(parseAddressListPipeExceptionFactory()).toEqual(new BadRequestException("Error! Missing address")); }); }); + + describe("getAccountMinedBlocks", () => { + it("returns not ok response when no blocks by miner found", async () => { + const response = await controller.getAccountMinedBlocks(address, { + page: 1, + offset: 10, + maxLimit: 100, + }); + expect(response).toEqual({ + status: ResponseStatus.NOTOK, + message: ResponseMessage.NO_TRANSACTIONS_FOUND, + result: [], + }); + }); + + it("returns blocks list response when block by miner are found", async () => { + jest + .spyOn(blockServiceMock, "findMany") + .mockResolvedValue([{ number: 1, timestamp: new Date("2023-03-03") } as BlockDetails]); + const response = await controller.getAccountMinedBlocks(address, { + page: 1, + offset: 10, + maxLimit: 100, + }); + expect(response).toEqual({ + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: [ + { + blockNumber: "1", + timeStamp: "1677801600", + blockReward: "0", + }, + ], + }); + }); + }); }); diff --git a/packages/api/src/api/account/account.controller.ts b/packages/api/src/api/account/account.controller.ts index 507875b9c9..5299fa44b6 100644 --- a/packages/api/src/api/account/account.controller.ts +++ b/packages/api/src/api/account/account.controller.ts @@ -2,6 +2,7 @@ import { Controller, Get, Query, Logger, UseFilters, ParseArrayPipe, BadRequestE import { ApiTags, ApiExcludeController } from "@nestjs/swagger"; import { L2_ETH_TOKEN_ADDRESS } from "../../common/constants"; import { TokenType } from "../../token/token.entity"; +import { dateToTimestamp } from "../../common/utils"; import { BlockService } from "../../block/block.service"; import { TransactionService } from "../../transaction/transaction.service"; import { TransferService } from "../../transfer/transfer.service"; @@ -25,6 +26,7 @@ import { AccountEtherBalanceResponseDto, AccountsEtherBalancesResponseDto, } from "../dtos/account/accountEtherBalanceResponse.dto"; +import { AccountMinedBlocksResponseDto } from "../dtos/account/accountMinedBlocksResponse.dto"; import { ApiExceptionFilter } from "../exceptionFilter"; const entityName = "account"; @@ -225,4 +227,32 @@ export class AccountController { result: balance, }; } + + @Get("/getminedblocks") + public async getAccountMinedBlocks( + @Query("address", new ParseAddressPipe()) address: string, + @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto + ): Promise { + const blocks = await this.blockService.findMany({ + miner: address, + ...pagingOptions, + selectFields: ["number", "timestamp"], + }); + if (!blocks.length) { + return { + status: ResponseStatus.NOTOK, + message: ResponseMessage.NO_TRANSACTIONS_FOUND, + result: [], + }; + } + return { + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: blocks.map((block) => ({ + blockNumber: block.number.toString(), + timeStamp: dateToTimestamp(block.timestamp).toString(), + blockReward: "0", + })), + }; + } } diff --git a/packages/api/src/api/api.controller.spec.ts b/packages/api/src/api/api.controller.spec.ts index bf6968c6c4..f1688725a0 100644 --- a/packages/api/src/api/api.controller.spec.ts +++ b/packages/api/src/api/api.controller.spec.ts @@ -16,11 +16,11 @@ describe("ApiController", () => { controller = module.get(ApiController); }); - describe("apiHandler", () => { + describe("apiGetHandler", () => { it("delegates request handling to a different controller based on module and action from query string", async () => { const request = mock(); const next = jest.fn(); - await controller.apiHandler(request, next, ApiModule.Contract, ApiContractAction.GetAbi, { + await controller.apiGetHandler(request, next, ApiContractAction.GetAbi, ApiModule.Contract, { module: ApiModule.Contract, action: ApiContractAction.GetAbi, address: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", @@ -34,6 +34,17 @@ describe("ApiController", () => { }); }); + describe("apiPostHandler", () => { + it("delegates request handling to a different controller based on module and action from body string", async () => { + const request = mock(); + const next = jest.fn(); + await controller.apiPostHandler(request, next, ApiContractAction.VerifySourceCode, ApiModule.Contract); + + expect(request.url).toBe(`/api/${ApiModule.Contract}/${ApiContractAction.VerifySourceCode}`); + expect(next).toBeCalledTimes(1); + }); + }); + describe("getContractAbi", () => { it("returns null as it is defined only to appear in docs and cannot be called", async () => { const result = await controller.getContractAbi(); @@ -48,6 +59,20 @@ describe("ApiController", () => { }); }); + describe("verifyContractSourceCode", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.verifyContractSourceCode(); + expect(result).toBe(null); + }); + }); + + describe("getVerificationStatus", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.getVerificationStatus(); + expect(result).toBe(null); + }); + }); + describe("getContractCreation", () => { it("returns null as it is defined only to appear in docs and cannot be called", async () => { const result = await controller.getContractCreation(); @@ -83,6 +108,20 @@ describe("ApiController", () => { }); }); + describe("getInternalTransactions", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.getInternalTransactions( + { + page: 1, + offset: 10, + maxLimit: 10000, + }, + { sort: SortingOrder.Desc } + ); + expect(result).toBe(null); + }); + }); + describe("getAccountInternalTransactions", () => { it("returns null as it is defined only to appear in docs and cannot be called", async () => { const result = await controller.getAccountInternalTransactions( @@ -97,6 +136,20 @@ describe("ApiController", () => { }); }); + describe("getInternalTransactionsByTxHash", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.getInternalTransactionsByTxHash( + { + page: 1, + offset: 10, + maxLimit: 10000, + }, + { sort: SortingOrder.Desc } + ); + expect(result).toBe(null); + }); + }); + describe("getAccountTokenTransfers", () => { it("returns null as it is defined only to appear in docs and cannot be called", async () => { const result = await controller.getAccountTokenTransfers( @@ -146,6 +199,13 @@ describe("ApiController", () => { }); }); + describe("getAccountMinedBlocks", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.getAccountMinedBlocks({ page: 1, offset: 10, maxLimit: 1000 }); + expect(result).toBe(null); + }); + }); + describe("getBlockNumberByTimestamp", () => { it("returns null as it is defined only to appear in docs and cannot be called", async () => { const result = await controller.getBlockNumberByTimestamp(); @@ -177,4 +237,18 @@ describe("ApiController", () => { expect(result).toBe(null); }); }); + + describe("tokenInfo", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.tokenInfo(); + expect(result).toBe(null); + }); + }); + + describe("ethPrice", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.ethPrice(); + expect(result).toBe(null); + }); + }); }); diff --git a/packages/api/src/api/api.controller.ts b/packages/api/src/api/api.controller.ts index 99932064fb..ccd2bb5ec8 100644 --- a/packages/api/src/api/api.controller.ts +++ b/packages/api/src/api/api.controller.ts @@ -1,11 +1,22 @@ -import { Controller, Get, Query, Req, Next, UseFilters } from "@nestjs/common"; -import { ApiTags, ApiOkResponse, ApiExcludeEndpoint, ApiQuery, ApiExtraModels, ApiOperation } from "@nestjs/swagger"; +import { Controller, Get, Query, Req, Next, UseFilters, Post, Body } from "@nestjs/common"; +import { + ApiTags, + ApiOkResponse, + ApiExcludeEndpoint, + ApiQuery, + ApiExtraModels, + ApiOperation, + ApiBody, +} from "@nestjs/swagger"; import { Request, NextFunction } from "express"; import { PagingOptionsWithMaxItemsLimitDto } from "./dtos/common/pagingOptionsWithMaxItemsLimit.dto"; import { SortingOptionsDto } from "./dtos/common/sortingOptions.dto"; import { ContractAbiResponseDto } from "./dtos/contract/contractAbiResponse.dto"; import { ContractCreationResponseDto, ContractCreationInfoDto } from "./dtos/contract/contractCreationResponse.dto"; import { ContractSourceCodeResponseDto } from "./dtos/contract/contractSourceCodeResponse.dto"; +import { VerifyContractRequestDto } from "./dtos/contract/verifyContractRequest.dto"; +import { VerifyContractResponseDto } from "./dtos/contract/verifyContractResponse.dto"; +import { ContractVerificationStatusResponseDto } from "./dtos/contract/contractVerificationStatusResponse.dto"; import { TransactionStatusResponseDto, TransactionStatusDto } from "./dtos/transaction/transactionStatusResponse.dto"; import { TransactionReceiptStatusResponseDto } from "./dtos/transaction/transactionReceiptStatusResponse.dto"; import { AccountTransactionDto } from "./dtos/account/accountTransaction.dto"; @@ -22,6 +33,8 @@ import { AccountsEtherBalancesResponseDto, } from "./dtos/account/accountEtherBalanceResponse.dto"; import { AccountTokenBalanceResponseDto } from "./dtos/account/accountTokenBalanceResponse.dto"; +import { AccountMinedBlock } from "./dtos/account/accountMinedBlock.dto"; +import { AccountMinedBlocksResponseDto } from "./dtos/account/accountMinedBlocksResponse.dto"; import { BlockNumberResponseDto } from "./dtos/block/blockNumberResponse.dto"; import { BlockCountdownResponseDto } from "./dtos/block/blockCountdownResponse.dto"; import { BlockRewardResponseDto } from "./dtos/block/blockRewardResponse.dto"; @@ -30,17 +43,20 @@ import { ParseModulePipe } from "./pipes/parseModule.pipe"; import { ParseActionPipe } from "./pipes/parseAction.pipe"; import { ApiExceptionFilter } from "./exceptionFilter"; import { LogsResponseDto, LogApiDto } from "./dtos/log/logs.dto"; +import { TokenInfoResponseDto, TokenInfoDto } from "./dtos/token/tokenInfo.dto"; +import { EthPriceResponseDto, EthPriceDto } from "./dtos/stats/ethPrice.dto"; +import { constants } from "../config/docs"; @Controller("") export class ApiController { @ApiExcludeEndpoint() @Get("api") @UseFilters(ApiExceptionFilter) - public async apiHandler( + public async apiGetHandler( @Req() request: Request, @Next() next: NextFunction, - @Query("module", new ParseModulePipe()) module: ApiModule, @Query(new ParseActionPipe()) action: string, + @Query("module", new ParseModulePipe()) module: ApiModule, @Query() query: ApiRequestQuery ) { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -50,13 +66,26 @@ export class ApiController { next(); } + @ApiExcludeEndpoint() + @Post("api") + @UseFilters(ApiExceptionFilter) + public async apiPostHandler( + @Req() request: Request, + @Next() next: NextFunction, + @Body(new ParseActionPipe()) action: string, + @Body("module", new ParseModulePipe()) module: ApiModule + ) { + request.url = `/api/${module}/${action}`; + next(); + } + @ApiTags("Contract API") @Get("api?module=contract&action=getabi") @ApiOperation({ summary: "Fetch the ABI for a given contract address" }) @ApiQuery({ name: "address", description: "The contract address that has a verified source code", - example: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + example: constants.verifiedContractAddress, required: true, }) @ApiOkResponse({ @@ -73,7 +102,7 @@ export class ApiController { @ApiQuery({ name: "address", description: "The contract address that has a verified source code", - example: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + example: constants.verifiedContractAddress, required: true, }) @ApiOkResponse({ @@ -92,7 +121,7 @@ export class ApiController { explode: false, name: "contractaddresses", description: "List of contract addresses, up to 5 at a time", - example: ["0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", "0x0E03197d697B592E5AE49EC14E952cddc9b28e14"], + example: [constants.verifiedContractAddress, constants.verifiedContractAddress2], required: true, }) @ApiExtraModels(ContractCreationInfoDto) @@ -104,13 +133,42 @@ export class ApiController { return null; } + @ApiTags("Contract API") + @Post("api") + @ApiOperation({ summary: "Submits a contract source code for verification" }) + @ApiBody({ type: VerifyContractRequestDto }) + @ApiOkResponse({ + description: "Verification ID for the submission", + type: VerifyContractResponseDto, + }) + public async verifyContractSourceCode(): Promise { + return null; + } + + @ApiTags("Contract API") + @Get("api?module=contract&action=checkverifystatus") + @ApiOperation({ summary: "Check source code verification submission status" }) + @ApiQuery({ + name: "guid", + description: "Verification ID", + example: "44071", + required: true, + }) + @ApiOkResponse({ + description: "Source code verification status", + type: ContractVerificationStatusResponseDto, + }) + public async getVerificationStatus(): Promise { + return null; + } + @ApiTags("Transaction API") @Get("api?module=transaction&action=getstatus") @ApiOperation({ summary: "Fetch the status for a given transaction hash" }) @ApiQuery({ name: "txhash", description: "The transaction hash to check the execution status", - example: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + example: constants.txHash, required: true, }) @ApiExtraModels(TransactionStatusDto) @@ -128,7 +186,7 @@ export class ApiController { @ApiQuery({ name: "txhash", description: "The transaction hash to check the execution status", - example: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + example: constants.txHash, required: true, }) @ApiOkResponse({ @@ -145,7 +203,7 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to filter transactions by", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: true, }) @ApiQuery({ @@ -178,18 +236,86 @@ export class ApiController { @ApiTags("Account API") @Get("api?module=account&action=txlistinternal") - @ApiOperation({ summary: "Retrieve internal transactions for a given address or transaction hash" }) + @ApiOperation({ + summary: "Retrieve internal transactions for a given blocks range (only transfers are supported for now)", + }) + @ApiQuery({ + name: "startblock", + type: "integer", + description: "The block number to start searching for internal transactions", + example: 0, + required: false, + }) + @ApiQuery({ + name: "endblock", + type: "integer", + description: "The block number to stop searching for internal transactions", + example: 99999999, + required: false, + }) + @ApiExtraModels(AccountInternalTransactionDto) + @ApiOkResponse({ + description: "Internal transactions list", + type: AccountInternalTransactionsResponseDto, + }) + public async getInternalTransactions( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Query() sortingOptions: SortingOptionsDto + ): Promise { + return null; + } + + @ApiTags("Account API") + @Get("api?module=account&action=txlistinternal&address=") + @ApiOperation({ + summary: "Retrieve internal transactions for a given address (only transfers are supported for now)", + }) @ApiQuery({ name: "address", description: "The address to filter internal transactions by", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.addressWithInternalTx, + required: true, + }) + @ApiQuery({ + name: "startblock", + type: "integer", + description: "The block number to start searching for internal transactions", + example: 0, required: false, }) + @ApiQuery({ + name: "endblock", + type: "integer", + description: "The block number to stop searching for internal transactions", + example: 99999999, + required: false, + }) + @ApiExtraModels(AccountInternalTransactionDto) + @ApiOkResponse({ + description: "Internal transactions list", + type: AccountInternalTransactionsResponseDto, + }) + public async getAccountInternalTransactions( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Query() sortingOptions: SortingOptionsDto + ): Promise { + return null; + } + + @ApiTags("Account API") + @Get("api?module=account&action=txlistinternal&txhash=") + @ApiOperation({ + summary: "Retrieve internal transactions for a given transaction hash (only transfers are supported for now)", + }) @ApiQuery({ name: "txhash", description: "The transaction hash to filter internal transaction by", - example: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", - required: false, + example: constants.addressTxWithInternalTransfers, + required: true, }) @ApiQuery({ name: "startblock", @@ -210,7 +336,7 @@ export class ApiController { description: "Internal transactions list", type: AccountInternalTransactionsResponseDto, }) - public async getAccountInternalTransactions( + public async getInternalTransactionsByTxHash( // eslint-disable-next-line @typescript-eslint/no-unused-vars @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto, // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -225,7 +351,7 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get Ether balance for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: true, }) @ApiOkResponse({ @@ -244,7 +370,7 @@ export class ApiController { explode: false, name: "address", description: "List of addresses to get Ether balance for", - example: ["0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", "0x0E03197d697B592E5AE49EC14E952cddc9b28e14"], + example: [constants.address, constants.addressWithInternalTx], required: true, }) @ApiOkResponse({ @@ -261,13 +387,13 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get Token balance for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: true, }) @ApiQuery({ name: "contractaddress", description: "The Token contract address to get balance for", - example: "0x0faF6df7054946141266420b43783387A78d82A9", + example: constants.erc20TokenAddress, required: true, }) @ApiOkResponse({ @@ -284,13 +410,13 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get transfers for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: false, }) @ApiQuery({ name: "contractaddress", description: "The Token contract address to get transfers for", - example: "0x0faF6df7054946141266420b43783387A78d82A9", + example: constants.erc20TokenAddress, required: false, }) @ApiQuery({ @@ -327,13 +453,13 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get transfers for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.erc721TokenHolderAddress, required: false, }) @ApiQuery({ name: "contractaddress", description: "The Token contract address to get transfers for", - example: "0x0faF6df7054946141266420b43783387A78d82A9", + example: constants.erc721TokenAddress, required: false, }) @ApiQuery({ @@ -364,6 +490,27 @@ export class ApiController { return null; } + @ApiTags("Account API") + @Get("api?module=account&action=getminedblocks") + @ApiOperation({ summary: "Get list of Blocks Validated by Address" }) + @ApiQuery({ + name: "address", + description: "The address to get validated blocks by", + example: "0x0000000000000000000000000000000000000000", + required: true, + }) + @ApiExtraModels(AccountMinedBlock) + @ApiOkResponse({ + description: "Blocks validated by address", + type: AccountMinedBlocksResponseDto, + }) + public async getAccountMinedBlocks( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto + ): Promise { + return null; + } + @ApiTags("Block API") @Get("api?module=block&action=getblocknobytime") @ApiOperation({ summary: "Retrieve block number closest to a specific timestamp" }) @@ -396,7 +543,7 @@ export class ApiController { name: "blockno", type: "integer", description: "The integer block number to estimate time remaining to be mined", - example: 12697906, + example: 20697906, required: true, }) @ApiOkResponse({ @@ -414,7 +561,7 @@ export class ApiController { name: "blockno", type: "integer", description: "The integer block number to check block rewards", - example: 12697906, + example: 1500, required: true, }) @ApiOkResponse({ @@ -431,21 +578,21 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to filter logs by", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.contractAddressWithLogs, required: true, }) @ApiQuery({ name: "fromBlock", type: "integer", description: "The integer block number to start searching for logs", - example: 12878196, + example: 0, required: false, }) @ApiQuery({ name: "toBlock", type: "integer", description: "The integer block number to stop searching for logs ", - example: 12879196, + example: 99999999, required: false, }) @ApiExtraModels(LogApiDto) @@ -459,4 +606,37 @@ export class ApiController { ): Promise { return null; } + + @ApiTags("Token API") + @Get("api?module=token&action=tokeninfo") + @ApiOperation({ + summary: + "Returns token information. Token price, liquidity and icon are retrieved from CoinGecko. The data is updated every 24 hours.", + }) + @ApiQuery({ + name: "contractaddress", + description: "The contract address of the ERC-20/ERC-721 token to retrieve token info", + example: constants.tokenAddress, + required: true, + }) + @ApiExtraModels(TokenInfoDto) + @ApiOkResponse({ + description: "Token information", + type: TokenInfoResponseDto, + }) + public async tokenInfo(): Promise { + return null; + } + + @ApiTags("Stats API") + @Get("api?module=stats&action=ethprice") + @ApiOperation({ summary: "Returns price of 1 ETH" }) + @ApiExtraModels(EthPriceDto) + @ApiOkResponse({ + description: "ETH price", + type: EthPriceResponseDto, + }) + public async ethPrice(): Promise { + return null; + } } diff --git a/packages/api/src/api/contract/contract.controller.spec.ts b/packages/api/src/api/contract/contract.controller.spec.ts index 28633189ac..47761405e8 100644 --- a/packages/api/src/api/contract/contract.controller.spec.ts +++ b/packages/api/src/api/contract/contract.controller.spec.ts @@ -7,9 +7,11 @@ import { AxiosResponse, AxiosError } from "axios"; import * as rxjs from "rxjs"; import { AddressService } from "../../address/address.service"; import { Address } from "../../address/address.entity"; -import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto"; +import { ResponseStatus, ResponseMessage, ResponseResultMessage } from "../dtos/common/responseBase.dto"; import { ContractController, parseAddressListPipeExceptionFactory } from "./contract.controller"; +import { VerifyContractRequestDto } from "../dtos/contract/verifyContractRequest.dto"; import { SOURCE_CODE_EMPTY_INFO, mapContractSourceCode } from "../mappers/sourceCodeMapper"; +import { ContractVerificationCodeFormatEnum } from "../types"; jest.mock("../mappers/sourceCodeMapper", () => ({ ...jest.requireActual("../mappers/sourceCodeMapper"), @@ -244,6 +246,430 @@ describe("ContractController", () => { }); }); + describe("verifySourceContract", () => { + let pipeMock = jest.fn(); + let request: VerifyContractRequestDto; + + beforeEach(() => { + pipeMock = jest.fn(); + jest.spyOn(httpServiceMock, "post").mockReturnValue({ + pipe: pipeMock, + } as unknown as rxjs.Observable); + jest.spyOn(rxjs, "catchError").mockImplementation((callback) => callback as any); + + request = { + module: "contract", + action: "verifysourcecode", + contractaddress: "0x14174c76E073f8efEf5C1FE0dd0f8c2Ca9F21e62", + sourceCode: { + language: "Solidity", + settings: { + optimizer: { + enabled: true, + }, + }, + sources: { + "contracts/HelloWorld.sol": { + content: "// SPDX-License-Identifier: UNLICENSED", + }, + }, + }, + codeformat: ContractVerificationCodeFormatEnum.solidityJsonInput, + contractname: "contracts/HelloWorld.sol:HelloWorld", + compilerversion: "0.8.17", + optimizationUsed: "1", + zkCompilerVersion: "v1.3.14", + constructorArguements: "0x94869207468657265210000000000000000000000000000000000000000000000", + runs: 700, + libraryname1: "contracts/MiniMath.sol:MiniMath", + libraryaddress1: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + libraryname2: "contracts/MiniMath2.sol:MiniMath2", + libraryaddress2: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + } as unknown as VerifyContractRequestDto; + }); + + it("sends proper payload to the verification endpoint for single file solidity contract", async () => { + request = { + ...request, + sourceCode: "// SPDX-License-Identifier: UNLICENSED", + codeformat: ContractVerificationCodeFormatEnum.soliditySingleFile, + } as unknown as VerifyContractRequestDto; + + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: 1234, + }); + }) + ); + + await controller.verifySourceContract(request.contractaddress, request); + expect(httpServiceMock.post).toBeCalledWith(`http://verification.api/contract_verification`, { + codeFormat: "solidity-single-file", + compilerSolcVersion: "0.8.17", + compilerZksolcVersion: "v1.3.14", + constructorArguments: "0x94869207468657265210000000000000000000000000000000000000000000000", + contractAddress: "0x14174c76E073f8efEf5C1FE0dd0f8c2Ca9F21e62", + contractName: "contracts/HelloWorld.sol:HelloWorld", + optimizationUsed: true, + sourceCode: "// SPDX-License-Identifier: UNLICENSED", + }); + }); + + it("sends proper payload to the verification endpoint for multi file solidity contract", async () => { + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: 1234, + }); + }) + ); + + await controller.verifySourceContract(request.contractaddress, request); + expect(httpServiceMock.post).toBeCalledWith(`http://verification.api/contract_verification`, { + codeFormat: "solidity-standard-json-input", + compilerSolcVersion: "0.8.17", + compilerZksolcVersion: "v1.3.14", + constructorArguments: "0x94869207468657265210000000000000000000000000000000000000000000000", + contractAddress: "0x14174c76E073f8efEf5C1FE0dd0f8c2Ca9F21e62", + contractName: "contracts/HelloWorld.sol:HelloWorld", + optimizationUsed: true, + sourceCode: { + language: "Solidity", + settings: { + libraries: { + "contracts/MiniMath.sol": { + MiniMath: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + }, + "contracts/MiniMath2.sol": { + MiniMath2: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + }, + }, + optimizer: { + enabled: true, + runs: 700, + }, + }, + sources: { + "contracts/HelloWorld.sol": { + content: "// SPDX-License-Identifier: UNLICENSED", + }, + }, + }, + }); + }); + + it("adds optimizer specific fields to the payload if they are not set for multi file solidity contract", async () => { + request.sourceCode = { + language: "Solidity", + sources: { + "contracts/HelloWorld.sol": { + content: "// SPDX-License-Identifier: UNLICENSED", + }, + }, + }; + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: 1234, + }); + }) + ); + + await controller.verifySourceContract(request.contractaddress, request); + expect(httpServiceMock.post).toBeCalledWith(`http://verification.api/contract_verification`, { + codeFormat: "solidity-standard-json-input", + compilerSolcVersion: "0.8.17", + compilerZksolcVersion: "v1.3.14", + constructorArguments: "0x94869207468657265210000000000000000000000000000000000000000000000", + contractAddress: "0x14174c76E073f8efEf5C1FE0dd0f8c2Ca9F21e62", + contractName: "contracts/HelloWorld.sol:HelloWorld", + optimizationUsed: true, + sourceCode: { + language: "Solidity", + settings: { + libraries: { + "contracts/MiniMath.sol": { + MiniMath: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + }, + "contracts/MiniMath2.sol": { + MiniMath2: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + }, + }, + optimizer: { + enabled: true, + runs: 700, + }, + }, + sources: { + "contracts/HelloWorld.sol": { + content: "// SPDX-License-Identifier: UNLICENSED", + }, + }, + }, + }); + }); + + it("sends proper payload to the verification endpoint for multi file vyper contract", async () => { + const vyperVerificationRequest = { + module: "contract", + action: "verifysourcecode", + contractaddress: "0x589160F112A9BFB16f0FD8C6434a27bC3703507D", + sourceCode: { + sources: { + "contracts/Greeter.vy": { + content: "# @version ^0.3.3 # vim: ft=python", + }, + }, + }, + codeformat: "vyper-multi-file", + contractname: "contracts/Greeter.vy:Greeter", + compilerversion: "0.3.3", + optimizationUsed: "1", + zkCompilerVersion: "v1.3.11", + } as unknown as VerifyContractRequestDto; + + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: 1234, + }); + }) + ); + + await controller.verifySourceContract(request.contractaddress, vyperVerificationRequest); + expect(httpServiceMock.post).toBeCalledWith(`http://verification.api/contract_verification`, { + codeFormat: "vyper-multi-file", + compilerVyperVersion: "0.3.3", + compilerZkvyperVersion: "v1.3.11", + constructorArguments: undefined, + contractAddress: "0x14174c76E073f8efEf5C1FE0dd0f8c2Ca9F21e62", + contractName: "contracts/Greeter.vy:Greeter", + optimizationUsed: true, + sourceCode: { + sources: { + "contracts/Greeter.vy": { + content: "# @version ^0.3.3 # vim: ft=python", + }, + }, + }, + }); + }); + + it("throws error when verification endpoint fails with response status different to 400", async () => { + pipeMock.mockImplementation((callback) => { + callback({ + stack: "error stack", + response: { + data: "response data", + status: 500, + }, + } as AxiosError); + }); + + await expect(controller.verifySourceContract(request.contractaddress, request)).rejects.toThrowError( + new InternalServerErrorException("Failed to send verification request") + ); + }); + + it("throws error when verification endpoint fails with response status 400", async () => { + pipeMock.mockImplementation((callback) => { + callback({ + stack: "error stack", + response: { + data: "Contract has already been verified", + status: 400, + }, + } as AxiosError); + }); + + await expect(controller.verifySourceContract(request.contractaddress, request)).rejects.toThrowError( + new BadRequestException("Contract has already been verified") + ); + }); + + it("throws error when contract verification info API fails without response data", async () => { + pipeMock.mockImplementation((callback) => { + callback({ + stack: "error stack", + } as AxiosError); + }); + + await expect(controller.verifySourceContract(request.contractaddress, request)).rejects.toThrowError( + new InternalServerErrorException("Failed to send verification request") + ); + }); + + it("returns verification id for verification request", async () => { + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: 1234, + }); + }) + ); + + const response = await controller.verifySourceContract(request.contractaddress, request); + expect(response).toEqual({ + message: "OK", + result: "1234", + status: "1", + }); + }); + }); + + describe("getVerificationStatus", () => { + let pipeMock = jest.fn(); + const verificationId = "1234"; + + beforeEach(() => { + pipeMock = jest.fn(); + jest.spyOn(httpServiceMock, "get").mockReturnValue({ + pipe: pipeMock, + } as unknown as rxjs.Observable); + jest.spyOn(rxjs, "catchError").mockImplementation((callback) => callback as any); + }); + + it("throws error when contract verification API fails with response status different to 404", async () => { + pipeMock.mockImplementation((callback) => { + callback({ + stack: "error stack", + response: { + data: "response data", + status: 500, + }, + } as AxiosError); + }); + + await expect(controller.getVerificationStatus(verificationId)).rejects.toThrowError( + new InternalServerErrorException("Failed to get verification status") + ); + }); + + it("throws error when contract verification info API fails with response status 404", async () => { + pipeMock.mockImplementation((callback) => { + callback({ + stack: "error stack", + response: { + data: "response data", + status: 404, + }, + } as AxiosError); + }); + + await expect(controller.getVerificationStatus(address)).rejects.toThrowError( + new InternalServerErrorException("Contract verification submission not found") + ); + }); + + it("throws error when contract verification info API fails without response data", async () => { + pipeMock.mockImplementation((callback) => { + callback({ + stack: "error stack", + } as AxiosError); + }); + + await expect(controller.getVerificationStatus(address)).rejects.toThrowError( + new InternalServerErrorException("Failed to get verification status") + ); + }); + + it("throws error when contract verification is not specified", async () => { + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: {}, + }); + }) + ); + + await expect(controller.getVerificationStatus(undefined)).rejects.toThrowError( + new BadRequestException("Verification ID is not specified") + ); + }); + + it("returns successful verification status", async () => { + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: { + status: "successful", + }, + }); + }) + ); + + const response = await controller.getVerificationStatus(verificationId); + expect(response).toEqual({ + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: ResponseResultMessage.VERIFICATION_SUCCESSFUL, + }); + expect(httpServiceMock.get).toBeCalledWith(`http://verification.api/contract_verification/${verificationId}`); + }); + + it("returns queued verification status", async () => { + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: { + status: "queued", + }, + }); + }) + ); + + const response = await controller.getVerificationStatus(verificationId); + expect(response).toEqual({ + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: ResponseResultMessage.VERIFICATION_QUEUED, + }); + expect(httpServiceMock.get).toBeCalledWith(`http://verification.api/contract_verification/${verificationId}`); + }); + + it("returns in progress verification status", async () => { + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: { + status: "in_progress", + }, + }); + }) + ); + + const response = await controller.getVerificationStatus(verificationId); + expect(response).toEqual({ + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: ResponseResultMessage.VERIFICATION_IN_PROGRESS, + }); + expect(httpServiceMock.get).toBeCalledWith(`http://verification.api/contract_verification/${verificationId}`); + }); + + it("returns in progress verification status", async () => { + pipeMock.mockReturnValue( + new rxjs.Observable((subscriber) => { + subscriber.next({ + data: { + status: "failed", + error: "ERROR! Compilation error.", + }, + }); + }) + ); + + const response = await controller.getVerificationStatus(verificationId); + expect(response).toEqual({ + status: ResponseStatus.NOTOK, + message: ResponseMessage.NOTOK, + result: "ERROR! Compilation error.", + }); + expect(httpServiceMock.get).toBeCalledWith(`http://verification.api/contract_verification/${verificationId}`); + }); + }); + describe("getContractCreation", () => { it("thrown an error when called with more than 5 addresses", async () => { await expect( diff --git a/packages/api/src/api/contract/contract.controller.ts b/packages/api/src/api/contract/contract.controller.ts index 0f91a2cd81..699ffe0467 100644 --- a/packages/api/src/api/contract/contract.controller.ts +++ b/packages/api/src/api/contract/contract.controller.ts @@ -1,12 +1,15 @@ import { Controller, Get, + Post, + Body, Query, Logger, InternalServerErrorException, BadRequestException, UseFilters, ParseArrayPipe, + HttpCode, } from "@nestjs/common"; import { HttpService } from "@nestjs/axios"; import { ApiTags, ApiExcludeController } from "@nestjs/swagger"; @@ -15,13 +18,20 @@ import { AxiosError } from "axios"; import { catchError, firstValueFrom, of } from "rxjs"; import { AddressService } from "../../address/address.service"; import { ParseAddressPipe } from "../../common/pipes/parseAddress.pipe"; -import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto"; +import { ResponseStatus, ResponseMessage, ResponseResultMessage } from "../dtos/common/responseBase.dto"; import { ContractAbiResponseDto } from "../dtos/contract/contractAbiResponse.dto"; import { ContractSourceCodeResponseDto } from "../dtos/contract/contractSourceCodeResponse.dto"; import { ContractCreationResponseDto } from "../dtos/contract/contractCreationResponse.dto"; +import { VerifyContractRequestDto } from "../dtos/contract/verifyContractRequest.dto"; +import { ContractVerificationStatusResponseDto } from "../dtos/contract/contractVerificationStatusResponse.dto"; import { ApiExceptionFilter } from "../exceptionFilter"; import { SOURCE_CODE_EMPTY_INFO, mapContractSourceCode } from "../mappers/sourceCodeMapper"; -import { ContractVerificationInfo } from "../types"; +import { + ContractVerificationInfo, + ContractVerificationCodeFormatEnum, + ContractVerificationStatusResponse, +} from "../types"; +import { VerifyContractResponseDto } from "../dtos/contract/verifyContractResponse.dto"; const entityName = "contract"; @@ -108,6 +118,96 @@ export class ContractController { }; } + @HttpCode(200) + @Post("/verifysourcecode") + public async verifySourceContract( + @Body( + "contractaddress", + new ParseAddressPipe({ + required: true, + errorMessage: "Missing or invalid contractAddress (should start with 0x)", + }) + ) + contractAddress, + @Body() request: VerifyContractRequestDto + ): Promise { + const isSolidityContract = [ + ContractVerificationCodeFormatEnum.soliditySingleFile, + ContractVerificationCodeFormatEnum.solidityJsonInput, + ].includes(request.codeformat); + + if (isSolidityContract && request.sourceCode instanceof Object) { + const libraries: { [key: string]: Record } = {}; + for (let i = 1; i <= 10; i++) { + const libName: string = request[`libraryname${i}`]; + const libAddress: string = request[`libraryaddress${i}`]; + if (libName && libAddress) { + const [filePath, contractName] = libName.split(":"); + libraries[filePath] = { + ...libraries[filePath], + [contractName]: libAddress, + }; + } + } + + if (!request.sourceCode.settings) { + request.sourceCode.settings = {}; + } + + request.sourceCode.settings.libraries = { ...request.sourceCode.settings.libraries, ...libraries }; + + if (request.runs) { + if (!request.sourceCode.settings.optimizer) { + request.sourceCode.settings.optimizer = { + enabled: true, + }; + } + request.sourceCode.settings.optimizer.runs = request.runs; + } + } + + const { data } = await firstValueFrom<{ data: number }>( + this.httpService + .post(`${this.contractVerificationApiUrl}/contract_verification`, { + codeFormat: request.codeformat, + contractAddress, + contractName: request.contractname, + optimizationUsed: request.optimizationUsed === "1", + sourceCode: request.sourceCode, + constructorArguments: request.constructorArguements, + ...(isSolidityContract && { + compilerZksolcVersion: request.zkCompilerVersion, + compilerSolcVersion: request.compilerversion, + }), + ...(!isSolidityContract && { + compilerZkvyperVersion: request.zkCompilerVersion, + compilerVyperVersion: request.compilerversion, + }), + }) + .pipe( + catchError((error: AxiosError) => { + this.logger.error({ + message: "Error posting contract for verification", + stack: error.stack, + response: error.response?.data, + }); + + if (error.response?.status === 400) { + throw new BadRequestException(error.response.data); + } + + throw new InternalServerErrorException("Failed to send verification request"); + }) + ) + ); + + return { + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: data.toString(), + }; + } + @Get("/getcontractcreation") public async getContractCreation( @Query( @@ -138,4 +238,59 @@ export class ContractController { result: result.length ? result : null, }; } + + @Get("/checkverifystatus") + public async getVerificationStatus( + @Query("guid") verificationId: string + ): Promise { + if (!verificationId) { + throw new BadRequestException("Verification ID is not specified"); + } + + const { data } = await firstValueFrom<{ data: ContractVerificationStatusResponse }>( + this.httpService.get(`${this.contractVerificationApiUrl}/contract_verification/${verificationId}`).pipe( + catchError((error: AxiosError) => { + if (error.response?.status === 404) { + throw new BadRequestException("Contract verification submission not found"); + } + this.logger.error({ + message: "Error fetching contract verification status", + stack: error.stack, + response: error.response?.data, + }); + throw new InternalServerErrorException("Failed to get verification status"); + }) + ) + ); + + if (data.status === "successful") { + return { + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: ResponseResultMessage.VERIFICATION_SUCCESSFUL, + }; + } + + if (data.status === "queued") { + return { + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: ResponseResultMessage.VERIFICATION_QUEUED, + }; + } + + if (data.status === "in_progress") { + return { + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: ResponseResultMessage.VERIFICATION_IN_PROGRESS, + }; + } + + return { + status: ResponseStatus.NOTOK, + message: ResponseMessage.NOTOK, + result: data.error, + }; + } } diff --git a/packages/api/src/api/dtos/account/accountInternalTransaction.dto.ts b/packages/api/src/api/dtos/account/accountInternalTransaction.dto.ts index eb3490e6e3..a01137a38e 100644 --- a/packages/api/src/api/dtos/account/accountInternalTransaction.dto.ts +++ b/packages/api/src/api/dtos/account/accountInternalTransaction.dto.ts @@ -113,4 +113,11 @@ export class AccountInternalTransactionDto { example: "", }) public readonly errCode: string; + + @ApiProperty({ + type: String, + description: "The type of the parent transaction", + example: "255", + }) + public readonly transactionType: string; } diff --git a/packages/api/src/api/dtos/account/accountMinedBlock.dto.ts b/packages/api/src/api/dtos/account/accountMinedBlock.dto.ts new file mode 100644 index 0000000000..ea2ed4cd0c --- /dev/null +++ b/packages/api/src/api/dtos/account/accountMinedBlock.dto.ts @@ -0,0 +1,24 @@ +import { ApiProperty } from "@nestjs/swagger"; + +export class AccountMinedBlock { + @ApiProperty({ + type: String, + description: "The number (height) of the block", + example: "3233097", + }) + public readonly blockNumber: string; + + @ApiProperty({ + type: String, + description: "The timestamp of the block", + example: "1679988122", + }) + public readonly timeStamp: string; + + @ApiProperty({ + type: String, + description: "Reward for the block", + example: "1000", + }) + public readonly blockReward: string; +} diff --git a/packages/api/src/api/dtos/account/accountMinedBlocksResponse.dto.ts b/packages/api/src/api/dtos/account/accountMinedBlocksResponse.dto.ts new file mode 100644 index 0000000000..e4f8d4c5de --- /dev/null +++ b/packages/api/src/api/dtos/account/accountMinedBlocksResponse.dto.ts @@ -0,0 +1,12 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { ResponseBaseDto } from "../common/responseBase.dto"; +import { AccountMinedBlock } from "./accountMinedBlock.dto"; + +export class AccountMinedBlocksResponseDto extends ResponseBaseDto { + @ApiProperty({ + description: "List of blocks validated by address", + type: AccountMinedBlock, + isArray: true, + }) + public readonly result: AccountMinedBlock[]; +} diff --git a/packages/api/src/api/dtos/account/accountTokenTransfer.dto.ts b/packages/api/src/api/dtos/account/accountTokenTransfer.dto.ts index 1b7af49478..d85c59dbb6 100644 --- a/packages/api/src/api/dtos/account/accountTokenTransfer.dto.ts +++ b/packages/api/src/api/dtos/account/accountTokenTransfer.dto.ts @@ -148,6 +148,13 @@ export class AccountTokenTransferDto { example: "18", }) public readonly tokenDecimal: string; + + @ApiProperty({ + type: String, + description: "The type of the parent transaction", + example: "255", + }) + public readonly transactionType: string; } export class AccountNFTTransferDto extends AccountTokenTransferDto { diff --git a/packages/api/src/api/dtos/account/accountTransaction.dto.ts b/packages/api/src/api/dtos/account/accountTransaction.dto.ts index c198431405..ed20047581 100644 --- a/packages/api/src/api/dtos/account/accountTransaction.dto.ts +++ b/packages/api/src/api/dtos/account/accountTransaction.dto.ts @@ -190,4 +190,11 @@ export class AccountTransactionDto { example: "transfer(address to, uint256 tokens)", }) public readonly functionName: string; + + @ApiProperty({ + type: String, + description: "The type of the transaction", + example: "255", + }) + public readonly type: string; } diff --git a/packages/api/src/api/dtos/common/pagingOptions.dto.ts b/packages/api/src/api/dtos/common/pagingOptions.dto.ts index a046d25201..9a1934a2e3 100644 --- a/packages/api/src/api/dtos/common/pagingOptions.dto.ts +++ b/packages/api/src/api/dtos/common/pagingOptions.dto.ts @@ -19,7 +19,7 @@ export class PagingOptionsDto { @ApiPropertyOptional({ type: "integer", minimum: 1, - maximum: 10000, + maximum: 100, default: 10, description: "The number of items returned per page", example: 10, diff --git a/packages/api/src/api/dtos/common/pagingOptionsWithMaxItemsLimit.dto.ts b/packages/api/src/api/dtos/common/pagingOptionsWithMaxItemsLimit.dto.ts index 6341f34c2d..db85df611e 100644 --- a/packages/api/src/api/dtos/common/pagingOptionsWithMaxItemsLimit.dto.ts +++ b/packages/api/src/api/dtos/common/pagingOptionsWithMaxItemsLimit.dto.ts @@ -6,7 +6,7 @@ import { PagingOptionsDto } from "./pagingOptions.dto"; import { config } from "dotenv"; config(); -const maxItemsLimit = parseInt(process.env.LIMITED_PAGINATION_MAX_ITEMS, 10) || 10000; +const maxItemsLimit = parseInt(process.env.API_LIMITED_PAGINATION_MAX_ITEMS, 10) || 1000; export class PagingOptionsWithMaxItemsLimitDto extends PagingOptionsDto { @ApiPropertyOptional({ diff --git a/packages/api/src/api/dtos/common/responseBase.dto.ts b/packages/api/src/api/dtos/common/responseBase.dto.ts index 8232b0226b..4b3f4488ca 100644 --- a/packages/api/src/api/dtos/common/responseBase.dto.ts +++ b/packages/api/src/api/dtos/common/responseBase.dto.ts @@ -15,6 +15,9 @@ export enum ResponseMessage { export enum ResponseResultMessage { INVALID_PARAM = "Error! Invalid parameter", + VERIFICATION_SUCCESSFUL = "Pass - Verified", + VERIFICATION_QUEUED = "Pending in queue", + VERIFICATION_IN_PROGRESS = "In progress", } export class ResponseBaseDto { diff --git a/packages/api/src/api/dtos/contract/contractAbiResponse.dto.ts b/packages/api/src/api/dtos/contract/contractAbiResponse.dto.ts index 9a03db437b..fe4d6ede0d 100644 --- a/packages/api/src/api/dtos/contract/contractAbiResponse.dto.ts +++ b/packages/api/src/api/dtos/contract/contractAbiResponse.dto.ts @@ -66,5 +66,5 @@ export class ContractAbiResponseDto extends ResponseBaseDto { }, ]), }) - public readonly result: any; + public readonly result: string; } diff --git a/packages/api/src/api/dtos/contract/contractSourceCodeResponse.dto.ts b/packages/api/src/api/dtos/contract/contractSourceCodeResponse.dto.ts index f017660046..763d59b966 100644 --- a/packages/api/src/api/dtos/contract/contractSourceCodeResponse.dto.ts +++ b/packages/api/src/api/dtos/contract/contractSourceCodeResponse.dto.ts @@ -138,18 +138,10 @@ export class ContractSourceCodeDto { public readonly CompilerVersion: string; @ApiProperty({ - description: "Zksolc compiler version", - example: "0.8.12", - required: false, - }) - public readonly CompilerZksolcVersion?: string; - - @ApiProperty({ - description: "Zkvyper compiler version", - example: "0.8.12", - required: false, + description: "Zk compiler version", + example: "v1.3.14", }) - public readonly CompilerZkvyperVersion?: string; + public readonly ZkCompilerVersion?: string; @ApiProperty({ description: "EVM version", diff --git a/packages/api/src/api/dtos/contract/contractVerificationStatusResponse.dto.ts b/packages/api/src/api/dtos/contract/contractVerificationStatusResponse.dto.ts new file mode 100644 index 0000000000..432e0f14d6 --- /dev/null +++ b/packages/api/src/api/dtos/contract/contractVerificationStatusResponse.dto.ts @@ -0,0 +1,11 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { ResponseBaseDto } from "../common/responseBase.dto"; + +export class ContractVerificationStatusResponseDto extends ResponseBaseDto { + @ApiProperty({ + description: "Verification result explanation", + example: "Pass - Verified", + examples: ["Pass - Verified", "Fail - Unable to verify", "Pending in queue", "In progress"], + }) + public readonly result: string; +} diff --git a/packages/api/src/api/dtos/contract/verifyContractRequest.dto.ts b/packages/api/src/api/dtos/contract/verifyContractRequest.dto.ts new file mode 100644 index 0000000000..ab25d00703 --- /dev/null +++ b/packages/api/src/api/dtos/contract/verifyContractRequest.dto.ts @@ -0,0 +1,377 @@ +import { IsInt, IsOptional, Max, Min, IsEnum, IsString, IsNotEmpty, Matches } from "class-validator"; +import { ApiProperty } from "@nestjs/swagger"; +import { Type } from "class-transformer"; +import { ContractVerificationCodeFormatEnum } from "../../types"; + +const fullLibraryNameRegexp = new RegExp("^(.)+:(.)+$"); + +export class VerifyContractRequestDto { + @ApiProperty({ + description: "Module is always 'contract' for this endpoint", + example: "contract", + required: true, + }) + private module: string; + + @ApiProperty({ + description: "Action is always 'verifysourcecode' for this endpoint", + example: "verifysourcecode", + required: true, + }) + private action: string; + + @ApiProperty({ + name: "contractaddress", + description: "Contract address to verify, starts with 0x", + example: "0x0faF6df7054946141266420b43783387A78d82A9", + required: true, + }) + public contractaddress: string; + + @ApiProperty({ + name: "sourceCode", + description: + "Contract source code (Flattened if necessary) for single file or json input for standard json input format", + example: { + language: "Solidity", + settings: { + optimizer: { + enabled: true, + }, + }, + sources: { + "contracts/HelloWorld.sol": { + content: + "// SPDX-License-Identifier: UNLICENSED\n// Specifies the version of Solidity, using semantic versioning.\n// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma\npragma solidity >=0.7.3;\n\n// Defines a contract named `HelloWorld`.\n// A contract is a collection of functions and data (its state). Once deployed, a contract resides at a specific address on the Ethereum blockchain. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html\ncontract HelloWorld {\n\n //Emitted when update function is called\n //Smart contract events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen.\n event UpdatedMessages(string oldStr, string newStr);\n\n // Declares a state variable `message` of type `string`.\n // State variables are variables whose values are permanently stored in contract storage. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value.\n string public message;\n\n // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation.\n // Constructors are used to initialize the contract's data. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors\n constructor(string memory initMessage) {\n\n // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable).\n message = initMessage;\n }\n\n // A public function that accepts a string argument and updates the `message` storage variable.\n function update(string memory newMessage) public {\n string memory oldMsg = message;\n message = newMessage;\n emit UpdatedMessages(oldMsg, newMessage);\n }\n}", + }, + }, + }, + required: true, + }) + @IsNotEmpty({ message: "Missing sourceCode" }) + public sourceCode: string | any; + + @ApiProperty({ + name: "codeformat", + description: `Contract code format. Supported values: ${Object.values(ContractVerificationCodeFormatEnum).join( + ", " + )}`, + example: "solidity-standard-json-input", + required: false, + }) + @IsEnum(ContractVerificationCodeFormatEnum, { + message: `Invalid codeformat. Supported values: ${Object.values(ContractVerificationCodeFormatEnum).join(", ")}`, + }) + @IsOptional() + public codeformat?: ContractVerificationCodeFormatEnum = ContractVerificationCodeFormatEnum.solidityJsonInput; + + @ApiProperty({ + name: "contractname", + description: "Fully qualified contract name (e.g. contracts/HelloWorld.sol:HelloWorld)", + example: "contracts/HelloWorld.sol:HelloWorld", + required: true, + }) + @IsString() + @IsNotEmpty({ + message: + "Missing Or invalid contractname. Fully qualified contract name is expected (e.g. contracts/HelloWorld.sol:HelloWorld)", + }) + public contractname: string; + + @ApiProperty({ + name: "compilerversion", + description: "Compiler version", + example: "0.8.12", + required: true, + }) + @IsString() + @IsNotEmpty({ message: "Missing Or invalid compilerversion." }) + public compilerversion: string; + + @ApiProperty({ + name: "zkCompilerVersion", + description: "Zk compiler version", + example: "v1.3.14", + required: true, + }) + @IsString() + @IsNotEmpty({ message: "Missing zkCompilerVersion" }) + public zkCompilerVersion: string; + + @ApiProperty({ + name: "runs", + description: "Number of expected contract calls", + example: 200, + required: false, + }) + @Min(0) + @Max(1000000) + @IsInt({ message: "Runs value should be a number" }) + @Type(() => Number) + @IsOptional() + public runs?: number; + + @ApiProperty({ + name: "optimizationUsed", + description: "0 = No Optimization, 1 = Optimization used", + example: "1", + required: true, + }) + @IsEnum(["0", "1"], { + message: "Invalid optimizationUsed", + }) + @IsNotEmpty({ message: "Missing optimizationUsed" }) + public optimizationUsed: string; + + @ApiProperty({ + name: "constructorArguements", + description: "Contract constructor arguments", + example: + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000094869207468657265210000000000000000000000000000000000000000000000", + required: false, + }) + @IsOptional() + @IsString() + public constructorArguements?: string; + + @ApiProperty({ + name: "libraryname1", + description: + "library used in the contract, eg. contracts/SafeMath.sol:SafeMath. Supports up to 10 different libraries", + example: "contracts/SafeMath.sol:SafeMath", + required: false, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname1?: string; + + @ApiProperty({ + name: "libraryaddress1", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + example: "0x0faF6df7054946141266420b43783387A78d82A9", + required: false, + }) + @IsOptional() + @IsString() + public libraryaddress1?: string; + + @ApiProperty({ + name: "libraryname2", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + required: false, + example: null, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname2?: string; + + @ApiProperty({ + name: "libraryaddress2", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + required: false, + example: null, + }) + @IsOptional() + @IsString() + public libraryaddress2?: string; + + @ApiProperty({ + name: "libraryname3", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + required: false, + example: null, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname3?: string; + + @ApiProperty({ + name: "libraryaddress3", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + required: false, + example: null, + }) + @IsOptional() + @IsString() + public libraryaddress3?: string; + + @ApiProperty({ + name: "libraryname4", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + required: false, + example: null, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname4?: string; + + @ApiProperty({ + name: "libraryaddress4", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + required: false, + example: null, + }) + @IsOptional() + @IsString() + public libraryaddress4?: string; + + @ApiProperty({ + name: "libraryname5", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + required: false, + example: null, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname5?: string; + + @ApiProperty({ + name: "libraryaddress5", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + required: false, + example: null, + }) + @IsOptional() + @IsString() + public libraryaddress5?: string; + + @ApiProperty({ + name: "libraryname6", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + required: false, + example: null, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname6?: string; + + @ApiProperty({ + name: "libraryaddress6", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + example: null, + required: false, + }) + @IsOptional() + @IsString() + public libraryaddress6?: string; + + @ApiProperty({ + name: "libraryname7", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + example: null, + required: false, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname7?: string; + + @ApiProperty({ + name: "libraryaddress7", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + example: null, + required: false, + }) + @IsOptional() + @IsString() + public libraryaddress7?: string; + + @ApiProperty({ + name: "libraryname8", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + example: null, + required: false, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname8?: string; + + @ApiProperty({ + name: "libraryaddress8", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + example: null, + required: false, + }) + @IsOptional() + @IsString() + public libraryaddress8?: string; + + @ApiProperty({ + name: "libraryname9", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + example: null, + required: false, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname9?: string; + + @ApiProperty({ + name: "libraryaddress9", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + example: null, + required: false, + }) + @IsOptional() + @IsString() + public libraryaddress9?: string; + + @ApiProperty({ + name: "libraryname10", + description: "library used in the contract, eg. contracts/SafeMath.sol:SafeMath", + example: null, + required: false, + }) + @Matches(fullLibraryNameRegexp, { + message: "Invalid library name. Fully qualified library name is expected, e.g. contracts/SafeMath.sol:SafeMath", + }) + @IsOptional() + @IsString() + public libraryname10?: string; + + @ApiProperty({ + name: "libraryaddress10", + description: + "library address eg. 0x0faF6df7054946141266420b43783387A78d82A9 a matching pair of libraryname - libraryaddress must be provided", + example: null, + required: false, + }) + @IsOptional() + @IsString() + public libraryaddress10?: string; +} diff --git a/packages/api/src/api/dtos/contract/verifyContractResponse.dto.ts b/packages/api/src/api/dtos/contract/verifyContractResponse.dto.ts new file mode 100644 index 0000000000..099ad7271a --- /dev/null +++ b/packages/api/src/api/dtos/contract/verifyContractResponse.dto.ts @@ -0,0 +1,10 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { ResponseBaseDto } from "../common/responseBase.dto"; + +export class VerifyContractResponseDto extends ResponseBaseDto { + @ApiProperty({ + description: "Verification ID that can be used for checking the verification status", + example: "43980", + }) + public readonly result: string; +} diff --git a/packages/api/src/api/dtos/stats/ethPrice.dto.ts b/packages/api/src/api/dtos/stats/ethPrice.dto.ts new file mode 100644 index 0000000000..6680b7c4a7 --- /dev/null +++ b/packages/api/src/api/dtos/stats/ethPrice.dto.ts @@ -0,0 +1,26 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { ResponseBaseDto } from "../common/responseBase.dto"; + +export class EthPriceDto { + @ApiProperty({ + type: String, + description: "ETH price in USD", + example: "1823.567", + }) + public readonly ethusd: string; + + @ApiProperty({ + type: String, + description: "ETH price timestamp", + example: "1624961308", + }) + public readonly ethusd_timestamp: string; +} + +export class EthPriceResponseDto extends ResponseBaseDto { + @ApiProperty({ + description: "ETH price", + type: EthPriceDto, + }) + public readonly result: EthPriceDto; +} diff --git a/packages/api/src/api/dtos/token/tokenInfo.dto.ts b/packages/api/src/api/dtos/token/tokenInfo.dto.ts new file mode 100644 index 0000000000..7a30de84bf --- /dev/null +++ b/packages/api/src/api/dtos/token/tokenInfo.dto.ts @@ -0,0 +1,69 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { ResponseBaseDto } from "../common/responseBase.dto"; + +export class TokenInfoDto { + @ApiProperty({ + type: String, + description: "Token contract address", + example: "0x000000000000000000000000000000000000800A", + }) + public readonly contractAddress: string; + + @ApiProperty({ + type: String, + description: "Token name", + example: "Ether", + }) + public readonly tokenName: string; + + @ApiProperty({ + type: String, + description: "Token symbol", + example: "ETH", + }) + public readonly symbol: string; + + @ApiProperty({ + type: String, + description: "Token decimals", + example: "18", + }) + public readonly tokenDecimal: string; + + @ApiProperty({ + type: String, + description: "Token price in USD", + example: "1823.567", + }) + public readonly tokenPriceUSD: string; + + @ApiProperty({ + type: String, + description: "Token liquidity in USD", + example: "220000000000", + }) + public readonly liquidity: string; + + @ApiProperty({ + type: String, + description: "Token L1 address", + example: "0x0000000000000000000000000000000000000000", + }) + public readonly l1Address: string; + + @ApiProperty({ + type: String, + description: "Token icon URL", + example: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", + }) + public readonly iconURL: string; +} + +export class TokenInfoResponseDto extends ResponseBaseDto { + @ApiProperty({ + description: "Token info", + type: TokenInfoDto, + isArray: true, + }) + public readonly result: TokenInfoDto[]; +} diff --git a/packages/api/src/api/dtos/transaction/transactionReceiptStatusResponse.dto.ts b/packages/api/src/api/dtos/transaction/transactionReceiptStatusResponse.dto.ts index 36efffbbb5..2afbcee077 100644 --- a/packages/api/src/api/dtos/transaction/transactionReceiptStatusResponse.dto.ts +++ b/packages/api/src/api/dtos/transaction/transactionReceiptStatusResponse.dto.ts @@ -8,5 +8,5 @@ export class TransactionReceiptStatusResponseDto extends ResponseBaseDto { status: "0", }, }) - public readonly result: { status: "0" | "1" | "" } | string; + public readonly result: { status: string } | string; } diff --git a/packages/api/src/api/exceptionFilter.spec.ts b/packages/api/src/api/exceptionFilter.spec.ts index 3c2fdf1403..01a03cb9ba 100644 --- a/packages/api/src/api/exceptionFilter.spec.ts +++ b/packages/api/src/api/exceptionFilter.spec.ts @@ -1,5 +1,5 @@ import { mock } from "jest-mock-extended"; -import { ArgumentsHost, HttpException } from "@nestjs/common"; +import { ArgumentsHost, HttpException, BadRequestException } from "@nestjs/common"; import { ResponseStatus, ResponseMessage } from "./dtos/common/responseBase.dto"; import { ApiExceptionFilter } from "./exceptionFilter"; @@ -30,5 +30,81 @@ describe("ApiExceptionFilter", () => { result: exception.message, }); }); + + it("sends http 200 response with exception message for BadRequestException with no validation message", () => { + const exception = mock({ + message: "error", + } as BadRequestException); + const response = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + }; + const ctx = { + getResponse: jest.fn().mockReturnValue(response), + }; + const host = mock({ + switchToHttp: jest.fn().mockReturnValue(ctx), + }); + + const exceptionFilter = new ApiExceptionFilter(); + exceptionFilter.catch(exception, host); + + expect(response.status).toBeCalledWith(200); + expect(response.json).toBeCalledWith({ + status: ResponseStatus.NOTOK, + message: ResponseMessage.NOTOK, + result: exception.message, + }); + }); + + it("sends http 200 response with validation message for BadRequestException with single validation message", () => { + const exception = new BadRequestException({ message: "validation error" }); + const response = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + }; + const ctx = { + getResponse: jest.fn().mockReturnValue(response), + }; + const host = mock({ + switchToHttp: jest.fn().mockReturnValue(ctx), + }); + + const exceptionFilter = new ApiExceptionFilter(); + exceptionFilter.catch(exception, host); + + expect(response.status).toBeCalledWith(200); + expect(response.json).toBeCalledWith({ + status: ResponseStatus.NOTOK, + message: ResponseMessage.NOTOK, + result: "validation error", + }); + }); + + it("sends http 200 response with first validation message for BadRequestException with multiple validation messages", () => { + const exception = new BadRequestException({ + message: ["validation error 1", "validation error 2"], + }); + const response = { + status: jest.fn().mockReturnThis(), + json: jest.fn(), + }; + const ctx = { + getResponse: jest.fn().mockReturnValue(response), + }; + const host = mock({ + switchToHttp: jest.fn().mockReturnValue(ctx), + }); + + const exceptionFilter = new ApiExceptionFilter(); + exceptionFilter.catch(exception, host); + + expect(response.status).toBeCalledWith(200); + expect(response.json).toBeCalledWith({ + status: ResponseStatus.NOTOK, + message: ResponseMessage.NOTOK, + result: "validation error 1", + }); + }); }); }); diff --git a/packages/api/src/api/exceptionFilter.ts b/packages/api/src/api/exceptionFilter.ts index 8ad0ab3a1b..0dd4ecc805 100644 --- a/packages/api/src/api/exceptionFilter.ts +++ b/packages/api/src/api/exceptionFilter.ts @@ -1,4 +1,4 @@ -import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from "@nestjs/common"; +import { ExceptionFilter, Catch, ArgumentsHost, HttpException, BadRequestException } from "@nestjs/common"; import { Response } from "express"; import { ResponseStatus, ResponseMessage } from "./dtos/common/responseBase.dto"; @@ -8,10 +8,17 @@ export class ApiExceptionFilter implements ExceptionFilter { const ctx = host.switchToHttp(); const response = ctx.getResponse(); + let validationErrorMessage; + // support of DTO validation error messages + if (exception instanceof BadRequestException) { + const response: { message: string[] } = <{ message: string[] }>(exception).getResponse(); + validationErrorMessage = response.message instanceof Array ? response.message.at(0) : response.message; + } + response.status(200).json({ status: ResponseStatus.NOTOK, message: ResponseMessage.NOTOK, - result: exception.message, + result: validationErrorMessage || exception.message, }); } } diff --git a/packages/api/src/api/log/log.controller.spec.ts b/packages/api/src/api/log/log.controller.spec.ts index 2d00756b71..6a9b16fb33 100644 --- a/packages/api/src/api/log/log.controller.spec.ts +++ b/packages/api/src/api/log/log.controller.spec.ts @@ -16,7 +16,7 @@ describe("LogController", () => { const address = "address"; beforeEach(async () => { logServiceMock = mock({ - findLogs: jest.fn().mockResolvedValue([ + findMany: jest.fn().mockResolvedValue([ { logIndex: 1, }, @@ -52,8 +52,8 @@ describe("LogController", () => { 0, 10 ); - expect(logServiceMock.findLogs).toBeCalledTimes(1); - expect(logServiceMock.findLogs).toBeCalledWith({ + expect(logServiceMock.findMany).toBeCalledTimes(1); + expect(logServiceMock.findMany).toBeCalledWith({ address, fromBlock: 0, toBlock: 10, @@ -89,7 +89,7 @@ describe("LogController", () => { }); it("returns not ok response and empty logs list when logs are not found", async () => { - (logServiceMock.findLogs as jest.Mock).mockResolvedValueOnce([]); + (logServiceMock.findMany as jest.Mock).mockResolvedValueOnce([]); const response = await controller.getLogs( address, { diff --git a/packages/api/src/api/log/log.controller.ts b/packages/api/src/api/log/log.controller.ts index f68fc6692d..9a138c3836 100644 --- a/packages/api/src/api/log/log.controller.ts +++ b/packages/api/src/api/log/log.controller.ts @@ -26,7 +26,7 @@ export class LogController { @Query("fromBlock", new ParseLimitedIntPipe({ min: 0, isOptional: true })) fromBlock?: number, @Query("toBlock", new ParseLimitedIntPipe({ min: 0, isOptional: true })) toBlock?: number ): Promise { - const logs = await this.logService.findLogs({ + const logs = await this.logService.findMany({ address, fromBlock, toBlock, diff --git a/packages/api/src/api/mappers/internalTransactionMapper.spec.ts b/packages/api/src/api/mappers/internalTransactionMapper.spec.ts index 408e736e37..ea81b68cfd 100644 --- a/packages/api/src/api/mappers/internalTransactionMapper.spec.ts +++ b/packages/api/src/api/mappers/internalTransactionMapper.spec.ts @@ -38,6 +38,7 @@ describe("internalTransactionMapper", () => { cumulativeGasUsed: "1200000", gasUsed: "900000", }, + type: 255, }, } as Transfer; @@ -60,6 +61,7 @@ describe("internalTransactionMapper", () => { traceId: "0", type: "call", value: "1000000", + transactionType: "255", }); }); diff --git a/packages/api/src/api/mappers/internalTransactionMapper.ts b/packages/api/src/api/mappers/internalTransactionMapper.ts index 88a963b116..239b386105 100644 --- a/packages/api/src/api/mappers/internalTransactionMapper.ts +++ b/packages/api/src/api/mappers/internalTransactionMapper.ts @@ -17,6 +17,7 @@ export const mapInternalTransactionListItem = (transfer: Transfer) => ({ fee: transfer.transaction?.fee ? BigNumber.from(transfer.transaction.fee).toString() : undefined, l1BatchNumber: transfer.transaction?.l1BatchNumber.toString(), traceId: "0", + transactionType: transfer.transaction?.type.toString(), isError: transfer.transaction?.status === TransactionStatus.Failed ? "1" : "0", errCode: "", }); diff --git a/packages/api/src/api/mappers/sourceCodeMapper.spec.ts b/packages/api/src/api/mappers/sourceCodeMapper.spec.ts index 9e3764e06c..77ac6e5a3a 100644 --- a/packages/api/src/api/mappers/sourceCodeMapper.spec.ts +++ b/packages/api/src/api/mappers/sourceCodeMapper.spec.ts @@ -1,5 +1,5 @@ import { SOURCE_CODE_EMPTY_INFO, mapContractSourceCode } from "./sourceCodeMapper"; -import { ContractVerificationInfo } from "../types"; +import { ContractVerificationInfo, SourceCodeData } from "../types"; describe("SOURCE_CODE_EMPTY_INFO", () => { it("returns ContractSourceCodeDto with empty or default values", () => { @@ -64,7 +64,7 @@ describe("mapContractSourceCode", () => { expect(mapContractSourceCode(verificationInfo)).toEqual({ ABI: "[]", CompilerVersion: "0.8.17", - CompilerZksolcVersion: "v1.3.9", + ZkCompilerVersion: "v1.3.9", ConstructorArguments: "", ContractName: "Greeter", EVMVersion: "Default", @@ -92,7 +92,7 @@ describe("mapContractSourceCode", () => { expect(mapContractSourceCode(verificationInfo)).toEqual({ ABI: "[]", CompilerVersion: "0.8.17", - CompilerZksolcVersion: "v1.3.9", + ZkCompilerVersion: "v1.3.9", ConstructorArguments: "", ContractName: "Greeter", EVMVersion: "Default", @@ -126,7 +126,7 @@ describe("mapContractSourceCode", () => { expect(mapContractSourceCode(verificationInfo)).toEqual({ ABI: "[]", CompilerVersion: "0.3.3", - CompilerZkvyperVersion: "v1.3.9", + ZkCompilerVersion: "v1.3.9", ConstructorArguments: "", ContractName: "Greeter", EVMVersion: "Default", @@ -162,7 +162,7 @@ describe("mapContractSourceCode", () => { expect(mapContractSourceCode(verificationInfo)).toEqual({ ABI: "[]", CompilerVersion: "0.3.3", - CompilerZkvyperVersion: "v1.3.9", + ZkCompilerVersion: "v1.3.9", ConstructorArguments: "", ContractName: "Greeter", EVMVersion: "Default", @@ -196,7 +196,7 @@ describe("mapContractSourceCode", () => { expect(mapContractSourceCode(verificationInfo)).toEqual({ ABI: "[]", CompilerVersion: "0.3.3", - CompilerZkvyperVersion: "v1.3.9", + ZkCompilerVersion: "v1.3.9", ConstructorArguments: "", ContractName: "Greeter", EVMVersion: "Default", @@ -222,7 +222,7 @@ describe("mapContractSourceCode", () => { expect(mapContractSourceCode(verificationInfo)).toEqual({ ABI: "[]", CompilerVersion: "0.8.17", - CompilerZksolcVersion: "v1.3.9", + ZkCompilerVersion: "v1.3.9", ConstructorArguments: "123", ContractName: "Greeter", EVMVersion: "Default", @@ -245,12 +245,12 @@ describe("mapContractSourceCode", () => { optimizationUsed: false, }, }; - (verificationInfo.request.sourceCode as any).settings.optimizer.enabled = false; + (verificationInfo.request.sourceCode as SourceCodeData).settings.optimizer.enabled = false; expect(mapContractSourceCode(verificationInfo)).toEqual({ ABI: "[]", CompilerVersion: "0.8.17", - CompilerZksolcVersion: "v1.3.9", + ZkCompilerVersion: "v1.3.9", ConstructorArguments: "", ContractName: "Greeter", EVMVersion: "Default", @@ -265,4 +265,106 @@ describe("mapContractSourceCode", () => { SwarmSource: "", }); }); + + it("returns Runs if specified", () => { + (verificationInfo.request.sourceCode as SourceCodeData).settings.optimizer.runs = 500; + + expect(mapContractSourceCode(verificationInfo)).toEqual({ + ABI: "[]", + CompilerVersion: "0.8.17", + ZkCompilerVersion: "v1.3.9", + ConstructorArguments: "", + ContractName: "Greeter", + EVMVersion: "Default", + Implementation: "", + Library: "", + LicenseType: "", + OptimizationUsed: "1", + Proxy: "0", + Runs: "500", + SourceCode: + '{{"language":"Solidity","settings":{"optimizer":{"enabled":true,"runs":500}},"sources":{"fileName1":{"content":"fileName1 content"},"fileName2":{"content":"fileName2 content"}}}}', + SwarmSource: "", + }); + }); + + it("returns empty Runs if there are no optimizer settings specified", () => { + (verificationInfo.request.sourceCode as SourceCodeData).settings.optimizer = undefined; + + expect(mapContractSourceCode(verificationInfo)).toEqual({ + ABI: "[]", + CompilerVersion: "0.8.17", + ZkCompilerVersion: "v1.3.9", + ConstructorArguments: "", + ContractName: "Greeter", + EVMVersion: "Default", + Implementation: "", + Library: "", + LicenseType: "", + OptimizationUsed: "1", + Proxy: "0", + Runs: "", + SourceCode: + '{{"language":"Solidity","settings":{},"sources":{"fileName1":{"content":"fileName1 content"},"fileName2":{"content":"fileName2 content"}}}}', + SwarmSource: "", + }); + }); + + it("returns Library for single library specified", () => { + (verificationInfo.request.sourceCode as SourceCodeData).settings.libraries = { + "contracts/MiniMath.sol": { + MiniMath: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + }, + }; + + expect(mapContractSourceCode(verificationInfo)).toEqual({ + ABI: "[]", + CompilerVersion: "0.8.17", + ZkCompilerVersion: "v1.3.9", + ConstructorArguments: "", + ContractName: "Greeter", + EVMVersion: "Default", + Implementation: "", + Library: "contracts/MiniMath.sol:MiniMath:0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + LicenseType: "", + OptimizationUsed: "1", + Proxy: "0", + Runs: "", + SourceCode: + '{{"language":"Solidity","settings":{"optimizer":{"enabled":true},"libraries":{"contracts/MiniMath.sol":{"MiniMath":"0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913"}}},"sources":{"fileName1":{"content":"fileName1 content"},"fileName2":{"content":"fileName2 content"}}}}', + SwarmSource: "", + }); + }); + + it("returns Library for multiple libraries specified", () => { + (verificationInfo.request.sourceCode as SourceCodeData).settings.libraries = { + "contracts/MiniMath.sol": { + MiniMath: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + MiniMath2: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5914", + }, + "contracts/MaxiMath.sol": { + MaxiMath: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5915", + MaxiMath2: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5916", + }, + }; + + expect(mapContractSourceCode(verificationInfo)).toEqual({ + ABI: "[]", + CompilerVersion: "0.8.17", + ZkCompilerVersion: "v1.3.9", + ConstructorArguments: "", + ContractName: "Greeter", + EVMVersion: "Default", + Implementation: "", + Library: + "contracts/MiniMath.sol:MiniMath:0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913;contracts/MiniMath.sol:MiniMath2:0x1c1cEFA394748048BE6b04Ea6081fE44B26a5914;contracts/MaxiMath.sol:MaxiMath:0x1c1cEFA394748048BE6b04Ea6081fE44B26a5915;contracts/MaxiMath.sol:MaxiMath2:0x1c1cEFA394748048BE6b04Ea6081fE44B26a5916", + LicenseType: "", + OptimizationUsed: "1", + Proxy: "0", + Runs: "", + SourceCode: + '{{"language":"Solidity","settings":{"optimizer":{"enabled":true},"libraries":{"contracts/MiniMath.sol":{"MiniMath":"0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913","MiniMath2":"0x1c1cEFA394748048BE6b04Ea6081fE44B26a5914"},"contracts/MaxiMath.sol":{"MaxiMath":"0x1c1cEFA394748048BE6b04Ea6081fE44B26a5915","MaxiMath2":"0x1c1cEFA394748048BE6b04Ea6081fE44B26a5916"}}},"sources":{"fileName1":{"content":"fileName1 content"},"fileName2":{"content":"fileName2 content"}}}}', + SwarmSource: "", + }); + }); }); diff --git a/packages/api/src/api/mappers/sourceCodeMapper.ts b/packages/api/src/api/mappers/sourceCodeMapper.ts index 0f5070a89b..e95d46fa56 100644 --- a/packages/api/src/api/mappers/sourceCodeMapper.ts +++ b/packages/api/src/api/mappers/sourceCodeMapper.ts @@ -1,4 +1,4 @@ -import { ContractVerificationInfo } from "../types"; +import { ContractVerificationInfo, SourceCodeData } from "../types"; import { ContractSourceCodeDto } from "../dtos/contract/contractSourceCodeResponse.dto"; export const SOURCE_CODE_EMPTY_INFO: ContractSourceCodeDto = { @@ -44,30 +44,40 @@ export const mapContractSourceCode = (data: ContractVerificationInfo): ContractS : `{${JSON.stringify(data.request.sourceCode)}}`; } + let libraryString = ""; + let runs = ""; + + const sourceCodeSettings = (data.request.sourceCode as SourceCodeData).settings; + if (sourceCodeSettings) { + runs = sourceCodeSettings.optimizer?.runs?.toString() || ""; + if (sourceCodeSettings.libraries) { + const librariesMapping: string[] = []; + for (const [fileName, contracts] of Object.entries(sourceCodeSettings.libraries)) { + for (const [contractName, contractAddress] of Object.entries(contracts)) { + librariesMapping.push(`${fileName}:${contractName}:${contractAddress}`); + } + } + libraryString = librariesMapping.join(";"); + } + } + return { - ...{ - ABI: JSON.stringify(data.artifacts.abi), - SourceCode: sourceCode, - // remove leading 0x as Etherscan does - ConstructorArguments: data.request.constructorArguments.startsWith("0x") - ? data.request.constructorArguments.substring(2) - : data.request.constructorArguments, - ContractName: data.request.contractName, - EVMVersion: "Default", - OptimizationUsed: data.request.optimizationUsed ? "1" : "0", - Library: "", - LicenseType: "", - CompilerVersion: data.request.compilerSolcVersion || data.request.compilerVyperVersion, - Runs: "", - SwarmSource: "", - Proxy: "0", - Implementation: "", - }, - ...(data.request.compilerZksolcVersion && { - CompilerZksolcVersion: data.request.compilerZksolcVersion, - }), - ...(data.request.compilerZkvyperVersion && { - CompilerZkvyperVersion: data.request.compilerZkvyperVersion, - }), + ABI: JSON.stringify(data.artifacts.abi), + SourceCode: sourceCode, + // remove leading 0x as Etherscan does + ConstructorArguments: data.request.constructorArguments.startsWith("0x") + ? data.request.constructorArguments.substring(2) + : data.request.constructorArguments, + ContractName: data.request.contractName, + EVMVersion: "Default", + OptimizationUsed: data.request.optimizationUsed ? "1" : "0", + Library: libraryString, + LicenseType: "", + CompilerVersion: data.request.compilerSolcVersion || data.request.compilerVyperVersion, + Runs: runs, + SwarmSource: "", + Proxy: "0", + Implementation: "", + ZkCompilerVersion: data.request.compilerZksolcVersion || data.request.compilerZkvyperVersion, }; }; diff --git a/packages/api/src/api/mappers/transactionMapper.spec.ts b/packages/api/src/api/mappers/transactionMapper.spec.ts index a1114e6244..cfba208d03 100644 --- a/packages/api/src/api/mappers/transactionMapper.spec.ts +++ b/packages/api/src/api/mappers/transactionMapper.spec.ts @@ -30,6 +30,7 @@ describe("transactionMapper", () => { cumulativeGasUsed: "1200000", gasUsed: "900000", }, + type: 255, }, } as AddressTransaction; @@ -62,6 +63,7 @@ describe("transactionMapper", () => { transactionIndex: "10", txreceipt_status: "1", value: "1000000", + type: "255", }); }); diff --git a/packages/api/src/api/mappers/transactionMapper.ts b/packages/api/src/api/mappers/transactionMapper.ts index e3bb3f18bd..1335e8f51d 100644 --- a/packages/api/src/api/mappers/transactionMapper.ts +++ b/packages/api/src/api/mappers/transactionMapper.ts @@ -29,6 +29,7 @@ export const mapTransactionListItem = (addressTransaction: AddressTransaction, l executeTxHash: addressTransaction.transaction.executeTxHash, isL1Originated: addressTransaction.transaction.isL1Originated ? "1" : "0", l1BatchNumber: addressTransaction.transaction.l1BatchNumber.toString(), + type: addressTransaction.transaction.type.toString(), methodId: getMethodId(addressTransaction.transaction.data), functionName: "", }); diff --git a/packages/api/src/api/mappers/transferMapper.spec.ts b/packages/api/src/api/mappers/transferMapper.spec.ts index 5d5d79b815..fc758d1da3 100644 --- a/packages/api/src/api/mappers/transferMapper.spec.ts +++ b/packages/api/src/api/mappers/transferMapper.spec.ts @@ -37,6 +37,7 @@ describe("transferMapper", () => { executeTxHash: "0x5e018d2a81dbd1ef80ff45171dd241cb10670dcb091e324401ff8f52293841b3", isL1Originated: true, l1BatchNumber: 3, + type: 255, transactionReceipt: { contractAddress: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35E", cumulativeGasUsed: "1200000", @@ -69,6 +70,7 @@ describe("transferMapper", () => { tokenSymbol: "TKN", transactionIndex: "10", value: "1000000", + transactionType: "255", }); }); @@ -157,8 +159,23 @@ describe("transferMapper", () => { tokenSymbol: "TKN", transactionIndex: "10", value: "1000000", + transactionType: "255", }); }); }); + + describe("when transfer amount is NULL", () => { + it("sets value as undefined", () => { + expect( + mapTransferListItem( + { + ...transfer, + amount: null, + } as unknown as Transfer, + 100 + ).value + ).toBe(undefined); + }); + }); }); }); diff --git a/packages/api/src/api/mappers/transferMapper.ts b/packages/api/src/api/mappers/transferMapper.ts index 5525b581a2..b6143573ab 100644 --- a/packages/api/src/api/mappers/transferMapper.ts +++ b/packages/api/src/api/mappers/transferMapper.ts @@ -10,7 +10,7 @@ export const mapTransferListItem = (transfer: Transfer, lastBlockNumber: number) transactionIndex: transfer.transaction?.transactionIndex.toString(), from: transfer.from, to: transfer.to, - value: transfer.amount, + value: transfer.amount || undefined, tokenID: transfer.fields?.tokenId, tokenName: transfer.token?.name, tokenSymbol: transfer.token?.symbol, @@ -24,4 +24,5 @@ export const mapTransferListItem = (transfer: Transfer, lastBlockNumber: number) confirmations: (lastBlockNumber - transfer.blockNumber).toString(), fee: transfer.transaction?.fee ? BigNumber.from(transfer.transaction.fee).toString() : undefined, l1BatchNumber: transfer.transaction?.l1BatchNumber.toString(), + transactionType: transfer.transaction?.type.toString(), }); diff --git a/packages/api/src/api/stats/stats.controller.spec.ts b/packages/api/src/api/stats/stats.controller.spec.ts new file mode 100644 index 0000000000..f9851dde0b --- /dev/null +++ b/packages/api/src/api/stats/stats.controller.spec.ts @@ -0,0 +1,72 @@ +import { Test } from "@nestjs/testing"; +import { mock } from "jest-mock-extended"; +import { Logger } from "@nestjs/common"; +import { TokenService } from "../../token/token.service"; +import { Token, ETH_TOKEN } from "../../token/token.entity"; +import { StatsController } from "./stats.controller"; + +describe("StatsController", () => { + let controller: StatsController; + let tokenServiceMock: TokenService; + + beforeEach(async () => { + tokenServiceMock = mock({ + findOne: jest.fn().mockResolvedValue(null), + }); + + const module = await Test.createTestingModule({ + controllers: [StatsController], + providers: [ + { + provide: TokenService, + useValue: tokenServiceMock, + }, + ], + }).compile(); + module.useLogger(mock()); + + controller = module.get(StatsController); + }); + + describe("ethPrice", () => { + it("returns ok response and ETH price when ETH token is found", async () => { + jest.spyOn(tokenServiceMock, "findOne").mockResolvedValueOnce({ + usdPrice: ETH_TOKEN.usdPrice, + offChainDataUpdatedAt: new Date("2023-03-03"), + } as Token); + + const response = await controller.ethPrice(); + expect(response).toEqual({ + status: "1", + message: "OK", + result: { + ethusd: ETH_TOKEN.usdPrice.toString(), + ethusd_timestamp: Math.floor(new Date("2023-03-03").getTime() / 1000).toString(), + }, + }); + }); + + it("returns ok response and ETH price with default values when ETH token doesn't have price details", async () => { + jest.spyOn(tokenServiceMock, "findOne").mockResolvedValueOnce({} as Token); + + const response = await controller.ethPrice(); + expect(response).toEqual({ + status: "1", + message: "OK", + result: { + ethusd: "", + ethusd_timestamp: "", + }, + }); + }); + + it("returns not ok response and no ETH price info when ETH token is not found", async () => { + const response = await controller.ethPrice(); + expect(response).toEqual({ + status: "0", + message: "No data found", + result: null, + }); + }); + }); +}); diff --git a/packages/api/src/api/stats/stats.controller.ts b/packages/api/src/api/stats/stats.controller.ts new file mode 100644 index 0000000000..972edb3680 --- /dev/null +++ b/packages/api/src/api/stats/stats.controller.ts @@ -0,0 +1,35 @@ +import { Controller, Get, UseFilters } from "@nestjs/common"; +import { ApiTags, ApiExcludeController } from "@nestjs/swagger"; +import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto"; +import { ApiExceptionFilter } from "../exceptionFilter"; +import { EthPriceResponseDto } from "../dtos/stats/ethPrice.dto"; +import { TokenService } from "../../token/token.service"; +import { ETH_TOKEN } from "../../token/token.entity"; +import { dateToTimestamp } from "../../common/utils"; + +const entityName = "stats"; + +@ApiExcludeController() +@ApiTags(entityName) +@Controller(`api/${entityName}`) +@UseFilters(ApiExceptionFilter) +export class StatsController { + constructor(private readonly tokenService: TokenService) {} + + @Get("/ethprice") + public async ethPrice(): Promise { + const token = await this.tokenService.findOne(ETH_TOKEN.l2Address, { usdPrice: true, offChainDataUpdatedAt: true }); + return { + status: token ? ResponseStatus.OK : ResponseStatus.NOTOK, + message: token ? ResponseMessage.OK : ResponseMessage.NO_DATA_FOUND, + result: token + ? { + ethusd: token.usdPrice?.toString() || "", + ethusd_timestamp: token.offChainDataUpdatedAt + ? dateToTimestamp(token.offChainDataUpdatedAt).toString() + : "", + } + : null, + }; + } +} diff --git a/packages/api/src/api/stats/stats.module.ts b/packages/api/src/api/stats/stats.module.ts new file mode 100644 index 0000000000..e5c1c3a712 --- /dev/null +++ b/packages/api/src/api/stats/stats.module.ts @@ -0,0 +1,9 @@ +import { Module } from "@nestjs/common"; +import { StatsController } from "./stats.controller"; +import { TokenModule } from "../../token/token.module"; + +@Module({ + imports: [TokenModule], + controllers: [StatsController], +}) +export class ApiStatsModule {} diff --git a/packages/api/src/api/token/token.controller.spec.ts b/packages/api/src/api/token/token.controller.spec.ts new file mode 100644 index 0000000000..e3d44eee71 --- /dev/null +++ b/packages/api/src/api/token/token.controller.spec.ts @@ -0,0 +1,91 @@ +import { Test } from "@nestjs/testing"; +import { mock } from "jest-mock-extended"; +import { Logger } from "@nestjs/common"; +import { TokenService } from "../../token/token.service"; +import { Token, ETH_TOKEN } from "../../token/token.entity"; +import { TokenController } from "./token.controller"; + +describe("TokenController", () => { + let controller: TokenController; + let tokenServiceMock: TokenService; + + const contractAddress = "address"; + + beforeEach(async () => { + tokenServiceMock = mock({ + findOne: jest.fn().mockResolvedValue(null), + }); + + const module = await Test.createTestingModule({ + controllers: [TokenController], + providers: [ + { + provide: TokenService, + useValue: tokenServiceMock, + }, + ], + }).compile(); + module.useLogger(mock()); + + controller = module.get(TokenController); + }); + + describe("tokenInfo", () => { + it("returns ok response and token info when token is found", async () => { + jest.spyOn(tokenServiceMock, "findOne").mockResolvedValueOnce(ETH_TOKEN); + + const response = await controller.tokenInfo(contractAddress); + expect(response).toEqual({ + status: "1", + message: "OK", + result: [ + { + contractAddress: ETH_TOKEN.l2Address, + iconURL: ETH_TOKEN.iconURL, + l1Address: ETH_TOKEN.l1Address, + liquidity: ETH_TOKEN.liquidity.toString(), + symbol: ETH_TOKEN.symbol, + tokenDecimal: ETH_TOKEN.decimals.toString(), + tokenName: ETH_TOKEN.name, + tokenPriceUSD: ETH_TOKEN.usdPrice.toString(), + }, + ], + }); + }); + + it("returns ok response and token info with default values when token doesn't have all details", async () => { + jest.spyOn(tokenServiceMock, "findOne").mockResolvedValueOnce({ + l2Address: "0x000000000000000000000000000000000000800A", + symbol: "", + decimals: 6, + } as Token); + + const response = await controller.tokenInfo(contractAddress); + expect(response).toEqual({ + status: "1", + message: "OK", + result: [ + { + contractAddress: "0x000000000000000000000000000000000000800A", + iconURL: "", + l1Address: "", + liquidity: "", + symbol: "", + tokenDecimal: "6", + tokenName: "", + tokenPriceUSD: "", + }, + ], + }); + }); + + it("returns not ok response and no token info when token is not found", async () => { + const response = await controller.tokenInfo(contractAddress); + expect(response).toEqual({ + status: "0", + message: "No data found", + result: [], + }); + }); + }); +}); diff --git a/packages/api/src/api/token/token.controller.ts b/packages/api/src/api/token/token.controller.ts new file mode 100644 index 0000000000..95c559696c --- /dev/null +++ b/packages/api/src/api/token/token.controller.ts @@ -0,0 +1,43 @@ +import { Controller, Get, Query, UseFilters } from "@nestjs/common"; +import { ApiTags, ApiExcludeController } from "@nestjs/swagger"; +import { ParseAddressPipe } from "../../common/pipes/parseAddress.pipe"; +import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto"; +import { ApiExceptionFilter } from "../exceptionFilter"; +import { TokenInfoResponseDto } from "../dtos/token/tokenInfo.dto"; +import { TokenService } from "../../token/token.service"; + +const entityName = "token"; + +@ApiExcludeController() +@ApiTags(entityName) +@Controller(`api/${entityName}`) +@UseFilters(ApiExceptionFilter) +export class TokenController { + constructor(private readonly tokenService: TokenService) {} + + @Get("/tokeninfo") + public async tokenInfo( + @Query("contractaddress", new ParseAddressPipe({ errorMessage: "Error! Invalid contract address format" })) + contractAddress: string + ): Promise { + const token = await this.tokenService.findOne(contractAddress); + return { + status: token ? ResponseStatus.OK : ResponseStatus.NOTOK, + message: token ? ResponseMessage.OK : ResponseMessage.NO_DATA_FOUND, + result: token + ? [ + { + contractAddress: token.l2Address, + tokenName: token.name || "", + symbol: token.symbol, + tokenDecimal: token.decimals.toString(), + tokenPriceUSD: token.usdPrice?.toString() || "", + liquidity: token.liquidity?.toString() || "", + l1Address: token.l1Address || "", + iconURL: token.iconURL || "", + }, + ] + : [], + }; + } +} diff --git a/packages/api/src/api/token/token.module.ts b/packages/api/src/api/token/token.module.ts new file mode 100644 index 0000000000..5677bf8625 --- /dev/null +++ b/packages/api/src/api/token/token.module.ts @@ -0,0 +1,9 @@ +import { Module } from "@nestjs/common"; +import { TokenController } from "./token.controller"; +import { TokenModule } from "../../token/token.module"; + +@Module({ + imports: [TokenModule], + controllers: [TokenController], +}) +export class ApiTokenModule {} diff --git a/packages/api/src/api/transaction/transaction.controller.spec.ts b/packages/api/src/api/transaction/transaction.controller.spec.ts index 5e85dddc84..049fec6b5e 100644 --- a/packages/api/src/api/transaction/transaction.controller.spec.ts +++ b/packages/api/src/api/transaction/transaction.controller.spec.ts @@ -3,7 +3,8 @@ import { mock } from "jest-mock-extended"; import { Logger } from "@nestjs/common"; import { TransactionService } from "../../transaction/transaction.service"; import { TransactionReceiptService } from "../../transaction/transactionReceipt.service"; -import { TransactionStatus, Transaction } from "../../transaction/entities/transaction.entity"; +import { TransactionStatus } from "../../transaction/entities/transaction.entity"; +import { TransactionDetails } from "../../transaction/entities/transactionDetails.entity"; import { TransactionReceipt } from "../../transaction/entities/transactionReceipt.entity"; import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto"; import { TransactionController } from "./transaction.controller"; @@ -56,7 +57,7 @@ describe("TransactionController", () => { it("returns isError as 0 when transaction is successful", async () => { jest .spyOn(transactionServiceMock, "findOne") - .mockResolvedValue({ status: TransactionStatus.Included } as Transaction); + .mockResolvedValue({ status: TransactionStatus.Included } as TransactionDetails); const response = await controller.getTransactionStatus(transactionHash); expect(response).toEqual({ @@ -72,7 +73,57 @@ describe("TransactionController", () => { it("returns isError as 1 when transaction is failed", async () => { jest .spyOn(transactionServiceMock, "findOne") - .mockResolvedValue({ status: TransactionStatus.Failed } as Transaction); + .mockResolvedValue({ status: TransactionStatus.Failed } as TransactionDetails); + + const response = await controller.getTransactionStatus(transactionHash); + expect(response).toEqual({ + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: { + isError: "1", + errDescription: "", + }, + }); + }); + + it("returns transaction error in errDescription when transaction is failed and transaction error is present", async () => { + jest.spyOn(transactionServiceMock, "findOne").mockResolvedValue({ + status: TransactionStatus.Failed, + error: "Error", + revertReason: "Reverted", + } as TransactionDetails); + + const response = await controller.getTransactionStatus(transactionHash); + expect(response).toEqual({ + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: { + isError: "1", + errDescription: "Error", + }, + }); + }); + + it("returns transaction revert reason in errDescription when transaction is failed and transaction revert reason is present", async () => { + jest + .spyOn(transactionServiceMock, "findOne") + .mockResolvedValue({ status: TransactionStatus.Failed, revertReason: "Reverted" } as TransactionDetails); + + const response = await controller.getTransactionStatus(transactionHash); + expect(response).toEqual({ + status: ResponseStatus.OK, + message: ResponseMessage.OK, + result: { + isError: "1", + errDescription: "Reverted", + }, + }); + }); + + it("returns empty errDescription when transaction is failed and transaction error and revert reason are not present", async () => { + jest + .spyOn(transactionServiceMock, "findOne") + .mockResolvedValue({ status: TransactionStatus.Failed } as TransactionDetails); const response = await controller.getTransactionStatus(transactionHash); expect(response).toEqual({ diff --git a/packages/api/src/api/transaction/transaction.controller.ts b/packages/api/src/api/transaction/transaction.controller.ts index 542074cda1..cede0e0c59 100644 --- a/packages/api/src/api/transaction/transaction.controller.ts +++ b/packages/api/src/api/transaction/transaction.controller.ts @@ -5,7 +5,8 @@ import { TransactionReceiptService } from "../../transaction/transactionReceipt. import { TransactionStatus } from "../../transaction/entities/transaction.entity"; import { ParseTransactionHashPipe } from "../../common/pipes/parseTransactionHash.pipe"; import { ResponseStatus, ResponseMessage } from "../dtos/common/responseBase.dto"; -import { ContractAbiResponseDto } from "../dtos/contract/contractAbiResponse.dto"; +import { TransactionStatusResponseDto } from "../dtos/transaction/transactionStatusResponse.dto"; +import { TransactionReceiptStatusResponseDto } from "../dtos/transaction/transactionReceiptStatusResponse.dto"; import { ApiExceptionFilter } from "../exceptionFilter"; const entityName = "transaction"; @@ -27,7 +28,7 @@ export class TransactionController { @Get("/getstatus") public async getTransactionStatus( @Query("txhash", new ParseTransactionHashPipe()) transactionHash: string - ): Promise { + ): Promise { const transaction = await this.transactionService.findOne(transactionHash); const hasError = transaction?.status === TransactionStatus.Failed; return { @@ -35,7 +36,7 @@ export class TransactionController { message: ResponseMessage.OK, result: { isError: hasError ? ResponseStatus.OK : ResponseStatus.NOTOK, - errDescription: "", + errDescription: transaction?.error || transaction?.revertReason || "", }, }; } @@ -43,7 +44,7 @@ export class TransactionController { @Get("/gettxreceiptstatus") public async getTransactionReceiptStatus( @Query("txhash", new ParseTransactionHashPipe()) transactionHash: string - ): Promise { + ): Promise { const transactionReceipt = await this.transactionReceiptService.findOne(transactionHash, ["status"]); const status = transactionReceipt?.status.toString() || ""; return { diff --git a/packages/api/src/api/types.ts b/packages/api/src/api/types.ts index 27a57afe97..3c819c9561 100644 --- a/packages/api/src/api/types.ts +++ b/packages/api/src/api/types.ts @@ -10,6 +10,8 @@ export enum ApiModule { Transaction = "transaction", Block = "block", Logs = "logs", + Token = "token", + Stats = "stats", } export enum ApiAccountAction { @@ -20,12 +22,15 @@ export enum ApiAccountAction { TokenBalance = "tokenbalance", TokenTransfers = "tokentx", NFTTransfers = "tokennfttx", + GetMinedBlocks = "getminedblocks", } export enum ApiContractAction { GetAbi = "getabi", GetSourceCode = "getsourcecode", GetContractCreation = "getcontractcreation", + VerifySourceCode = "verifysourcecode", + GetVerificationStatus = "checkverifystatus", } export enum ApiTransactionAction { @@ -43,12 +48,22 @@ export enum ApiLogsAction { getLogs = "getLogs", } +export enum ApiTokenAction { + tokenInfo = "tokeninfo", +} + +export enum ApiStatsAction { + ethPrice = "ethprice", +} + export const apiActionsMap = { [ApiModule.Account]: Object.values(ApiAccountAction) as string[], [ApiModule.Contract]: Object.values(ApiContractAction) as string[], [ApiModule.Transaction]: Object.values(ApiTransactionAction) as string[], [ApiModule.Block]: Object.values(ApiBlockAction) as string[], [ApiModule.Logs]: Object.values(ApiLogsAction) as string[], + [ApiModule.Token]: Object.values(ApiTokenAction) as string[], + [ApiModule.Stats]: Object.values(ApiStatsAction) as string[], }; type ContractFunctionInput = { @@ -71,6 +86,26 @@ export type AbiFragment = { type: string; }; +export type SourceCodeData = { + language: string; + settings: { + optimizer?: { + enabled: boolean; + runs?: number; + }; + libraries?: { + [file: string]: { + [library: string]: string; + }; + }; + }; + sources: { + [key: string]: { + content: string; + }; + }; +}; + type ContractVerificationRequest = { id: number; codeFormat: string; @@ -81,22 +116,7 @@ type ContractVerificationRequest = { compilerVyperVersion?: string; compilerZkvyperVersion?: string; constructorArguments: string; - sourceCode: - | string - | { - language: string; - settings: { - optimizer: { - enabled: boolean; - }; - }; - sources: { - [key: string]: { - content: string; - }; - }; - } - | Record; + sourceCode: string | SourceCodeData | Record; optimizationUsed: boolean; }; @@ -108,3 +128,14 @@ export type ContractVerificationInfo = { request: ContractVerificationRequest; verifiedAt: string; }; + +export enum ContractVerificationCodeFormatEnum { + soliditySingleFile = "solidity-single-file", + solidityJsonInput = "solidity-standard-json-input", + vyperMultiFile = "vyper-multi-file", +} + +export type ContractVerificationStatusResponse = { + status: "successful" | "failed" | "in_progress" | "queued"; + error?: string; +}; diff --git a/packages/api/src/app.module.ts b/packages/api/src/app.module.ts index fccac26cbf..d0c104ed09 100644 --- a/packages/api/src/app.module.ts +++ b/packages/api/src/app.module.ts @@ -8,6 +8,8 @@ import { ApiAccountModule } from "./api/account/account.module"; import { ApiContractModule } from "./api/contract/contract.module"; import { ApiTransactionModule } from "./api/transaction/transaction.module"; import { ApiLogModule } from "./api/log/log.module"; +import { ApiTokenModule } from "./api/token/token.module"; +import { ApiStatsModule } from "./api/stats/stats.module"; import { TokenModule } from "./token/token.module"; import { BatchModule } from "./batch/batch.module"; import { BlockModule } from "./block/block.module"; @@ -20,11 +22,9 @@ import { StatsModule } from "./stats/stats.module"; import { MetricsMiddleware } from "./middlewares/metrics.middleware"; import { metricProviders } from "./metrics"; import { DbMetricsService } from "./dbMetrics.service"; +import { disableExternalAPI } from "./config/featureFlags"; import config from "./config"; -// TMP: disable external API until release -const { disableExternalAPI } = config(); - @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, load: [config] }), @@ -35,7 +35,10 @@ const { disableExternalAPI } = config(); }), ApiModule, ApiContractModule, - ...(disableExternalAPI ? [] : [ApiBlockModule, ApiAccountModule, ApiTransactionModule, ApiLogModule]), + // TMP: disable external API until release + ...(disableExternalAPI + ? [] + : [ApiBlockModule, ApiAccountModule, ApiTransactionModule, ApiLogModule, ApiTokenModule, ApiStatsModule]), TokenModule, AddressModule, BalanceModule, diff --git a/packages/api/src/balance/balance.entity.ts b/packages/api/src/balance/balance.entity.ts index a06ff27866..1d0dc898e5 100644 --- a/packages/api/src/balance/balance.entity.ts +++ b/packages/api/src/balance/balance.entity.ts @@ -1,6 +1,6 @@ -import { Entity, Column, PrimaryColumn, Index, ManyToOne, JoinColumn } from "typeorm"; +import { Entity, Column, PrimaryColumn, Index, ManyToOne, JoinColumn, AfterLoad } from "typeorm"; import { BaseEntity } from "../common/entities/base.entity"; -import { Token } from "../token/token.entity"; +import { Token, ETH_TOKEN } from "../token/token.entity"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; import { bigIntNumberTransformer } from "../common/transformers/bigIntNumber.transformer"; @@ -9,9 +9,9 @@ export class Balance extends BaseEntity { @PrimaryColumn({ type: "bytea", transformer: normalizeAddressTransformer }) public readonly address: string; - @ManyToOne(() => Token) + @ManyToOne(() => Token, { createForeignKeyConstraints: false }) @JoinColumn({ name: "tokenAddress" }) - public readonly token?: Token; + public token?: Token; @PrimaryColumn({ type: "bytea", transformer: normalizeAddressTransformer }) public readonly tokenAddress: string; @@ -22,4 +22,11 @@ export class Balance extends BaseEntity { @Column({ type: "varchar", length: 128 }) public readonly balance: string; + + @AfterLoad() + populateEthToken() { + if (this.tokenAddress === ETH_TOKEN.l2Address && !this.token) { + this.token = ETH_TOKEN; + } + } } diff --git a/packages/api/src/batch/batch.controller.ts b/packages/api/src/batch/batch.controller.ts index 1d4bbf670b..a9666b7338 100644 --- a/packages/api/src/batch/batch.controller.ts +++ b/packages/api/src/batch/batch.controller.ts @@ -1,5 +1,12 @@ import { Controller, Get, Param, NotFoundException, Query } from "@nestjs/common"; -import { ApiTags, ApiParam, ApiOkResponse, ApiBadRequestResponse, ApiNotFoundResponse } from "@nestjs/swagger"; +import { + ApiTags, + ApiParam, + ApiOkResponse, + ApiBadRequestResponse, + ApiNotFoundResponse, + ApiExcludeController, +} from "@nestjs/swagger"; import { Pagination } from "nestjs-typeorm-paginate"; import { ParseLimitedIntPipe } from "../common/pipes/parseLimitedInt.pipe"; import { PagingOptionsDto, ListFiltersDto } from "../common/dtos"; @@ -8,10 +15,12 @@ import { ApiListPageOkResponse } from "../common/decorators/apiListPageOkRespons import { BatchService } from "./batch.service"; import { BatchDto } from "./batch.dto"; import { BatchDetailsDto } from "./batchDetails.dto"; +import { swagger } from "../config/featureFlags"; const entityName = "batches"; -@ApiTags(entityName) +@ApiTags("Batch BFF") +@ApiExcludeController(!swagger.bffEnabled) @Controller(entityName) export class BatchController { constructor(private readonly batchService: BatchService) {} diff --git a/packages/api/src/block/block.controller.ts b/packages/api/src/block/block.controller.ts index 941d48498b..f9a3a4febf 100644 --- a/packages/api/src/block/block.controller.ts +++ b/packages/api/src/block/block.controller.ts @@ -1,5 +1,12 @@ import { Controller, Get, Param, NotFoundException, Query } from "@nestjs/common"; -import { ApiTags, ApiParam, ApiOkResponse, ApiBadRequestResponse, ApiNotFoundResponse } from "@nestjs/swagger"; +import { + ApiTags, + ApiParam, + ApiOkResponse, + ApiBadRequestResponse, + ApiNotFoundResponse, + ApiExcludeController, +} from "@nestjs/swagger"; import { Pagination } from "nestjs-typeorm-paginate"; import { buildDateFilter } from "../common/utils"; import { ParseLimitedIntPipe } from "../common/pipes/parseLimitedInt.pipe"; @@ -7,11 +14,13 @@ import { PagingOptionsDto, ListFiltersDto } from "../common/dtos"; import { ApiListPageOkResponse } from "../common/decorators/apiListPageOkResponse"; import { BlockService } from "./block.service"; import { BlockDto } from "./block.dto"; -import { BlockDetailDto } from "./blockDetail.dto"; +import { BlockDetailsDto } from "./blockDetails.dto"; +import { swagger } from "../config/featureFlags"; const entityName = "blocks"; -@ApiTags(entityName) +@ApiTags("Block BFF") +@ApiExcludeController(!swagger.bffEnabled) @Controller(entityName) export class BlockController { constructor(private readonly blockService: BlockService) {} @@ -39,12 +48,12 @@ export class BlockController { example: "1", description: "Block number", }) - @ApiOkResponse({ description: "Block was returned successfully", type: BlockDetailDto }) + @ApiOkResponse({ description: "Block was returned successfully", type: BlockDetailsDto }) @ApiBadRequestResponse({ description: "Block number is invalid" }) @ApiNotFoundResponse({ description: "Block with the specified number does not exist" }) public async getBlock( @Param("blockNumber", new ParseLimitedIntPipe({ min: 0 })) blockNumber: number - ): Promise { + ): Promise { const block = await this.blockService.findOne(blockNumber); if (!block) { throw new NotFoundException(); diff --git a/packages/api/src/block/block.module.ts b/packages/api/src/block/block.module.ts index cbca1ea4d3..05687a8292 100644 --- a/packages/api/src/block/block.module.ts +++ b/packages/api/src/block/block.module.ts @@ -3,10 +3,10 @@ import { TypeOrmModule } from "@nestjs/typeorm"; import { BlockService } from "../block/block.service"; import { BlockController } from "./block.controller"; import { Block } from "./block.entity"; -import { BlockDetail } from "./blockDetail.entity"; +import { BlockDetails } from "./blockDetails.entity"; @Module({ - imports: [TypeOrmModule.forFeature([Block, BlockDetail])], + imports: [TypeOrmModule.forFeature([Block, BlockDetails])], controllers: [BlockController], providers: [BlockService], exports: [BlockService], diff --git a/packages/api/src/block/block.service.spec.ts b/packages/api/src/block/block.service.spec.ts index cdbcf88004..b1d2c853da 100644 --- a/packages/api/src/block/block.service.spec.ts +++ b/packages/api/src/block/block.service.spec.ts @@ -4,9 +4,9 @@ import { getRepositoryToken } from "@nestjs/typeorm"; import { Repository, SelectQueryBuilder, FindOptionsOrder } from "typeorm"; import { Pagination, IPaginationMeta } from "nestjs-typeorm-paginate"; import * as utils from "../common/utils"; -import { BlockService } from "./block.service"; +import { BlockService, FindManyOptions } from "./block.service"; import { Block } from "./block.entity"; -import { BlockDetail } from "./blockDetail.entity"; +import { BlockDetails } from "./blockDetails.entity"; jest.mock("../common/utils"); @@ -14,11 +14,11 @@ describe("BlockService", () => { let blockRecord; let service: BlockService; let repositoryMock: Repository; - let blockDetailRepositoryMock: Repository; + let blockDetailRepositoryMock: Repository; beforeEach(async () => { repositoryMock = mock>(); - blockDetailRepositoryMock = mock>(); + blockDetailRepositoryMock = mock>(); blockRecord = { number: 123, @@ -32,7 +32,7 @@ describe("BlockService", () => { useValue: repositoryMock, }, { - provide: getRepositoryToken(BlockDetail), + provide: getRepositoryToken(BlockDetails), useValue: blockDetailRepositoryMock, }, ], @@ -299,4 +299,81 @@ describe("BlockService", () => { expect(number).toBe(1000); }); }); + + describe("findMany", () => { + let queryBuilderMock; + let filterOptions: FindManyOptions; + + beforeEach(() => { + queryBuilderMock = mock>({ + getMany: jest.fn().mockResolvedValue([ + { + number: 1, + timestamp: new Date("2023-03-03"), + }, + ]), + }); + (blockDetailRepositoryMock.createQueryBuilder as jest.Mock).mockReturnValue(queryBuilderMock); + + filterOptions = { + miner: "address", + }; + }); + + it("creates query builder with proper params", async () => { + await service.findMany(filterOptions); + expect(blockDetailRepositoryMock.createQueryBuilder).toHaveBeenCalledTimes(1); + expect(blockDetailRepositoryMock.createQueryBuilder).toHaveBeenCalledWith("block"); + }); + + it("selects specified fields", async () => { + await service.findMany({ + ...filterOptions, + selectFields: ["number", "timestamp"], + }); + expect(queryBuilderMock.addSelect).toHaveBeenCalledTimes(1); + expect(queryBuilderMock.addSelect).toHaveBeenCalledWith(["number", "timestamp"]); + }); + + it("adds where condition for miner when specified", async () => { + await service.findMany(filterOptions); + expect(queryBuilderMock.where).toHaveBeenCalledTimes(1); + expect(queryBuilderMock.where).toHaveBeenCalledWith({ + miner: "address", + }); + }); + + it("does not add where condition for miner when not specified", async () => { + await service.findMany({}); + expect(queryBuilderMock.where).not.toBeCalled(); + }); + + it("sets offset and limit", async () => { + await service.findMany({ + page: 10, + offset: 100, + }); + expect(queryBuilderMock.offset).toHaveBeenCalledTimes(1); + expect(queryBuilderMock.offset).toHaveBeenCalledWith(900); + expect(queryBuilderMock.limit).toHaveBeenCalledTimes(1); + expect(queryBuilderMock.limit).toHaveBeenCalledWith(100); + }); + + it("orders by block number DESC", async () => { + await service.findMany({}); + expect(queryBuilderMock.orderBy).toHaveBeenCalledTimes(1); + expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("block.number", "DESC"); + }); + + it("returns block list", async () => { + const result = await service.findMany({}); + expect(queryBuilderMock.getMany).toHaveBeenCalledTimes(1); + expect(result).toEqual([ + { + number: 1, + timestamp: new Date("2023-03-03"), + }, + ]); + }); + }); }); diff --git a/packages/api/src/block/block.service.ts b/packages/api/src/block/block.service.ts index c098ab766d..ef5f37735c 100644 --- a/packages/api/src/block/block.service.ts +++ b/packages/api/src/block/block.service.ts @@ -5,15 +5,22 @@ import { Pagination } from "nestjs-typeorm-paginate"; import { paginate } from "../common/utils"; import { IPaginationOptions } from "../common/types"; import { Block } from "./block.entity"; -import { BlockDetail } from "./blockDetail.entity"; +import { BlockDetails } from "./blockDetails.entity"; + +export interface FindManyOptions { + miner?: string; + page?: number; + offset?: number; + selectFields?: (keyof BlockDetails)[]; +} @Injectable() export class BlockService { public constructor( @InjectRepository(Block) private readonly blocksRepository: Repository, - @InjectRepository(BlockDetail) - private readonly blockDetailsRepository: Repository + @InjectRepository(BlockDetails) + private readonly blockDetailsRepository: Repository ) {} private getBlock(filterOptions: FindOptionsWhere, orderOptions: FindOptionsOrder): Promise { @@ -43,9 +50,9 @@ export class BlockService { public async findOne( number: number, - selectFields?: (keyof BlockDetail)[], - relations: FindOptionsRelations = { batch: true } - ): Promise { + selectFields?: (keyof BlockDetails)[], + relations: FindOptionsRelations = { batch: true } + ): Promise { return await this.blockDetailsRepository.findOne({ where: { number }, relations: relations, @@ -82,4 +89,18 @@ export class BlockService { return await paginate(queryBuilder, paginationOptions, () => this.count(filterOptions)); } + + public async findMany({ miner, page = 1, offset = 10, selectFields }: FindManyOptions): Promise { + const queryBuilder = this.blockDetailsRepository.createQueryBuilder("block"); + queryBuilder.addSelect(selectFields); + if (miner) { + queryBuilder.where({ + miner, + }); + } + queryBuilder.offset((page - 1) * offset); + queryBuilder.limit(offset); + queryBuilder.orderBy("block.number", "DESC"); + return await queryBuilder.getMany(); + } } diff --git a/packages/api/src/block/blockDetail.dto.ts b/packages/api/src/block/blockDetails.dto.ts similarity index 98% rename from packages/api/src/block/blockDetail.dto.ts rename to packages/api/src/block/blockDetails.dto.ts index 6034d3c86b..d80673960e 100644 --- a/packages/api/src/block/blockDetail.dto.ts +++ b/packages/api/src/block/blockDetails.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from "@nestjs/swagger"; import { BlockDto } from "./block.dto"; -export class BlockDetailDto extends BlockDto { +export class BlockDetailsDto extends BlockDto { @ApiProperty({ type: String, description: "The hash of the previous block", diff --git a/packages/api/src/block/blockDetail.entity.ts b/packages/api/src/block/blockDetails.entity.ts similarity index 97% rename from packages/api/src/block/blockDetail.entity.ts rename to packages/api/src/block/blockDetails.entity.ts index b5d81236eb..151f812a98 100644 --- a/packages/api/src/block/blockDetail.entity.ts +++ b/packages/api/src/block/blockDetails.entity.ts @@ -3,7 +3,7 @@ import { Block } from "./block.entity"; import { hexTransformer } from "../common/transformers/hex.transformer"; @Entity({ name: "blocks" }) -export class BlockDetail extends Block { +export class BlockDetails extends Block { @Column({ type: "bytea", transformer: hexTransformer, nullable: true }) public readonly parentHash?: string; diff --git a/packages/api/src/common/dtos/pagingOptionsWithMaxItemsLimit.dto.ts b/packages/api/src/common/dtos/pagingOptionsWithMaxItemsLimit.dto.ts index a1ac934035..dd5f8607c8 100644 --- a/packages/api/src/common/dtos/pagingOptionsWithMaxItemsLimit.dto.ts +++ b/packages/api/src/common/dtos/pagingOptionsWithMaxItemsLimit.dto.ts @@ -6,7 +6,7 @@ import { PagingOptionsDto } from "./pagingOptions.dto"; import { config } from "dotenv"; config(); -const maxItemsLimit = parseInt(process.env.LIMITED_PAGINATION_MAX_ITEMS, 10) || 100000; +const maxItemsLimit = parseInt(process.env.LIMITED_PAGINATION_MAX_ITEMS, 10) || 10000; export class PagingOptionsWithMaxItemsLimitDto extends PagingOptionsDto { @ApiPropertyOptional({ diff --git a/packages/api/src/common/transformers/hexToDecimalNumber.transformer.spec.ts b/packages/api/src/common/transformers/hexToDecimalNumber.transformer.spec.ts new file mode 100644 index 0000000000..b53f7c9d9a --- /dev/null +++ b/packages/api/src/common/transformers/hexToDecimalNumber.transformer.spec.ts @@ -0,0 +1,27 @@ +import { hexToDecimalNumberTransformer } from "./hexToDecimalNumber.transformer"; + +describe("hexToDecimalNumberTransformer", () => { + describe("to", () => { + it("returns null for null input", () => { + const result = hexToDecimalNumberTransformer.to(null); + expect(result).toBeNull(); + }); + + it("returns hex representation of the decimal number string", () => { + const result = hexToDecimalNumberTransformer.to("800"); + expect(result).toBe("0x0320"); + }); + }); + + describe("from", () => { + it("returns null for null input", () => { + const result = hexToDecimalNumberTransformer.from(null); + expect(result).toBeNull(); + }); + + it("returns decimal representation of the hex number string", () => { + const result = hexToDecimalNumberTransformer.from("0x320"); + expect(result).toBe("800"); + }); + }); +}); diff --git a/packages/api/src/common/transformers/hexToDecimalNumber.transformer.ts b/packages/api/src/common/transformers/hexToDecimalNumber.transformer.ts new file mode 100644 index 0000000000..edb849a2a8 --- /dev/null +++ b/packages/api/src/common/transformers/hexToDecimalNumber.transformer.ts @@ -0,0 +1,17 @@ +import { BigNumber } from "ethers"; +import { ValueTransformer } from "typeorm"; + +export const hexToDecimalNumberTransformer: ValueTransformer = { + to(decimalNumberStr: string | null): string | null { + if (!decimalNumberStr) { + return null; + } + return BigNumber.from(decimalNumberStr).toHexString(); + }, + from(hexNumberStr: string | null): string | null { + if (!hexNumberStr) { + return null; + } + return BigNumber.from(hexNumberStr).toString(); + }, +}; diff --git a/packages/api/src/common/types.ts b/packages/api/src/common/types.ts index eb37a7b7ae..743cd580ca 100644 --- a/packages/api/src/common/types.ts +++ b/packages/api/src/common/types.ts @@ -6,6 +6,7 @@ interface IPaginationFilterOptions { blockNumber?: number; address?: string; l1BatchNumber?: number; + minLiquidity?: number; } export interface IPaginationOptions extends NestIPaginationOptions { diff --git a/packages/api/src/config/docs/constants.mainnet.json b/packages/api/src/config/docs/constants.mainnet.json new file mode 100644 index 0000000000..6e40b24abe --- /dev/null +++ b/packages/api/src/config/docs/constants.mainnet.json @@ -0,0 +1,13 @@ +{ + "verifiedContractAddress": "0x2da10A1e27bF85cEdD8FFb1AbBe97e53391C0295", + "verifiedContractAddress2": "0x1fa66e2B38d0cC496ec51F81c3e05E6A6708986F", + "contractAddressWithLogs": "0x1fa66e2B38d0cC496ec51F81c3e05E6A6708986F", + "txHash": "0xbca76582802d8172fe5bf6ba9c42d675a2ceab858dff555929f2c4021bf77386", + "address": "0xd3D526A8CCA22Fe072cD1852faA4F0a6F2C21765", + "addressWithInternalTx": "0x8B021d2BeD73675F7715422C4BFcBfE759890308", + "addressTxWithInternalTransfers": "0x4683986b4d6b07aa5a8ba6c4a6aa7b1a420a0dfd944ac7128f3e4ab7bd74567c", + "tokenAddress": "0x000000000000000000000000000000000000800A", + "erc20TokenAddress": "0x319897e0F6bEBDf39B46c2eFc5549701C53B53C0", + "erc721TokenAddress": "0xF27e53EDC24Be11B4C5dc4631Fd75EA0Ed896D64", + "erc721TokenHolderAddress": "0x96a337e1B3ccf03E78D5a41272615ee02cb14473" +} \ No newline at end of file diff --git a/packages/api/src/config/docs/constants.testnet-goerli.json b/packages/api/src/config/docs/constants.testnet-goerli.json new file mode 100644 index 0000000000..e848c9d3b5 --- /dev/null +++ b/packages/api/src/config/docs/constants.testnet-goerli.json @@ -0,0 +1,13 @@ +{ + "verifiedContractAddress": "0x53E185A2FA7c9caF14A887E8E9a4862D4bd094ea", + "verifiedContractAddress2": "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + "contractAddressWithLogs": "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + "txHash": "0x3d36c6e6a3625d698ef41d20c9457a6628254c8307df54b7c887e30f7dda00c8", + "address": "0xE4ce1da467a7Ca37727eb7e19857e5167DE25966", + "addressWithInternalTx": "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + "addressTxWithInternalTransfers": "0x8a453b8dd3e095b3034dc3692663d5bf0c9883cbe6e9f9a0425a3ebf9b9360ab", + "tokenAddress": "0x000000000000000000000000000000000000800A", + "erc20TokenAddress": "0x0faF6df7054946141266420b43783387A78d82A9", + "erc721TokenAddress": "0x09B0196641D91eDEC4042e4bb8C605bb35a02546", + "erc721TokenHolderAddress": "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28" +} \ No newline at end of file diff --git a/packages/api/src/config/docs/index.spec.ts b/packages/api/src/config/docs/index.spec.ts new file mode 100644 index 0000000000..02e7958f64 --- /dev/null +++ b/packages/api/src/config/docs/index.spec.ts @@ -0,0 +1,74 @@ +const existsSyncMock = jest.fn().mockReturnValue(false); +const readFileSyncMock = jest.fn().mockReturnValue(null); + +jest.mock("node:fs", () => ({ + existsSync: existsSyncMock, + readFileSync: readFileSyncMock, +})); + +jest.mock("../../logger", () => ({ + getLogger: () => ({ error: jest.fn() }), +})); + +describe("constants", () => { + const env = process.env; + const defaultConstants = { + address: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + addressTxWithInternalTransfers: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + addressWithInternalTx: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + contractAddressWithLogs: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + tokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9", + txHash: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + verifiedContractAddress: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + verifiedContractAddress2: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + erc20TokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9", + erc721TokenAddress: "0x09B0196641D91eDEC4042e4bb8C605bb35a02546", + erc721TokenHolderAddress: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + }; + + beforeEach(() => { + jest.resetModules(); + }); + + afterAll(() => { + process.env = env; + }); + + it("should return default constants", async () => { + const { constants } = await import("./"); + expect(constants).toEqual(defaultConstants); + }); + + it("should return constants for the specified environment", async () => { + process.env.NETWORK_NAME = "testnet"; + const testnetConfig = { + verifiedContractAddress: "0x53E185A2FA7c9caF14A887E8E9a4862D4bd094ea", + verifiedContractAddress2: "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + contractAddressWithLogs: "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + txHash: "0x3d36c6e6a3625d698ef41d20c9457a6628254c8307df54b7c887e30f7dda00c8", + address: "0xE4ce1da467a7Ca37727eb7e19857e5167DE25966", + addressWithInternalTx: "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + addressTxWithInternalTransfers: "0x8a453b8dd3e095b3034dc3692663d5bf0c9883cbe6e9f9a0425a3ebf9b9360ab", + tokenAddress: "0x000000000000000000000000000000000000800A", + erc20TokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9", + erc721TokenAddress: "0x09B0196641D91eDEC4042e4bb8C605bb35a02546", + erc721TokenHolderAddress: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + }; + + existsSyncMock.mockReturnValue(true); + readFileSyncMock.mockReturnValue(JSON.stringify(testnetConfig)); + const { constants } = await import("./"); + + expect(constants).toEqual(testnetConfig); + }); + + it("should return default constants if environment constants cannot be read", async () => { + process.env.NETWORK_NAME = "testnet"; + + existsSyncMock.mockReturnValue(true); + readFileSyncMock.mockReturnValue(new Error("Cannot read the file")); + const { constants } = await import("./"); + + expect(constants).toEqual(defaultConstants); + }); +}); diff --git a/packages/api/src/config/docs/index.ts b/packages/api/src/config/docs/index.ts new file mode 100644 index 0000000000..14da43c4bf --- /dev/null +++ b/packages/api/src/config/docs/index.ts @@ -0,0 +1,40 @@ +import { config } from "dotenv"; +import * as path from "path"; +import * as fs from "node:fs"; +import { getLogger } from "../../logger"; + +config(); + +const { NETWORK_NAME } = process.env; + +const defaultDocsConstants = { + verifiedContractAddress: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + verifiedContractAddress2: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + contractAddressWithLogs: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + txHash: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + address: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + addressWithInternalTx: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + addressTxWithInternalTransfers: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + tokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9", + erc20TokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9", + erc721TokenAddress: "0x09B0196641D91eDEC4042e4bb8C605bb35a02546", + erc721TokenHolderAddress: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", +}; +let networkDocsConstants = {}; + +if (NETWORK_NAME) { + try { + const networkConstantsFilePath = path.resolve(__dirname, `./constants.${NETWORK_NAME.toLowerCase()}.json`); + if (fs.existsSync(networkConstantsFilePath)) { + networkDocsConstants = JSON.parse(fs.readFileSync(networkConstantsFilePath, { encoding: "utf8" })); + } + } catch (error) { + const logger = getLogger(process.env.NODE_ENV, process.env.LOG_LEVEL); + logger.error(error.message, error.stack, "ConfigDocs"); + } +} + +export const constants = { + ...defaultDocsConstants, + ...networkDocsConstants, +}; diff --git a/packages/api/src/config/featureFlags.spec.ts b/packages/api/src/config/featureFlags.spec.ts new file mode 100644 index 0000000000..61a1530792 --- /dev/null +++ b/packages/api/src/config/featureFlags.spec.ts @@ -0,0 +1,7 @@ +import * as featureFlags from "./featureFlags.spec"; + +describe("featureFlags", () => { + it("sets default values", () => { + expect(featureFlags).toEqual({}); + }); +}); diff --git a/packages/api/src/config/featureFlags.ts b/packages/api/src/config/featureFlags.ts new file mode 100644 index 0000000000..ef77b0a852 --- /dev/null +++ b/packages/api/src/config/featureFlags.ts @@ -0,0 +1,11 @@ +import { config } from "dotenv"; +config(); + +const { DISABLE_API_SCHEMA_DOCS, DISABLE_BFF_API_SCHEMA_DOCS, DISABLE_EXTERNAL_API } = process.env; + +export const swagger = { + enabled: DISABLE_API_SCHEMA_DOCS !== "true", + bffEnabled: DISABLE_BFF_API_SCHEMA_DOCS !== "true", +}; + +export const disableExternalAPI = DISABLE_EXTERNAL_API === "true"; diff --git a/packages/api/src/config.spec.ts b/packages/api/src/config/index.spec.ts similarity index 87% rename from packages/api/src/config.spec.ts rename to packages/api/src/config/index.spec.ts index 4fd877f374..f7a1b7bf14 100644 --- a/packages/api/src/config.spec.ts +++ b/packages/api/src/config/index.spec.ts @@ -1,4 +1,9 @@ -import config from "./config"; +import config from "../config"; + +jest.mock("./featureFlags", () => ({ + feature1Enabled: true, + feature2Enabled: false, +})); describe("config", () => { const env = process.env; @@ -36,11 +41,11 @@ describe("config", () => { retryDelay: 3000, applicationName: "block-explorer-api", }, - swagger: { - enabled: true, - }, contractVerificationApiUrl: "http://127.0.0.1:3070", - disableExternalAPI: false, + featureFlags: { + feature1Enabled: true, + feature2Enabled: false, + }, }); }); diff --git a/packages/api/src/config.ts b/packages/api/src/config/index.ts similarity index 93% rename from packages/api/src/config.ts rename to packages/api/src/config/index.ts index 13ab9543c8..6b9c5f2a57 100644 --- a/packages/api/src/config.ts +++ b/packages/api/src/config/index.ts @@ -1,4 +1,5 @@ import { TypeOrmModuleOptions } from "@nestjs/typeorm"; +import * as featureFlags from "./featureFlags"; export default () => { const { @@ -9,8 +10,6 @@ export default () => { DATABASE_URL, DATABASE_CONNECTION_POOL_SIZE, DATABASE_CONNECTION_IDLE_TIMEOUT_MS, - DISABLE_API_SCHEMA_DOCS, - DISABLE_EXTERNAL_API, DATABASE_STATEMENT_TIMEOUT_MS, CONTRACT_VERIFICATION_API_URL, } = process.env; @@ -73,10 +72,7 @@ export default () => { collectDbConnectionPoolMetricsInterval: parseInt(COLLECT_DB_CONNECTION_POOL_METRICS_INTERVAL, 10) || 10000, }, typeORM: getTypeOrmModuleOptions(), - swagger: { - enabled: DISABLE_API_SCHEMA_DOCS !== "true", - }, - disableExternalAPI: DISABLE_EXTERNAL_API === "true", contractVerificationApiUrl: CONTRACT_VERIFICATION_API_URL || "http://127.0.0.1:3070", + featureFlags, }; }; diff --git a/packages/api/src/configureApp.ts b/packages/api/src/configureApp.ts index 03a2de32a4..7e71be6c57 100644 --- a/packages/api/src/configureApp.ts +++ b/packages/api/src/configureApp.ts @@ -3,7 +3,7 @@ import { INestApplication, ValidationPipe } from "@nestjs/common"; export const configureApp = (app: INestApplication) => { app.useGlobalPipes( new ValidationPipe({ - disableErrorMessages: true, + disableErrorMessages: false, transform: true, whitelist: true, }) diff --git a/packages/api/src/log/log.service.spec.ts b/packages/api/src/log/log.service.spec.ts index 96c7017b5b..ea68bc16bf 100644 --- a/packages/api/src/log/log.service.spec.ts +++ b/packages/api/src/log/log.service.spec.ts @@ -101,7 +101,7 @@ describe("LogService", () => { }); }); - describe("findLogs", () => { + describe("findMany", () => { let queryBuilderMock; let filterOptions: FilterLogsByAddressOptions; @@ -127,26 +127,26 @@ describe("LogService", () => { }); it("creates query builder with proper params", async () => { - await service.findLogs(filterOptions); + await service.findMany(filterOptions); expect(repositoryMock.createQueryBuilder).toHaveBeenCalledTimes(1); expect(repositoryMock.createQueryBuilder).toHaveBeenCalledWith("log"); }); it("joins transaction and transactionReceipt records to the logs", async () => { - await service.findLogs(filterOptions); + await service.findMany(filterOptions); expect(queryBuilderMock.leftJoin).toBeCalledTimes(2); expect(queryBuilderMock.leftJoin).toHaveBeenCalledWith("log.transaction", "transaction"); expect(queryBuilderMock.leftJoin).toHaveBeenCalledWith("transaction.transactionReceipt", "transactionReceipt"); }); it("selects only needed fields from joined records", async () => { - await service.findLogs(filterOptions); + await service.findMany(filterOptions); expect(queryBuilderMock.addSelect).toBeCalledTimes(1); expect(queryBuilderMock.addSelect).toHaveBeenCalledWith(["transaction.gasPrice", "transactionReceipt.gasUsed"]); }); it("filters logs by address", async () => { - await service.findLogs(filterOptions); + await service.findMany(filterOptions); expect(queryBuilderMock.where).toBeCalledTimes(1); expect(queryBuilderMock.where).toHaveBeenCalledWith({ address: filterOptions.address, @@ -155,7 +155,7 @@ describe("LogService", () => { describe("when fromBlock filter is specified", () => { it("adds blockNumber filter", async () => { - await service.findLogs({ + await service.findMany({ ...filterOptions, fromBlock: 10, }); @@ -168,7 +168,7 @@ describe("LogService", () => { describe("when toBlock filter is specified", () => { it("adds toBlock filter", async () => { - await service.findLogs({ + await service.findMany({ ...filterOptions, toBlock: 10, }); @@ -180,7 +180,7 @@ describe("LogService", () => { }); it("sets offset and limit", async () => { - await service.findLogs({ + await service.findMany({ ...filterOptions, page: 2, offset: 100, @@ -192,7 +192,7 @@ describe("LogService", () => { }); it("sorts by blockNumber asc and logIndex asc", async () => { - await service.findLogs(filterOptions); + await service.findMany(filterOptions); expect(queryBuilderMock.orderBy).toBeCalledTimes(1); expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("log.blockNumber", "ASC"); expect(queryBuilderMock.addOrderBy).toBeCalledTimes(1); @@ -200,7 +200,7 @@ describe("LogService", () => { }); it("executes query and returns transfers list", async () => { - const result = await service.findLogs(filterOptions); + const result = await service.findMany(filterOptions); expect(result).toEqual([ { logIndex: 1, diff --git a/packages/api/src/log/log.service.ts b/packages/api/src/log/log.service.ts index 6f65dabba1..c06f936b85 100644 --- a/packages/api/src/log/log.service.ts +++ b/packages/api/src/log/log.service.ts @@ -37,7 +37,7 @@ export class LogService { return await paginate(queryBuilder, paginationOptions); } - public async findLogs({ + public async findMany({ address, fromBlock, toBlock, diff --git a/packages/api/src/main.ts b/packages/api/src/main.ts index 8be6b8bdd9..49246daeb9 100644 --- a/packages/api/src/main.ts +++ b/packages/api/src/main.ts @@ -22,7 +22,7 @@ async function bootstrap() { const metricsApp = await NestFactory.create(AppMetricsModule); metricsApp.enableShutdownHooks(); - if (configService.get("swagger.enabled")) { + if (configService.get("featureFlags.swagger.enabled")) { const swaggerConfig = new DocumentBuilder() .setTitle("Block explorer API") .setDescription("ZkSync Block Explorer API") diff --git a/packages/api/src/stats/stats.controller.ts b/packages/api/src/stats/stats.controller.ts index eff5b73b64..6878b0fe73 100644 --- a/packages/api/src/stats/stats.controller.ts +++ b/packages/api/src/stats/stats.controller.ts @@ -1,14 +1,16 @@ import { Controller, Get } from "@nestjs/common"; -import { ApiTags, ApiOkResponse } from "@nestjs/swagger"; +import { ApiTags, ApiOkResponse, ApiExcludeController } from "@nestjs/swagger"; import { Not, IsNull } from "typeorm"; import { BatchService } from "../batch/batch.service"; import { BlockService } from "../block/block.service"; import { TransactionService } from "../transaction/transaction.service"; import { StatsDto } from "./stats.dto"; +import { swagger } from "../config/featureFlags"; const entityName = "stats"; -@ApiTags(entityName) +@ApiTags("Stats BFF") +@ApiExcludeController(!swagger.bffEnabled) @Controller(entityName) export class StatsController { constructor( diff --git a/packages/api/src/token/token.controller.spec.ts b/packages/api/src/token/token.controller.spec.ts index 25a9e0979a..2b6cfe890f 100644 --- a/packages/api/src/token/token.controller.spec.ts +++ b/packages/api/src/token/token.controller.spec.ts @@ -50,9 +50,12 @@ describe("TokenController", () => { }); it("queries tokens with the specified options", async () => { - await controller.getTokens(pagingOptions); + await controller.getTokens(pagingOptions, 1000); expect(serviceMock.findAll).toHaveBeenCalledTimes(1); - expect(serviceMock.findAll).toHaveBeenCalledWith({ ...pagingOptions, route: "tokens" }); + expect(serviceMock.findAll).toHaveBeenCalledWith( + { minLiquidity: 1000 }, + { ...pagingOptions, filterOptions: { minLiquidity: 1000 }, route: "tokens" } + ); }); it("returns the tokens", async () => { diff --git a/packages/api/src/token/token.controller.ts b/packages/api/src/token/token.controller.ts index fb0991e856..660f18ae3f 100644 --- a/packages/api/src/token/token.controller.ts +++ b/packages/api/src/token/token.controller.ts @@ -1,5 +1,13 @@ import { Controller, Get, Param, NotFoundException, Query } from "@nestjs/common"; -import { ApiTags, ApiParam, ApiOkResponse, ApiBadRequestResponse, ApiNotFoundResponse } from "@nestjs/swagger"; +import { + ApiTags, + ApiParam, + ApiOkResponse, + ApiBadRequestResponse, + ApiNotFoundResponse, + ApiExcludeController, + ApiQuery, +} from "@nestjs/swagger"; import { Pagination } from "nestjs-typeorm-paginate"; import { PagingOptionsDto, PagingOptionsWithMaxItemsLimitDto } from "../common/dtos"; import { ApiListPageOkResponse } from "../common/decorators/apiListPageOkResponse"; @@ -7,11 +15,15 @@ import { TokenService } from "./token.service"; import { TransferService } from "../transfer/transfer.service"; import { TokenDto } from "./token.dto"; import { TransferDto } from "../transfer/transfer.dto"; +import { ParseLimitedIntPipe } from "../common/pipes/parseLimitedInt.pipe"; import { ParseAddressPipe, ADDRESS_REGEX_PATTERN } from "../common/pipes/parseAddress.pipe"; +import { swagger } from "../config/featureFlags"; +import { constants } from "../config/docs"; const entityName = "tokens"; -@ApiTags(entityName) +@ApiTags("Token BFF") +@ApiExcludeController(!swagger.bffEnabled) @Controller(entityName) export class TokenController { constructor(private readonly tokenService: TokenService, private readonly transferService: TransferService) {} @@ -19,18 +31,34 @@ export class TokenController { @Get("") @ApiListPageOkResponse(TokenDto, { description: "Successfully returned token list" }) @ApiBadRequestResponse({ description: "Paging query params are not valid or out of range" }) - public async getTokens(@Query() pagingOptions: PagingOptionsDto): Promise> { - return await this.tokenService.findAll({ - ...pagingOptions, - route: entityName, - }); + @ApiQuery({ + name: "minLiquidity", + type: "integer", + description: "Min liquidity filter", + example: 100000, + required: false, + }) + public async getTokens( + @Query() pagingOptions: PagingOptionsDto, + @Query("minLiquidity", new ParseLimitedIntPipe({ min: 0, isOptional: true })) minLiquidity?: number + ): Promise> { + return await this.tokenService.findAll( + { + minLiquidity, + }, + { + filterOptions: { minLiquidity }, + ...pagingOptions, + route: entityName, + } + ); } @Get(":address") @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.tokenAddress, description: "Valid hex address", }) @ApiOkResponse({ description: "Token was returned successfully", type: TokenDto }) @@ -48,7 +76,7 @@ export class TokenController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.tokenAddress, description: "Valid hex address", }) @ApiListPageOkResponse(TransferDto, { description: "Successfully returned token transfers list" }) diff --git a/packages/api/src/token/token.dto.ts b/packages/api/src/token/token.dto.ts index e7dbcbcd5b..b0deb7d33c 100644 --- a/packages/api/src/token/token.dto.ts +++ b/packages/api/src/token/token.dto.ts @@ -31,4 +31,31 @@ export class TokenDto { @ApiProperty({ type: Number, description: "Token decimals value", example: 18 }) public readonly decimals: number; + + @ApiProperty({ + type: Number, + description: "Token USD price", + example: 1.00001, + examples: [1.0001, null], + required: false, + }) + public readonly usdPrice?: number; + + @ApiProperty({ + type: Number, + description: "Token liquidity", + example: 1000000, + examples: [1000000, null], + required: false, + }) + public readonly liquidity?: number; + + @ApiProperty({ + type: String, + description: "Token icon URL", + example: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", + examples: ["https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", null], + required: false, + }) + public readonly iconURL?: string; } diff --git a/packages/api/src/token/token.entity.ts b/packages/api/src/token/token.entity.ts index 2dbbdfaf17..234bc60315 100644 --- a/packages/api/src/token/token.entity.ts +++ b/packages/api/src/token/token.entity.ts @@ -3,12 +3,25 @@ import { BaseEntity } from "../common/entities/base.entity"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; export enum TokenType { + ETH = "ETH", ERC20 = "ERC20", ERC721 = "ERC721", } +export const ETH_TOKEN: Token = { + l2Address: "0x000000000000000000000000000000000000800A", + l1Address: "0x0000000000000000000000000000000000000000", + symbol: "ETH", + name: "Ether", + decimals: 18, + // Fallback data in case ETH token is not in the DB + iconURL: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1698873266", + liquidity: 220000000000, + usdPrice: 1800, +} as Token; + @Entity({ name: "tokens" }) -@Index(["blockNumber", "logIndex"]) +@Index(["liquidity", "blockNumber", "logIndex"]) export class Token extends BaseEntity { @PrimaryColumn({ type: "bytea", transformer: normalizeAddressTransformer }) public readonly l2Address: string; @@ -16,6 +29,7 @@ export class Token extends BaseEntity { @Column({ generated: true, type: "bigint", select: false }) public readonly number: number; + @Index() @Column({ type: "bytea", nullable: true, transformer: normalizeAddressTransformer }) public readonly l1Address?: string; @@ -33,4 +47,17 @@ export class Token extends BaseEntity { @Column({ type: "int", select: false }) public readonly logIndex: number; + + @Column({ type: "double precision", nullable: true }) + public readonly usdPrice?: number; + + @Column({ type: "double precision", nullable: true }) + public readonly liquidity?: number; + + @Column({ nullable: true }) + public readonly iconURL?: string; + + @Index() + @Column({ type: "timestamp", nullable: true, select: false }) + public readonly offChainDataUpdatedAt?: Date; } diff --git a/packages/api/src/token/token.service.spec.ts b/packages/api/src/token/token.service.spec.ts index 5cdccb82dd..2b61764b4f 100644 --- a/packages/api/src/token/token.service.spec.ts +++ b/packages/api/src/token/token.service.spec.ts @@ -1,9 +1,9 @@ import { Test, TestingModule } from "@nestjs/testing"; import { mock } from "jest-mock-extended"; import { getRepositoryToken } from "@nestjs/typeorm"; -import { Repository, SelectQueryBuilder } from "typeorm"; +import { Repository, SelectQueryBuilder, MoreThanOrEqual } from "typeorm"; import { TokenService } from "./token.service"; -import { Token } from "./token.entity"; +import { Token, ETH_TOKEN } from "./token.entity"; import { Pagination, IPaginationMeta } from "nestjs-typeorm-paginate"; import * as utils from "../common/utils"; @@ -41,19 +41,46 @@ describe("TokenService", () => { token = { l2Address: tokenAddress, }; - (repositoryMock.findOneBy as jest.Mock).mockResolvedValue(token); + (repositoryMock.findOne as jest.Mock).mockResolvedValue(token); }); it("queries tokens by specified token address", async () => { await service.findOne(tokenAddress); - expect(repositoryMock.findOneBy).toHaveBeenCalledTimes(1); - expect(repositoryMock.findOneBy).toHaveBeenCalledWith({ l2Address: tokenAddress }); + expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); + expect(repositoryMock.findOne).toHaveBeenCalledWith({ where: { l2Address: tokenAddress } }); }); it("returns token by address", async () => { const result = await service.findOne(tokenAddress); expect(result).toBe(token); }); + + describe("when called with fields", () => { + it("queries only specified fields", async () => { + await service.findOne(tokenAddress, { l2Address: true }); + expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); + expect(repositoryMock.findOne).toHaveBeenCalledWith({ + where: { l2Address: tokenAddress }, + select: { l2Address: true }, + }); + }); + }); + + describe("when requested token does not exist", () => { + beforeEach(() => { + (repositoryMock.findOne as jest.Mock).mockResolvedValue(null); + }); + + it("returns ETH token for ETH address", async () => { + const result = await service.findOne("0x000000000000000000000000000000000000800a"); + expect(result).toEqual(ETH_TOKEN); + }); + + it("returns null for non ETH address", async () => { + const result = await service.findOne("0x000000000000000000000000000000000000800b"); + expect(result).toBeNull(); + }); + }); }); describe("exists", () => { @@ -82,10 +109,20 @@ describe("TokenService", () => { expect(result).toBe(true); }); - it("returns false if there is no token with the specified address", async () => { - (repositoryMock.findOne as jest.Mock).mockResolvedValue(null); - const result = await service.exists(tokenAddress); - expect(result).toBe(false); + describe("when requested token does not exist", () => { + beforeEach(() => { + (repositoryMock.findOne as jest.Mock).mockResolvedValue(null); + }); + + it("returns true for ETH address", async () => { + const result = await service.exists("0x000000000000000000000000000000000000800a"); + expect(result).toBe(true); + }); + + it("returns false for non ETH address", async () => { + const result = await service.exists(tokenAddress); + expect(result).toBe(false); + }); }); }); @@ -102,23 +139,37 @@ describe("TokenService", () => { }); it("creates query builder with proper params", async () => { - await service.findAll(pagingOptions); + await service.findAll({}, pagingOptions); expect(repositoryMock.createQueryBuilder).toHaveBeenCalledTimes(1); expect(repositoryMock.createQueryBuilder).toHaveBeenCalledWith("token"); }); - it("returns tokens ordered by blockNumber and logIndex DESC", async () => { - await service.findAll(pagingOptions); + it("does not add liquidity filter when minLiquidity is not provided", async () => { + await service.findAll({}, pagingOptions); + expect(queryBuilderMock.where).not.toBeCalled(); + }); + + it("adds liquidity filter when minLiquidity is provided", async () => { + await service.findAll({ minLiquidity: 1000 }, pagingOptions); + expect(queryBuilderMock.where).toBeCalledTimes(1); + expect(queryBuilderMock.where).toHaveBeenCalledWith({ + liquidity: MoreThanOrEqual(1000), + }); + }); + + it("returns tokens ordered by liquidity, blockNumber and logIndex DESC", async () => { + await service.findAll({}, pagingOptions); expect(queryBuilderMock.orderBy).toBeCalledTimes(1); - expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("token.blockNumber", "DESC"); - expect(queryBuilderMock.addOrderBy).toBeCalledTimes(1); + expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("token.liquidity", "DESC", "NULLS LAST"); + expect(queryBuilderMock.addOrderBy).toBeCalledTimes(2); + expect(queryBuilderMock.addOrderBy).toHaveBeenCalledWith("token.blockNumber", "DESC"); expect(queryBuilderMock.addOrderBy).toHaveBeenCalledWith("token.logIndex", "DESC"); }); it("returns paginated result", async () => { const paginationResult = mock>(); (utils.paginate as jest.Mock).mockResolvedValue(paginationResult); - const result = await service.findAll(pagingOptions); + const result = await service.findAll({}, pagingOptions); expect(utils.paginate).toBeCalledTimes(1); expect(utils.paginate).toBeCalledWith(queryBuilderMock, pagingOptions); expect(result).toBe(paginationResult); diff --git a/packages/api/src/token/token.service.ts b/packages/api/src/token/token.service.ts index 09695b66e3..4adafbc315 100644 --- a/packages/api/src/token/token.service.ts +++ b/packages/api/src/token/token.service.ts @@ -1,9 +1,14 @@ import { Injectable } from "@nestjs/common"; import { InjectRepository } from "@nestjs/typeorm"; -import { Repository } from "typeorm"; -import { Pagination, IPaginationOptions } from "nestjs-typeorm-paginate"; +import { Repository, FindOptionsSelect, MoreThanOrEqual } from "typeorm"; +import { Pagination } from "nestjs-typeorm-paginate"; +import { IPaginationOptions } from "../common/types"; import { paginate } from "../common/utils"; -import { Token } from "./token.entity"; +import { Token, ETH_TOKEN } from "./token.entity"; + +export interface FilterTokensOptions { + minLiquidity?: number; +} @Injectable() export class TokenService { @@ -12,17 +17,40 @@ export class TokenService { private readonly tokenRepository: Repository ) {} - public async findOne(address: string): Promise { - return await this.tokenRepository.findOneBy({ l2Address: address }); + public async findOne(address: string, fields?: FindOptionsSelect): Promise { + const token = await this.tokenRepository.findOne({ + where: { + l2Address: address, + }, + select: fields, + }); + if (!token && address.toLowerCase() === ETH_TOKEN.l2Address.toLowerCase()) { + return ETH_TOKEN; + } + return token; } public async exists(address: string): Promise { - return (await this.tokenRepository.findOne({ where: { l2Address: address }, select: { l2Address: true } })) != null; + const tokenExists = + (await this.tokenRepository.findOne({ where: { l2Address: address }, select: { l2Address: true } })) != null; + if (!tokenExists && address === ETH_TOKEN.l2Address.toLowerCase()) { + return true; + } + return tokenExists; } - public async findAll(paginationOptions: IPaginationOptions): Promise> { + public async findAll( + { minLiquidity }: FilterTokensOptions, + paginationOptions: IPaginationOptions + ): Promise> { const queryBuilder = this.tokenRepository.createQueryBuilder("token"); - queryBuilder.orderBy("token.blockNumber", "DESC"); + if (minLiquidity >= 0) { + queryBuilder.where({ + liquidity: MoreThanOrEqual(minLiquidity), + }); + } + queryBuilder.orderBy("token.liquidity", "DESC", "NULLS LAST"); + queryBuilder.addOrderBy("token.blockNumber", "DESC"); queryBuilder.addOrderBy("token.logIndex", "DESC"); return await paginate(queryBuilder, paginationOptions); } diff --git a/packages/api/src/transaction/dtos/transaction.dto.ts b/packages/api/src/transaction/dtos/transaction.dto.ts index f2d23b043f..597ec07753 100644 --- a/packages/api/src/transaction/dtos/transaction.dto.ts +++ b/packages/api/src/transaction/dtos/transaction.dto.ts @@ -40,7 +40,7 @@ export class TransactionDto { @ApiProperty({ type: String, description: "The amount this transaction sent", - example: "0x2386f26fc10000", + example: "100000000", }) public readonly value: string; @@ -58,6 +58,47 @@ export class TransactionDto { }) public readonly nonce: number; + @ApiProperty({ + type: String, + description: "Gas price", + example: "100000000", + }) + public readonly gasPrice: string; + + @ApiProperty({ + type: String, + description: "Gas limit", + example: "100000000", + }) + public readonly gasLimit: string; + + @ApiProperty({ + type: String, + description: "Gas per pubdata limit", + example: "100000000", + examples: ["100000000", null], + required: false, + }) + public readonly gasPerPubdata?: string; + + @ApiProperty({ + type: String, + description: "Max fee per gas", + example: "100000000", + examples: ["100000000", null], + required: false, + }) + public readonly maxFeePerGas?: string; + + @ApiProperty({ + type: String, + description: "Max priority fee per gas", + example: "100000000", + examples: ["100000000", null], + required: false, + }) + public readonly maxPriorityFeePerGas?: string; + @ApiProperty({ type: Number, description: "The number (height) of the block this transaction was mined in", @@ -131,6 +172,13 @@ export class TransactionDto { }) public readonly isL1BatchSealed: boolean; + @ApiProperty({ + type: Number, + description: "The type of the transaction", + example: 255, + }) + public readonly type: number; + @ApiProperty({ enum: TransactionStatus, description: "The status of the transaction", @@ -138,4 +186,22 @@ export class TransactionDto { examples: ["included", "committed", "proved", "verified", "failed"], }) public readonly status: TransactionStatus; + + @ApiProperty({ + type: String, + description: "Transaction error", + example: "Some test error", + examples: ["Some test error", null], + nullable: true, + }) + public readonly error?: string; + + @ApiProperty({ + type: String, + description: "Transaction revert reason", + example: "Some test revert reason", + examples: ["Some test revert reason", null], + nullable: true, + }) + public readonly revertReason?: string; } diff --git a/packages/api/src/transaction/dtos/transactionDetails.dto.ts b/packages/api/src/transaction/dtos/transactionDetails.dto.ts new file mode 100644 index 0000000000..0f18c8b72a --- /dev/null +++ b/packages/api/src/transaction/dtos/transactionDetails.dto.ts @@ -0,0 +1,11 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { TransactionDto } from "./transaction.dto"; + +export class TransactionDetailsDto extends TransactionDto { + @ApiProperty({ + type: String, + description: "Gas used by the transaction", + example: "50000000", + }) + public readonly gasUsed: string; +} diff --git a/packages/api/src/transaction/entities/transaction.entity.ts b/packages/api/src/transaction/entities/transaction.entity.ts index 28923251f5..b907d539c5 100644 --- a/packages/api/src/transaction/entities/transaction.entity.ts +++ b/packages/api/src/transaction/entities/transaction.entity.ts @@ -3,6 +3,7 @@ import { BaseEntity } from "../../common/entities/base.entity"; import { normalizeAddressTransformer } from "../../common/transformers/normalizeAddress.transformer"; import { bigIntNumberTransformer } from "../../common/transformers/bigIntNumber.transformer"; import { hexTransformer } from "../../common/transformers/hex.transformer"; +import { hexToDecimalNumberTransformer } from "../../common/transformers/hexToDecimalNumber.transformer"; import { TransactionReceipt } from "./transactionReceipt.entity"; import { Transfer } from "../../transfer/transfer.entity"; import { Block } from "../../block/block.entity"; @@ -61,6 +62,15 @@ export class Transaction extends BaseEntity { @Column({ type: "varchar", length: 128 }) public readonly gasPrice: string; + @Column({ type: "varchar", length: 128, nullable: true, transformer: hexToDecimalNumberTransformer }) + public readonly gasPerPubdata?: string; + + @Column({ type: "varchar", length: 128, nullable: true }) + public readonly maxFeePerGas?: string; + + @Column({ type: "varchar", length: 128, nullable: true }) + public readonly maxPriorityFeePerGas?: string; + @ManyToOne(() => Block) @JoinColumn({ name: "blockNumber" }) public readonly block: Block; @@ -79,6 +89,9 @@ export class Transaction extends BaseEntity { @Column({ type: "bytea", transformer: hexTransformer }) public readonly blockHash: string; + @Column({ type: "int" }) + public readonly type: number; + @Column({ type: "int" }) public readonly transactionIndex: number; @@ -88,6 +101,12 @@ export class Transaction extends BaseEntity { @OneToMany(() => Transfer, (transfer) => transfer.transaction) public readonly transfers: Transfer[]; + @Column({ nullable: true }) + public readonly error?: string; + + @Column({ nullable: true }) + public readonly revertReason?: string; + public get status(): TransactionStatus { if (this.receiptStatus === 0) { return TransactionStatus.Failed; diff --git a/packages/api/src/transaction/entities/transactionDetails.entity.ts b/packages/api/src/transaction/entities/transactionDetails.entity.ts new file mode 100644 index 0000000000..1b8fdb9f4f --- /dev/null +++ b/packages/api/src/transaction/entities/transactionDetails.entity.ts @@ -0,0 +1,18 @@ +import { Entity } from "typeorm"; +import { Transaction } from "./transaction.entity"; + +@Entity({ name: "transactions" }) +export class TransactionDetails extends Transaction { + public get gasUsed(): string { + return this.transactionReceipt ? this.transactionReceipt.gasUsed : null; + } + + toJSON(): any { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { transactionReceipt, ...restFields } = super.toJSON(); + return { + ...restFields, + gasUsed: this.gasUsed, + }; + } +} diff --git a/packages/api/src/transaction/transaction.controller.ts b/packages/api/src/transaction/transaction.controller.ts index a8e5bc95f9..f8465723d9 100644 --- a/packages/api/src/transaction/transaction.controller.ts +++ b/packages/api/src/transaction/transaction.controller.ts @@ -1,5 +1,12 @@ import { Controller, Get, Param, NotFoundException, Query } from "@nestjs/common"; -import { ApiTags, ApiParam, ApiBadRequestResponse, ApiNotFoundResponse, ApiOkResponse } from "@nestjs/swagger"; +import { + ApiTags, + ApiParam, + ApiBadRequestResponse, + ApiNotFoundResponse, + ApiOkResponse, + ApiExcludeController, +} from "@nestjs/swagger"; import { Pagination } from "nestjs-typeorm-paginate"; import { ApiListPageOkResponse } from "../common/decorators/apiListPageOkResponse"; import { PagingOptionsWithMaxItemsLimitDto, ListFiltersDto } from "../common/dtos"; @@ -7,15 +14,19 @@ import { buildDateFilter } from "../common/utils"; import { FilterTransactionsOptionsDto } from "./dtos/filterTransactionsOptions.dto"; import { TransferDto } from "../transfer/transfer.dto"; import { TransactionDto } from "./dtos/transaction.dto"; +import { TransactionDetailsDto } from "./dtos/transactionDetails.dto"; import { TransferService } from "../transfer/transfer.service"; import { LogDto } from "../log/log.dto"; import { LogService } from "../log/log.service"; import { TransactionService } from "./transaction.service"; import { ParseTransactionHashPipe, TX_HASH_REGEX_PATTERN } from "../common/pipes/parseTransactionHash.pipe"; +import { swagger } from "../config/featureFlags"; +import { constants } from "../config/docs"; const entityName = "transactions"; -@ApiTags(entityName) +@ApiTags("Transaction BFF") +@ApiExcludeController(!swagger.bffEnabled) @Controller(entityName) export class TransactionController { constructor( @@ -54,7 +65,7 @@ export class TransactionController { @ApiParam({ name: "transactionHash", schema: { pattern: TX_HASH_REGEX_PATTERN }, - example: "0xd99bd0a1ed5de1c258637e40f3e4e1f461375f5ca4712339031a8dade8079e88", + example: constants.txHash, description: "Valid transaction hash", }) @ApiOkResponse({ description: "Transaction was returned successfully", type: TransactionDto }) @@ -62,19 +73,19 @@ export class TransactionController { @ApiNotFoundResponse({ description: "Transaction with the specified hash does not exist" }) public async getTransaction( @Param("transactionHash", new ParseTransactionHashPipe()) transactionHash: string - ): Promise { - const transaction = await this.transactionService.findOne(transactionHash); - if (!transaction) { + ): Promise { + const transactionDetail = await this.transactionService.findOne(transactionHash); + if (!transactionDetail) { throw new NotFoundException(); } - return transaction; + return transactionDetail; } @Get(":transactionHash/transfers") @ApiParam({ name: "transactionHash", schema: { pattern: TX_HASH_REGEX_PATTERN }, - example: "0xd99bd0a1ed5de1c258637e40f3e4e1f461375f5ca4712339031a8dade8079e88", + example: constants.txHash, description: "Valid transaction hash", }) @ApiListPageOkResponse(TransferDto, { description: "Successfully returned transaction transfers list" }) @@ -103,7 +114,7 @@ export class TransactionController { @ApiParam({ name: "transactionHash", schema: { pattern: TX_HASH_REGEX_PATTERN }, - example: "0xd99bd0a1ed5de1c258637e40f3e4e1f461375f5ca4712339031a8dade8079e88", + example: constants.txHash, description: "Valid transaction hash", }) @ApiListPageOkResponse(LogDto, { description: "Successfully returned transaction logs list" }) diff --git a/packages/api/src/transaction/transaction.module.ts b/packages/api/src/transaction/transaction.module.ts index 299313a968..b121a319bd 100644 --- a/packages/api/src/transaction/transaction.module.ts +++ b/packages/api/src/transaction/transaction.module.ts @@ -4,6 +4,7 @@ import { TransactionController } from "./transaction.controller"; import { TransactionService } from "./transaction.service"; import { TransactionReceiptService } from "./transactionReceipt.service"; import { Transaction } from "./entities/transaction.entity"; +import { TransactionDetails } from "./entities/transactionDetails.entity"; import { AddressTransaction } from "./entities/addressTransaction.entity"; import { TransactionReceipt } from "./entities/transactionReceipt.entity"; import { Batch } from "../batch/batch.entity"; @@ -13,7 +14,7 @@ import { LogModule } from "../log/log.module"; @Module({ imports: [ - TypeOrmModule.forFeature([Transaction, AddressTransaction, TransactionReceipt, Batch]), + TypeOrmModule.forFeature([Transaction, TransactionDetails, AddressTransaction, TransactionReceipt, Batch]), TransferModule, LogModule, CounterModule, diff --git a/packages/api/src/transaction/transaction.service.spec.ts b/packages/api/src/transaction/transaction.service.spec.ts index 7fabab7d56..b8c5e7e3cb 100644 --- a/packages/api/src/transaction/transaction.service.spec.ts +++ b/packages/api/src/transaction/transaction.service.spec.ts @@ -8,6 +8,7 @@ import { SortingOrder } from "../common/types"; import { CounterService } from "../counter/counter.service"; import { TransactionService, FilterTransactionsOptions } from "./transaction.service"; import { Transaction } from "./entities/transaction.entity"; +import { TransactionDetails } from "./entities/transactionDetails.entity"; import { AddressTransaction } from "./entities/addressTransaction.entity"; import { Batch } from "../batch/batch.entity"; @@ -17,6 +18,7 @@ describe("TransactionService", () => { let transaction; let service: TransactionService; let repositoryMock: typeorm.Repository; + let repositoryDetailMock: typeorm.Repository; let addressTransactionRepositoryMock: typeorm.Repository; let batchRepositoryMock: typeorm.Repository; let counterServiceMock: CounterService; @@ -25,6 +27,7 @@ describe("TransactionService", () => { beforeEach(async () => { counterServiceMock = mock(); repositoryMock = mock>(); + repositoryDetailMock = mock>(); addressTransactionRepositoryMock = mock>(); batchRepositoryMock = mock>(); transaction = { @@ -38,6 +41,10 @@ describe("TransactionService", () => { provide: getRepositoryToken(Transaction), useValue: repositoryMock, }, + { + provide: getRepositoryToken(TransactionDetails), + useValue: repositoryDetailMock, + }, { provide: getRepositoryToken(AddressTransaction), useValue: addressTransactionRepositoryMock, @@ -61,21 +68,45 @@ describe("TransactionService", () => { }); describe("findOne", () => { + let queryBuilderMock; + const hash = "txHash"; + beforeEach(() => { - (repositoryMock.findOne as jest.Mock).mockResolvedValue(transaction); + queryBuilderMock = mock>(); + (repositoryDetailMock.createQueryBuilder as jest.Mock).mockReturnValue(queryBuilderMock); + (queryBuilderMock.getOne as jest.Mock).mockResolvedValue(null); }); - it("queries transactions by specified transaction hash", async () => { - await service.findOne(transactionHash); - expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); - expect(repositoryMock.findOne).toHaveBeenCalledWith({ - where: { hash: transactionHash }, - relations: { batch: true }, - }); + it("creates query builder with proper params", async () => { + await service.findOne(hash); + expect(repositoryDetailMock.createQueryBuilder).toHaveBeenCalledWith("transaction"); + }); + + it("filters transactions by the specified hash", async () => { + await service.findOne(hash); + expect(queryBuilderMock.where).toHaveBeenCalledWith({ hash }); + }); + + it("joins batch record to get batch specific fields", async () => { + await service.findOne(hash); + expect(queryBuilderMock.leftJoinAndSelect).toHaveBeenCalledWith("transaction.batch", "batch"); + }); + + it("joins transactionReceipt record to get transactionReceipt specific fields", async () => { + await service.findOne(hash); + expect(queryBuilderMock.leftJoin).toHaveBeenCalledWith("transaction.transactionReceipt", "transactionReceipt"); + }); + + it("selects only needed transactionReceipt fields", async () => { + await service.findOne(hash); + expect(queryBuilderMock.addSelect).toHaveBeenCalledWith(["transactionReceipt.gasUsed"]); }); - it("returns transaction by hash", async () => { - const result = await service.findOne(transactionHash); + it("returns paginated result", async () => { + const transaction = mock(); + (queryBuilderMock.getOne as jest.Mock).mockResolvedValue(transaction); + + const result = await service.findOne(hash); expect(result).toBe(transaction); }); }); @@ -155,11 +186,12 @@ describe("TransactionService", () => { ]); }); - it("orders transactions by receivedAt and transactionIndex DESC", async () => { + it("orders transactions by blockNumber, receivedAt and transactionIndex DESC", async () => { await service.findAll(filterTransactionsOptions, pagingOptions); expect(queryBuilderMock.orderBy).toBeCalledTimes(1); - expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("transaction.receivedAt", "DESC"); - expect(queryBuilderMock.addOrderBy).toBeCalledTimes(1); + expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("transaction.blockNumber", "DESC"); + expect(queryBuilderMock.addOrderBy).toBeCalledTimes(2); + expect(queryBuilderMock.addOrderBy).toHaveBeenCalledWith("transaction.receivedAt", "DESC"); expect(queryBuilderMock.addOrderBy).toHaveBeenCalledWith("transaction.transactionIndex", "DESC"); }); diff --git a/packages/api/src/transaction/transaction.service.ts b/packages/api/src/transaction/transaction.service.ts index 95821b839f..a79376148f 100644 --- a/packages/api/src/transaction/transaction.service.ts +++ b/packages/api/src/transaction/transaction.service.ts @@ -5,6 +5,7 @@ import { Pagination } from "nestjs-typeorm-paginate"; import { paginate } from "../common/utils"; import { IPaginationOptions, CounterCriteria, SortingOrder } from "../common/types"; import { Transaction } from "./entities/transaction.entity"; +import { TransactionDetails } from "./entities/transactionDetails.entity"; import { AddressTransaction } from "./entities/addressTransaction.entity"; import { Batch } from "../batch/batch.entity"; import { CounterService } from "../counter/counter.service"; @@ -29,6 +30,8 @@ export class TransactionService { constructor( @InjectRepository(Transaction) private readonly transactionRepository: Repository, + @InjectRepository(TransactionDetails) + private readonly transactionDetailsRepository: Repository, @InjectRepository(AddressTransaction) private readonly addressTransactionRepository: Repository, @InjectRepository(Batch) @@ -36,8 +39,13 @@ export class TransactionService { private readonly counterService: CounterService ) {} - public async findOne(hash: string): Promise { - return await this.transactionRepository.findOne({ where: { hash }, relations: { batch: true } }); + public async findOne(hash: string): Promise { + const queryBuilder = this.transactionDetailsRepository.createQueryBuilder("transaction"); + queryBuilder.leftJoinAndSelect("transaction.batch", "batch"); + queryBuilder.leftJoin("transaction.transactionReceipt", "transactionReceipt"); + queryBuilder.addSelect(["transactionReceipt.gasUsed"]); + queryBuilder.where({ hash }); + return await queryBuilder.getOne(); } public async exists(hash: string): Promise { @@ -82,7 +90,8 @@ export class TransactionService { queryBuilder.leftJoin("transaction.batch", "batch"); queryBuilder.addSelect(["batch.commitTxHash", "batch.executeTxHash", "batch.proveTxHash"]); queryBuilder.where(filterOptions); - queryBuilder.orderBy("transaction.receivedAt", "DESC"); + queryBuilder.orderBy("transaction.blockNumber", "DESC"); + queryBuilder.addOrderBy("transaction.receivedAt", "DESC"); queryBuilder.addOrderBy("transaction.transactionIndex", "DESC"); return await paginate(queryBuilder, paginationOptions); } diff --git a/packages/api/src/transfer/addressTransfer.entity.ts b/packages/api/src/transfer/addressTransfer.entity.ts index 597b32ff20..65e9677020 100644 --- a/packages/api/src/transfer/addressTransfer.entity.ts +++ b/packages/api/src/transfer/addressTransfer.entity.ts @@ -1,12 +1,14 @@ import { Entity, Column, Index, ManyToOne, JoinColumn, PrimaryColumn } from "typeorm"; import { BaseEntity } from "../common/entities/base.entity"; import { Transfer } from "./transfer.entity"; +import { TokenType } from "../token/token.entity"; import { bigIntNumberTransformer } from "../common/transformers/bigIntNumber.transformer"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; @Entity({ name: "addressTransfers" }) @Index(["address", "isFeeOrRefund", "timestamp", "logIndex"]) -@Index(["address", "tokenAddress", "fields", "blockNumber", "logIndex"]) +@Index(["address", "tokenType", "blockNumber", "logIndex"]) +@Index(["address", "tokenAddress", "blockNumber", "logIndex"]) export class AddressTransfer extends BaseEntity { @PrimaryColumn({ generated: true, type: "bigint" }) public readonly number: number; @@ -32,6 +34,9 @@ export class AddressTransfer extends BaseEntity { @Column({ type: "timestamp" }) public readonly timestamp: Date; + @Column({ type: "enum", enum: TokenType, default: TokenType.ETH }) + public readonly tokenType: TokenType; + @Column({ type: "boolean" }) public readonly isFeeOrRefund: boolean; diff --git a/packages/api/src/transfer/transfer.entity.ts b/packages/api/src/transfer/transfer.entity.ts index f079a21a52..c4ec6c6727 100644 --- a/packages/api/src/transfer/transfer.entity.ts +++ b/packages/api/src/transfer/transfer.entity.ts @@ -1,6 +1,6 @@ -import { Entity, Column, Index, ManyToOne, JoinColumn, PrimaryColumn } from "typeorm"; +import { Entity, Column, Index, ManyToOne, JoinColumn, PrimaryColumn, AfterLoad } from "typeorm"; import { BaseEntity } from "../common/entities/base.entity"; -import { Token } from "../token/token.entity"; +import { Token, TokenType, ETH_TOKEN } from "../token/token.entity"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; import { bigIntNumberTransformer } from "../common/transformers/bigIntNumber.transformer"; import { hexTransformer } from "../common/transformers/hex.transformer"; @@ -19,7 +19,7 @@ export enum TransferType { @Index(["blockNumber", "logIndex"]) @Index(["transactionHash", "timestamp", "logIndex"]) @Index(["tokenAddress", "isFeeOrRefund", "timestamp", "logIndex"]) -@Index(["tokenAddress", "fields", "blockNumber", "logIndex"]) +@Index(["tokenAddress", "blockNumber", "logIndex"]) export class Transfer extends BaseEntity { @PrimaryColumn({ generated: true, type: "bigint", select: false }) public number: number; @@ -53,9 +53,9 @@ export class Transfer extends BaseEntity { @Column({ type: "varchar", length: 128, nullable: true }) public readonly amount?: string; - @ManyToOne(() => Token) + @ManyToOne(() => Token, { createForeignKeyConstraints: false }) @JoinColumn({ name: "tokenAddress" }) - public readonly token?: Token; + public token?: Token; @Index() @Column({ type: "bytea", transformer: normalizeAddressTransformer }) @@ -64,6 +64,9 @@ export class Transfer extends BaseEntity { @Column({ type: "enum", enum: TransferType, default: TransferType.Transfer }) public readonly type: TransferType; + @Column({ type: "enum", enum: TokenType, default: TokenType.ETH }) + public readonly tokenType: TokenType; + @Column({ type: "boolean", select: false }) public readonly isFeeOrRefund: boolean; @@ -81,4 +84,11 @@ export class Transfer extends BaseEntity { const { number, ...restFields } = this; return restFields; } + + @AfterLoad() + populateEthToken() { + if (!this.token && this.tokenAddress === ETH_TOKEN.l2Address) { + this.token = ETH_TOKEN; + } + } } diff --git a/packages/api/src/transfer/transfer.service.spec.ts b/packages/api/src/transfer/transfer.service.spec.ts index 79df6df828..f8d580280b 100644 --- a/packages/api/src/transfer/transfer.service.spec.ts +++ b/packages/api/src/transfer/transfer.service.spec.ts @@ -16,7 +16,6 @@ import { TokenType } from "../token/token.entity"; import { AddressTransfer } from "./addressTransfer.entity"; import * as utils from "../common/utils"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; -import { L2_ETH_TOKEN_ADDRESS } from "../common/constants"; jest.mock("../common/utils"); @@ -228,18 +227,17 @@ describe("TransferService", () => { }); describe("when token type is ERC20", () => { - it("adds ERC20 filter", async () => { + it("adds tokenAddress filter", async () => { await service.findTokenTransfers(filterOptions); expect(queryBuilderMock.where).toBeCalledTimes(1); expect(queryBuilderMock.where).toHaveBeenCalledWith({ tokenAddress: filterOptions.tokenAddress, - fields: typeorm.IsNull(), }); }); }); describe("when token type is ERC721", () => { - it("adds ERC721 filter", async () => { + it("adds tokenAddress filter", async () => { await service.findTokenTransfers({ ...filterOptions, tokenType: TokenType.ERC721, @@ -247,7 +245,6 @@ describe("TransferService", () => { expect(queryBuilderMock.where).toBeCalledTimes(1); expect(queryBuilderMock.where).toHaveBeenCalledWith({ tokenAddress: "tokenAddress", - fields: typeorm.Not(typeorm.IsNull()), }); }); }); @@ -260,9 +257,25 @@ describe("TransferService", () => { it("joins transactions and transaction receipts records to the transfers", async () => { await service.findTokenTransfers(filterOptions); - expect(queryBuilderMock.leftJoin).toBeCalledTimes(2); + expect(queryBuilderMock.leftJoin).toHaveBeenCalledTimes(2); + expect(queryBuilderMock.addSelect).toHaveBeenCalledTimes(2); expect(queryBuilderMock.leftJoin).toHaveBeenCalledWith("transfer.transaction", "transaction"); + expect(queryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transaction.nonce", + "transaction.blockHash", + "transaction.transactionIndex", + "transaction.gasLimit", + "transaction.gasPrice", + "transaction.data", + "transaction.fee", + "transaction.l1BatchNumber", + "transaction.type", + ]); expect(queryBuilderMock.leftJoin).toHaveBeenCalledWith("transaction.transactionReceipt", "transactionReceipt"); + expect(queryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transactionReceipt.gasUsed", + "transactionReceipt.cumulativeGasUsed", + ]); }); it("adds start block filter when startBlock is specified", async () => { @@ -345,13 +358,19 @@ describe("TransferService", () => { }); describe("when token type is ERC20", () => { - it("adds ERC20 filter", async () => { + it("adds address and ERC20 filter", async () => { await service.findTokenTransfers(filterOptions); expect(addressTransfersQueryBuilderMock.where).toBeCalledTimes(1); expect(addressTransfersQueryBuilderMock.where).toHaveBeenCalledWith({ address: filterOptions.address, - fields: typeorm.IsNull(), }); + expect(addressTransfersQueryBuilderMock.andWhere).toBeCalledTimes(1); + expect(addressTransfersQueryBuilderMock.andWhere).toHaveBeenCalledWith( + `"addressTransfer"."tokenType" = :tokenType`, + { + tokenType: TokenType.ERC20, + } + ); }); }); @@ -364,8 +383,14 @@ describe("TransferService", () => { expect(addressTransfersQueryBuilderMock.where).toBeCalledTimes(1); expect(addressTransfersQueryBuilderMock.where).toHaveBeenCalledWith({ address: filterOptions.address, - fields: typeorm.Not(typeorm.IsNull()), }); + expect(addressTransfersQueryBuilderMock.andWhere).toBeCalledTimes(1); + expect(addressTransfersQueryBuilderMock.andWhere).toHaveBeenCalledWith( + `"addressTransfer"."tokenType" = :tokenType`, + { + tokenType: TokenType.ERC721, + } + ); }); }); @@ -385,19 +410,6 @@ describe("TransferService", () => { }); }); - describe("when token address is not specified", () => { - it("adds filter to exclude ETH token", async () => { - await service.findTokenTransfers(filterOptions); - expect(addressTransfersQueryBuilderMock.andWhere).toBeCalledTimes(1); - expect(addressTransfersQueryBuilderMock.andWhere).toHaveBeenCalledWith( - `"addressTransfer"."tokenAddress" != :tokenAddress`, - { - tokenAddress: normalizeAddressTransformer.to(L2_ETH_TOKEN_ADDRESS), - } - ); - }); - }); - it("joins transfers and tokens records to the address transfers", async () => { await service.findTokenTransfers(filterOptions); expect(addressTransfersQueryBuilderMock.leftJoinAndSelect).toBeCalledTimes(2); @@ -411,11 +423,27 @@ describe("TransferService", () => { it("joins transactions and transaction receipts records to the transfers", async () => { await service.findTokenTransfers(filterOptions); expect(addressTransfersQueryBuilderMock.leftJoin).toBeCalledTimes(2); + expect(addressTransfersQueryBuilderMock.addSelect).toBeCalledTimes(2); expect(addressTransfersQueryBuilderMock.leftJoin).toHaveBeenCalledWith("transfer.transaction", "transaction"); + expect(addressTransfersQueryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transaction.nonce", + "transaction.blockHash", + "transaction.transactionIndex", + "transaction.gasLimit", + "transaction.gasPrice", + "transaction.data", + "transaction.fee", + "transaction.l1BatchNumber", + "transaction.type", + ]); expect(addressTransfersQueryBuilderMock.leftJoin).toHaveBeenCalledWith( "transaction.transactionReceipt", "transactionReceipt" ); + expect(addressTransfersQueryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transactionReceipt.gasUsed", + "transactionReceipt.cumulativeGasUsed", + ]); }); it("adds start block filter when startBlock is specified", async () => { @@ -531,8 +559,20 @@ describe("TransferService", () => { it("joins transactions and transaction receipts records to the transfers", async () => { await service.findInternalTransfers(filterOptions); expect(queryBuilderMock.leftJoin).toBeCalledTimes(2); + expect(queryBuilderMock.addSelect).toBeCalledTimes(2); expect(queryBuilderMock.leftJoin).toHaveBeenCalledWith("transfer.transaction", "transaction"); + expect(queryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transaction.receiptStatus", + "transaction.gasLimit", + "transaction.fee", + "transaction.l1BatchNumber", + "transaction.type", + ]); expect(queryBuilderMock.leftJoin).toHaveBeenCalledWith("transaction.transactionReceipt", "transactionReceipt"); + expect(queryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transactionReceipt.gasUsed", + "transactionReceipt.contractAddress", + ]); }); it("adds start block filter when startBlock is specified", async () => { @@ -635,11 +675,23 @@ describe("TransferService", () => { it("joins transactions and transaction receipts records to the transfers", async () => { await service.findInternalTransfers(filterOptions); expect(addressTransfersQueryBuilderMock.leftJoin).toBeCalledTimes(2); + expect(addressTransfersQueryBuilderMock.addSelect).toBeCalledTimes(2); expect(addressTransfersQueryBuilderMock.leftJoin).toHaveBeenCalledWith("transfer.transaction", "transaction"); + expect(addressTransfersQueryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transaction.receiptStatus", + "transaction.gasLimit", + "transaction.fee", + "transaction.l1BatchNumber", + "transaction.type", + ]); expect(addressTransfersQueryBuilderMock.leftJoin).toHaveBeenCalledWith( "transaction.transactionReceipt", "transactionReceipt" ); + expect(addressTransfersQueryBuilderMock.addSelect).toHaveBeenCalledWith([ + "transactionReceipt.gasUsed", + "transactionReceipt.contractAddress", + ]); }); it("adds start block filter when startBlock is specified", async () => { diff --git a/packages/api/src/transfer/transfer.service.ts b/packages/api/src/transfer/transfer.service.ts index d038bfa55d..98ce2a2b6b 100644 --- a/packages/api/src/transfer/transfer.service.ts +++ b/packages/api/src/transfer/transfer.service.ts @@ -1,9 +1,8 @@ import { BadRequestException, Injectable } from "@nestjs/common"; import { InjectRepository } from "@nestjs/typeorm"; -import { Repository, FindOperator, MoreThanOrEqual, LessThanOrEqual, IsNull, Not } from "typeorm"; +import { Repository, FindOperator, MoreThanOrEqual, LessThanOrEqual } from "typeorm"; import { Pagination } from "nestjs-typeorm-paginate"; import { paginate } from "../common/utils"; -import { L2_ETH_TOKEN_ADDRESS } from "../common/constants"; import { IPaginationOptions, SortingOrder } from "../common/types"; import { Transfer } from "./transfer.entity"; import { TokenType } from "../token/token.entity"; @@ -100,20 +99,20 @@ export class TransferService { "transaction.data", "transaction.fee", "transaction.l1BatchNumber", + "transaction.type", ]); queryBuilder.leftJoin("transaction.transactionReceipt", "transactionReceipt"); queryBuilder.addSelect(["transactionReceipt.gasUsed", "transactionReceipt.cumulativeGasUsed"]); queryBuilder.where({ address, - fields: tokenType === TokenType.ERC721 ? Not(IsNull()) : IsNull(), }); if (tokenAddress) { queryBuilder.andWhere(`"addressTransfer"."tokenAddress" = :tokenAddress`, { tokenAddress: normalizeAddressTransformer.to(tokenAddress), }); } else { - queryBuilder.andWhere(`"addressTransfer"."tokenAddress" != :tokenAddress`, { - tokenAddress: normalizeAddressTransformer.to(L2_ETH_TOKEN_ADDRESS), + queryBuilder.andWhere(`"addressTransfer"."tokenType" = :tokenType`, { + tokenType, }); } if (startBlock !== undefined) { @@ -149,12 +148,12 @@ export class TransferService { "transaction.data", "transaction.fee", "transaction.l1BatchNumber", + "transaction.type", ]); queryBuilder.leftJoin("transaction.transactionReceipt", "transactionReceipt"); queryBuilder.addSelect(["transactionReceipt.gasUsed", "transactionReceipt.cumulativeGasUsed"]); queryBuilder.where({ tokenAddress, - fields: tokenType === TokenType.ERC721 ? Not(IsNull()) : IsNull(), }); if (startBlock !== undefined) { queryBuilder.andWhere({ @@ -194,6 +193,7 @@ export class TransferService { "transaction.gasLimit", "transaction.fee", "transaction.l1BatchNumber", + "transaction.type", ]); queryBuilder.leftJoin("transaction.transactionReceipt", "transactionReceipt"); queryBuilder.addSelect(["transactionReceipt.gasUsed", "transactionReceipt.contractAddress"]); @@ -226,6 +226,7 @@ export class TransferService { "transaction.gasLimit", "transaction.fee", "transaction.l1BatchNumber", + "transaction.type", ]); queryBuilder.leftJoin("transaction.transactionReceipt", "transactionReceipt"); queryBuilder.addSelect(["transactionReceipt.gasUsed", "transactionReceipt.contractAddress"]); diff --git a/packages/api/test/account-api.e2e-spec.ts b/packages/api/test/account-api.e2e-spec.ts index 84417ee430..f529cc56aa 100644 --- a/packages/api/test/account-api.e2e-spec.ts +++ b/packages/api/test/account-api.e2e-spec.ts @@ -4,12 +4,14 @@ import { getRepositoryToken } from "@nestjs/typeorm"; import * as request from "supertest"; import { Repository } from "typeorm"; import { BatchDetails } from "../src/batch/batchDetails.entity"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { AddressTransaction } from "../src/transaction/entities/addressTransaction.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; import { TransactionReceipt } from "../src/transaction/entities/transactionReceipt.entity"; -import { Token } from "../src/token/token.entity"; +import { Token, TokenType } from "../src/token/token.entity"; import { Balance } from "../src/balance/balance.entity"; +import { AddressTransfer } from "../src/transfer/addressTransfer.entity"; +import { Transfer, TransferType } from "../src/transfer/transfer.entity"; import { L2_ETH_TOKEN_ADDRESS } from "../src/common/constants"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; @@ -18,8 +20,10 @@ describe("Account API (e2e)", () => { let app: INestApplication; let addressTransactionRepository: Repository; let transactionRepository: Repository; + let addressTransferRepository: Repository; + let transferRepository: Repository; let transactionReceiptRepository: Repository; - let blockRepository: Repository; + let blockRepository: Repository; let batchRepository: Repository; let tokenRepository: Repository; let balanceRepository: Repository; @@ -35,8 +39,10 @@ describe("Account API (e2e)", () => { addressTransactionRepository = app.get>(getRepositoryToken(AddressTransaction)); transactionRepository = app.get>(getRepositoryToken(Transaction)); + addressTransferRepository = app.get>(getRepositoryToken(AddressTransfer)); + transferRepository = app.get>(getRepositoryToken(Transfer)); transactionReceiptRepository = app.get>(getRepositoryToken(TransactionReceipt)); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); batchRepository = app.get>(getRepositoryToken(BatchDetails)); tokenRepository = app.get>(getRepositoryToken(Token)); balanceRepository = app.get>(getRepositoryToken(Balance)); @@ -53,19 +59,21 @@ describe("Account API (e2e)", () => { executeTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e23", }); - await blockRepository.insert({ - number: 1, - hash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", - timestamp: new Date("2022-11-10T14:44:08.000Z"), - gasLimit: "0", - gasUsed: "0", - baseFeePerGas: "100000000", - extraData: "0x", - l1TxCount: 1, - l2TxCount: 1, - l1BatchNumber: 0, - miner: "0x0000000000000000000000000000000000000000", - }); + for (let i = 1; i <= 2; i++) { + await blockRepository.insert({ + number: i, + hash: `0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb${i}`, + timestamp: new Date("2022-11-10T14:44:08.000Z"), + gasLimit: "0", + gasUsed: "0", + baseFeePerGas: "100000000", + extraData: "0x", + l1TxCount: 1, + l2TxCount: 1, + l1BatchNumber: 0, + miner: "0x0000000000000000000000000000000000000000", + }); + } await transactionRepository.insert({ to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", @@ -84,6 +92,7 @@ describe("Account API (e2e)", () => { receiptStatus: 0, gasLimit: "1000000", gasPrice: "100", + type: 255, }); await transactionReceiptRepository.insert({ @@ -104,16 +113,6 @@ describe("Account API (e2e)", () => { transactionIndex: 1, }); - await tokenRepository.insert({ - l1Address: L2_ETH_TOKEN_ADDRESS, - l2Address: L2_ETH_TOKEN_ADDRESS, - symbol: "ETH", - name: "ETH", - decimals: 18, - blockNumber: 1, - logIndex: 1, - }); - await tokenRepository.insert({ l1Address: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe111", l2Address: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe112", @@ -124,6 +123,51 @@ describe("Account API (e2e)", () => { logIndex: 1, }); + const tokens = [ + { + tokenType: TokenType.ETH, + tokenAddress: "0x000000000000000000000000000000000000800a", + }, + { + tokenType: TokenType.ERC20, + tokenAddress: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe112", + }, + ]; + + for (let i = 0; i < 6; i++) { + const transferSpec = { + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35E", + blockNumber: i < 3 ? 1 : 2, + transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + transactionIndex: i, + timestamp: new Date("2022-11-21T18:16:51.000Z"), + type: TransferType.Deposit, + tokenType: tokens[i % 2].tokenType, + tokenAddress: tokens[i % 2].tokenAddress, + logIndex: i, + isFeeOrRefund: false, + isInternal: false, + amount: (100 + i).toString(), + }; + + const insertResult = await transferRepository.insert(transferSpec); + + for (const address of new Set([transferSpec.from, transferSpec.to])) { + await addressTransferRepository.insert({ + transferNumber: Number(insertResult.identifiers[0].number), + address, + tokenAddress: transferSpec.tokenAddress, + blockNumber: transferSpec.blockNumber, + timestamp: transferSpec.timestamp, + tokenType: transferSpec.tokenType, + isFeeOrRefund: transferSpec.isFeeOrRefund, + logIndex: transferSpec.logIndex, + isInternal: transferSpec.isInternal, + }); + } + } + await balanceRepository.insert({ address: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", tokenAddress: L2_ETH_TOKEN_ADDRESS, @@ -147,9 +191,12 @@ describe("Account API (e2e)", () => { }); afterAll(async () => { + await addressTransferRepository.delete({}); + await transferRepository.delete({}); await addressTransactionRepository.delete({}); await transactionReceiptRepository.delete({}); await transactionRepository.delete({}); + await transactionRepository.delete({}); await balanceRepository.delete({}); await tokenRepository.delete({}); await blockRepository.delete({}); @@ -184,7 +231,7 @@ describe("Account API (e2e)", () => { blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", blockNumber: "1", commitTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e21", - confirmations: "0", + confirmations: "1", contractAddress: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", cumulativeGasUsed: "1100000", executeTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e23", @@ -207,6 +254,7 @@ describe("Account API (e2e)", () => { transactionIndex: "1", txreceipt_status: "0", value: "0x2386f26fc10000", + type: "255", }, ], }) @@ -214,6 +262,295 @@ describe("Account API (e2e)", () => { }); }); + describe("/api?module=account&action=tokentx GET", () => { + it("returns HTTP 200 and no transactions found response when no account transfers found", () => { + return request(app.getHttpServer()) + .get(`/api?module=account&action=tokentx&address=0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35b`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + status: "0", + message: "No transactions found", + result: [], + }) + ); + }); + + it("returns HTTP 200 and token transfers for the specified address", () => { + return request(app.getHttpServer()) + .get(`/api?module=account&action=tokentx&address=0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: [ + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "2", + confirmations: "0", + contractAddress: "0xC7e0220D02d549c4846A6ec31d89c3B670ebe112", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "TKN", + tokenSymbol: "TKN", + transactionIndex: "1", + value: "105", + transactionType: "255", + }, + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "2", + confirmations: "0", + contractAddress: "0xC7e0220D02d549c4846A6ec31d89c3B670ebe112", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "TKN", + tokenSymbol: "TKN", + transactionIndex: "1", + value: "103", + transactionType: "255", + }, + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "1", + confirmations: "1", + contractAddress: "0xC7e0220D02d549c4846A6ec31d89c3B670ebe112", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "TKN", + tokenSymbol: "TKN", + transactionIndex: "1", + value: "101", + transactionType: "255", + }, + ], + status: "1", + }) + ); + }); + + it("returns HTTP 200 and ETH transfers for the specified address and contract address", () => { + return request(app.getHttpServer()) + .get( + `/api?module=account&action=tokentx&address=0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C&contractaddress=0x000000000000000000000000000000000000800a` + ) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: [ + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "2", + confirmations: "0", + contractAddress: "0x000000000000000000000000000000000000800A", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "Ether", + tokenSymbol: "ETH", + transactionIndex: "1", + value: "104", + transactionType: "255", + }, + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "1", + confirmations: "1", + contractAddress: "0x000000000000000000000000000000000000800A", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "Ether", + tokenSymbol: "ETH", + transactionIndex: "1", + value: "102", + transactionType: "255", + }, + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "1", + confirmations: "1", + contractAddress: "0x000000000000000000000000000000000000800A", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "Ether", + tokenSymbol: "ETH", + transactionIndex: "1", + value: "100", + transactionType: "255", + }, + ], + status: "1", + }) + ); + }); + + it("returns HTTP 200 and token transfers for the specified address and startblock param", () => { + return request(app.getHttpServer()) + .get(`/api?module=account&action=tokentx&address=0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C&startblock=2`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: [ + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "2", + confirmations: "0", + contractAddress: "0xC7e0220D02d549c4846A6ec31d89c3B670ebe112", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "TKN", + tokenSymbol: "TKN", + transactionIndex: "1", + value: "105", + transactionType: "255", + }, + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "2", + confirmations: "0", + contractAddress: "0xC7e0220D02d549c4846A6ec31d89c3B670ebe112", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "TKN", + tokenSymbol: "TKN", + transactionIndex: "1", + value: "103", + transactionType: "255", + }, + ], + status: "1", + }) + ); + }); + + it("returns HTTP 200 and token transfers for the specified address and endblock param", () => { + return request(app.getHttpServer()) + .get(`/api?module=account&action=tokentx&address=0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C&endblock=1`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: [ + { + blockHash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + blockNumber: "1", + confirmations: "1", + contractAddress: "0xC7e0220D02d549c4846A6ec31d89c3B670ebe112", + cumulativeGasUsed: "1100000", + fee: "10000000000000000", + from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", + gas: "1000000", + gasPrice: "100", + gasUsed: "900000", + hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e20", + input: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + l1BatchNumber: "0", + nonce: "42", + timeStamp: "1669054611", + to: "0xc7E0220D02D549C4846a6eC31d89c3b670ebE35e", + tokenDecimal: "18", + tokenName: "TKN", + tokenSymbol: "TKN", + transactionIndex: "1", + value: "101", + transactionType: "255", + }, + ], + status: "1", + }) + ); + }); + }); + describe("/api?module=account&action=balance GET", () => { it("returns HTTP 200 and 0 balance when account has no Ether balance", () => { return request(app.getHttpServer()) @@ -303,4 +640,30 @@ describe("Account API (e2e)", () => { ); }); }); + + describe("/api?module=account&action=getminedblocks GET", () => { + it("returns HTTP 200 and list of mined blocks by address", () => { + return request(app.getHttpServer()) + .get(`/api?module=account&action=getminedblocks&address=0x0000000000000000000000000000000000000000`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + status: "1", + message: "OK", + result: [ + { + blockNumber: "2", + blockReward: "0", + timeStamp: "1668091448", + }, + { + blockNumber: "1", + blockReward: "0", + timeStamp: "1668091448", + }, + ], + }) + ); + }); + }); }); diff --git a/packages/api/test/address.e2e-spec.ts b/packages/api/test/address.e2e-spec.ts index b5eee34877..0c51412dcc 100644 --- a/packages/api/test/address.e2e-spec.ts +++ b/packages/api/test/address.e2e-spec.ts @@ -7,12 +7,12 @@ import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; import { Address } from "../src/address/address.entity"; import { Balance } from "../src/balance/balance.entity"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; import { AddressTransaction } from "../src/transaction/entities/addressTransaction.entity"; import { TransactionReceipt } from "../src/transaction/entities/transactionReceipt.entity"; import { Log } from "../src/log/log.entity"; -import { Token } from "../src/token/token.entity"; +import { Token, TokenType, ETH_TOKEN } from "../src/token/token.entity"; import { BatchDetails } from "../src/batch/batchDetails.entity"; import { Counter } from "../src/counter/counter.entity"; import { Transfer, TransferType } from "../src/transfer/transfer.entity"; @@ -21,7 +21,7 @@ import { AddressTransfer } from "../src/transfer/addressTransfer.entity"; describe("AddressController (e2e)", () => { let app: INestApplication; let addressRepository: Repository
; - let blockRepository: Repository; + let blockRepository: Repository; let transactionRepository: Repository; let addressTransactionRepository: Repository; let transactionReceiptRepository: Repository; @@ -45,7 +45,7 @@ describe("AddressController (e2e)", () => { await app.init(); addressRepository = app.get>(getRepositoryToken(Address)); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); transactionRepository = app.get>(getRepositoryToken(Transaction)); addressTransactionRepository = app.get>(getRepositoryToken(AddressTransaction)); transactionReceiptRepository = app.get>(getRepositoryToken(TransactionReceipt)); @@ -110,6 +110,7 @@ describe("AddressController (e2e)", () => { receiptStatus: 1, gasLimit: "1000000", gasPrice: "100", + type: 255, }; await transactionRepository.insert(transactionSpec); @@ -149,6 +150,16 @@ describe("AddressController (e2e)", () => { bytecode: "0x", }); + await tokenRepository.insert({ + l2Address: ETH_TOKEN.l2Address, + l1Address: ETH_TOKEN.l1Address, + symbol: ETH_TOKEN.symbol, + name: ETH_TOKEN.name, + decimals: ETH_TOKEN.decimals, + blockNumber: 0, + logIndex: 0, + }); + // tokens for balances for (let i = 0; i <= 9; i++) { await tokenRepository.insert({ @@ -184,6 +195,13 @@ describe("AddressController (e2e)", () => { blockNumber: i + 3, balance: (345 * i).toString(), }); + + await balanceRepository.insert({ + address: "0x91d0a23f34e535e44df8ba84c53a0945cf0eeb67", + tokenAddress: "0x000000000000000000000000000000000000800A", + blockNumber: i + 3, + balance: (345 * i).toString(), + }); } // balances without address record @@ -208,6 +226,13 @@ describe("AddressController (e2e)", () => { blockNumber: i + 3, balance: (345 * i).toString(), }); + + await balanceRepository.insert({ + address: "0x91d0a23f34e535e44df8ba84c53a0945cf0eeb71", + tokenAddress: "0x000000000000000000000000000000000000800A", + blockNumber: i + 3, + balance: (345 * i).toString(), + }); } // contract address @@ -278,16 +303,6 @@ describe("AddressController (e2e)", () => { logIndex: 0, }); - await tokenRepository.insert({ - l2Address: "0x000000000000000000000000000000000000800a", - l1Address: "0x0000000000000000000000000000000000000000", - symbol: "ETH", - name: "Ether", - decimals: 18, - blockNumber: 1, - logIndex: 0, - }); - for (let i = 0; i < 30; i++) { let type = TransferType.Transfer; if (i % 6 === 1) { @@ -310,6 +325,7 @@ describe("AddressController (e2e)", () => { transactionIndex: i, timestamp: new Date("2022-11-21T18:16:51.000Z"), type, + tokenType: i % 2 ? TokenType.ERC20 : TokenType.ETH, tokenAddress: i % 2 ? "0x97d0a23f34e535e44df8ba84c53a0945cf0eeb67" : "0x000000000000000000000000000000000000800a", logIndex: i, @@ -326,6 +342,7 @@ describe("AddressController (e2e)", () => { tokenAddress: transferSpec.tokenAddress, blockNumber: transferSpec.blockNumber, timestamp: transferSpec.timestamp, + tokenType: transferSpec.tokenType, isFeeOrRefund: transferSpec.isFeeOrRefund, logIndex: transferSpec.logIndex, isInternal: transferSpec.isInternal, @@ -376,6 +393,19 @@ describe("AddressController (e2e)", () => { expect(res.body).toStrictEqual({ address: "0x91D0a23f34E535E44dF8ba84c53A0945CF0EEb67", balances: { + "0x000000000000000000000000000000000000800A": { + balance: "34500", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + }, "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956": { balance: "34500", token: { @@ -384,6 +414,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956", name: "TEST 6", symbol: "TEST 6", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954": { @@ -394,6 +427,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954", name: "TEST 4", symbol: "TEST 4", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955": { @@ -404,6 +440,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955", name: "TEST 5", symbol: "TEST 5", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, @@ -423,6 +462,19 @@ describe("AddressController (e2e)", () => { expect(res.body).toStrictEqual({ address: "0x91D0a23f34E535E44dF8ba84c53A0945CF0EEb67", balances: { + "0x000000000000000000000000000000000000800A": { + balance: "34500", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + }, "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956": { balance: "34500", token: { @@ -431,6 +483,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956", name: "TEST 6", symbol: "TEST 6", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954": { @@ -441,6 +496,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954", name: "TEST 4", symbol: "TEST 4", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955": { @@ -451,6 +509,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955", name: "TEST 5", symbol: "TEST 5", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, @@ -470,6 +531,19 @@ describe("AddressController (e2e)", () => { expect(res.body).toStrictEqual({ address: "0x91D0a23f34E535E44dF8ba84c53A0945CF0EEb67", balances: { + "0x000000000000000000000000000000000000800A": { + balance: "34500", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + }, "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956": { balance: "34500", token: { @@ -478,6 +552,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956", name: "TEST 6", symbol: "TEST 6", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954": { @@ -488,6 +565,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954", name: "TEST 4", symbol: "TEST 4", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955": { @@ -498,6 +578,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955", name: "TEST 5", symbol: "TEST 5", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, @@ -517,6 +600,19 @@ describe("AddressController (e2e)", () => { expect(res.body).toStrictEqual({ address: "0x91D0a23f34E535E44dF8ba84c53A0945CF0EEb67", balances: { + "0x000000000000000000000000000000000000800A": { + balance: "34500", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + }, "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956": { balance: "34500", token: { @@ -525,6 +621,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956", name: "TEST 6", symbol: "TEST 6", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954": { @@ -535,6 +634,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954", name: "TEST 4", symbol: "TEST 4", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955": { @@ -545,6 +647,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955", name: "TEST 5", symbol: "TEST 5", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, @@ -566,6 +671,19 @@ describe("AddressController (e2e)", () => { expect(res.body).toStrictEqual({ address: "0x91d0A23F34e535E44dF8ba84c53a0945cf0EEB71", balances: { + "0x000000000000000000000000000000000000800A": { + balance: "34500", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + }, "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956": { balance: "34500", token: { @@ -574,6 +692,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488FC54FcCc6f319D4863Ddc2c2899Ed35d8956", name: "TEST 6", symbol: "TEST 6", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954": { @@ -584,6 +705,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488Fc54FCcC6f319d4863dDc2C2899ED35D8954", name: "TEST 4", symbol: "TEST 4", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955": { @@ -594,6 +718,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54fCcC6F319D4863dDC2c2899ED35D8955", name: "TEST 5", symbol: "TEST 5", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, @@ -623,6 +750,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fcCC6f319D4863Ddc2C2899ED35d8957", name: "TEST 7", symbol: "TEST 7", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959": { @@ -633,6 +763,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959", name: "TEST 9", symbol: "TEST 9", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958": { @@ -643,13 +776,16 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958", name: "TEST 8", symbol: "TEST 8", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, blockNumber: 106, bytecode: "0x000012", createdInBlockNumber: 10, - creatorAddress: "0xc7e0220d02D549C4846A6EC31D89C3B670eBE355", + creatorAddress: "0x91d0a23f34e535e44Df8Ba84c53a0945cf0eEB60", creatorTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e15", totalTransactions: 4, type: "contract", @@ -673,6 +809,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fcCC6f319D4863Ddc2C2899ED35d8957", name: "TEST 7", symbol: "TEST 7", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959": { @@ -683,6 +822,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959", name: "TEST 9", symbol: "TEST 9", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958": { @@ -693,13 +835,16 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958", name: "TEST 8", symbol: "TEST 8", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, blockNumber: 106, bytecode: "0x000012", createdInBlockNumber: 10, - creatorAddress: "0xc7e0220d02D549C4846A6EC31D89C3B670eBE355", + creatorAddress: "0x91d0a23f34e535e44Df8Ba84c53a0945cf0eEB60", creatorTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e15", totalTransactions: 4, type: "contract", @@ -723,6 +868,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fcCC6f319D4863Ddc2C2899ED35d8957", name: "TEST 7", symbol: "TEST 7", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959": { @@ -733,6 +881,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959", name: "TEST 9", symbol: "TEST 9", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958": { @@ -743,13 +894,16 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958", name: "TEST 8", symbol: "TEST 8", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, blockNumber: 106, bytecode: "0x000012", createdInBlockNumber: 10, - creatorAddress: "0xc7e0220d02D549C4846A6EC31D89C3B670eBE355", + creatorAddress: "0x91d0a23f34e535e44Df8Ba84c53a0945cf0eEB60", creatorTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e15", totalTransactions: 4, type: "contract", @@ -773,6 +927,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fcCC6f319D4863Ddc2C2899ED35d8957", name: "TEST 7", symbol: "TEST 7", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959": { @@ -783,6 +940,9 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fC54fccC6F319d4863DDc2C2899ed35d8959", name: "TEST 9", symbol: "TEST 9", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958": { @@ -793,13 +953,16 @@ describe("AddressController (e2e)", () => { l2Address: "0x9488fc54FCCC6f319D4863dDc2c2899Ed35D8958", name: "TEST 8", symbol: "TEST 8", + iconURL: null, + liquidity: null, + usdPrice: null, }, }, }, blockNumber: 106, bytecode: "0x000012", createdInBlockNumber: 10, - creatorAddress: "0xc7e0220d02D549C4846A6EC31D89C3B670eBE355", + creatorAddress: "0x91d0a23f34e535e44Df8Ba84c53a0945cf0eEB60", creatorTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e15", totalTransactions: 4, type: "contract", @@ -819,7 +982,7 @@ describe("AddressController (e2e)", () => { blockNumber: 10, bytecode: "0x000012", createdInBlockNumber: 10, - creatorAddress: "0xc7e0220d02D549C4846A6EC31D89C3B670eBE355", + creatorAddress: "0x91d0a23f34e535e44Df8Ba84c53a0945cf0eEB60", creatorTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e15", totalTransactions: 0, type: "contract", @@ -1025,10 +1188,14 @@ describe("AddressController (e2e)", () => { l2Address: "0x97d0a23F34E535e44dF8ba84c53A0945cF0eEb67", name: "TEST", symbol: "TST", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x97d0a23F34E535e44dF8ba84c53A0945cF0eEb67", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e11", type: "mint", + tokenType: "ERC20", isInternal: false, }, { @@ -1044,10 +1211,14 @@ describe("AddressController (e2e)", () => { symbol: "ETH", name: "Ether", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x000000000000000000000000000000000000800A", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e11", type: "transfer", + tokenType: "ETH", isInternal: false, }, { @@ -1063,10 +1234,14 @@ describe("AddressController (e2e)", () => { l2Address: "0x97d0a23F34E535e44dF8ba84c53A0945cF0eEb67", name: "TEST", symbol: "TST", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x97d0a23F34E535e44dF8ba84c53A0945cF0eEb67", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e11", type: "deposit", + tokenType: "ERC20", isInternal: false, }, ]) diff --git a/packages/api/test/block-api.e2e-spec.ts b/packages/api/test/block-api.e2e-spec.ts index dab94a051e..c04f833be8 100644 --- a/packages/api/test/block-api.e2e-spec.ts +++ b/packages/api/test/block-api.e2e-spec.ts @@ -5,12 +5,12 @@ import { Repository } from "typeorm"; import { getRepositoryToken } from "@nestjs/typeorm"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { BatchDetails } from "../src/batch/batchDetails.entity"; describe("Block API (e2e)", () => { let app: INestApplication; - let blockRepository: Repository; + let blockRepository: Repository; let batchRepository: Repository; beforeAll(async () => { @@ -24,7 +24,7 @@ describe("Block API (e2e)", () => { await app.init(); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); batchRepository = app.get>(getRepositoryToken(BatchDetails)); for (let i = 0; i < 9; i++) { diff --git a/packages/api/test/block.e2e-spec.ts b/packages/api/test/block.e2e-spec.ts index c2bcf91129..3cf78d81e8 100644 --- a/packages/api/test/block.e2e-spec.ts +++ b/packages/api/test/block.e2e-spec.ts @@ -5,12 +5,12 @@ import { Repository } from "typeorm"; import { getRepositoryToken } from "@nestjs/typeorm"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { BatchDetails } from "../src/batch/batchDetails.entity"; describe("BlockController (e2e)", () => { let app: INestApplication; - let blockRepository: Repository; + let blockRepository: Repository; let batchRepository: Repository; beforeAll(async () => { @@ -24,7 +24,7 @@ describe("BlockController (e2e)", () => { await app.init(); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); batchRepository = app.get>(getRepositoryToken(BatchDetails)); for (let i = 0; i < 9; i++) { diff --git a/packages/api/test/contract-api.e2e-spec.ts b/packages/api/test/contract-api.e2e-spec.ts index e68ffe3fdc..67b20c348e 100644 --- a/packages/api/test/contract-api.e2e-spec.ts +++ b/packages/api/test/contract-api.e2e-spec.ts @@ -113,7 +113,7 @@ describe("Contract API (e2e)", () => { { ABI: "[]", CompilerVersion: "8.10.0", - CompilerZksolcVersion: "10.0.0", + ZkCompilerVersion: "10.0.0", ConstructorArguments: "0001", ContractName: "contractName", EVMVersion: "Default", @@ -149,6 +149,14 @@ describe("Contract API (e2e)", () => { optimizer: { enabled: true, }, + libraries: { + "contracts/MiniMath.sol": { + MiniMath: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + }, + "contracts/MiniMath2.sol": { + MiniMath2: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5914", + }, + }, }, sources: { "@openzeppelin/contracts/access/Ownable.sol": { @@ -177,18 +185,19 @@ describe("Contract API (e2e)", () => { { ABI: "[]", CompilerVersion: "8.10.0", - CompilerZksolcVersion: "10.0.0", + ZkCompilerVersion: "10.0.0", ConstructorArguments: "0001", ContractName: "contractName", EVMVersion: "Default", Implementation: "", - Library: "", + Library: + "contracts/MiniMath.sol:MiniMath:0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913;contracts/MiniMath2.sol:MiniMath2:0x1c1cEFA394748048BE6b04Ea6081fE44B26a5914", LicenseType: "", OptimizationUsed: "1", Proxy: "0", Runs: "", SourceCode: - '{{"language":"Solidity","settings":{"optimizer":{"enabled":true}},"sources":{"@openzeppelin/contracts/access/Ownable.sol":{"content":"Ownable.sol content"},"faucet.sol":{"content":"faucet.sol content"}}}}', + '{{"language":"Solidity","settings":{"optimizer":{"enabled":true},"libraries":{"contracts/MiniMath.sol":{"MiniMath":"0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913"},"contracts/MiniMath2.sol":{"MiniMath2":"0x1c1cEFA394748048BE6b04Ea6081fE44B26a5914"}}},"sources":{"@openzeppelin/contracts/access/Ownable.sol":{"content":"Ownable.sol content"},"faucet.sol":{"content":"faucet.sol content"}}}}', SwarmSource: "", }, ], @@ -229,7 +238,7 @@ describe("Contract API (e2e)", () => { { ABI: "[]", CompilerVersion: "9.10.0", - CompilerZkvyperVersion: "11.0.0", + ZkCompilerVersion: "11.0.0", ConstructorArguments: "0001", ContractName: "contractName", EVMVersion: "Default", @@ -281,7 +290,7 @@ describe("Contract API (e2e)", () => { { ABI: "[]", CompilerVersion: "9.10.0", - CompilerZkvyperVersion: "11.0.0", + ZkCompilerVersion: "11.0.0", ConstructorArguments: "0001", ContractName: "contractName", EVMVersion: "Default", @@ -337,6 +346,276 @@ describe("Contract API (e2e)", () => { }); }); + describe("/api POST", () => { + it("returns HTTP 200 and contract verification id for single file Solidity contract", () => { + nock(CONTRACT_VERIFICATION_API_URL) + .post("/contract_verification") + .reply(200, 123 as unknown as nock.Body); + + return request(app.getHttpServer()) + .post("/api") + .send({ + module: "contract", + action: "verifysourcecode", + contractaddress: "0x79efF59e5ae65D9876F1020b3cCAb4027B49c2a2", + sourceCode: "// SPDX-License-Identifier: UNLICENSED", + codeformat: "solidity-single-file", + contractname: "contracts/HelloWorld.sol:HelloWorld", + compilerversion: "0.8.17", + optimizationUsed: "1", + zkCompilerVersion: "v1.3.14", + }) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: "123", + status: "1", + }) + ); + }); + + it("returns HTTP 200 and contract verification id for multi file Solidity contract", () => { + nock(CONTRACT_VERIFICATION_API_URL) + .post("/contract_verification") + .reply(200, 123 as unknown as nock.Body); + + return request(app.getHttpServer()) + .post("/api") + .send({ + module: "contract", + action: "verifysourcecode", + contractaddress: "0x14174c76E073f8efEf5C1FE0dd0f8c2Ca9F21e62", + sourceCode: { + language: "Solidity", + settings: { + optimizer: { + enabled: true, + }, + }, + sources: { + "contracts/HelloWorldCtor.sol": { + content: "// SPDX-License-Identifier: UNLICENSED", + }, + }, + }, + codeformat: "solidity-standard-json-input", + contractname: "contracts/HelloWorldCtor.sol:HelloWorldCtor", + compilerversion: "0.8.17", + optimizationUsed: "1", + zkCompilerVersion: "v1.3.14", + constructorArguements: "0x94869207468657265210000000000000000000000000000000000000000000000", + runs: 700, + }) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: "123", + status: "1", + }) + ); + }); + + it("returns HTTP 200 and contract verification id for multi file Vyper contract", () => { + nock(CONTRACT_VERIFICATION_API_URL) + .post("/contract_verification") + .reply(200, 123 as unknown as nock.Body); + + return request(app.getHttpServer()) + .post("/api") + .send({ + module: "contract", + action: "verifysourcecode", + contractaddress: "0xD60F82CF24eEF908026B1920323FF586F328B3fe", + sourceCode: { + language: "Solidity", + settings: { + optimizer: { + enabled: true, + }, + }, + sources: { + "contracts/Main.sol": { + content: "// SPDX-License-Identifier 1", + }, + "contracts/MiniMath.sol": { + content: "// SPDX-License-Identifier 2", + }, + "contracts/MiniMath2.sol": { + content: "// SPDX-License-Identifier 3", + }, + }, + }, + codeformat: "solidity-standard-json-input", + contractname: "contracts/Main.sol:Main", + compilerversion: "0.8.17", + optimizationUsed: "1", + zkCompilerVersion: "v1.3.14", + constructorArguements: "0x94869207468657265210000000000000000000000000000000000000000000000", + runs: 600, + libraryname1: "contracts/MiniMath.sol:MiniMath", + libraryaddress1: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + libraryname2: "contracts/MiniMath2.sol:MiniMath2", + libraryaddress2: "0x1c1cEFA394748048BE6b04Ea6081fE44B26a5913", + }) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: "123", + status: "1", + }) + ); + }); + + it("returns HTTP 200 with NOTOK result and validation message for 400 verification response", () => { + nock(CONTRACT_VERIFICATION_API_URL) + .post("/contract_verification") + .reply(400, "Contract has been already verified"); + + return request(app.getHttpServer()) + .post("/api") + .send({ + module: "contract", + action: "verifysourcecode", + contractaddress: "0x79efF59e5ae65D9876F1020b3cCAb4027B49c2a2", + sourceCode: "// SPDX-License-Identifier: UNLICENSED", + codeformat: "solidity-single-file", + contractname: "contracts/HelloWorld.sol:HelloWorld", + compilerversion: "0.8.17", + optimizationUsed: "1", + zkCompilerVersion: "v1.3.14", + }) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "NOTOK", + result: "Contract has been already verified", + status: "0", + }) + ); + }); + + it("returns HTTP 200 with NOTOK and a generic error message for non 400 verification response", () => { + nock(CONTRACT_VERIFICATION_API_URL).post("/contract_verification").reply(500, "Error"); + + return request(app.getHttpServer()) + .post("/api") + .send({ + module: "contract", + action: "verifysourcecode", + contractaddress: "0x79efF59e5ae65D9876F1020b3cCAb4027B49c2a2", + sourceCode: "// SPDX-License-Identifier: UNLICENSED", + codeformat: "solidity-single-file", + contractname: "contracts/HelloWorld.sol:HelloWorld", + compilerversion: "0.8.17", + optimizationUsed: "1", + zkCompilerVersion: "v1.3.14", + }) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "NOTOK", + result: "Failed to send verification request", + status: "0", + }) + ); + }); + }); + + describe("/api?module=contract&action=checkverifystatus GET", () => { + it("returns HTTP 200 and successful verification status", () => { + const verificationId = "1234"; + + nock(CONTRACT_VERIFICATION_API_URL).get(`/contract_verification/${verificationId}`).reply(200, { + status: "successful", + }); + + return request(app.getHttpServer()) + .get(`/api?module=contract&action=checkverifystatus&guid=${verificationId}`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: "Pass - Verified", + status: "1", + }) + ); + }); + + it("returns HTTP 200 and queued verification status", () => { + const verificationId = "1234"; + + nock(CONTRACT_VERIFICATION_API_URL).get(`/contract_verification/${verificationId}`).reply(200, { + status: "queued", + }); + + return request(app.getHttpServer()) + .get(`/api?module=contract&action=checkverifystatus&guid=${verificationId}`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: "Pending in queue", + status: "1", + }) + ); + }); + + it("returns HTTP 200 and in progress verification status", () => { + const verificationId = "1234"; + + nock(CONTRACT_VERIFICATION_API_URL).get(`/contract_verification/${verificationId}`).reply(200, { + status: "in_progress", + }); + + return request(app.getHttpServer()) + .get(`/api?module=contract&action=checkverifystatus&guid=${verificationId}`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: "In progress", + status: "1", + }) + ); + }); + + it("returns HTTP 200 and in progress failed status", () => { + const verificationId = "1234"; + + nock(CONTRACT_VERIFICATION_API_URL).get(`/contract_verification/${verificationId}`).reply(200, { + status: "failed", + error: "ERROR! Compilation error.", + }); + + return request(app.getHttpServer()) + .get(`/api?module=contract&action=checkverifystatus&guid=${verificationId}`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "NOTOK", + result: "ERROR! Compilation error.", + status: "0", + }) + ); + }); + + it("returns HTTP 200 and not OK if verification id is not valid", () => { + return request(app.getHttpServer()) + .get(`/api?module=contract&action=checkverifystatus`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "NOTOK", + result: "Verification ID is not specified", + status: "0", + }) + ); + }); + }); + describe("/api?module=contract&action=getcontractcreation GET", () => { it("returns HTTP 200 and contract creation info when contract is found in DB", () => { const address = "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; diff --git a/packages/api/test/log-api.e2e-spec.ts b/packages/api/test/log-api.e2e-spec.ts index d97d124d5c..ad04223e9e 100644 --- a/packages/api/test/log-api.e2e-spec.ts +++ b/packages/api/test/log-api.e2e-spec.ts @@ -4,7 +4,7 @@ import { getRepositoryToken } from "@nestjs/typeorm"; import * as request from "supertest"; import { Repository } from "typeorm"; import { BatchDetails } from "../src/batch/batchDetails.entity"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { Log } from "../src/log/log.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; import { TransactionReceipt } from "../src/transaction/entities/transactionReceipt.entity"; @@ -15,7 +15,7 @@ describe("Logs API (e2e)", () => { let app: INestApplication; let transactionRepository: Repository; let transactionReceiptRepository: Repository; - let blockRepository: Repository; + let blockRepository: Repository; let batchRepository: Repository; let logRepository: Repository; @@ -30,7 +30,7 @@ describe("Logs API (e2e)", () => { transactionRepository = app.get>(getRepositoryToken(Transaction)); transactionReceiptRepository = app.get>(getRepositoryToken(TransactionReceipt)); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); batchRepository = app.get>(getRepositoryToken(BatchDetails)); logRepository = app.get>(getRepositoryToken(Log)); @@ -91,6 +91,7 @@ describe("Logs API (e2e)", () => { receiptStatus: 0, gasLimit: "1000000", gasPrice: "100", + type: 255, }); await transactionReceiptRepository.insert({ diff --git a/packages/api/test/stats-api.e2e-spec.ts b/packages/api/test/stats-api.e2e-spec.ts new file mode 100644 index 0000000000..c805e8648c --- /dev/null +++ b/packages/api/test/stats-api.e2e-spec.ts @@ -0,0 +1,96 @@ +import { Test, TestingModule } from "@nestjs/testing"; +import { INestApplication } from "@nestjs/common"; +import { getRepositoryToken } from "@nestjs/typeorm"; +import * as request from "supertest"; +import { Repository } from "typeorm"; +import { BatchDetails } from "../src/batch/batchDetails.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; +import { Token, ETH_TOKEN } from "../src/token/token.entity"; +import { AppModule } from "../src/app.module"; +import { configureApp } from "../src/configureApp"; + +describe("Stats API (e2e)", () => { + let app: INestApplication; + let blockRepository: Repository; + let batchRepository: Repository; + let tokenRepository: Repository; + + beforeAll(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication({ logger: false }); + configureApp(app); + await app.init(); + + blockRepository = app.get>(getRepositoryToken(BlockDetails)); + batchRepository = app.get>(getRepositoryToken(BatchDetails)); + tokenRepository = app.get>(getRepositoryToken(Token)); + + await batchRepository.insert({ + number: 0, + timestamp: new Date(), + l1TxCount: 10, + l2TxCount: 20, + l1GasPrice: "10000000", + l2FairGasPrice: "20000000", + commitTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e21", + proveTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e22", + executeTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e23", + }); + + await blockRepository.insert({ + number: 0, + hash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + timestamp: new Date(), + gasLimit: "0", + gasUsed: "0", + baseFeePerGas: "100000000", + extraData: "0x", + l1TxCount: 1, + l2TxCount: 1, + l1BatchNumber: 0, + miner: "0x0000000000000000000000000000000000000000", + }); + + await tokenRepository.insert({ + l2Address: ETH_TOKEN.l2Address, + l1Address: ETH_TOKEN.l1Address, + symbol: ETH_TOKEN.symbol, + name: ETH_TOKEN.name, + decimals: ETH_TOKEN.decimals, + blockNumber: 0, + logIndex: 0, + usdPrice: ETH_TOKEN.usdPrice, + liquidity: ETH_TOKEN.liquidity, + iconURL: ETH_TOKEN.iconURL, + offChainDataUpdatedAt: new Date("2023-03-03"), + }); + }); + + afterAll(async () => { + await tokenRepository.delete({}); + await blockRepository.delete({}); + await batchRepository.delete({}); + await app.close(); + }); + + describe("/api?module=stats&action=ethprice GET", () => { + it("returns HTTP 200 and ETH price", () => { + return request(app.getHttpServer()) + .get(`/api?module=stats&action=ethprice`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: { + ethusd: ETH_TOKEN.usdPrice.toString(), + ethusd_timestamp: Math.floor(new Date("2023-03-03").getTime() / 1000).toString(), + }, + status: "1", + }) + ); + }); + }); +}); diff --git a/packages/api/test/stats.e2e-spec.ts b/packages/api/test/stats.e2e-spec.ts index 1b1d172c86..4666a6e379 100644 --- a/packages/api/test/stats.e2e-spec.ts +++ b/packages/api/test/stats.e2e-spec.ts @@ -6,14 +6,14 @@ import { getRepositoryToken } from "@nestjs/typeorm"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; import { BatchDetails } from "../src/batch/batchDetails.entity"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; import { Counter } from "../src/counter/counter.entity"; describe("StatsController (e2e)", () => { let app: INestApplication; let batchRepository: Repository; - let blockRepository: Repository; + let blockRepository: Repository; let transactionRepository: Repository; let counterRepository: Repository; @@ -29,7 +29,7 @@ describe("StatsController (e2e)", () => { await app.init(); batchRepository = app.get>(getRepositoryToken(BatchDetails)); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); transactionRepository = app.get>(getRepositoryToken(Transaction)); counterRepository = app.get>(getRepositoryToken(Counter)); @@ -86,6 +86,7 @@ describe("StatsController (e2e)", () => { receiptStatus: 1, gasLimit: "1000000", gasPrice: "100", + type: 255, }); } diff --git a/packages/api/test/token-api.e2e-spec.ts b/packages/api/test/token-api.e2e-spec.ts new file mode 100644 index 0000000000..f3735bc8e2 --- /dev/null +++ b/packages/api/test/token-api.e2e-spec.ts @@ -0,0 +1,153 @@ +import { Test, TestingModule } from "@nestjs/testing"; +import { INestApplication } from "@nestjs/common"; +import { getRepositoryToken } from "@nestjs/typeorm"; +import * as request from "supertest"; +import { Repository } from "typeorm"; +import { BatchDetails } from "../src/batch/batchDetails.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; +import { Token, ETH_TOKEN } from "../src/token/token.entity"; +import { AppModule } from "../src/app.module"; +import { configureApp } from "../src/configureApp"; + +describe("Token API (e2e)", () => { + let app: INestApplication; + let blockRepository: Repository; + let batchRepository: Repository; + let tokenRepository: Repository; + + beforeAll(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication({ logger: false }); + configureApp(app); + await app.init(); + + blockRepository = app.get>(getRepositoryToken(BlockDetails)); + batchRepository = app.get>(getRepositoryToken(BatchDetails)); + tokenRepository = app.get>(getRepositoryToken(Token)); + + await batchRepository.insert({ + number: 0, + timestamp: new Date(), + l1TxCount: 10, + l2TxCount: 20, + l1GasPrice: "10000000", + l2FairGasPrice: "20000000", + commitTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e21", + proveTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e22", + executeTxHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e23", + }); + + await blockRepository.insert({ + number: 0, + hash: "0x4f86d6647711915ac90e5ef69c29845946f0a55b3feaa0488aece4a359f79cb1", + timestamp: new Date(), + gasLimit: "0", + gasUsed: "0", + baseFeePerGas: "100000000", + extraData: "0x", + l1TxCount: 1, + l2TxCount: 1, + l1BatchNumber: 0, + miner: "0x0000000000000000000000000000000000000000", + }); + + await tokenRepository.insert({ + l2Address: ETH_TOKEN.l2Address, + l1Address: ETH_TOKEN.l1Address, + symbol: ETH_TOKEN.symbol, + name: ETH_TOKEN.name, + decimals: ETH_TOKEN.decimals, + blockNumber: 0, + logIndex: 0, + usdPrice: ETH_TOKEN.usdPrice, + liquidity: ETH_TOKEN.liquidity, + iconURL: ETH_TOKEN.iconURL, + }); + + await tokenRepository.insert({ + l2Address: "0x91d0a23f34e535e44df8ba84c53a0945cf0eeb67", + l1Address: "0x91d0a23f34e535e44df8ba84c53a0945cf0eeb68", + symbol: "TKN", + name: "Token", + decimals: 6, + blockNumber: 0, + logIndex: 1, + usdPrice: 123.456, + liquidity: 1000000, + iconURL: "http://token.url", + }); + }); + + afterAll(async () => { + await tokenRepository.delete({}); + await blockRepository.delete({}); + await batchRepository.delete({}); + await app.close(); + }); + + describe("/api?module=token&action=tokenInfo GET", () => { + it("returns HTTP 200 and no data found response when no token is found", () => { + return request(app.getHttpServer()) + .get(`/api?module=token&action=tokeninfo&contractaddress=0x91d0a23f34e535e44df8ba84c53a0945cf0eeb66`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + status: "0", + message: "No data found", + result: [], + }) + ); + }); + + it("returns HTTP 200 and token info when token is found", () => { + return request(app.getHttpServer()) + .get(`/api?module=token&action=tokeninfo&contractaddress=0x91d0a23f34e535e44df8ba84c53a0945cf0eeb67`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: [ + { + contractAddress: "0x91D0a23f34E535E44dF8ba84c53A0945CF0EEb67", + iconURL: "http://token.url", + l1Address: "0x91d0A23f34E535E44Df8Ba84c53a0945Cf0eEb68", + liquidity: "1000000", + symbol: "TKN", + tokenDecimal: "6", + tokenName: "Token", + tokenPriceUSD: "123.456", + }, + ], + status: "1", + }) + ); + }); + + it("returns HTTP 200 and ETH token info for ETH token", () => { + return request(app.getHttpServer()) + .get(`/api?module=token&action=tokeninfo&contractaddress=${ETH_TOKEN.l2Address}`) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + message: "OK", + result: [ + { + contractAddress: ETH_TOKEN.l2Address, + iconURL: ETH_TOKEN.iconURL, + l1Address: ETH_TOKEN.l1Address, + liquidity: ETH_TOKEN.liquidity.toString(), + symbol: ETH_TOKEN.symbol, + tokenDecimal: ETH_TOKEN.decimals.toString(), + tokenName: ETH_TOKEN.name, + tokenPriceUSD: ETH_TOKEN.usdPrice.toString(), + }, + ], + status: "1", + }) + ); + }); + }); +}); diff --git a/packages/api/test/token.e2e-spec.ts b/packages/api/test/token.e2e-spec.ts index 8e4b64d072..b307db3298 100644 --- a/packages/api/test/token.e2e-spec.ts +++ b/packages/api/test/token.e2e-spec.ts @@ -5,8 +5,8 @@ import { Repository } from "typeorm"; import { getRepositoryToken } from "@nestjs/typeorm"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; -import { Token } from "../src/token/token.entity"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { Token, TokenType, ETH_TOKEN } from "../src/token/token.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; import { Transfer, TransferType } from "../src/transfer/transfer.entity"; import { BatchDetails } from "../src/batch/batchDetails.entity"; @@ -14,7 +14,7 @@ import { BatchDetails } from "../src/batch/batchDetails.entity"; describe("TokenController (e2e)", () => { let app: INestApplication; let tokenRepository: Repository; - let blockRepository: Repository; + let blockRepository: Repository; let transactionRepository: Repository; let transferRepository: Repository; let batchRepository: Repository; @@ -31,7 +31,7 @@ describe("TokenController (e2e)", () => { await app.init(); tokenRepository = app.get>(getRepositoryToken(Token)); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); transactionRepository = app.get>(getRepositoryToken(Transaction)); transferRepository = app.get>(getRepositoryToken(Transfer)); batchRepository = app.get>(getRepositoryToken(BatchDetails)); @@ -82,11 +82,22 @@ describe("TokenController (e2e)", () => { receiptStatus: 1, gasLimit: "1000000", gasPrice: "100", + type: 255, }); let tokenIndex = 0; let transferIndex = 0; + await tokenRepository.insert({ + l2Address: ETH_TOKEN.l2Address, + l1Address: ETH_TOKEN.l1Address, + symbol: ETH_TOKEN.symbol, + name: ETH_TOKEN.name, + decimals: ETH_TOKEN.decimals, + blockNumber: 0, + logIndex: 0, + }); + for (let i = 1; i <= 30; i++) { await tokenRepository.insert({ l1Address: i % 2 != 0 ? `0xf754ff5e8a6f257e162f72578a4bb0493c0681${i < 10 ? "0" : ""}${i}` : null, @@ -108,6 +119,7 @@ describe("TokenController (e2e)", () => { tokenAddress: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", amount: "1000", type: TransferType.Deposit, + tokenType: TokenType.ERC20, logIndex: transferIndex++, transactionIndex: 0, timestamp: "2022-11-21T18:16:51.000Z", @@ -123,6 +135,7 @@ describe("TokenController (e2e)", () => { tokenAddress: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", amount: "1000", type: TransferType.Fee, + tokenType: TokenType.ERC20, logIndex: transferIndex++, transactionIndex: 0, timestamp: "2022-11-21T18:16:51.000Z", @@ -138,6 +151,7 @@ describe("TokenController (e2e)", () => { tokenAddress: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", amount: "1000", type: TransferType.Mint, + tokenType: TokenType.ERC20, logIndex: transferIndex++, transactionIndex: 0, timestamp: "2022-11-21T18:16:51.000Z", @@ -153,6 +167,7 @@ describe("TokenController (e2e)", () => { tokenAddress: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", amount: "1000", type: TransferType.Transfer, + tokenType: TokenType.ERC20, logIndex: transferIndex++, transactionIndex: 0, timestamp: "2022-11-21T18:16:51.000Z", @@ -168,6 +183,7 @@ describe("TokenController (e2e)", () => { tokenAddress: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", amount: "1000", type: TransferType.Withdrawal, + tokenType: TokenType.ERC20, logIndex: transferIndex++, transactionIndex: 0, timestamp: "2022-11-21T18:16:51.000Z", @@ -183,6 +199,7 @@ describe("TokenController (e2e)", () => { tokenAddress: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", amount: undefined, type: TransferType.Mint, + tokenType: TokenType.ERC721, fields: { tokenId: "1" }, logIndex: transferIndex++, transactionIndex: 0, @@ -199,12 +216,29 @@ describe("TokenController (e2e)", () => { tokenAddress: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", amount: "1000", type: TransferType.Refund, + tokenType: TokenType.ERC20, logIndex: transferIndex++, transactionIndex: 0, timestamp: "2022-11-21T18:16:51.000Z", isFeeOrRefund: true, isInternal: false, }); + + await transferRepository.insert({ + from: "0x0000000000000000000000000000000000008001", + to: "0x52312ad6f01657413b2eae9287f6b9adad93d5fe", + blockNumber: 1, + transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", + tokenAddress: "0x000000000000000000000000000000000000800A", + amount: "1000", + type: TransferType.Refund, + tokenType: TokenType.ETH, + logIndex: transferIndex++, + transactionIndex: 0, + timestamp: "2022-11-21T18:16:51.000Z", + isFeeOrRefund: false, + isInternal: false, + }); } }); @@ -230,6 +264,9 @@ describe("TokenController (e2e)", () => { symbol: "TEST1", name: "TEST token 1", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }) ); }); @@ -245,6 +282,9 @@ describe("TokenController (e2e)", () => { symbol: "TEST1", name: "TEST token 1", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }) ); }); @@ -260,6 +300,27 @@ describe("TokenController (e2e)", () => { symbol: "TEST1", name: "TEST token 1", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, + }) + ); + }); + + it("returns HTTP 200 and ETH token even if it does not exist in DB", () => { + return request(app.getHttpServer()) + .get("/tokens/0x000000000000000000000000000000000000800a") + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + l2Address: "0x000000000000000000000000000000000000800A", + l1Address: "0x0000000000000000000000000000000000000000", + symbol: "ETH", + name: "Ether", + decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }) ); }); @@ -302,6 +363,9 @@ describe("TokenController (e2e)", () => { name: "TEST token 28", symbol: "TEST28", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, { l1Address: "0xF754ff5E8a6F257E162f72578A4bB0493C068127", @@ -309,6 +373,9 @@ describe("TokenController (e2e)", () => { name: "TEST token 27", symbol: "TEST27", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, ]) ); @@ -323,8 +390,8 @@ describe("TokenController (e2e)", () => { currentPage: 2, itemCount: 10, itemsPerPage: 10, - totalItems: 30, - totalPages: 3, + totalItems: 31, + totalPages: 4, }) ); }); @@ -336,7 +403,7 @@ describe("TokenController (e2e)", () => { .expect((res) => expect(res.body.links).toStrictEqual({ first: "tokens?limit=10", - last: "tokens?page=3&limit=10", + last: "tokens?page=4&limit=10", next: "tokens?page=3&limit=10", previous: "tokens?page=1&limit=10", }) @@ -388,10 +455,14 @@ describe("TokenController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token 1", symbol: "TEST1", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "transfer", + tokenType: "ERC20", isInternal: false, }, { @@ -407,10 +478,14 @@ describe("TokenController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token 1", symbol: "TEST1", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "withdrawal", + tokenType: "ERC20", isInternal: false, }, { @@ -428,10 +503,14 @@ describe("TokenController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token 1", symbol: "TEST1", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "mint", + tokenType: "ERC721", isInternal: false, }, { @@ -447,10 +526,14 @@ describe("TokenController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token 1", symbol: "TEST1", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "deposit", + tokenType: "ERC20", isInternal: false, }, { @@ -466,10 +549,14 @@ describe("TokenController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token 1", symbol: "TEST1", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "mint", + tokenType: "ERC20", isInternal: false, }, { @@ -485,10 +572,14 @@ describe("TokenController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token 1", symbol: "TEST1", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "transfer", + tokenType: "ERC20", isInternal: false, }, { @@ -504,10 +595,14 @@ describe("TokenController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token 1", symbol: "TEST1", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "withdrawal", + tokenType: "ERC20", isInternal: false, }, ]) @@ -543,6 +638,100 @@ describe("TokenController (e2e)", () => { ); }); + it("returns HTTP 200 and transfers for ETH token even if it is not in DB", () => { + return request(app.getHttpServer()) + .get("/tokens/0x000000000000000000000000000000000000800a/transfers?page=1&limit=7") + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + items: [ + { + amount: "1000", + blockNumber: 1, + fields: null, + from: "0x0000000000000000000000000000000000008001", + isInternal: false, + timestamp: "2022-11-21T18:16:51.000Z", + to: "0x52312AD6f01657413b2eaE9287f6B9ADaD93D5FE", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + tokenAddress: "0x000000000000000000000000000000000000800A", + tokenType: "ETH", + transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", + type: "refund", + }, + { + amount: "1000", + blockNumber: 1, + fields: null, + from: "0x0000000000000000000000000000000000008001", + isInternal: false, + timestamp: "2022-11-21T18:16:51.000Z", + to: "0x52312AD6f01657413b2eaE9287f6B9ADaD93D5FE", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + tokenAddress: "0x000000000000000000000000000000000000800A", + tokenType: "ETH", + transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", + type: "refund", + }, + { + amount: "1000", + blockNumber: 1, + fields: null, + from: "0x0000000000000000000000000000000000008001", + isInternal: false, + timestamp: "2022-11-21T18:16:51.000Z", + to: "0x52312AD6f01657413b2eaE9287f6B9ADaD93D5FE", + token: { + decimals: 18, + l1Address: "0x0000000000000000000000000000000000000000", + l2Address: "0x000000000000000000000000000000000000800A", + name: "Ether", + symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, + }, + tokenAddress: "0x000000000000000000000000000000000000800A", + tokenType: "ETH", + transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", + type: "refund", + }, + ], + links: { + first: "tokens/0x000000000000000000000000000000000000800a/transfers?limit=7", + last: "tokens/0x000000000000000000000000000000000000800a/transfers?page=1&limit=7", + next: "", + previous: "", + }, + meta: { + currentPage: 1, + itemCount: 3, + itemsPerPage: 7, + totalItems: 3, + totalPages: 1, + }, + }) + ); + }); + it("returns HTTP 400 for not valid token address", () => { return request(app.getHttpServer()).get("/tokens/invalidAddressParam/transfers").expect(400); }); diff --git a/packages/api/test/transaction-api.e2e-spec.ts b/packages/api/test/transaction-api.e2e-spec.ts index 01a4b9d89f..4fb83e5454 100644 --- a/packages/api/test/transaction-api.e2e-spec.ts +++ b/packages/api/test/transaction-api.e2e-spec.ts @@ -4,7 +4,7 @@ import { getRepositoryToken } from "@nestjs/typeorm"; import * as request from "supertest"; import { Repository } from "typeorm"; import { BatchDetails } from "../src/batch/batchDetails.entity"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; import { TransactionReceipt } from "../src/transaction/entities/transactionReceipt.entity"; import { AppModule } from "../src/app.module"; @@ -14,7 +14,7 @@ describe("Transaction API (e2e)", () => { let app: INestApplication; let transactionRepository: Repository; let transactionReceiptRepository: Repository; - let blockRepository: Repository; + let blockRepository: Repository; let batchRepository: Repository; beforeAll(async () => { @@ -28,7 +28,7 @@ describe("Transaction API (e2e)", () => { transactionRepository = app.get>(getRepositoryToken(Transaction)); transactionReceiptRepository = app.get>(getRepositoryToken(TransactionReceipt)); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); batchRepository = app.get>(getRepositoryToken(BatchDetails)); await batchRepository.insert({ @@ -71,6 +71,7 @@ describe("Transaction API (e2e)", () => { receiptStatus: 0, gasLimit: "1000000", gasPrice: "100", + type: 255, }); await transactionRepository.insert({ @@ -90,6 +91,7 @@ describe("Transaction API (e2e)", () => { receiptStatus: 1, gasLimit: "1000000", gasPrice: "100", + type: 255, }); await transactionReceiptRepository.insert({ diff --git a/packages/api/test/transaction.e2e-spec.ts b/packages/api/test/transaction.e2e-spec.ts index c367034f60..28f55e29f1 100644 --- a/packages/api/test/transaction.e2e-spec.ts +++ b/packages/api/test/transaction.e2e-spec.ts @@ -2,12 +2,15 @@ import { Test, TestingModule } from "@nestjs/testing"; import { INestApplication } from "@nestjs/common"; import * as request from "supertest"; import { Repository } from "typeorm"; +import { BigNumber } from "ethers"; import { getRepositoryToken } from "@nestjs/typeorm"; import { AppModule } from "../src/app.module"; import { configureApp } from "../src/configureApp"; -import { Token } from "../src/token/token.entity"; -import { BlockDetail } from "../src/block/blockDetail.entity"; +import { Token, TokenType } from "../src/token/token.entity"; +import { BlockDetails } from "../src/block/blockDetails.entity"; import { Transaction } from "../src/transaction/entities/transaction.entity"; +import { TransactionReceipt } from "../src/transaction/entities/transactionReceipt.entity"; +import { ETH_TOKEN } from "../src/token/token.entity"; import { AddressTransaction } from "../src/transaction/entities/addressTransaction.entity"; import { Transfer, TransferType } from "../src/transfer/transfer.entity"; import { Log } from "../src/log/log.entity"; @@ -16,8 +19,9 @@ import { BatchDetails } from "../src/batch/batchDetails.entity"; describe("TransactionController (e2e)", () => { let app: INestApplication; let tokenRepository: Repository; - let blockRepository: Repository; + let blockRepository: Repository; let transactionRepository: Repository; + let transactionReceiptRepository: Repository; let addressTransactionRepository: Repository; let transferRepository: Repository; let logRepository: Repository; @@ -35,8 +39,9 @@ describe("TransactionController (e2e)", () => { await app.init(); tokenRepository = app.get>(getRepositoryToken(Token)); - blockRepository = app.get>(getRepositoryToken(BlockDetail)); + blockRepository = app.get>(getRepositoryToken(BlockDetails)); transactionRepository = app.get>(getRepositoryToken(Transaction)); + transactionReceiptRepository = app.get>(getRepositoryToken(TransactionReceipt)); addressTransactionRepository = app.get>(getRepositoryToken(AddressTransaction)); transferRepository = app.get>(getRepositoryToken(Transfer)); logRepository = app.get>(getRepositoryToken(Log)); @@ -89,6 +94,7 @@ describe("TransactionController (e2e)", () => { isL1Originated: true, gasLimit: "1000000", gasPrice: "100", + type: 255, }; for (let i = 0; i < 10; i++) { @@ -123,6 +129,11 @@ describe("TransactionController (e2e)", () => { receivedAt: `2022-11-21T18:16:0${i}.000Z`, l1BatchNumber: i < 3 ? 1 : i, receiptStatus: i < 9 ? 1 : 0, + gasPrice: BigNumber.from(1000 + i).toString(), + gasLimit: BigNumber.from(2000 + i).toString(), + maxFeePerGas: BigNumber.from(3000 + i).toString(), + maxPriorityFeePerGas: BigNumber.from(4000 + i).toString(), + gasPerPubdata: BigNumber.from(5000 + i).toHexString(), }; await transactionRepository.insert(transactionSpec); @@ -135,6 +146,14 @@ describe("TransactionController (e2e)", () => { transactionIndex: transactionSpec.transactionIndex, }); } + + await transactionReceiptRepository.insert({ + transactionHash: transactionSpec.hash, + from: transactionSpec.from, + status: 1, + gasUsed: (7000 + i).toString(), + cumulativeGasUsed: (10000 + i).toString(), + }); } for (let i = 0; i < 20; i++) { @@ -156,20 +175,20 @@ describe("TransactionController (e2e)", () => { } await tokenRepository.insert({ - l2Address: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", - l1Address: "0xf754ff5e8a6f257e162f72578a4bb0493c068101", - symbol: "TEST", - name: "TEST token", - decimals: 18, - blockNumber: 1, + l2Address: ETH_TOKEN.l2Address, + l1Address: ETH_TOKEN.l1Address, + symbol: ETH_TOKEN.symbol, + name: ETH_TOKEN.name, + decimals: ETH_TOKEN.decimals, + blockNumber: 0, logIndex: 0, }); await tokenRepository.insert({ - l2Address: "0x000000000000000000000000000000000000800a", - l1Address: "0x0000000000000000000000000000000000000000", - symbol: "ETH", - name: "Ether", + l2Address: "0xd754ff5e8a6f257e162f72578a4bb0493c068101", + l1Address: "0xf754ff5e8a6f257e162f72578a4bb0493c068101", + symbol: "TEST", + name: "TEST token", decimals: 18, blockNumber: 1, logIndex: 0, @@ -188,6 +207,7 @@ describe("TransactionController (e2e)", () => { transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", tokenAddress: i % 2 ? "0xd754ff5e8a6f257e162f72578a4bb0493c068101" : "0x000000000000000000000000000000000000800a", + tokenType: i % 2 ? TokenType.ERC20 : TokenType.ETH, amount: "2000", type, logIndex: i, @@ -205,6 +225,7 @@ describe("TransactionController (e2e)", () => { await tokenRepository.delete({}); await addressTransactionRepository.delete({}); await transactionRepository.delete({}); + await transactionReceiptRepository.delete({}); await blockRepository.delete({}); await batchRepository.delete({}); @@ -235,11 +256,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 9, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2009", + gasPrice: "1009", + gasPerPubdata: "5009", + maxFeePerGas: "3009", + maxPriorityFeePerGas: "4009", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e19", isL1BatchSealed: false, isL1Originated: true, @@ -250,6 +276,7 @@ describe("TransactionController (e2e)", () => { status: "failed", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233106, + type: 255, value: "0x2386f26fc10000", }, { @@ -257,11 +284,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 8, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa8", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab8", fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2008", + gasPrice: "1008", + gasPerPubdata: "5008", + maxFeePerGas: "3008", + maxPriorityFeePerGas: "4008", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e18", isL1BatchSealed: true, isL1Originated: true, @@ -272,6 +304,7 @@ describe("TransactionController (e2e)", () => { status: "verified", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233105, + type: 255, value: "0x2386f26fc10000", }, { @@ -279,11 +312,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 7, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa7", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab7", fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2007", + gasPrice: "1007", + gasPerPubdata: "5007", + maxFeePerGas: "3007", + maxPriorityFeePerGas: "4007", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e17", isL1BatchSealed: true, isL1Originated: true, @@ -294,6 +332,7 @@ describe("TransactionController (e2e)", () => { status: "verified", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233104, + type: 255, value: "0x2386f26fc10000", }, { @@ -301,11 +340,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 6, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa6", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2006", + gasPrice: "1006", + gasPerPubdata: "5006", + maxFeePerGas: "3006", + maxPriorityFeePerGas: "4006", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e16", isL1BatchSealed: true, isL1Originated: true, @@ -316,6 +360,7 @@ describe("TransactionController (e2e)", () => { status: "proved", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233103, + type: 255, value: "0x2386f26fc10000", }, { @@ -323,11 +368,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 5, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa5", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2005", + gasPrice: "1005", + gasPerPubdata: "5005", + maxFeePerGas: "3005", + maxPriorityFeePerGas: "4005", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e15", isL1BatchSealed: true, isL1Originated: true, @@ -338,6 +388,7 @@ describe("TransactionController (e2e)", () => { status: "proved", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233102, + type: 255, value: "0x2386f26fc10000", }, { @@ -345,11 +396,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 4, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa4", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasPrice: "1004", + gasLimit: "2004", + gasPerPubdata: "5004", + maxFeePerGas: "3004", + maxPriorityFeePerGas: "4004", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e14", isL1BatchSealed: true, isL1Originated: true, @@ -360,6 +416,7 @@ describe("TransactionController (e2e)", () => { status: "committed", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233101, + type: 255, value: "0x2386f26fc10000", }, { @@ -367,11 +424,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 3, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa3", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2003", + gasPrice: "1003", + gasPerPubdata: "5003", + maxFeePerGas: "3003", + maxPriorityFeePerGas: "4003", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e13", isL1BatchSealed: true, isL1Originated: true, @@ -382,6 +444,7 @@ describe("TransactionController (e2e)", () => { status: "committed", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233100, + type: 255, value: "0x2386f26fc10000", }, { @@ -389,11 +452,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 1, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasPrice: "1002", + gasLimit: "2002", + gasPerPubdata: "5002", + maxFeePerGas: "3002", + maxPriorityFeePerGas: "4002", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e12", isL1BatchSealed: false, isL1Originated: true, @@ -404,6 +472,7 @@ describe("TransactionController (e2e)", () => { status: "included", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233099, + type: 255, value: "0x2386f26fc10000", }, { @@ -411,11 +480,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 1, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasPrice: "1001", + gasLimit: "2001", + gasPerPubdata: "5001", + maxFeePerGas: "3001", + maxPriorityFeePerGas: "4001", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e11", isL1BatchSealed: false, isL1Originated: true, @@ -426,6 +500,7 @@ describe("TransactionController (e2e)", () => { status: "included", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233098, + type: 255, value: "0x2386f26fc10000", }, { @@ -433,11 +508,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 1, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2000", + gasPrice: "1000", + gasPerPubdata: "5000", + maxFeePerGas: "3000", + maxPriorityFeePerGas: "4000", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", isL1BatchSealed: false, isL1Originated: true, @@ -448,6 +528,7 @@ describe("TransactionController (e2e)", () => { status: "included", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233097, + type: 255, value: "0x2386f26fc10000", }, ]) @@ -465,11 +546,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 8, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa8", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab8", fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2008", + gasPrice: "1008", + gasPerPubdata: "5008", + maxFeePerGas: "3008", + maxPriorityFeePerGas: "4008", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e18", isL1BatchSealed: true, isL1Originated: true, @@ -480,6 +566,7 @@ describe("TransactionController (e2e)", () => { status: "verified", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233105, + type: 255, value: "0x2386f26fc10000", }, { @@ -487,11 +574,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 7, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa7", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab7", fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2007", + gasPrice: "1007", + gasPerPubdata: "5007", + maxFeePerGas: "3007", + maxPriorityFeePerGas: "4007", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e17", isL1BatchSealed: true, isL1Originated: true, @@ -502,6 +594,7 @@ describe("TransactionController (e2e)", () => { status: "verified", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233104, + type: 255, value: "0x2386f26fc10000", }, { @@ -509,11 +602,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 6, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa6", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2006", + gasPrice: "1006", + gasPerPubdata: "5006", + maxFeePerGas: "3006", + maxPriorityFeePerGas: "4006", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e16", isL1BatchSealed: true, isL1Originated: true, @@ -524,6 +622,7 @@ describe("TransactionController (e2e)", () => { status: "proved", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233103, + type: 255, value: "0x2386f26fc10000", }, ]) @@ -587,11 +686,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 1, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2001", + gasPrice: "1001", + gasPerPubdata: "5001", + maxFeePerGas: "3001", + maxPriorityFeePerGas: "4001", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e11", isL1BatchSealed: false, isL1Originated: true, @@ -602,6 +706,7 @@ describe("TransactionController (e2e)", () => { status: "included", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233098, + type: 255, value: "0x2386f26fc10000", }, ], @@ -634,11 +739,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 1, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2001", + gasPrice: "1001", + gasPerPubdata: "5001", + maxFeePerGas: "3001", + maxPriorityFeePerGas: "4001", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e11", isL1BatchSealed: false, isL1Originated: true, @@ -649,6 +759,7 @@ describe("TransactionController (e2e)", () => { status: "included", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233098, + type: 255, value: "0x2386f26fc10000", }, ], @@ -681,11 +792,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 7, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa7", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab7", fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2007", + gasPrice: "1007", + gasPerPubdata: "5007", + maxFeePerGas: "3007", + maxPriorityFeePerGas: "4007", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e17", isL1BatchSealed: true, isL1Originated: true, @@ -696,6 +812,7 @@ describe("TransactionController (e2e)", () => { status: "verified", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233104, + type: 255, value: "0x2386f26fc10000", }, { @@ -703,11 +820,16 @@ describe("TransactionController (e2e)", () => { blockNumber: 6, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa6", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2006", + gasPrice: "1006", + gasPerPubdata: "5006", + maxFeePerGas: "3006", + maxPriorityFeePerGas: "4006", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e16", isL1BatchSealed: true, isL1Originated: true, @@ -718,6 +840,7 @@ describe("TransactionController (e2e)", () => { status: "proved", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233103, + type: 255, value: "0x2386f26fc10000", }, ], @@ -786,11 +909,17 @@ describe("TransactionController (e2e)", () => { blockNumber: 8, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa8", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5ab8", fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2008", + gasPrice: "1008", + gasUsed: "7008", + gasPerPubdata: "5008", + maxFeePerGas: "3008", + maxPriorityFeePerGas: "4008", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e18", isL1BatchSealed: true, isL1Originated: true, @@ -801,6 +930,7 @@ describe("TransactionController (e2e)", () => { status: "verified", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233105, + type: 255, value: "0x2386f26fc10000", }) ); @@ -816,11 +946,17 @@ describe("TransactionController (e2e)", () => { blockNumber: 5, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa5", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2005", + gasPrice: "1005", + gasUsed: "7005", + gasPerPubdata: "5005", + maxFeePerGas: "3005", + maxPriorityFeePerGas: "4005", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e15", isL1BatchSealed: true, isL1Originated: true, @@ -831,6 +967,7 @@ describe("TransactionController (e2e)", () => { status: "proved", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233102, + type: 255, value: "0x2386f26fc10000", }) ); @@ -846,11 +983,17 @@ describe("TransactionController (e2e)", () => { blockNumber: 3, commitTxHash: "0xeb5ead20476b91008c3b6e44005017e697de78e4fd868d99d2c58566655c5aa3", data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2003", + gasPrice: "1003", + gasUsed: "7003", + gasPerPubdata: "5003", + maxFeePerGas: "3003", + maxPriorityFeePerGas: "4003", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e13", isL1BatchSealed: true, isL1Originated: true, @@ -861,6 +1004,7 @@ describe("TransactionController (e2e)", () => { status: "committed", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233100, + type: 255, value: "0x2386f26fc10000", }) ); @@ -876,11 +1020,17 @@ describe("TransactionController (e2e)", () => { blockNumber: 1, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2000", + gasPrice: "1000", + gasUsed: "7000", + gasPerPubdata: "5000", + maxFeePerGas: "3000", + maxPriorityFeePerGas: "4000", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", isL1BatchSealed: true, isL1Originated: true, @@ -891,6 +1041,7 @@ describe("TransactionController (e2e)", () => { status: "included", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233097, + type: 255, value: "0x2386f26fc10000", }) ); @@ -906,11 +1057,17 @@ describe("TransactionController (e2e)", () => { blockNumber: 9, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2009", + gasPrice: "1009", + gasUsed: "7009", + gasPerPubdata: "5009", + maxFeePerGas: "3009", + maxPriorityFeePerGas: "4009", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e19", isL1BatchSealed: true, isL1Originated: true, @@ -921,6 +1078,7 @@ describe("TransactionController (e2e)", () => { status: "failed", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233106, + type: 255, value: "0x2386f26fc10000", }) ); @@ -936,11 +1094,17 @@ describe("TransactionController (e2e)", () => { blockNumber: 1, commitTxHash: null, data: "0x000000000000000000000000000000000000000000000000016345785d8a0000", + error: null, + revertReason: null, executeTxHash: null, fee: "0x2386f26fc10000", from: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", - gasLimit: "1000000", - gasPrice: "100", + gasLimit: "2000", + gasPrice: "1000", + gasUsed: "7000", + gasPerPubdata: "5000", + maxFeePerGas: "3000", + maxPriorityFeePerGas: "4000", hash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", isL1BatchSealed: true, isL1Originated: true, @@ -951,6 +1115,7 @@ describe("TransactionController (e2e)", () => { status: "included", to: "0xc7e0220d02d549c4846A6EC31D89C3B670Ebe35C", transactionIndex: 3233097, + type: 255, value: "0x2386f26fc10000", }) ); @@ -1001,10 +1166,14 @@ describe("TransactionController (e2e)", () => { symbol: "ETH", name: "Ether", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x000000000000000000000000000000000000800A", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "deposit", + tokenType: "ETH", isInternal: false, }, { @@ -1020,10 +1189,14 @@ describe("TransactionController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token", symbol: "TEST", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "transfer", + tokenType: "ERC20", isInternal: false, }, { @@ -1039,10 +1212,14 @@ describe("TransactionController (e2e)", () => { symbol: "ETH", name: "Ether", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x000000000000000000000000000000000000800A", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "withdrawal", + tokenType: "ETH", isInternal: false, }, { @@ -1058,10 +1235,14 @@ describe("TransactionController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token", symbol: "TEST", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "fee", + tokenType: "ERC20", isInternal: false, }, { @@ -1077,10 +1258,14 @@ describe("TransactionController (e2e)", () => { symbol: "ETH", name: "Ether", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x000000000000000000000000000000000000800A", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "mint", + tokenType: "ETH", isInternal: false, }, { @@ -1096,10 +1281,14 @@ describe("TransactionController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token", symbol: "TEST", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "refund", + tokenType: "ERC20", isInternal: false, }, { @@ -1115,10 +1304,14 @@ describe("TransactionController (e2e)", () => { symbol: "ETH", name: "Ether", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x000000000000000000000000000000000000800A", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "deposit", + tokenType: "ETH", isInternal: false, }, { @@ -1134,10 +1327,14 @@ describe("TransactionController (e2e)", () => { l2Address: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", name: "TEST token", symbol: "TEST", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0xD754FF5E8a6F257E162f72578a4bB0493c068101", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "deposit", + tokenType: "ERC20", isInternal: false, }, { @@ -1153,10 +1350,14 @@ describe("TransactionController (e2e)", () => { symbol: "ETH", name: "Ether", decimals: 18, + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x000000000000000000000000000000000000800A", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "transfer", + tokenType: "ETH", isInternal: false, }, ]) @@ -1217,10 +1418,14 @@ describe("TransactionController (e2e)", () => { l2Address: "0x000000000000000000000000000000000000800A", name: "Ether", symbol: "ETH", + iconURL: null, + liquidity: null, + usdPrice: null, }, tokenAddress: "0x000000000000000000000000000000000000800A", transactionHash: "0x8a008b8dbbc18035e56370abb820e736b705d68d6ac12b203603db8d9ea87e10", type: "deposit", + tokenType: "ETH", isInternal: false, }, ], diff --git a/packages/app/Dockerfile b/packages/app/Dockerfile index aca6217127..6f78044359 100644 --- a/packages/app/Dockerfile +++ b/packages/app/Dockerfile @@ -1,5 +1,5 @@ -FROM node:18.17.1-alpine -ENV NODE_ENV=development +FROM node:18.17.1-alpine AS base-stage +ENV NODE_ENV=production WORKDIR /usr/src/app RUN apk add --update python3 make g++ && rm -rf /var/cache/apk/* @@ -8,5 +8,30 @@ COPY --chown=node:node .npmrc .npmrc COPY --chown=node:node lerna.json ./ COPY --chown=node:node package*.json ./ COPY --chown=node:node ./packages/app/package*.json ./packages/app/ +RUN npm ci --ignore-scripts && npm cache clean --force +COPY --chown=node:node ./packages/app/. ./packages/app +RUN rm -f .npmrc + +FROM base-stage AS development-stage +ENV NODE_ENV=development +COPY --chown=node:node .npmrc .npmrc RUN npm ci -COPY --chown=node:node ./packages/app/. ./packages/app \ No newline at end of file +RUN rm -f .npmrc + +FROM development-stage AS build-stage +RUN npm run build + +FROM base-stage AS production-stage +COPY --chown=node:node --from=build-stage /usr/src/app/packages/app/dist ./packages/app/dist +RUN npm i -g http-server + +ARG NODE_ENV=production +ENV NODE_ENV $NODE_ENV + +ARG PORT=3010 +ENV PORT $PORT + +USER node +WORKDIR /usr/src/app/packages/app/dist + +CMD http-server -p $PORT -c-1 --proxy="http://127.0.0.1:$PORT/index.html?" \ No newline at end of file diff --git a/packages/app/README.md b/packages/app/README.md index 061fdc096a..692aeb3de6 100644 --- a/packages/app/README.md +++ b/packages/app/README.md @@ -44,10 +44,8 @@ const config: EnvironmentConfig = { verificationApiUrl: "https://zksync2-testnet-explorer.zksync.dev", hostnames: ["localhost"], icon: "/images/icons/zksync-arrows.svg", - l1ExplorerUrl: "https://goerli.etherscan.io", l2ChainId: 270, l2NetworkName: "Local", - l2WalletUrl: "https://goerli.staging-portal.zksync.dev/", maintenance: false, name: "local", published: true, @@ -59,10 +57,8 @@ const config: EnvironmentConfig = { verificationApiUrl: "https://zksync2-testnet-explorer.zksync.dev", hostnames: ["localhost"], icon: "/images/icons/zksync-arrows.svg", - l1ExplorerUrl: "https://goerli.etherscan.io", l2ChainId: 270, l2NetworkName: "Local Hyperchain", - l2WalletUrl: "https://goerli.staging-portal.zksync.dev/", maintenance: false, name: "local-hyperchain", published: true, @@ -108,3 +104,13 @@ npm run lint ## Production links - [Web Application](https://explorer.zksync.io) - [Storybook](https://storybook-scan-v2.zksync.dev) + + +## Verify Block Explorer UI test results in GitHub Actions +GitHub Actions test results are available in: + +- `GitHub Actions` --> `Summary` page at the very end of a page. +- Inside of each test run in the log: `Feature on Mainnet + Sepolia` --> `@search` --> `Upload test results to Allure reporter` --> `https://raw.githack.com/matter-labs/block-explorer/gh-pages/_github.run_number_/index.html` +- Directly via a link `https://raw.githack.com/matter-labs/block-explorer/gh-pages/_github.run_number_/index.html` after each PR running. The history of test runs for public view locates in `gh-pages` branch. + +In case of 404 page, make sure that the folder with its `github.run_number` exists in the `gh-pages`. If the folder exist, try again in a few minutes as `https://raw.githack.com` needs to update the data. Public report link will be available when the 'Allure Report' job will be succesfully executed. diff --git a/packages/app/firebase.json b/packages/app/firebase.json index 3cd0e346e8..f2525ac862 100644 --- a/packages/app/firebase.json +++ b/packages/app/firebase.json @@ -36,7 +36,7 @@ }, { "key": "Content-Security-Policy-Report-Only", - "value": "default-src 'self'; child-src 'self' blob:; script-src 'self' 'unsafe-eval' blob:; connect-src https://*.ingest.sentry.io https://firestore.googleapis.com/ https://*.zkscan.io https://*.zksync.io https://*.zksync.dev https://storage.googleapis.com; style-src 'self' fonts.googleapis.com; font-src 'self' fonts.gstatic.com; img-src 'self' blob: data: https://firebasestorage.googleapis.com/v0/b/token-library.appspot.com/o/;" + "value": "default-src 'self'; child-src 'self' blob:; script-src 'self' 'unsafe-eval' blob:; connect-src https://*.ingest.sentry.io https://firestore.googleapis.com/ https://*.zkscan.io https://*.zksync.io https://*.zksync.dev https://storage.googleapis.com; style-src 'self' fonts.googleapis.com; font-src 'self' fonts.gstatic.com; img-src 'self' https://assets.coingecko.com blob: data: https://firebasestorage.googleapis.com/v0/b/token-library.appspot.com/o/;" } ] } diff --git a/packages/app/mock/transactions/Execute.json b/packages/app/mock/transactions/Execute.json index c26b1e4b1d..32b78b14b5 100644 --- a/packages/app/mock/transactions/Execute.json +++ b/packages/app/mock/transactions/Execute.json @@ -11,6 +11,7 @@ "fee": "0x2279f530c00", "feeData": { "amountPaid": "0x2279f530c00", + "isPaidByPaymaster": false, "refunds": [], "amountRefunded": "0x00" }, @@ -33,7 +34,7 @@ "symbol": "LINK", "name": "ChainLink Token (goerli)", "decimals": 18, - "usdPrice": "1" + "usdPrice": 1 }, "from": "0xcfa3DD0CBa60484d1C8D0cDd22C5432013368875", "to": "0xde03a0B5963f75f1C8485B355fF6D30f3093BDE7", @@ -47,7 +48,7 @@ "symbol": "LINK", "name": "ChainLink Token (goerli)", "decimals": 18, - "usdPrice": "1" + "usdPrice": 1 }, "from": "0xcfa3DD0CBa60484d1C8D0cDd22C5432013368875", "to": "0x6c557bc88804254760Be210c01fd9B6B5dE96e53", @@ -62,7 +63,7 @@ "symbol": "LINK", "name": "ChainLink Token (goerli)", "decimals": 18, - "usdPrice": "1" + "usdPrice": 1 }, "from": "0xcfa3DD0CBa60484d1C8D0cDd22C5432013368875", "to": "0x6c557bc88804254760Be210c01fd9B6B5dE96e53", @@ -77,7 +78,7 @@ "symbol": "ETH", "name": "Ether", "decimals": 18, - "usdPrice": "1" + "usdPrice": 1 }, "from": "0xcfa3DD0CBa60484d1C8D0cDd22C5432013368875", "to": "0xde03a0B5963f75f1C8485B355fF6D30f3093BDE7", @@ -94,7 +95,7 @@ "symbol": "LINK", "name": "ChainLink Token (goerli)", "decimals": 18, - "usdPrice": "1" + "usdPrice": 1 }, "from": "0xcfa3DD0CBa60484d1C8D0cDd22C5432013368875", "to": "0x6c557bc88804254760Be210c01fd9B6B5dE96e53", @@ -113,7 +114,7 @@ "symbol": "LINK", "name": "ChainLink Token (goerli)", "decimals": 18, - "usdPrice": "1" + "usdPrice": 1 }, "from": "0xcfa3DD0CBa60484d1C8D0cDd22C5432013368875", "to": "0x6c557bc88804254760Be210c01fd9B6B5dE96e53", @@ -164,5 +165,11 @@ ], "isL1BatchSealed": false, "to": "0x4732C03B2CF6eDe46500e799DE79a15Df44929eB", - "value": "0x00" + "value": "0x00", + "gasPrice": "4000", + "gasLimit": "5000", + "gasUsed": "3000", + "gasPerPubdata": "800", + "maxFeePerGas": "7000", + "maxPriorityFeePerGas": "8000" } diff --git a/packages/app/package.json b/packages/app/package.json index 7dcfb315ae..9e7060b904 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -26,7 +26,6 @@ }, "dependencies": { "@matterlabs/composables": "1.1.7", - "@matterlabs/token-library": "2.9.0", "@vueuse/components": "8.9.2", "@vueuse/core": "8.9.2", "date-fns": "2.28.0", diff --git a/packages/app/src/App.vue b/packages/app/src/App.vue index a2541a6834..f6e453715a 100644 --- a/packages/app/src/App.vue +++ b/packages/app/src/App.vue @@ -2,6 +2,8 @@ diff --git a/packages/app/src/components/blocks/TransactionEmptyState.vue b/packages/app/src/components/blocks/TransactionEmptyState.vue index 77699cfb06..e5837e96e8 100644 --- a/packages/app/src/components/blocks/TransactionEmptyState.vue +++ b/packages/app/src/components/blocks/TransactionEmptyState.vue @@ -1,17 +1,10 @@ @@ -22,16 +15,17 @@ import { useI18n } from "vue-i18n"; import EmptyState from "@/components/common/EmptyState.vue"; const { t } = useI18n(); + +defineProps({ + blockExists: { + type: Boolean, + required: true, + }, +}); diff --git a/packages/app/src/components/common/CheckBoxInput.stories.ts b/packages/app/src/components/common/CheckBoxInput.stories.ts new file mode 100644 index 0000000000..6f1d6a20fc --- /dev/null +++ b/packages/app/src/components/common/CheckBoxInput.stories.ts @@ -0,0 +1,29 @@ +import CheckBoxInput from "./CheckBoxInput.vue"; + +export default { + title: "Common/CheckBoxInput", + component: CheckBoxInput, +}; + +type Args = { + modelValue: boolean; +}; + +const Template = (args: Args) => ({ + components: { CheckBoxInput }, + setup() { + return { args }; + }, + template: ` + CheckBox Input`, +}); + +export const Checked = Template.bind({}) as unknown as { args: Args }; +Checked.args = { + modelValue: true, +}; + +export const Unchecked = Template.bind({}) as unknown as { args: Args }; +Unchecked.args = { + modelValue: false, +}; diff --git a/packages/app/src/components/common/CheckBoxInput.vue b/packages/app/src/components/common/CheckBoxInput.vue new file mode 100644 index 0000000000..04f1de75b6 --- /dev/null +++ b/packages/app/src/components/common/CheckBoxInput.vue @@ -0,0 +1,42 @@ + + + + + + + diff --git a/packages/app/src/components/common/SystemAlert.vue b/packages/app/src/components/common/SystemAlert.vue new file mode 100644 index 0000000000..4dd6e3c059 --- /dev/null +++ b/packages/app/src/components/common/SystemAlert.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/packages/app/src/components/common/table/fields/TokenPrice.vue b/packages/app/src/components/common/table/fields/TokenPrice.vue index 7143c89d51..9092ca7d27 100644 --- a/packages/app/src/components/common/table/fields/TokenPrice.vue +++ b/packages/app/src/components/common/table/fields/TokenPrice.vue @@ -33,7 +33,7 @@ const { getTokenInfo, tokenInfo, isRequestPending } = useToken(); watchEffect(() => { if (props.address) { - getTokenInfo(props.address!); + getTokenInfo(props.address); } }); @@ -42,7 +42,7 @@ const priceAmount = computed(() => { return formatPricePretty( "1".padEnd(tokenInfo.value.decimals + 1, "0"), tokenInfo.value.decimals, - tokenInfo.value.usdPrice + tokenInfo.value.usdPrice.toString() ); } return ""; diff --git a/packages/app/src/components/debugger/SourceViewer.vue b/packages/app/src/components/debugger/SourceViewer.vue index de67dcaf77..42bff9735f 100644 --- a/packages/app/src/components/debugger/SourceViewer.vue +++ b/packages/app/src/components/debugger/SourceViewer.vue @@ -15,7 +15,13 @@ :data-testid="item.expandable ? 'instruction-list-item-expandable' : 'instruction-list-item'" > - + {{ item.error }} @@ -69,6 +75,14 @@ const props = defineProps({ type: String, default: "", }, + traceCountPercentage: { + type: Object as PropType<{ [key: string]: number }>, + required: true, + }, + pcLineMapping: { + type: Object as PropType<{ [key: number]: number }>, + required: true, + }, }); type InstructionNode = { @@ -79,7 +93,10 @@ type InstructionNode = { expandable: boolean; }; -type VirtualInstructionNode = InstructionNode & { index: number }; +type VirtualInstructionNode = InstructionNode & { + index: number; + traceCountPercentage: number; +}; const expanded = ref([]); const isReady = ref(false); @@ -134,7 +151,17 @@ watchEffect(() => { } return val; }) - .map((item, index) => ({ ...item, index, line: item.line })); + .map((item, index) => ({ + ...item, + index, + line: item.line, + traceCountPercentage: + props.traceCountPercentage[ + `${props.address}_${Object.keys(props.pcLineMapping).find( + (key) => props.pcLineMapping[parseInt(key)] === index + )}` + ], + })); if (isReady.value) { rebuild(); } diff --git a/packages/app/src/components/form/FormItem.vue b/packages/app/src/components/form/FormItem.vue index 8e179ae1be..f5a72f24e3 100644 --- a/packages/app/src/components/form/FormItem.vue +++ b/packages/app/src/components/form/FormItem.vue @@ -42,7 +42,7 @@ defineProps({ } .label-inline-block { .form-item-label { - @apply inline-block; + @apply float-left; } } diff --git a/packages/app/src/components/header/TheHeader.vue b/packages/app/src/components/header/TheHeader.vue index db0cf0a8aa..dd75815f1d 100644 --- a/packages/app/src/components/header/TheHeader.vue +++ b/packages/app/src/components/header/TheHeader.vue @@ -48,7 +48,11 @@ -
+
t("header.nav.documentation")), - url: "https://era.zksync.io/docs/dev/", + url: "https://docs.zksync.io/build/tooling/block-explorer/getting-started.html", }, ]); @@ -173,19 +177,19 @@ const blockExplorerLinks = reactive([ to: { name: "transactions" }, }, { - label: computed(() => t("tokenListView.title")), - to: { name: "token-list" }, + label: computed(() => t("tokensView.title")), + to: { name: "tokens" }, }, ]); const links = [ { - label: computed(() => t("header.nav.contractVerification")), - to: { name: "contract-verification" }, + label: computed(() => t("header.nav.apiDocs")), + url: computed(() => `${currentNetwork.value.apiUrl}/docs`), }, { - label: computed(() => t("header.nav.portal")), - url: computed(() => currentNetwork.value.l2WalletUrl), + label: computed(() => t("header.nav.contractVerification")), + to: { name: "contract-verification" }, }, ]; @@ -297,12 +301,20 @@ const hasContent = computed(() => { .hero-banner-container { @apply absolute left-0 top-full flex h-64 w-full items-end justify-end overflow-hidden bg-primary-900; + &.goerli { + @apply h-[25rem] md:h-[23rem] lg:h-[19rem]; + } + .hero-image { @apply h-5/6 w-auto; } } .home-banner { @apply h-80; + + &.goerli { + @apply h-[30rem] md:h-[27rem] lg:h-[24rem]; + } } } .header-mobile-popover { diff --git a/packages/app/src/components/token/TokenListTable.vue b/packages/app/src/components/token/TokenListTable.vue index da27218629..7e2475aa04 100644 --- a/packages/app/src/components/token/TokenListTable.vue +++ b/packages/app/src/components/token/TokenListTable.vue @@ -1,24 +1,24 @@