diff --git a/.dialyzer-ignore b/.dialyzer-ignore
index 84162c2785e0..6dd625f3298f 100644
--- a/.dialyzer-ignore
+++ b/.dialyzer-ignore
@@ -6,8 +6,8 @@
lib/ethereum_jsonrpc/rolling_window.ex:171
lib/explorer/smart_contract/solidity/publisher_worker.ex:1
lib/explorer/smart_contract/vyper/publisher_worker.ex:1
-lib/explorer/smart_contract/solidity/publisher_worker.ex:6
-lib/explorer/smart_contract/vyper/publisher_worker.ex:6
+lib/explorer/smart_contract/solidity/publisher_worker.ex:8
+lib/explorer/smart_contract/vyper/publisher_worker.ex:8
lib/block_scout_web/router.ex:1
lib/block_scout_web/schema/types.ex:31
lib/phoenix/router.ex:324
diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml
index 6bbec02ea1cb..18d436a17d06 100644
--- a/.github/workflows/config.yml
+++ b/.github/workflows/config.yml
@@ -12,6 +12,7 @@ on:
- production-sokol-stg
- production-rsk-stg
- production-lukso-stg
+ - production-immutable-stg
- staging-l2
pull_request:
branches:
@@ -47,7 +48,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-
@@ -105,7 +106,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -129,7 +130,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -152,7 +153,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -161,7 +162,7 @@ jobs:
id: dialyzer-cache
with:
path: priv/plts
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-"
@@ -192,7 +193,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -218,7 +219,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -247,7 +248,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -295,7 +296,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -341,7 +342,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -398,7 +399,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -452,7 +453,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -517,7 +518,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -581,7 +582,7 @@ jobs:
path: |
deps
_build
- key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_20-${{ hashFiles('mix.lock') }}
+ key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_22-${{ hashFiles('mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-"
@@ -624,7 +625,7 @@ jobs:
PGUSER: postgres
ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox"
ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox"
- CHAIN_ID: "77"
+ CHAIN_ID: "10200"
API_RATE_LIMIT_DISABLED: "true"
ADMIN_PANEL_ENABLED: "true"
ACCOUNT_ENABLED: "true"
diff --git a/.github/workflows/publish-docker-image-every-push.yml b/.github/workflows/publish-docker-image-every-push.yml
index a2205707247d..c748dfd25ea2 100644
--- a/.github/workflows/publish-docker-image-every-push.yml
+++ b/.github/workflows/publish-docker-image-every-push.yml
@@ -7,7 +7,7 @@ on:
env:
OTP_VERSION: '25.2.1'
ELIXIR_VERSION: '1.14.3'
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
jobs:
push_to_registry:
diff --git a/.github/workflows/publish-docker-image-for-core.yml b/.github/workflows/publish-docker-image-for-core.yml
index d15ef3531a54..48470e040e3a 100644
--- a/.github/workflows/publish-docker-image-for-core.yml
+++ b/.github/workflows/publish-docker-image-for-core.yml
@@ -14,7 +14,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: poa
steps:
- name: Check out the repo
@@ -41,12 +41,12 @@ jobs:
context: .
file: ./docker/Dockerfile
push: true
- tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-for-eth-goerli.yml b/.github/workflows/publish-docker-image-for-eth-goerli.yml
index 0f1dfbb47991..95c8e9fa996f 100644
--- a/.github/workflows/publish-docker-image-for-eth-goerli.yml
+++ b/.github/workflows/publish-docker-image-for-eth-goerli.yml
@@ -14,7 +14,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: eth-goerli
steps:
- name: Check out the repo
@@ -41,12 +41,12 @@ jobs:
context: .
file: ./docker/Dockerfile
push: true
- tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-for-eth.yml b/.github/workflows/publish-docker-image-for-eth.yml
index 058b5f77d9a5..237eec76e5cd 100644
--- a/.github/workflows/publish-docker-image-for-eth.yml
+++ b/.github/workflows/publish-docker-image-for-eth.yml
@@ -14,7 +14,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: mainnet
steps:
- name: Check out the repo
@@ -41,12 +41,12 @@ jobs:
context: .
file: ./docker/Dockerfile
push: true
- tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}-experimental
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-experimental
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=false
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-for-immutable.yml b/.github/workflows/publish-docker-image-for-immutable.yml
new file mode 100644
index 000000000000..92eff232935f
--- /dev/null
+++ b/.github/workflows/publish-docker-image-for-immutable.yml
@@ -0,0 +1,63 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+name: Publish Docker image for specific chain branches
+
+on:
+ push:
+ branches:
+ - production-immutable-stg
+env:
+ OTP_VERSION: '24.3.4.1'
+ ELIXIR_VERSION: '1.13.4'
+jobs:
+ push_to_registry:
+ name: Push Docker image to Docker Hub
+ runs-on: ubuntu-latest
+ env:
+ RELEASE_VERSION: 5.2.2
+ DOCKER_CHAIN_NAME: immutable
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v3
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v2
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@v2
+ with:
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@v4
+ with:
+ images: blockscout/blockscout
+
+ - name: Add SHORT_SHA env property with commit short sha
+ run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v3
+ with:
+ context: .
+ file: ./docker/Dockerfile
+ push: true
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
+ build-args: |
+ CACHE_EXCHANGE_RATES_PERIOD=
+ API_V1_READ_METHODS_DISABLED=false
+ DISABLE_WEBAPP=false
+ API_V1_WRITE_METHODS_DISABLED=false
+ CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
+ ADMIN_PANEL_ENABLED=false
+ CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
+ BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }}
+ RELEASE_VERSION=${{ env.RELEASE_VERSION }}
\ No newline at end of file
diff --git a/.github/workflows/publish-docker-image-for-l2-staging.yml b/.github/workflows/publish-docker-image-for-l2-staging.yml
index c903fe819c44..a95c63ad9e66 100644
--- a/.github/workflows/publish-docker-image-for-l2-staging.yml
+++ b/.github/workflows/publish-docker-image-for-l2-staging.yml
@@ -14,7 +14,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: optimism-l2-advanced
steps:
- name: Check out the repo
@@ -41,12 +41,12 @@ jobs:
context: .
file: ./docker/Dockerfile
push: true
- tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-for-lukso.yml b/.github/workflows/publish-docker-image-for-lukso.yml
index 544f0729d5cc..8279c009f00f 100644
--- a/.github/workflows/publish-docker-image-for-lukso.yml
+++ b/.github/workflows/publish-docker-image-for-lukso.yml
@@ -14,7 +14,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: lukso
steps:
- name: Check out the repo
@@ -41,12 +41,12 @@ jobs:
context: .
file: ./docker/Dockerfile
push: true
- tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-for-optimism.yml b/.github/workflows/publish-docker-image-for-optimism.yml
index e1406ee5a24f..7c7bd2f11e64 100644
--- a/.github/workflows/publish-docker-image-for-optimism.yml
+++ b/.github/workflows/publish-docker-image-for-optimism.yml
@@ -14,7 +14,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: optimism
steps:
- name: Check out the repo
@@ -44,9 +44,9 @@ jobs:
tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-for-rsk.yml b/.github/workflows/publish-docker-image-for-rsk.yml
index df49d64ccac0..5eb97cf0de37 100644
--- a/.github/workflows/publish-docker-image-for-rsk.yml
+++ b/.github/workflows/publish-docker-image-for-rsk.yml
@@ -14,7 +14,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: rsk
steps:
- name: Check out the repo
@@ -41,12 +41,12 @@ jobs:
context: .
file: ./docker/Dockerfile
push: true
- tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-for-xdai.yml b/.github/workflows/publish-docker-image-for-xdai.yml
index 9f3ecd4a772e..37295fedd354 100644
--- a/.github/workflows/publish-docker-image-for-xdai.yml
+++ b/.github/workflows/publish-docker-image-for-xdai.yml
@@ -17,7 +17,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
DOCKER_CHAIN_NAME: xdai
steps:
- name: Check out the repo
@@ -50,12 +50,12 @@ jobs:
context: .
file: ./docker/Dockerfile
push: true
- tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-prerelease-${{ env.SHORT_SHA }}
+ tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:latest, blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}
build-args: |
CACHE_EXCHANGE_RATES_PERIOD=
- DISABLE_READ_API=false
+ API_V1_READ_METHODS_DISABLED=false
DISABLE_WEBAPP=false
- DISABLE_WRITE_API=false
+ API_V1_WRITE_METHODS_DISABLED=false
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED=
ADMIN_PANEL_ENABLED=false
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=
diff --git a/.github/workflows/publish-docker-image-release.yml b/.github/workflows/publish-docker-image-release.yml
index 689f3d7ec858..918abd13067d 100644
--- a/.github/workflows/publish-docker-image-release.yml
+++ b/.github/workflows/publish-docker-image-release.yml
@@ -18,7 +18,7 @@ jobs:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
env:
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
steps:
- name: Check out the repo
uses: actions/checkout@v3
@@ -82,6 +82,7 @@ jobs:
production-xdai-stg
production-polygon-supernets-stg
production-rsk-stg
+ production-immutable-stg
steps:
- uses: actions/checkout@v2
- name: Set Git config
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 000000000000..505db0421db5
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,5 @@
+repos:
+ - repo: https://github.com/gitleaks/gitleaks
+ rev: v8.17.0
+ hooks:
+ - id: gitleaks
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e63f5eec164..f31d821ced65 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,15 +4,105 @@
### Features
+- [#8181](https://github.com/blockscout/blockscout/pull/8181) - Insert current token balances placeholders along with historical
+- [#8210](https://github.com/blockscout/blockscout/pull/8210) - Drop address foreign keys
+- [#8292](https://github.com/blockscout/blockscout/pull/8292) - Add ETHEREUM_JSONRPC_WAIT_PER_TIMEOUT env var
+
+### Fixes
+
+- [#8293](https://github.com/blockscout/blockscout/pull/8293) - Add ETHEREUM_JSONRPC_TRACE_URL for Geth in docker-compose.yml
+- [#8240](https://github.com/blockscout/blockscout/pull/8240) - Refactor and fix paging params in API v2
+- [#8242](https://github.com/blockscout/blockscout/pull/8242) - Fixing visualizer service CORS issue when running docker-compose
+
+### Chore
+
+- [#8281](https://github.com/blockscout/blockscout/pull/8281) - Planned removal of duplicate API endpoints: for CSV export and GraphQL
+
+
+ Dependencies version bumps
+
+
+
+## 5.2.2-beta
+
+### Features
+
+- [#8218](https://github.com/blockscout/blockscout/pull/8218) - Add `/api/v2/search/quick` method
+- [#8202](https://github.com/blockscout/blockscout/pull/8202) - Add `/api/v2/addresses/:address_hash/tabs-counters` endpoint
+- [#8156](https://github.com/blockscout/blockscout/pull/8156) - Add `is_verified_via_admin_panel` property to tokens table
+- [#8165](https://github.com/blockscout/blockscout/pull/8165), [#8201](https://github.com/blockscout/blockscout/pull/8201) - Add broadcast of updated address_current_token_balances
+- [#7952](https://github.com/blockscout/blockscout/pull/7952) - Add parsing constructor arguments for sourcify contracts
+- [#6190](https://github.com/blockscout/blockscout/pull/6190) - Add EIP-1559 support to gas price oracle
+- [#7977](https://github.com/blockscout/blockscout/pull/7977) - GraphQL: extend schema with new field for existing objects
+- [#8158](https://github.com/blockscout/blockscout/pull/8158), [#8164](https://github.com/blockscout/blockscout/pull/8164) - Include unfetched balances in TokenBalanceOnDemand fetcher
+
### Fixes
+- [#8233](https://github.com/blockscout/blockscout/pull/8233) - Fix API v2 broken tx response
+- [#8147](https://github.com/blockscout/blockscout/pull/8147) - Switch sourcify tests from POA Sokol to Gnosis Chiado
+- [#8145](https://github.com/blockscout/blockscout/pull/8145) - Handle negative holders count in API v2
- [#8040](https://github.com/blockscout/blockscout/pull/8040) - Resolve issue with Docker image for Mac M1/M2
+- [#8060](https://github.com/blockscout/blockscout/pull/8060) - Fix eth_getLogs API endpoint
+- [#8082](https://github.com/blockscout/blockscout/pull/8082), [#8088](https://github.com/blockscout/blockscout/pull/8088) - Fix Rootstock charts API
+- [#7992](https://github.com/blockscout/blockscout/pull/7992) - Fix missing range insert
+- [#8022](https://github.com/blockscout/blockscout/pull/8022) - Don't add reorg block number to missing blocks
### Chore
+- [#8222](https://github.com/blockscout/blockscout/pull/8222) - docker-compose for new UI with external backend
+- [#8177](https://github.com/blockscout/blockscout/pull/8177) - Refactor address counter functions
+- [#8183](https://github.com/blockscout/blockscout/pull/8183) - Update frontend envs in order to pass their validation
+- [#8167](https://github.com/blockscout/blockscout/pull/8167) - Manage concurrency for Token and TokenBalance fetcher
+- [#8179](https://github.com/blockscout/blockscout/pull/8179) - Enhance nginx config
+- [#8146](https://github.com/blockscout/blockscout/pull/8146) - Add method_id to write methods in API v2 response
+- [#8105](https://github.com/blockscout/blockscout/pull/8105) - Extend API v1 with endpoints used by new UI
+- [#8104](https://github.com/blockscout/blockscout/pull/8104) - remove "TODO" from API v2 response
+- [#8100](https://github.com/blockscout/blockscout/pull/8100), [#8103](https://github.com/blockscout/blockscout/pull/8103) - Extend docker-compose configs with new config when front is running externally
+- [#8012](https://github.com/blockscout/blockscout/pull/8012) - API v2 smart-contract verification extended logging
+
Dependencies version bumps
+- [#7980](https://github.com/blockscout/blockscout/pull/7980) - Bump solc from 0.8.20 to 0.8.21 in /apps/explorer
+- [#7986](https://github.com/blockscout/blockscout/pull/7986) - Bump sass from 1.63.6 to 1.64.0 in /apps/block_scout_web/assets
+- [#8030](https://github.com/blockscout/blockscout/pull/8030) - Bump sweetalert2 from 11.7.18 to 11.7.20 in /apps/block_scout_web/assets
+- [#8029](https://github.com/blockscout/blockscout/pull/8029) - Bump viewerjs from 1.11.3 to 1.11.4 in /apps/block_scout_web/assets
+- [#8028](https://github.com/blockscout/blockscout/pull/8028) - Bump sass from 1.64.0 to 1.64.1 in /apps/block_scout_web/assets
+- [#8026](https://github.com/blockscout/blockscout/pull/8026) - Bump dataloader from 1.0.10 to 1.0.11
+- [#8036](https://github.com/blockscout/blockscout/pull/8036) - Bump ex_cldr_numbers from 2.31.1 to 2.31.3
+- [#8027](https://github.com/blockscout/blockscout/pull/8027) - Bump absinthe from 1.7.4 to 1.7.5
+- [#8035](https://github.com/blockscout/blockscout/pull/8035) - Bump wallaby from 0.30.4 to 0.30.5
+- [#8038](https://github.com/blockscout/blockscout/pull/8038) - Bump chart.js from 4.3.0 to 4.3.1 in /apps/block_scout_web/assets
+- [#8047](https://github.com/blockscout/blockscout/pull/8047) - Bump chart.js from 4.3.1 to 4.3.2 in /apps/block_scout_web/assets
+- [#8000](https://github.com/blockscout/blockscout/pull/8000) - Bump postcss from 8.4.26 to 8.4.27 in /apps/block_scout_web/assets
+- [#8052](https://github.com/blockscout/blockscout/pull/8052) - Bump @amplitude/analytics-browser from 2.1.2 to 2.1.3 in /apps/block_scout_web/assets
+- [#8054](https://github.com/blockscout/blockscout/pull/8054) - Bump jest-environment-jsdom from 29.6.1 to 29.6.2 in /apps/block_scout_web/assets
+- [#8063](https://github.com/blockscout/blockscout/pull/8063) - Bump eslint from 8.45.0 to 8.46.0 in /apps/block_scout_web/assets
+- [#8066](https://github.com/blockscout/blockscout/pull/8066) - Bump ex_json_schema from 0.9.3 to 0.10.1
+- [#8064](https://github.com/blockscout/blockscout/pull/8064) - Bump core-js from 3.31.1 to 3.32.0 in /apps/block_scout_web/assets
+- [#8053](https://github.com/blockscout/blockscout/pull/8053) - Bump jest from 29.6.1 to 29.6.2 in /apps/block_scout_web/assets
+- [#8065](https://github.com/blockscout/blockscout/pull/8065) - Bump eslint-plugin-import from 2.27.5 to 2.28.0 in /apps/block_scout_web/assets
+- [#8092](https://github.com/blockscout/blockscout/pull/8092) - Bump exvcr from 0.14.1 to 0.14.2
+- [#8091](https://github.com/blockscout/blockscout/pull/8091) - Bump sass from 1.64.1 to 1.64.2 in /apps/block_scout_web/assets
+- [#8114](https://github.com/blockscout/blockscout/pull/8114) - Bump ex_doc from 0.30.3 to 0.30.4
+- [#8115](https://github.com/blockscout/blockscout/pull/8115) - Bump chart.js from 4.3.2 to 4.3.3 in /apps/block_scout_web/assets
+- [#8116](https://github.com/blockscout/blockscout/pull/8116) - Bump @fortawesome/fontawesome-free from 6.4.0 to 6.4.2 in /apps/block_scout_web/assets
+- [#8142](https://github.com/blockscout/blockscout/pull/8142) - Bump sobelow from 0.12.2 to 0.13.0
+- [#8141](https://github.com/blockscout/blockscout/pull/8141) - Bump @babel/core from 7.22.9 to 7.22.10 in /apps/block_scout_web/assets
+- [#8140](https://github.com/blockscout/blockscout/pull/8140) - Bump @babel/preset-env from 7.22.9 to 7.22.10 in /apps/block_scout_web/assets
+- [#8160](https://github.com/blockscout/blockscout/pull/8160) - Bump exvcr from 0.14.2 to 0.14.3
+- [#8159](https://github.com/blockscout/blockscout/pull/8159) - Bump luxon from 3.3.0 to 3.4.0 in /apps/block_scout_web/assets
+- [#8169](https://github.com/blockscout/blockscout/pull/8169) - Bump sass from 1.64.2 to 1.65.1 in /apps/block_scout_web/assets
+- [#8170](https://github.com/blockscout/blockscout/pull/8170) - Bump sweetalert2 from 11.7.20 to 11.7.22 in /apps/block_scout_web/assets
+- [#8188](https://github.com/blockscout/blockscout/pull/8188) - Bump eslint from 8.46.0 to 8.47.0 in /apps/block_scout_web/assets
+- [#8204](https://github.com/blockscout/blockscout/pull/8204) - Bump ex_doc from 0.30.4 to 0.30.5
+- [#8207](https://github.com/blockscout/blockscout/pull/8207) - Bump wallaby from 0.30.5 to 0.30.6
+- [#8212](https://github.com/blockscout/blockscout/pull/8212) - Bump sweetalert2 from 11.7.22 to 11.7.23 in /apps/block_scout_web/assets
+- [#8203](https://github.com/blockscout/blockscout/pull/8203) - Bump autoprefixer from 10.4.14 to 10.4.15 in /apps/block_scout_web/assets
+- [#8214](https://github.com/blockscout/blockscout/pull/8214) - Bump @amplitude/analytics-browser from 2.1.3 to 2.2.0 in /apps/block_scout_web/assets
+- [#8225](https://github.com/blockscout/blockscout/pull/8225) - Bump postcss from 8.4.27 to 8.4.28 in /apps/block_scout_web/assets
+- [#8224](https://github.com/blockscout/blockscout/pull/8224) - Bump gettext from 0.22.3 to 0.23.1
+
## 5.2.1-beta
@@ -36,6 +126,7 @@
### Fixes
+- [#8187](https://github.com/blockscout/blockscout/pull/8187) - API v1 500 error convert to 404, if requested path is incorrect
- [#7852](https://github.com/blockscout/blockscout/pull/7852) - Token balances refactoring & fixes
- [#7872](https://github.com/blockscout/blockscout/pull/7872) - Fix pending gas price in pending tx
- [#7875](https://github.com/blockscout/blockscout/pull/7875) - Fix twin compiler version
@@ -88,7 +179,7 @@
- [#7867](https://github.com/blockscout/blockscout/pull/7867) - Bump postcss from 8.4.24 to 8.4.25 in /apps/block_scout_web/assets
- [#7871](https://github.com/blockscout/blockscout/pull/7871) - Bump @babel/core from 7.22.6 to 7.22.8 in /apps/block_scout_web/assets
- [#7868](https://github.com/blockscout/blockscout/pull/7868) - Bump jest-environment-jsdom from 29.6.0 to 29.6.1 in /apps/block_scout_web/assets
-- [#7866](https://github.com/blockscout/blockscout/pull/7866) - Bump @babel/preset-env from 7.22.6 to 7.22.7 in /apps/block_scout_web/assets
+- [#7866](https://github.com/blockscout/blockscout/pull/7866) - Bump @babel/preset-env from 7.22.6 to 7.22.7 in /apps/block_scout_web/assets
- [#7869](https://github.com/blockscout/blockscout/pull/7869) - Bump core-js from 3.31.0 to 3.31.1 in /apps/block_scout_web/assets
- [#7884](https://github.com/blockscout/blockscout/pull/7884) - Bump ecto from 3.10.2 to 3.10.3
- [#7882](https://github.com/blockscout/blockscout/pull/7882) - Bump jason from 1.4.0 to 1.4.1
@@ -215,7 +306,7 @@
- [#7702](https://github.com/blockscout/blockscout/pull/7702) - Bump @amplitude/analytics-browser from 1.10.8 to 1.11.0 in /apps/block_scout_web/assets
- [#7708](https://github.com/blockscout/blockscout/pull/7708) - Bump phoenix_pubsub from 2.1.2 to 2.1.3
- [#7707](https://github.com/blockscout/blockscout/pull/7707) - Bump @amplitude/analytics-browser from 1.11.0 to 2.0.0 in /apps/block_scout_web/assets
-- [#7706](https://github.com/blockscout/blockscout/pull/7706) - Bump webpack from 5.86.0 to 5.87.0 in /apps/block_scout_web/assets
+- [#7706](https://github.com/blockscout/blockscout/pull/7706) - Bump webpack from 5.86.0 to 5.87.0 in /apps/block_scout_web/assets
- [#7705](https://github.com/blockscout/blockscout/pull/7705) - Bump sass from 1.63.3 to 1.63.4 in /apps/block_scout_web/assets
- [#7714](https://github.com/blockscout/blockscout/pull/7714) - Bump ex_cldr_units from 3.16.1 to 3.16.2
- [#7748](https://github.com/blockscout/blockscout/pull/7748) - Bump mock from 0.3.7 to 0.3.8
diff --git a/README.md b/README.md
index 316e101047f5..0a59692f9704 100644
--- a/README.md
+++ b/README.md
@@ -8,24 +8,21 @@
-BlockScout provides a comprehensive, easy-to-use interface for users to view, confirm, and inspect transactions on EVM (Ethereum Virtual Machine) blockchains. This includes the POA Network, Gnosis Chain, Ethereum Classic and other **Ethereum testnets, private networks and sidechains**.
+BlockScout provides a comprehensive, easy-to-use interface for users to view, confirm, and inspect transactions on EVM (Ethereum Virtual Machine) blockchains. This includes Ethereum Mainnet, Ethereum Classic, Optimism, Gnosis Chain and many other **Ethereum testnets, private networks, L2s and sidechains**.
See our [project documentation](https://docs.blockscout.com/) for detailed information and setup instructions.
-For questions, comments and feature requests see the [discussions section](https://github.com/blockscout/blockscout/discussions).
+For questions, comments and feature requests see the [discussions section](https://github.com/blockscout/blockscout/discussions) or via [Discord](https://discord.com/invite/blockscout).
## About BlockScout
-BlockScout is an Elixir application that allows users to search transactions, view accounts and balances, and verify smart contracts on the Ethereum network including all forks and sidechains.
+BlockScout allows users to search transactions, view accounts and balances, verify and interact with smart contracts and view and interact with applications on the Ethereum network including many forks, sidechains, L2s and testnets.
-Currently available full-featured block explorers (Etherscan, Etherchain, Blockchair) are closed systems which are not independently verifiable. As Ethereum sidechains continue to proliferate in both private and public settings, transparent, open-source tools are needed to analyze and validate transactions.
+Blockscout is an open-source alternative to centralized, closed source block explorers such as Etherscan, Etherchain and others. As Ethereum sidechains and L2s continue to proliferate in both private and public settings, transparent, open-source tools are needed to analyze and validate all transactions.
## Supported Projects
-BlockScout supports a number of projects. Hosted instances include POA Network, Gnosis Chain, Ethereum Classic, Sokol & Kovan testnets, and other EVM chains.
-
-- [List of hosted mainnets, testnets, and additional chains using BlockScout](https://docs.blockscout.com/for-projects/supported-projects)
-- [Hosted instance versions](https://docs.blockscout.com/about/use-cases/hosted-blockscout)
+BlockScout currently supports several hundred chains and rollups throughout the greater blockchain ecosystem. Ethereum, Cosmos, Polkadot, Avalanche, Near and many others include Blockscout integrations. [A comprehensive list is available here](https://docs.blockscout.com/about/projects). If your project is not listed, please submit a PR or [contact the team in Discord](https://discord.com/invite/blockscout).
## Getting Started
diff --git a/apps/block_scout_web/assets/package-lock.json b/apps/block_scout_web/assets/package-lock.json
index a521866da3aa..421a0861ea94 100644
--- a/apps/block_scout_web/assets/package-lock.json
+++ b/apps/block_scout_web/assets/package-lock.json
@@ -7,17 +7,17 @@
"name": "blockscout",
"license": "GPL-3.0",
"dependencies": {
- "@amplitude/analytics-browser": "^2.1.2",
- "@fortawesome/fontawesome-free": "^6.4.0",
+ "@amplitude/analytics-browser": "^2.2.0",
+ "@fortawesome/fontawesome-free": "^6.4.2",
"@tarekraafat/autocomplete.js": "^10.2.7",
"@walletconnect/web3-provider": "^1.8.0",
"assert": "^2.0.0",
"bignumber.js": "^9.1.1",
"bootstrap": "^4.6.0",
- "chart.js": "^4.3.2",
+ "chart.js": "^4.3.3",
"chartjs-adapter-luxon": "^1.3.1",
"clipboard": "^2.0.11",
- "core-js": "^3.31.1",
+ "core-js": "^3.32.1",
"crypto-browserify": "^3.12.0",
"dropzone": "^5.9.3",
"eth-net-props": "^1.0.41",
@@ -44,7 +44,7 @@
"lodash.omit": "^4.5.0",
"lodash.rangeright": "^4.2.0",
"lodash.reduce": "^4.6.0",
- "luxon": "^3.3.0",
+ "luxon": "^3.4.1",
"malihu-custom-scrollbar-plugin": "3.1.5",
"mixpanel-browser": "^2.47.0",
"moment": "^2.29.4",
@@ -61,7 +61,7 @@
"redux": "^4.2.1",
"stream-browserify": "^3.0.0",
"stream-http": "^3.1.1",
- "sweetalert2": "^11.7.20",
+ "sweetalert2": "^11.7.27",
"urijs": "^1.19.11",
"url": "^0.11.1",
"util": "^0.12.5",
@@ -71,25 +71,25 @@
"xss": "^1.0.14"
},
"devDependencies": {
- "@babel/core": "^7.22.9",
- "@babel/preset-env": "^7.22.9",
- "autoprefixer": "^10.4.14",
+ "@babel/core": "^7.22.10",
+ "@babel/preset-env": "^7.22.10",
+ "autoprefixer": "^10.4.15",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^5.2.7",
"css-minimizer-webpack-plugin": "^5.0.1",
- "eslint": "^8.45.0",
+ "eslint": "^8.47.0",
"eslint-config-standard": "^17.1.0",
- "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-import": "^2.28.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"file-loader": "^6.2.0",
- "jest": "^29.6.1",
- "jest-environment-jsdom": "^29.6.1",
+ "jest": "^29.6.3",
+ "jest-environment-jsdom": "^29.6.3",
"mini-css-extract-plugin": "^2.7.6",
- "postcss": "^8.4.26",
+ "postcss": "^8.4.28",
"postcss-loader": "^7.3.3",
- "sass": "^1.64.1",
+ "sass": "^1.66.1",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"webpack": "^5.88.2",
@@ -116,15 +116,15 @@
}
},
"node_modules/@amplitude/analytics-browser": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.1.2.tgz",
- "integrity": "sha512-1XoWJmLgGrszxupz61yCjen53bq7+kJN2gedu+kSrq/Ze9ow5R5QI0YfLyuzi1FHchzmSVWd2PheXOVYC4K/Cw==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.2.0.tgz",
+ "integrity": "sha512-gCRnvXT5FDmaXbrmDVdVLbm7ubYgpQX2dRnA3R8uPfqw3YGXszueVxTPKYuMf0fdQ3+1N9RcPmyEycpywN9vKg==",
"dependencies": {
"@amplitude/analytics-client-common": "^2.0.4",
"@amplitude/analytics-core": "^2.0.3",
"@amplitude/analytics-types": "^2.1.1",
- "@amplitude/plugin-page-view-tracking-browser": "^2.0.4",
- "@amplitude/plugin-web-attribution-browser": "^2.0.4",
+ "@amplitude/plugin-page-view-tracking-browser": "^2.0.6",
+ "@amplitude/plugin-web-attribution-browser": "^2.0.6",
"tslib": "^2.4.1"
}
},
@@ -145,9 +145,9 @@
}
},
"node_modules/@amplitude/analytics-client-common/node_modules/tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
},
"node_modules/@amplitude/analytics-connector": {
"version": "1.4.8",
@@ -164,9 +164,9 @@
}
},
"node_modules/@amplitude/analytics-core/node_modules/tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
},
"node_modules/@amplitude/analytics-types": {
"version": "2.1.1",
@@ -174,9 +174,9 @@
"integrity": "sha512-H3vebPR9onRdp0WzAZmI/4qmAE903uLOd2ZfMeHsVc1zaFTTCk46SoCuV4IrlF+VILrDw9Fy6gC9yl5N2PZcJQ=="
},
"node_modules/@amplitude/plugin-page-view-tracking-browser": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.0.4.tgz",
- "integrity": "sha512-XQlgydCmfUb+mkXjD8NoOU80eO/578m2AupRcV0dPKwk+VN5D7D1s+xXYM6Bg7l1HSJx2mt0Qwa5xsdSCFzF2g==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.0.6.tgz",
+ "integrity": "sha512-V8ef24E+KYINQf1o9MQnkmhFmQHGD5lb6mlTH8jGD2PdUe/KDXdO4S4rpBewxcrAfUH+iEqEanbVnTWpg6iPnw==",
"dependencies": {
"@amplitude/analytics-client-common": "^2.0.4",
"@amplitude/analytics-types": "^2.1.1",
@@ -184,14 +184,14 @@
}
},
"node_modules/@amplitude/plugin-page-view-tracking-browser/node_modules/tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
},
"node_modules/@amplitude/plugin-web-attribution-browser": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-attribution-browser/-/plugin-web-attribution-browser-2.0.4.tgz",
- "integrity": "sha512-y/VQjDH7tnevRlKO9IWzELF9L87MwiR+y7WCRxR5/wRGKDxKS5Ol33vHYWe1RaOzkC/7wO0px7pZGRZkj/X+1Q==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-attribution-browser/-/plugin-web-attribution-browser-2.0.6.tgz",
+ "integrity": "sha512-+WQuhHJn7ZsYaTMe6iPE081b6y2oe9m+W/eZW+Lyf99Vt3rntDVYZIgZVwwds0s2SsUBcSvYFu1JgS65NfxWNQ==",
"dependencies": {
"@amplitude/analytics-client-common": "^2.0.4",
"@amplitude/analytics-core": "^2.0.3",
@@ -200,9 +200,9 @@
}
},
"node_modules/@amplitude/plugin-web-attribution-browser/node_modules/tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
},
"node_modules/@ampproject/remapping": {
"version": "2.2.0",
@@ -229,11 +229,12 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
- "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
+ "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
"dependencies": {
- "@babel/highlight": "^7.22.5"
+ "@babel/highlight": "^7.22.10",
+ "chalk": "^2.4.2"
},
"engines": {
"node": ">=6.9.0"
@@ -248,20 +249,20 @@
}
},
"node_modules/@babel/core": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz",
- "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz",
+ "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.22.5",
- "@babel/generator": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/code-frame": "^7.22.10",
+ "@babel/generator": "^7.22.10",
+ "@babel/helper-compilation-targets": "^7.22.10",
"@babel/helper-module-transforms": "^7.22.9",
- "@babel/helpers": "^7.22.6",
- "@babel/parser": "^7.22.7",
+ "@babel/helpers": "^7.22.10",
+ "@babel/parser": "^7.22.10",
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.8",
- "@babel/types": "^7.22.5",
+ "@babel/traverse": "^7.22.10",
+ "@babel/types": "^7.22.10",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -277,11 +278,11 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz",
- "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
+ "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
"dependencies": {
- "@babel/types": "^7.22.5",
+ "@babel/types": "^7.22.10",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
@@ -314,9 +315,9 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz",
- "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz",
+ "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==",
"dependencies": {
"@babel/compat-data": "^7.22.9",
"@babel/helper-validator-option": "^7.22.5",
@@ -326,9 +327,6 @@
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
@@ -493,15 +491,14 @@
}
},
"node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz",
- "integrity": "sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g==",
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz",
+ "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-wrap-function": "^7.22.5",
- "@babel/types": "^7.22.5"
+ "@babel/helper-wrap-function": "^7.22.9"
},
"engines": {
"node": ">=6.9.0"
@@ -586,40 +583,39 @@
}
},
"node_modules/@babel/helper-wrap-function": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz",
- "integrity": "sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz",
+ "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==",
"dev": true,
"dependencies": {
"@babel/helper-function-name": "^7.22.5",
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.5",
- "@babel/types": "^7.22.5"
+ "@babel/types": "^7.22.10"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
- "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz",
+ "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==",
"dependencies": {
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.6",
- "@babel/types": "^7.22.5"
+ "@babel/traverse": "^7.22.10",
+ "@babel/types": "^7.22.10"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
- "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
+ "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
"dependencies": {
"@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.0.0",
+ "chalk": "^2.4.2",
"js-tokens": "^4.0.0"
},
"engines": {
@@ -627,9 +623,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.22.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
- "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz",
+ "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -681,22 +677,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
- "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
@@ -990,14 +970,14 @@
}
},
"node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.22.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz",
- "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz",
+ "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==",
"dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.9",
"@babel/plugin-syntax-async-generators": "^7.8.4"
},
"engines": {
@@ -1040,9 +1020,9 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz",
- "integrity": "sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz",
+ "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -1127,9 +1107,9 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz",
- "integrity": "sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz",
+ "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -1496,9 +1476,9 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz",
- "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz",
+ "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
@@ -1577,13 +1557,13 @@
}
},
"node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz",
- "integrity": "sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz",
+ "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
- "regenerator-transform": "^0.15.1"
+ "regenerator-transform": "^0.15.2"
},
"engines": {
"node": ">=6.9.0"
@@ -1715,9 +1695,9 @@
}
},
"node_modules/@babel/plugin-transform-unicode-escapes": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz",
- "integrity": "sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz",
+ "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -1778,13 +1758,13 @@
}
},
"node_modules/@babel/preset-env": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz",
- "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz",
+ "integrity": "sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.10",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-validator-option": "^7.22.5",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5",
@@ -1809,15 +1789,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.7",
+ "@babel/plugin-transform-async-generator-functions": "^7.22.10",
"@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.5",
+ "@babel/plugin-transform-block-scoping": "^7.22.10",
"@babel/plugin-transform-class-properties": "^7.22.5",
"@babel/plugin-transform-class-static-block": "^7.22.5",
"@babel/plugin-transform-classes": "^7.22.6",
"@babel/plugin-transform-computed-properties": "^7.22.5",
- "@babel/plugin-transform-destructuring": "^7.22.5",
+ "@babel/plugin-transform-destructuring": "^7.22.10",
"@babel/plugin-transform-dotall-regex": "^7.22.5",
"@babel/plugin-transform-duplicate-keys": "^7.22.5",
"@babel/plugin-transform-dynamic-import": "^7.22.5",
@@ -1840,27 +1820,27 @@
"@babel/plugin-transform-object-rest-spread": "^7.22.5",
"@babel/plugin-transform-object-super": "^7.22.5",
"@babel/plugin-transform-optional-catch-binding": "^7.22.5",
- "@babel/plugin-transform-optional-chaining": "^7.22.6",
+ "@babel/plugin-transform-optional-chaining": "^7.22.10",
"@babel/plugin-transform-parameters": "^7.22.5",
"@babel/plugin-transform-private-methods": "^7.22.5",
"@babel/plugin-transform-private-property-in-object": "^7.22.5",
"@babel/plugin-transform-property-literals": "^7.22.5",
- "@babel/plugin-transform-regenerator": "^7.22.5",
+ "@babel/plugin-transform-regenerator": "^7.22.10",
"@babel/plugin-transform-reserved-words": "^7.22.5",
"@babel/plugin-transform-shorthand-properties": "^7.22.5",
"@babel/plugin-transform-spread": "^7.22.5",
"@babel/plugin-transform-sticky-regex": "^7.22.5",
"@babel/plugin-transform-template-literals": "^7.22.5",
"@babel/plugin-transform-typeof-symbol": "^7.22.5",
- "@babel/plugin-transform-unicode-escapes": "^7.22.5",
+ "@babel/plugin-transform-unicode-escapes": "^7.22.10",
"@babel/plugin-transform-unicode-property-regex": "^7.22.5",
"@babel/plugin-transform-unicode-regex": "^7.22.5",
"@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
- "@babel/preset-modules": "^0.1.5",
- "@babel/types": "^7.22.5",
- "babel-plugin-polyfill-corejs2": "^0.4.4",
- "babel-plugin-polyfill-corejs3": "^0.8.2",
- "babel-plugin-polyfill-regenerator": "^0.5.1",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "@babel/types": "^7.22.10",
+ "babel-plugin-polyfill-corejs2": "^0.4.5",
+ "babel-plugin-polyfill-corejs3": "^0.8.3",
+ "babel-plugin-polyfill-regenerator": "^0.5.2",
"core-js-compat": "^3.31.0",
"semver": "^6.3.1"
},
@@ -1872,9 +1852,9 @@
}
},
"node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz",
- "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==",
+ "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==",
"dev": true,
"dependencies": {
"@babel/helper-compilation-targets": "^7.22.6",
@@ -1884,49 +1864,47 @@
"resolve": "^1.14.2"
},
"peerDependencies": {
- "@babel/core": "^7.4.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.4.tgz",
- "integrity": "sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==",
+ "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==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.22.6",
- "@babel/helper-define-polyfill-provider": "^0.4.1",
- "@nicolo-ribaudo/semver-v6": "^6.3.3"
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
+ "semver": "^6.3.1"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.1.tgz",
- "integrity": "sha512-L8OyySuI6OSQ5hFy9O+7zFjyr4WhAfRjLIOkhQGYl+emwJkd/S4XXT1JpfrgR1jrQ1NcGiOh+yAdGlF8pnC3Jw==",
+ "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==",
"dev": true,
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.4.1"
+ "@babel/helper-define-polyfill-provider": "^0.4.2"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/@babel/preset-modules": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
- "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "version": "0.1.6-no-external-plugins",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
- "@babel/plugin-transform-dotall-regex": "^7.4.4",
"@babel/types": "^7.4.4",
"esutils": "^2.0.2"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/@babel/regjsgen": {
@@ -1960,18 +1938,18 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.22.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
- "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz",
+ "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==",
"dependencies": {
- "@babel/code-frame": "^7.22.5",
- "@babel/generator": "^7.22.7",
+ "@babel/code-frame": "^7.22.10",
+ "@babel/generator": "^7.22.10",
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-function-name": "^7.22.5",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/parser": "^7.22.7",
- "@babel/types": "^7.22.5",
+ "@babel/parser": "^7.22.10",
+ "@babel/types": "^7.22.10",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -1980,9 +1958,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
- "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
+ "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
"dependencies": {
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.5",
@@ -2046,18 +2024,18 @@
}
},
"node_modules/@eslint-community/regexpp": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz",
- "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==",
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz",
+ "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==",
"dev": true,
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
"node_modules/@eslint/eslintrc": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
- "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
+ "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
@@ -2084,9 +2062,9 @@
"dev": true
},
"node_modules/@eslint/eslintrc/node_modules/globals": {
- "version": "13.20.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
- "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "version": "13.21.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz",
+ "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@@ -2123,9 +2101,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.44.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
- "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
+ "version": "8.47.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz",
+ "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2524,9 +2502,9 @@
}
},
"node_modules/@fortawesome/fontawesome-free": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz",
- "integrity": "sha512-0NyytTlPJwB/BF5LtRV8rrABDbe3TdTXqNB3PdZ+UUUZAEIrdOJdmABqKjt4AXwIoJNaRVVZEXxpNrqvE1GAYQ==",
+ "version": "6.4.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.2.tgz",
+ "integrity": "sha512-m5cPn3e2+FDCOgi1mz0RexTUvvQibBebOUlUlW0+YrMjDTPkiJ6VTKukA1GRsvRw+12KyJndNjj0O4AgTxm2Pg==",
"hasInstallScript": true,
"engines": {
"node": ">=6"
@@ -2600,16 +2578,16 @@
}
},
"node_modules/@jest/console": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz",
- "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.3.tgz",
+ "integrity": "sha512-ukZbHAdDH4ktZIOKvWs1juAXhiVAdvCyM8zv4S/7Ii3vJSDvMW5k+wOVGMQmHLHUFw3Ko63ZQNy7NI6PSlsD5w==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3",
"slash": "^3.0.0"
},
"engines": {
@@ -2687,37 +2665,37 @@
}
},
"node_modules/@jest/core": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz",
- "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.3.tgz",
+ "integrity": "sha512-skV1XrfNxfagmjRUrk2FyN5/2YwIzdWVVBa/orUfbLvQUANXxERq2pTvY0I+FinWHjDKB2HRmpveUiph4X0TJw==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.6.1",
- "@jest/reporters": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/reporters": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@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.5.0",
- "jest-config": "^29.6.1",
- "jest-haste-map": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-resolve-dependencies": "^29.6.1",
- "jest-runner": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
- "jest-watcher": "^29.6.1",
+ "jest-changed-files": "^29.6.3",
+ "jest-config": "^29.6.3",
+ "jest-haste-map": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-resolve-dependencies": "^29.6.3",
+ "jest-runner": "^29.6.3",
+ "jest-runtime": "^29.6.3",
+ "jest-snapshot": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
+ "jest-watcher": "^29.6.3",
"micromatch": "^4.0.4",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"slash": "^3.0.0",
"strip-ansi": "^6.0.0"
},
@@ -2804,88 +2782,88 @@
}
},
"node_modules/@jest/environment": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz",
- "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.3.tgz",
+ "integrity": "sha512-u/u3cCztYCfgBiGHsamqP5x+XvucftOGPbf5RJQxfpeC1y4AL8pCjKvPDA3oCmdhZYPgk5AE0VOD/flweR69WA==",
"dev": true,
"dependencies": {
- "@jest/fake-timers": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-mock": "^29.6.1"
+ "jest-mock": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/expect": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz",
- "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.3.tgz",
+ "integrity": "sha512-Ic08XbI2jlg6rECy+CGwk/8NDa6VE7UmIG6++9OTPAMnQmNGY28hu69Nf629CWv6T7YMODLbONxDFKdmQeI9FA==",
"dev": true,
"dependencies": {
- "expect": "^29.6.1",
- "jest-snapshot": "^29.6.1"
+ "expect": "^29.6.3",
+ "jest-snapshot": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/expect-utils": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz",
- "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.3.tgz",
+ "integrity": "sha512-nvOEW4YoqRKD9HBJ9OJ6przvIvP9qilp5nAn1462P5ZlL/MM9SgPEZFyjTGPfs7QkocdUsJa6KjHhyRn4ueItA==",
"dev": true,
"dependencies": {
- "jest-get-type": "^29.4.3"
+ "jest-get-type": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/fake-timers": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz",
- "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.3.tgz",
+ "integrity": "sha512-pa1wmqvbj6eX0nMvOM2VDAWvJOI5A/Mk3l8O7n7EsAh71sMZblaKO9iT4GjIj0LwwK3CP/Jp1ypEV0x3m89RvA==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@sinonjs/fake-timers": "^10.0.2",
"@types/node": "*",
- "jest-message-util": "^29.6.1",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1"
+ "jest-message-util": "^29.6.3",
+ "jest-mock": "^29.6.3",
+ "jest-util": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/globals": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz",
- "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.3.tgz",
+ "integrity": "sha512-RB+uI+CZMHntzlnOPlll5x/jgRff3LEPl/td/jzMXiIgR0iIhKq9qm1HLU+EC52NuoVy/1swit/sDGjVn4bc6A==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/expect": "^29.6.1",
- "@jest/types": "^29.6.1",
- "jest-mock": "^29.6.1"
+ "@jest/environment": "^29.6.3",
+ "@jest/expect": "^29.6.3",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/reporters": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz",
- "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.3.tgz",
+ "integrity": "sha512-kGz59zMi0GkVjD2CJeYWG9k6cvj7eBqt9aDAqo2rcCLRTYlvQ62Gu/n+tOmJMBHGjzeijjuCENjzTyYBgrtLUw==",
"dev": true,
"dependencies": {
"@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@jridgewell/trace-mapping": "^0.3.18",
"@types/node": "*",
"chalk": "^4.0.0",
@@ -2894,13 +2872,13 @@
"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": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-worker": "^29.6.3",
"slash": "^3.0.0",
"string-length": "^4.0.1",
"strip-ansi": "^6.0.0",
@@ -2977,13 +2955,13 @@
}
},
"node_modules/@jest/reporters/node_modules/jest-worker": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
- "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz",
+ "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==",
"dev": true,
"dependencies": {
"@types/node": "*",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@@ -3019,9 +2997,9 @@
}
},
"node_modules/@jest/schemas": {
- "version": "29.6.0",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
- "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
+ "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"
@@ -3031,9 +3009,9 @@
}
},
"node_modules/@jest/source-map": {
- "version": "29.6.0",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz",
- "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==",
+ "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",
@@ -3045,13 +3023,13 @@
}
},
"node_modules/@jest/test-result": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz",
- "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.3.tgz",
+ "integrity": "sha512-k7ZZaNvOSMBHPZYiy0kuiaFoyansR5QnTwDux1EjK3kD5iWpRVyJIJ0RAIV39SThafchuW59vra7F8mdy5Hfgw==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/istanbul-lib-coverage": "^2.0.0",
"collect-v8-coverage": "^1.0.0"
},
@@ -3060,14 +3038,14 @@
}
},
"node_modules/@jest/test-sequencer": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz",
- "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.3.tgz",
+ "integrity": "sha512-/SmijaAU2TY9ComFGIYa6Z+fmKqQMnqs2Nmwb0P/Z/tROdZ7M0iruES1EaaU9PBf8o9uED5xzaJ3YPFEIcDgAg==",
"dev": true,
"dependencies": {
- "@jest/test-result": "^29.6.1",
+ "@jest/test-result": "^29.6.3",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
"slash": "^3.0.0"
},
"engines": {
@@ -3075,22 +3053,22 @@
}
},
"node_modules/@jest/transform": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz",
- "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.3.tgz",
+ "integrity": "sha512-dPIc3DsvMZ/S8ut4L2ViCj265mKO0owB0wfzBv2oGzL9pQ+iRvJewHqLBmsGb7XFb5UotWIEtvY5A/lnylaIoQ==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
- "@jest/types": "^29.6.1",
+ "@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.6.1",
- "jest-regex-util": "^29.4.3",
- "jest-util": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.6.3",
"micromatch": "^4.0.4",
"pirates": "^4.0.4",
"slash": "^3.0.0",
@@ -3177,12 +3155,12 @@
}
},
"node_modules/@jest/types": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz",
- "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==",
+ "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.0",
+ "@jest/schemas": "^29.6.3",
"@types/istanbul-lib-coverage": "^2.0.0",
"@types/istanbul-reports": "^3.0.0",
"@types/node": "*",
@@ -3326,15 +3304,6 @@
"resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz",
"integrity": "sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q=="
},
- "node_modules/@nicolo-ribaudo/semver-v6": {
- "version": "6.3.3",
- "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
- "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -3612,12 +3581,6 @@
"@types/node": "*"
}
},
- "node_modules/@types/prettier": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
- "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==",
- "dev": true
- },
"node_modules/@types/responselike": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
@@ -4337,6 +4300,19 @@
"sprintf-js": "~1.0.2"
}
},
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -4361,6 +4337,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz",
+ "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/array.prototype.flat": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
@@ -4397,6 +4392,26 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz",
+ "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "get-intrinsic": "^1.2.1",
+ "is-array-buffer": "^3.0.2",
+ "is-shared-array-buffer": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -4488,9 +4503,9 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"node_modules/autoprefixer": {
- "version": "10.4.14",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
- "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
+ "version": "10.4.15",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz",
+ "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==",
"dev": true,
"funding": [
{
@@ -4500,11 +4515,15 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
- "browserslist": "^4.21.5",
- "caniuse-lite": "^1.0.30001464",
+ "browserslist": "^4.21.10",
+ "caniuse-lite": "^1.0.30001520",
"fraction.js": "^4.2.0",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
@@ -4545,15 +4564,15 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"node_modules/babel-jest": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz",
- "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.3.tgz",
+ "integrity": "sha512-1Ne93zZZEy5XmTa4Q+W5+zxBrDpExX8E3iy+xJJ+24ewlfo/T3qHfQJCzi/MMVFmBQDNxtRR/Gfd2dwb/0yrQw==",
"dev": true,
"dependencies": {
- "@jest/transform": "^29.6.1",
+ "@jest/transform": "^29.6.3",
"@types/babel__core": "^7.1.14",
"babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^29.5.0",
+ "babel-preset-jest": "^29.6.3",
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
"slash": "^3.0.0"
@@ -4668,10 +4687,26 @@
"node": ">=8"
}
},
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/babel-plugin-jest-hoist": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz",
- "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
"dev": true,
"dependencies": {
"@babel/template": "^7.3.3",
@@ -4697,22 +4732,22 @@
}
},
"node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz",
- "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==",
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz",
+ "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==",
"dev": true,
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.4.1",
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
"core-js-compat": "^3.31.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz",
- "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==",
+ "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==",
"dev": true,
"dependencies": {
"@babel/helper-compilation-targets": "^7.22.6",
@@ -4722,7 +4757,7 @@
"resolve": "^1.14.2"
},
"peerDependencies": {
- "@babel/core": "^7.4.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/babel-plugin-polyfill-regenerator": {
@@ -4779,12 +4814,12 @@
}
},
"node_modules/babel-preset-jest": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz",
- "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
"dev": true,
"dependencies": {
- "babel-plugin-jest-hoist": "^29.5.0",
+ "babel-plugin-jest-hoist": "^29.6.3",
"babel-preset-current-node-syntax": "^1.0.0"
},
"engines": {
@@ -5068,9 +5103,9 @@
]
},
"node_modules/browserslist": {
- "version": "4.21.9",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
- "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
"funding": [
{
"type": "opencollective",
@@ -5086,9 +5121,9 @@
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001503",
- "electron-to-chromium": "^1.4.431",
- "node-releases": "^2.0.12",
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
"update-browserslist-db": "^1.0.11"
},
"bin": {
@@ -5338,9 +5373,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001512",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
- "integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==",
+ "version": "1.0.30001520",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz",
+ "integrity": "sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA==",
"funding": [
{
"type": "opencollective",
@@ -5400,9 +5435,9 @@
}
},
"node_modules/chart.js": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.2.tgz",
- "integrity": "sha512-pvQNyFOY1QmbmIr8oDORL16/FFivfxj8V26VFpFilMo4cNvkV5WXLJetDio365pd9gKUHGdirUTbqJfw8tr+Dg==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz",
+ "integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
@@ -5778,9 +5813,9 @@
}
},
"node_modules/core-js": {
- "version": "3.31.1",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.1.tgz",
- "integrity": "sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==",
+ "version": "3.32.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.1.tgz",
+ "integrity": "sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@@ -6408,10 +6443,18 @@
}
},
"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
+ "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
+ }
+ }
},
"node_modules/deep-eql": {
"version": "3.0.1",
@@ -6456,9 +6499,9 @@
}
},
"node_modules/define-properties": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
- "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
"dependencies": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
@@ -6524,9 +6567,9 @@
}
},
"node_modules/diff-sequences": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
- "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
"dev": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -6668,9 +6711,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
"node_modules/electron-to-chromium": {
- "version": "1.4.450",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz",
- "integrity": "sha512-BLG5HxSELlrMx7dJ2s+8SFlsCtJp37Zpk2VAxyC6CZtbc+9AJeZHfYHbrlSgdXp6saQ8StMqOTEDaBKgA7u1sw=="
+ "version": "1.4.490",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz",
+ "integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A=="
},
"node_modules/elliptic": {
"version": "6.5.4",
@@ -6815,18 +6858,19 @@
}
},
"node_modules/es-abstract": {
- "version": "1.21.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz",
- "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==",
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz",
+ "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==",
"dev": true,
"dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "arraybuffer.prototype.slice": "^1.0.1",
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-set-tostringtag": "^2.0.1",
"es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
"function.prototype.name": "^1.1.5",
- "get-intrinsic": "^1.1.3",
+ "get-intrinsic": "^1.2.1",
"get-symbol-description": "^1.0.0",
"globalthis": "^1.0.3",
"gopd": "^1.0.1",
@@ -6834,8 +6878,8 @@
"has-property-descriptors": "^1.0.0",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
- "internal-slot": "^1.0.4",
- "is-array-buffer": "^3.0.1",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
"is-callable": "^1.2.7",
"is-negative-zero": "^2.0.2",
"is-regex": "^1.1.4",
@@ -6843,16 +6887,21 @@
"is-string": "^1.0.7",
"is-typed-array": "^1.1.10",
"is-weakref": "^1.0.2",
- "object-inspect": "^1.12.2",
+ "object-inspect": "^1.12.3",
"object-keys": "^1.1.1",
"object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.4.3",
+ "regexp.prototype.flags": "^1.5.0",
+ "safe-array-concat": "^1.0.0",
"safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
"string.prototype.trimend": "^1.0.6",
"string.prototype.trimstart": "^1.0.6",
+ "typed-array-buffer": "^1.0.0",
+ "typed-array-byte-length": "^1.0.0",
+ "typed-array-byte-offset": "^1.0.0",
"typed-array-length": "^1.0.4",
"unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.9"
+ "which-typed-array": "^1.1.10"
},
"engines": {
"node": ">= 0.4"
@@ -7054,27 +7103,27 @@
}
},
"node_modules/eslint": {
- "version": "8.45.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz",
- "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==",
+ "version": "8.47.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz",
+ "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.4.0",
- "@eslint/eslintrc": "^2.1.0",
- "@eslint/js": "8.44.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.2",
+ "@eslint/js": "^8.47.0",
"@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
- "ajv": "^6.10.0",
+ "ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.3.2",
"doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.0",
- "eslint-visitor-keys": "^3.4.1",
- "espree": "^9.6.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -7157,9 +7206,9 @@
}
},
"node_modules/eslint-module-utils": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
- "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
+ "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
"dev": true,
"dependencies": {
"debug": "^3.2.7"
@@ -7203,26 +7252,28 @@
}
},
"node_modules/eslint-plugin-import": {
- "version": "2.27.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
- "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
+ "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==",
"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",
"debug": "^3.2.7",
"doctrine": "^2.1.0",
"eslint-import-resolver-node": "^0.3.7",
- "eslint-module-utils": "^2.7.4",
+ "eslint-module-utils": "^2.8.0",
"has": "^1.0.3",
- "is-core-module": "^2.11.0",
+ "is-core-module": "^2.13.0",
"is-glob": "^4.0.3",
"minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.6",
+ "object.groupby": "^1.0.0",
"object.values": "^1.1.6",
- "resolve": "^1.22.1",
- "semver": "^6.3.0",
- "tsconfig-paths": "^3.14.1"
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.14.2"
},
"engines": {
"node": ">=4"
@@ -7412,9 +7463,9 @@
}
},
"node_modules/eslint-visitor-keys": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
- "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -7491,9 +7542,9 @@
}
},
"node_modules/eslint/node_modules/eslint-scope": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
- "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
"dev": true,
"dependencies": {
"esrecurse": "^4.3.0",
@@ -7631,9 +7682,9 @@
}
},
"node_modules/espree": {
- "version": "9.6.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
- "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
"dev": true,
"dependencies": {
"acorn": "^8.9.0",
@@ -8275,17 +8326,16 @@
}
},
"node_modules/expect": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz",
- "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.3.tgz",
+ "integrity": "sha512-x1vY4LlEMWUYVZQrFi4ZANXFwqYbJ/JNQspLVvzhW2BNY28aNcXMQH6imBbt+RBf5sVRTodYHXtSP/TLEU0Dxw==",
"dev": true,
"dependencies": {
- "@jest/expect-utils": "^29.6.1",
- "@types/node": "*",
- "jest-get-type": "^29.4.3",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1"
+ "@jest/expect-utils": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -8834,12 +8884,13 @@
}
},
"node_modules/get-intrinsic": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
- "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
+ "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"dependencies": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
+ "has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
},
"funding": {
@@ -9111,7 +9162,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -9462,12 +9512,12 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/internal-slot": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz",
- "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
"dev": true,
"dependencies": {
- "get-intrinsic": "^1.1.3",
+ "get-intrinsic": "^1.2.0",
"has": "^1.0.3",
"side-channel": "^1.0.4"
},
@@ -9508,13 +9558,13 @@
}
},
"node_modules/is-array-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz",
- "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
+ "get-intrinsic": "^1.2.0",
"is-typed-array": "^1.1.10"
},
"funding": {
@@ -9579,9 +9629,9 @@
}
},
"node_modules/is-core-module": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
- "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
+ "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
"dependencies": {
"has": "^1.0.3"
},
@@ -9897,33 +9947,48 @@
}
},
"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.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz",
+ "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==",
"dev": true,
"dependencies": {
"@babel/core": "^7.12.3",
"@babel/parser": "^7.14.7",
"@istanbuljs/schema": "^0.1.2",
"istanbul-lib-coverage": "^3.2.0",
- "semver": "^6.3.0"
+ "semver": "^7.5.4"
},
"engines": {
- "node": ">=8"
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
"dependencies": {
"istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^3.0.0",
+ "make-dir": "^4.0.0",
"supports-color": "^7.1.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
}
},
"node_modules/istanbul-lib-report/node_modules/has-flag": {
@@ -9962,9 +10027,9 @@
}
},
"node_modules/istanbul-reports": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
- "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz",
+ "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==",
"dev": true,
"dependencies": {
"html-escaper": "^2.0.0",
@@ -9975,15 +10040,15 @@
}
},
"node_modules/jest": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz",
- "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.3.tgz",
+ "integrity": "sha512-alueLuoPCDNHFcFGmgETR4KpQ+0ff3qVaiJwxQM4B5sC0CvXcgg4PEi7xrDkxuItDmdz/FVc7SSit4KEu8GRvw==",
"dev": true,
"dependencies": {
- "@jest/core": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/core": "^29.6.3",
+ "@jest/types": "^29.6.3",
"import-local": "^3.0.2",
- "jest-cli": "^29.6.1"
+ "jest-cli": "^29.6.3"
},
"bin": {
"jest": "bin/jest.js"
@@ -10001,12 +10066,13 @@
}
},
"node_modules/jest-changed-files": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz",
- "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz",
+ "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==",
"dev": true,
"dependencies": {
"execa": "^5.0.0",
+ "jest-util": "^29.6.3",
"p-limit": "^3.1.0"
},
"engines": {
@@ -10014,28 +10080,28 @@
}
},
"node_modules/jest-circus": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz",
- "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.3.tgz",
+ "integrity": "sha512-p0R5YqZEMnOpHqHLWRSjm2z/0p6RNsrNE/GRRT3eli8QGOAozj6Ys/3Tv+Ej+IfltJoSPwcQ6/hOCRkNlxLLCw==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/expect": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/environment": "^29.6.3",
+ "@jest/expect": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@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": "^29.6.1",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-each": "^29.6.3",
+ "jest-matcher-utils": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-runtime": "^29.6.3",
+ "jest-snapshot": "^29.6.3",
+ "jest-util": "^29.6.3",
"p-limit": "^3.1.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"pure-rand": "^6.0.0",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
@@ -10115,21 +10181,21 @@
}
},
"node_modules/jest-cli": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz",
- "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.3.tgz",
+ "integrity": "sha512-KuPdXUPXQIf0t6DvmG8MV4QyhcjR1a6ruKl3YL7aGn/AQ8JkROwFkWzEpDIpt11Qy188dHbRm8WjwMsV/4nmnQ==",
"dev": true,
"dependencies": {
- "@jest/core": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/core": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/types": "^29.6.3",
"chalk": "^4.0.0",
"exit": "^0.1.2",
"graceful-fs": "^4.2.9",
"import-local": "^3.0.2",
- "jest-config": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-config": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
"prompts": "^2.0.1",
"yargs": "^17.3.1"
},
@@ -10219,31 +10285,31 @@
}
},
"node_modules/jest-config": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz",
- "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.3.tgz",
+ "integrity": "sha512-nb9bOq2aEqogbyL4F9mLkAeQGAgNt7Uz6U59YtQDIxFPiL7Ejgq0YIrp78oyEHD6H4CIV/k7mFrK7eFDzUJ69w==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.6.1",
- "@jest/types": "^29.6.1",
- "babel-jest": "^29.6.1",
+ "@jest/test-sequencer": "^29.6.3",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.6.3",
"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.6.1",
- "jest-environment-node": "^29.6.1",
- "jest-get-type": "^29.4.3",
- "jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-runner": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-circus": "^29.6.3",
+ "jest-environment-node": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-runner": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
"micromatch": "^4.0.4",
"parse-json": "^5.2.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"slash": "^3.0.0",
"strip-json-comments": "^3.1.1"
},
@@ -10334,15 +10400,15 @@
}
},
"node_modules/jest-diff": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz",
- "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.3.tgz",
+ "integrity": "sha512-3sw+AdWnwH9sSNohMRKA7JiYUJSRr/WS6+sEFfBuhxU5V5GlEVKfvUn8JuMHE0wqKowemR1C2aHy8VtXbaV8dQ==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
- "diff-sequences": "^29.4.3",
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -10419,9 +10485,9 @@
}
},
"node_modules/jest-docblock": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz",
- "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz",
+ "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==",
"dev": true,
"dependencies": {
"detect-newline": "^3.0.0"
@@ -10431,16 +10497,16 @@
}
},
"node_modules/jest-each": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz",
- "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz",
+ "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"chalk": "^4.0.0",
- "jest-get-type": "^29.4.3",
- "jest-util": "^29.6.1",
- "pretty-format": "^29.6.1"
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "pretty-format": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -10517,18 +10583,18 @@
}
},
"node_modules/jest-environment-jsdom": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.1.tgz",
- "integrity": "sha512-PoY+yLaHzVRhVEjcVKSfJ7wXmJW4UqPYNhR05h7u/TK0ouf6DmRNZFBL/Z00zgQMyWGMBXn69/FmOvhEJu8cIw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.3.tgz",
+ "integrity": "sha512-nMJz/i27Moit9bv8Z323/13Melj4FEQH93yRu7GnilvBmPBMH4EGEkEfBTJXYuubyzhMO7w/VHzljIDV+Q/SeQ==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/environment": "^29.6.3",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/jsdom": "^20.0.0",
"@types/node": "*",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-mock": "^29.6.3",
+ "jest-util": "^29.6.3",
"jsdom": "^20.0.0"
},
"engines": {
@@ -10544,46 +10610,46 @@
}
},
"node_modules/jest-environment-node": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz",
- "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.3.tgz",
+ "integrity": "sha512-PKl7upfPJXMYbWpD+60o4HP86KvFO2c9dZ+Zr6wUzsG5xcPx/65o3ArNgHW5M0RFvLYdW4/aieR4JSooD0a2ew==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/environment": "^29.6.3",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1"
+ "jest-mock": "^29.6.3",
+ "jest-util": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-get-type": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
- "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
"dev": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-haste-map": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz",
- "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.3.tgz",
+ "integrity": "sha512-GecR5YavfjkhOytEFHAeI6aWWG3f/cOKNB1YJvj/B76xAmeVjy4zJUYobGF030cRmKaO1FBw3V8CZZ6KVh9ZSw==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.6.1",
+ "@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.4.3",
- "jest-util": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-worker": "^29.6.3",
"micromatch": "^4.0.4",
"walker": "^1.0.8"
},
@@ -10604,13 +10670,13 @@
}
},
"node_modules/jest-haste-map/node_modules/jest-worker": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
- "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz",
+ "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==",
"dev": true,
"dependencies": {
"@types/node": "*",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@@ -10634,28 +10700,28 @@
}
},
"node_modules/jest-leak-detector": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz",
- "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz",
+ "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==",
"dev": true,
"dependencies": {
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-matcher-utils": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz",
- "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.3.tgz",
+ "integrity": "sha512-6ZrMYINZdwduSt5Xu18/n49O1IgXdjsfG7NEZaQws9k69eTKWKcVbJBw/MZsjOZe2sSyJFmuzh8042XWwl54Zg==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
- "jest-diff": "^29.6.1",
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "jest-diff": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -10732,18 +10798,18 @@
}
},
"node_modules/jest-message-util": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz",
- "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz",
+ "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.12.13",
- "@jest/types": "^29.6.1",
+ "@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.6.1",
+ "pretty-format": "^29.6.3",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
},
@@ -10822,14 +10888,14 @@
}
},
"node_modules/jest-mock": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz",
- "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz",
+ "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-util": "^29.6.1"
+ "jest-util": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -10853,26 +10919,26 @@
}
},
"node_modules/jest-regex-util": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz",
- "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==",
+ "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/jest-resolve": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz",
- "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.3.tgz",
+ "integrity": "sha512-WMXwxhvzDeA/J+9jz1i8ZKGmbw/n+s988EiUvRI4egM+eTn31Hb5v10Re3slG3/qxntkBt2/6GkQVDGu6Bwyhw==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
"jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
"resolve": "^1.20.0",
"resolve.exports": "^2.0.0",
"slash": "^3.0.0"
@@ -10882,13 +10948,13 @@
}
},
"node_modules/jest-resolve-dependencies": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz",
- "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.3.tgz",
+ "integrity": "sha512-iah5nhSPTwtUV7yzpTc9xGg8gP3Ch2VNsuFMsKoCkNCrQSbFtx5KRPemmPJ32AUhTSDqJXB6djPN6zAaUGV53g==",
"dev": true,
"dependencies": {
- "jest-regex-util": "^29.4.3",
- "jest-snapshot": "^29.6.1"
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -10965,30 +11031,30 @@
}
},
"node_modules/jest-runner": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz",
- "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.3.tgz",
+ "integrity": "sha512-E4zsMhQnjhirFPhDTJgoLMWUrVCDij/KGzWlbslDHGuO8Hl2pVUfOiygMzVZtZq+BzmlqwEr7LYmW+WFLlmX8w==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.6.1",
- "@jest/environment": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/environment": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
"graceful-fs": "^4.2.9",
- "jest-docblock": "^29.4.3",
- "jest-environment-node": "^29.6.1",
- "jest-haste-map": "^29.6.1",
- "jest-leak-detector": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-resolve": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-watcher": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-docblock": "^29.6.3",
+ "jest-environment-node": "^29.6.3",
+ "jest-haste-map": "^29.6.3",
+ "jest-leak-detector": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-runtime": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-watcher": "^29.6.3",
+ "jest-worker": "^29.6.3",
"p-limit": "^3.1.0",
"source-map-support": "0.5.13"
},
@@ -11055,13 +11121,13 @@
}
},
"node_modules/jest-runner/node_modules/jest-worker": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
- "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz",
+ "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==",
"dev": true,
"dependencies": {
"@types/node": "*",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@@ -11107,31 +11173,31 @@
}
},
"node_modules/jest-runtime": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz",
- "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==",
- "dev": true,
- "dependencies": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
- "@jest/globals": "^29.6.1",
- "@jest/source-map": "^29.6.0",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.3.tgz",
+ "integrity": "sha512-VM0Z3a9xaqizGpEKwCOIhImkrINYzxgwk8oQAvrmAiXX8LNrJrRjyva30RkuRY0ETAotHLlUcd2moviCA1hgsQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.3",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/globals": "^29.6.3",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@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.6.1",
- "jest-message-util": "^29.6.1",
- "jest-mock": "^29.6.1",
- "jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-mock": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-snapshot": "^29.6.3",
+ "jest-util": "^29.6.3",
"slash": "^3.0.0",
"strip-bom": "^4.0.0"
},
@@ -11210,9 +11276,9 @@
}
},
"node_modules/jest-snapshot": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz",
- "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.3.tgz",
+ "integrity": "sha512-66Iu7H1ojiveQMGFnKecHIZPPPBjZwfQEnF6wxqpxGf57sV3YSUtAb5/sTKM5TPa3OndyxZp1wxHFbmgVhc53w==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
@@ -11220,21 +11286,20 @@
"@babel/plugin-syntax-jsx": "^7.7.2",
"@babel/plugin-syntax-typescript": "^7.7.2",
"@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
- "@types/prettier": "^2.1.5",
+ "@jest/expect-utils": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@jest/types": "^29.6.3",
"babel-preset-current-node-syntax": "^1.0.0",
"chalk": "^4.0.0",
- "expect": "^29.6.1",
+ "expect": "^29.6.3",
"graceful-fs": "^4.2.9",
- "jest-diff": "^29.6.1",
- "jest-get-type": "^29.4.3",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-diff": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3",
"natural-compare": "^1.4.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"semver": "^7.5.3"
},
"engines": {
@@ -11300,9 +11365,9 @@
}
},
"node_modules/jest-snapshot/node_modules/semver": {
- "version": "7.5.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
- "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
+ "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"
@@ -11327,12 +11392,12 @@
}
},
"node_modules/jest-util": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz",
- "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz",
+ "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
"ci-info": "^3.2.0",
@@ -11414,17 +11479,17 @@
}
},
"node_modules/jest-validate": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz",
- "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz",
+ "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"camelcase": "^6.2.0",
"chalk": "^4.0.0",
- "jest-get-type": "^29.4.3",
+ "jest-get-type": "^29.6.3",
"leven": "^3.1.0",
- "pretty-format": "^29.6.1"
+ "pretty-format": "^29.6.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -11513,18 +11578,18 @@
}
},
"node_modules/jest-watcher": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz",
- "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.3.tgz",
+ "integrity": "sha512-NgpFjZ2U2MKusjidbi4Oiu7tfs+nrgdIxIEVROvH1cFmOei9Uj25lwkMsakqLnH/s0nEcvxO1ck77FiRlcnpZg==",
"dev": true,
"dependencies": {
- "@jest/test-result": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/test-result": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"ansi-escapes": "^4.2.1",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"string-length": "^4.0.1"
},
"engines": {
@@ -12271,28 +12336,43 @@
"integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU="
},
"node_modules/luxon": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz",
- "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==",
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.1.tgz",
+ "integrity": "sha512-2USspxOCXWGIKHwuQ9XElxPPYrDOJHDQ5DQ870CoD+CxJbBnRDIBCfhioUJJjct7BKOy80Ia8cVstIcIMb/0+Q==",
"engines": {
"node": ">=12"
}
},
"node_modules/make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
"dependencies": {
- "semver": "^6.0.0"
+ "semver": "^7.5.3"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/make-dir/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/makeerror": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
@@ -12806,9 +12886,9 @@
"dev": true
},
"node_modules/node-releases": {
- "version": "2.0.12",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
- "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ=="
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -12960,6 +13040,35 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object.fromentries": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz",
+ "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz",
+ "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.21.2",
+ "get-intrinsic": "^1.2.1"
+ }
+ },
"node_modules/object.values": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
@@ -13419,9 +13528,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.26",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz",
- "integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==",
+ "version": "8.4.28",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
+ "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
"dev": true,
"funding": [
{
@@ -13994,12 +14103,12 @@
}
},
"node_modules/pretty-format": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
- "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz",
+ "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==",
"dev": true,
"dependencies": {
- "@jest/schemas": "^29.6.0",
+ "@jest/schemas": "^29.6.3",
"ansi-styles": "^5.0.0",
"react-is": "^18.0.0"
},
@@ -14516,23 +14625,23 @@
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"node_modules/regenerator-transform": {
- "version": "0.15.1",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz",
- "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==",
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
+ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.8.4"
}
},
"node_modules/regexp.prototype.flags": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
- "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
+ "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "functions-have-names": "^1.2.2"
+ "define-properties": "^1.2.0",
+ "functions-have-names": "^1.2.3"
},
"engines": {
"node": ">= 0.4"
@@ -14663,11 +14772,11 @@
"dev": true
},
"node_modules/resolve": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "version": "1.22.3",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
+ "integrity": "sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==",
"dependencies": {
- "is-core-module": "^2.9.0",
+ "is-core-module": "^2.12.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -14814,6 +14923,30 @@
"resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz",
"integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA=="
},
+ "node_modules/safe-array-concat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz",
+ "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-array-concat/node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -14848,9 +14981,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sass": {
- "version": "1.64.1",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz",
- "integrity": "sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==",
+ "version": "1.66.1",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.66.1.tgz",
+ "integrity": "sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -15423,6 +15556,23 @@
"node": ">=8"
}
},
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/string.prototype.trimend": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
@@ -15702,9 +15852,9 @@
}
},
"node_modules/sweetalert2": {
- "version": "11.7.20",
- "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.7.20.tgz",
- "integrity": "sha512-GdU1TkiLpGGC0mcPV8bKmS7G0MR7caxambPkEU8zyepRSNR9EaEvIjNhX5QNkL0VFVzHbI3l12NtuEklkJ0D4Q==",
+ "version": "11.7.27",
+ "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.7.27.tgz",
+ "integrity": "sha512-QbRXGQn1sb7HEhzA/K2xtWIwQHh/qkSbb1w6jYcTql2xy17876lTREEt1D4X6Q0x2wHtfUjKJ+Cb8IVkRoq7DQ==",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/limonte"
@@ -15962,13 +16112,13 @@
}
},
"node_modules/tsconfig-paths": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
- "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==",
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+ "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
"dev": true,
"dependencies": {
"@types/json5": "^0.0.29",
- "json5": "^1.0.1",
+ "json5": "^1.0.2",
"minimist": "^1.2.6",
"strip-bom": "^3.0.0"
}
@@ -16064,6 +16214,57 @@
"node": ">= 0.6"
}
},
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
+ "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+ "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/typed-array-length": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
@@ -17122,16 +17323,15 @@
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q=="
},
"node_modules/which-typed-array": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
- "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
+ "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0",
- "is-typed-array": "^1.1.10"
+ "has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -17404,15 +17604,15 @@
"dev": true
},
"@amplitude/analytics-browser": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.1.2.tgz",
- "integrity": "sha512-1XoWJmLgGrszxupz61yCjen53bq7+kJN2gedu+kSrq/Ze9ow5R5QI0YfLyuzi1FHchzmSVWd2PheXOVYC4K/Cw==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.2.0.tgz",
+ "integrity": "sha512-gCRnvXT5FDmaXbrmDVdVLbm7ubYgpQX2dRnA3R8uPfqw3YGXszueVxTPKYuMf0fdQ3+1N9RcPmyEycpywN9vKg==",
"requires": {
"@amplitude/analytics-client-common": "^2.0.4",
"@amplitude/analytics-core": "^2.0.3",
"@amplitude/analytics-types": "^2.1.1",
- "@amplitude/plugin-page-view-tracking-browser": "^2.0.4",
- "@amplitude/plugin-web-attribution-browser": "^2.0.4",
+ "@amplitude/plugin-page-view-tracking-browser": "^2.0.6",
+ "@amplitude/plugin-web-attribution-browser": "^2.0.6",
"tslib": "^2.4.1"
},
"dependencies": {
@@ -17435,9 +17635,9 @@
},
"dependencies": {
"tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
}
}
},
@@ -17456,9 +17656,9 @@
},
"dependencies": {
"tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
}
}
},
@@ -17468,9 +17668,9 @@
"integrity": "sha512-H3vebPR9onRdp0WzAZmI/4qmAE903uLOd2ZfMeHsVc1zaFTTCk46SoCuV4IrlF+VILrDw9Fy6gC9yl5N2PZcJQ=="
},
"@amplitude/plugin-page-view-tracking-browser": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.0.4.tgz",
- "integrity": "sha512-XQlgydCmfUb+mkXjD8NoOU80eO/578m2AupRcV0dPKwk+VN5D7D1s+xXYM6Bg7l1HSJx2mt0Qwa5xsdSCFzF2g==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.0.6.tgz",
+ "integrity": "sha512-V8ef24E+KYINQf1o9MQnkmhFmQHGD5lb6mlTH8jGD2PdUe/KDXdO4S4rpBewxcrAfUH+iEqEanbVnTWpg6iPnw==",
"requires": {
"@amplitude/analytics-client-common": "^2.0.4",
"@amplitude/analytics-types": "^2.1.1",
@@ -17478,16 +17678,16 @@
},
"dependencies": {
"tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
}
}
},
"@amplitude/plugin-web-attribution-browser": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-attribution-browser/-/plugin-web-attribution-browser-2.0.4.tgz",
- "integrity": "sha512-y/VQjDH7tnevRlKO9IWzELF9L87MwiR+y7WCRxR5/wRGKDxKS5Ol33vHYWe1RaOzkC/7wO0px7pZGRZkj/X+1Q==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-attribution-browser/-/plugin-web-attribution-browser-2.0.6.tgz",
+ "integrity": "sha512-+WQuhHJn7ZsYaTMe6iPE081b6y2oe9m+W/eZW+Lyf99Vt3rntDVYZIgZVwwds0s2SsUBcSvYFu1JgS65NfxWNQ==",
"requires": {
"@amplitude/analytics-client-common": "^2.0.4",
"@amplitude/analytics-core": "^2.0.3",
@@ -17496,9 +17696,9 @@
},
"dependencies": {
"tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig=="
}
}
},
@@ -17523,11 +17723,12 @@
}
},
"@babel/code-frame": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
- "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
+ "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
"requires": {
- "@babel/highlight": "^7.22.5"
+ "@babel/highlight": "^7.22.10",
+ "chalk": "^2.4.2"
}
},
"@babel/compat-data": {
@@ -17536,20 +17737,20 @@
"integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
},
"@babel/core": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz",
- "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz",
+ "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==",
"requires": {
"@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.22.5",
- "@babel/generator": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/code-frame": "^7.22.10",
+ "@babel/generator": "^7.22.10",
+ "@babel/helper-compilation-targets": "^7.22.10",
"@babel/helper-module-transforms": "^7.22.9",
- "@babel/helpers": "^7.22.6",
- "@babel/parser": "^7.22.7",
+ "@babel/helpers": "^7.22.10",
+ "@babel/parser": "^7.22.10",
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.8",
- "@babel/types": "^7.22.5",
+ "@babel/traverse": "^7.22.10",
+ "@babel/types": "^7.22.10",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -17558,11 +17759,11 @@
}
},
"@babel/generator": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz",
- "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
+ "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
"requires": {
- "@babel/types": "^7.22.5",
+ "@babel/types": "^7.22.10",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
@@ -17586,9 +17787,9 @@
}
},
"@babel/helper-compilation-targets": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz",
- "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz",
+ "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==",
"requires": {
"@babel/compat-data": "^7.22.9",
"@babel/helper-validator-option": "^7.22.5",
@@ -17719,15 +17920,14 @@
"integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
},
"@babel/helper-remap-async-to-generator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz",
- "integrity": "sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g==",
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz",
+ "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-wrap-function": "^7.22.5",
- "@babel/types": "^7.22.5"
+ "@babel/helper-wrap-function": "^7.22.9"
}
},
"@babel/helper-replace-supers": {
@@ -17785,41 +17985,40 @@
"integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw=="
},
"@babel/helper-wrap-function": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz",
- "integrity": "sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz",
+ "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==",
"dev": true,
"requires": {
"@babel/helper-function-name": "^7.22.5",
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.5",
- "@babel/types": "^7.22.5"
+ "@babel/types": "^7.22.10"
}
},
"@babel/helpers": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
- "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz",
+ "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==",
"requires": {
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.6",
- "@babel/types": "^7.22.5"
+ "@babel/traverse": "^7.22.10",
+ "@babel/types": "^7.22.10"
}
},
"@babel/highlight": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
- "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
+ "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
"requires": {
"@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.0.0",
+ "chalk": "^2.4.2",
"js-tokens": "^4.0.0"
}
},
"@babel/parser": {
- "version": "7.22.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
- "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q=="
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz",
+ "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ=="
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.22.5",
@@ -17848,16 +18047,6 @@
"dev": true,
"requires": {}
},
- "@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
- "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
- "dev": true,
- "requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
- }
- },
"@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
@@ -18058,14 +18247,14 @@
}
},
"@babel/plugin-transform-async-generator-functions": {
- "version": "7.22.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz",
- "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz",
+ "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==",
"dev": true,
"requires": {
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.9",
"@babel/plugin-syntax-async-generators": "^7.8.4"
}
},
@@ -18090,9 +18279,9 @@
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz",
- "integrity": "sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz",
+ "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -18147,9 +18336,9 @@
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz",
- "integrity": "sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz",
+ "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -18378,9 +18567,9 @@
}
},
"@babel/plugin-transform-optional-chaining": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz",
- "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz",
+ "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.22.5",
@@ -18429,13 +18618,13 @@
}
},
"@babel/plugin-transform-regenerator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz",
- "integrity": "sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz",
+ "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.22.5",
- "regenerator-transform": "^0.15.1"
+ "regenerator-transform": "^0.15.2"
}
},
"@babel/plugin-transform-reserved-words": {
@@ -18518,9 +18707,9 @@
}
},
"@babel/plugin-transform-unicode-escapes": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz",
- "integrity": "sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz",
+ "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -18557,13 +18746,13 @@
}
},
"@babel/preset-env": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz",
- "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz",
+ "integrity": "sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.10",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-validator-option": "^7.22.5",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5",
@@ -18588,15 +18777,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.7",
+ "@babel/plugin-transform-async-generator-functions": "^7.22.10",
"@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.5",
+ "@babel/plugin-transform-block-scoping": "^7.22.10",
"@babel/plugin-transform-class-properties": "^7.22.5",
"@babel/plugin-transform-class-static-block": "^7.22.5",
"@babel/plugin-transform-classes": "^7.22.6",
"@babel/plugin-transform-computed-properties": "^7.22.5",
- "@babel/plugin-transform-destructuring": "^7.22.5",
+ "@babel/plugin-transform-destructuring": "^7.22.10",
"@babel/plugin-transform-dotall-regex": "^7.22.5",
"@babel/plugin-transform-duplicate-keys": "^7.22.5",
"@babel/plugin-transform-dynamic-import": "^7.22.5",
@@ -18619,35 +18808,35 @@
"@babel/plugin-transform-object-rest-spread": "^7.22.5",
"@babel/plugin-transform-object-super": "^7.22.5",
"@babel/plugin-transform-optional-catch-binding": "^7.22.5",
- "@babel/plugin-transform-optional-chaining": "^7.22.6",
+ "@babel/plugin-transform-optional-chaining": "^7.22.10",
"@babel/plugin-transform-parameters": "^7.22.5",
"@babel/plugin-transform-private-methods": "^7.22.5",
"@babel/plugin-transform-private-property-in-object": "^7.22.5",
"@babel/plugin-transform-property-literals": "^7.22.5",
- "@babel/plugin-transform-regenerator": "^7.22.5",
+ "@babel/plugin-transform-regenerator": "^7.22.10",
"@babel/plugin-transform-reserved-words": "^7.22.5",
"@babel/plugin-transform-shorthand-properties": "^7.22.5",
"@babel/plugin-transform-spread": "^7.22.5",
"@babel/plugin-transform-sticky-regex": "^7.22.5",
"@babel/plugin-transform-template-literals": "^7.22.5",
"@babel/plugin-transform-typeof-symbol": "^7.22.5",
- "@babel/plugin-transform-unicode-escapes": "^7.22.5",
+ "@babel/plugin-transform-unicode-escapes": "^7.22.10",
"@babel/plugin-transform-unicode-property-regex": "^7.22.5",
"@babel/plugin-transform-unicode-regex": "^7.22.5",
"@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
- "@babel/preset-modules": "^0.1.5",
- "@babel/types": "^7.22.5",
- "babel-plugin-polyfill-corejs2": "^0.4.4",
- "babel-plugin-polyfill-corejs3": "^0.8.2",
- "babel-plugin-polyfill-regenerator": "^0.5.1",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "@babel/types": "^7.22.10",
+ "babel-plugin-polyfill-corejs2": "^0.4.5",
+ "babel-plugin-polyfill-corejs3": "^0.8.3",
+ "babel-plugin-polyfill-regenerator": "^0.5.2",
"core-js-compat": "^3.31.0",
"semver": "^6.3.1"
},
"dependencies": {
"@babel/helper-define-polyfill-provider": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz",
- "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==",
+ "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==",
"dev": true,
"requires": {
"@babel/helper-compilation-targets": "^7.22.6",
@@ -18658,36 +18847,34 @@
}
},
"babel-plugin-polyfill-corejs2": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.4.tgz",
- "integrity": "sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==",
+ "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==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.22.6",
- "@babel/helper-define-polyfill-provider": "^0.4.1",
- "@nicolo-ribaudo/semver-v6": "^6.3.3"
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
+ "semver": "^6.3.1"
}
},
"babel-plugin-polyfill-regenerator": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.1.tgz",
- "integrity": "sha512-L8OyySuI6OSQ5hFy9O+7zFjyr4WhAfRjLIOkhQGYl+emwJkd/S4XXT1JpfrgR1jrQ1NcGiOh+yAdGlF8pnC3Jw==",
+ "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==",
"dev": true,
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.4.1"
+ "@babel/helper-define-polyfill-provider": "^0.4.2"
}
}
}
},
"@babel/preset-modules": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
- "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "version": "0.1.6-no-external-plugins",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
- "@babel/plugin-transform-dotall-regex": "^7.4.4",
"@babel/types": "^7.4.4",
"esutils": "^2.0.2"
}
@@ -18717,26 +18904,26 @@
}
},
"@babel/traverse": {
- "version": "7.22.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
- "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz",
+ "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==",
"requires": {
- "@babel/code-frame": "^7.22.5",
- "@babel/generator": "^7.22.7",
+ "@babel/code-frame": "^7.22.10",
+ "@babel/generator": "^7.22.10",
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-function-name": "^7.22.5",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/parser": "^7.22.7",
- "@babel/types": "^7.22.5",
+ "@babel/parser": "^7.22.10",
+ "@babel/types": "^7.22.10",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
- "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
+ "version": "7.22.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
+ "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
"requires": {
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.5",
@@ -18788,15 +18975,15 @@
}
},
"@eslint-community/regexpp": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz",
- "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==",
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz",
+ "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==",
"dev": true
},
"@eslint/eslintrc": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
- "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
+ "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
@@ -18817,9 +19004,9 @@
"dev": true
},
"globals": {
- "version": "13.20.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
- "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "version": "13.21.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz",
+ "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==",
"dev": true,
"requires": {
"type-fest": "^0.20.2"
@@ -18843,9 +19030,9 @@
}
},
"@eslint/js": {
- "version": "8.44.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
- "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
+ "version": "8.47.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz",
+ "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==",
"dev": true
},
"@ethereumjs/common": {
@@ -19061,9 +19248,9 @@
}
},
"@fortawesome/fontawesome-free": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz",
- "integrity": "sha512-0NyytTlPJwB/BF5LtRV8rrABDbe3TdTXqNB3PdZ+UUUZAEIrdOJdmABqKjt4AXwIoJNaRVVZEXxpNrqvE1GAYQ=="
+ "version": "6.4.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.2.tgz",
+ "integrity": "sha512-m5cPn3e2+FDCOgi1mz0RexTUvvQibBebOUlUlW0+YrMjDTPkiJ6VTKukA1GRsvRw+12KyJndNjj0O4AgTxm2Pg=="
},
"@humanwhocodes/config-array": {
"version": "0.11.10",
@@ -19116,16 +19303,16 @@
"dev": true
},
"@jest/console": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz",
- "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.3.tgz",
+ "integrity": "sha512-ukZbHAdDH4ktZIOKvWs1juAXhiVAdvCyM8zv4S/7Ii3vJSDvMW5k+wOVGMQmHLHUFw3Ko63ZQNy7NI6PSlsD5w==",
"dev": true,
"requires": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3",
"slash": "^3.0.0"
},
"dependencies": {
@@ -19181,37 +19368,37 @@
}
},
"@jest/core": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz",
- "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.3.tgz",
+ "integrity": "sha512-skV1XrfNxfagmjRUrk2FyN5/2YwIzdWVVBa/orUfbLvQUANXxERq2pTvY0I+FinWHjDKB2HRmpveUiph4X0TJw==",
"dev": true,
"requires": {
- "@jest/console": "^29.6.1",
- "@jest/reporters": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/reporters": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@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.5.0",
- "jest-config": "^29.6.1",
- "jest-haste-map": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-resolve-dependencies": "^29.6.1",
- "jest-runner": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
- "jest-watcher": "^29.6.1",
+ "jest-changed-files": "^29.6.3",
+ "jest-config": "^29.6.3",
+ "jest-haste-map": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-resolve-dependencies": "^29.6.3",
+ "jest-runner": "^29.6.3",
+ "jest-runtime": "^29.6.3",
+ "jest-snapshot": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
+ "jest-watcher": "^29.6.3",
"micromatch": "^4.0.4",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"slash": "^3.0.0",
"strip-ansi": "^6.0.0"
},
@@ -19268,73 +19455,73 @@
}
},
"@jest/environment": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz",
- "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.3.tgz",
+ "integrity": "sha512-u/u3cCztYCfgBiGHsamqP5x+XvucftOGPbf5RJQxfpeC1y4AL8pCjKvPDA3oCmdhZYPgk5AE0VOD/flweR69WA==",
"dev": true,
"requires": {
- "@jest/fake-timers": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-mock": "^29.6.1"
+ "jest-mock": "^29.6.3"
}
},
"@jest/expect": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz",
- "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.3.tgz",
+ "integrity": "sha512-Ic08XbI2jlg6rECy+CGwk/8NDa6VE7UmIG6++9OTPAMnQmNGY28hu69Nf629CWv6T7YMODLbONxDFKdmQeI9FA==",
"dev": true,
"requires": {
- "expect": "^29.6.1",
- "jest-snapshot": "^29.6.1"
+ "expect": "^29.6.3",
+ "jest-snapshot": "^29.6.3"
}
},
"@jest/expect-utils": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz",
- "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.3.tgz",
+ "integrity": "sha512-nvOEW4YoqRKD9HBJ9OJ6przvIvP9qilp5nAn1462P5ZlL/MM9SgPEZFyjTGPfs7QkocdUsJa6KjHhyRn4ueItA==",
"dev": true,
"requires": {
- "jest-get-type": "^29.4.3"
+ "jest-get-type": "^29.6.3"
}
},
"@jest/fake-timers": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz",
- "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.3.tgz",
+ "integrity": "sha512-pa1wmqvbj6eX0nMvOM2VDAWvJOI5A/Mk3l8O7n7EsAh71sMZblaKO9iT4GjIj0LwwK3CP/Jp1ypEV0x3m89RvA==",
"dev": true,
"requires": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@sinonjs/fake-timers": "^10.0.2",
"@types/node": "*",
- "jest-message-util": "^29.6.1",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1"
+ "jest-message-util": "^29.6.3",
+ "jest-mock": "^29.6.3",
+ "jest-util": "^29.6.3"
}
},
"@jest/globals": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz",
- "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.3.tgz",
+ "integrity": "sha512-RB+uI+CZMHntzlnOPlll5x/jgRff3LEPl/td/jzMXiIgR0iIhKq9qm1HLU+EC52NuoVy/1swit/sDGjVn4bc6A==",
"dev": true,
"requires": {
- "@jest/environment": "^29.6.1",
- "@jest/expect": "^29.6.1",
- "@jest/types": "^29.6.1",
- "jest-mock": "^29.6.1"
+ "@jest/environment": "^29.6.3",
+ "@jest/expect": "^29.6.3",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.6.3"
}
},
"@jest/reporters": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz",
- "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.3.tgz",
+ "integrity": "sha512-kGz59zMi0GkVjD2CJeYWG9k6cvj7eBqt9aDAqo2rcCLRTYlvQ62Gu/n+tOmJMBHGjzeijjuCENjzTyYBgrtLUw==",
"dev": true,
"requires": {
"@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@jridgewell/trace-mapping": "^0.3.18",
"@types/node": "*",
"chalk": "^4.0.0",
@@ -19343,13 +19530,13 @@
"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": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-worker": "^29.6.3",
"slash": "^3.0.0",
"string-length": "^4.0.1",
"strip-ansi": "^6.0.0",
@@ -19397,13 +19584,13 @@
"dev": true
},
"jest-worker": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
- "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz",
+ "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==",
"dev": true,
"requires": {
"@types/node": "*",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@@ -19431,18 +19618,18 @@
}
},
"@jest/schemas": {
- "version": "29.6.0",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
- "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
+ "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,
"requires": {
"@sinclair/typebox": "^0.27.8"
}
},
"@jest/source-map": {
- "version": "29.6.0",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz",
- "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==",
+ "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,
"requires": {
"@jridgewell/trace-mapping": "^0.3.18",
@@ -19451,46 +19638,46 @@
}
},
"@jest/test-result": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz",
- "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.3.tgz",
+ "integrity": "sha512-k7ZZaNvOSMBHPZYiy0kuiaFoyansR5QnTwDux1EjK3kD5iWpRVyJIJ0RAIV39SThafchuW59vra7F8mdy5Hfgw==",
"dev": true,
"requires": {
- "@jest/console": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/istanbul-lib-coverage": "^2.0.0",
"collect-v8-coverage": "^1.0.0"
}
},
"@jest/test-sequencer": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz",
- "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.3.tgz",
+ "integrity": "sha512-/SmijaAU2TY9ComFGIYa6Z+fmKqQMnqs2Nmwb0P/Z/tROdZ7M0iruES1EaaU9PBf8o9uED5xzaJ3YPFEIcDgAg==",
"dev": true,
"requires": {
- "@jest/test-result": "^29.6.1",
+ "@jest/test-result": "^29.6.3",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
"slash": "^3.0.0"
}
},
"@jest/transform": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz",
- "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.3.tgz",
+ "integrity": "sha512-dPIc3DsvMZ/S8ut4L2ViCj265mKO0owB0wfzBv2oGzL9pQ+iRvJewHqLBmsGb7XFb5UotWIEtvY5A/lnylaIoQ==",
"dev": true,
"requires": {
"@babel/core": "^7.11.6",
- "@jest/types": "^29.6.1",
+ "@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.6.1",
- "jest-regex-util": "^29.4.3",
- "jest-util": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.6.3",
"micromatch": "^4.0.4",
"pirates": "^4.0.4",
"slash": "^3.0.0",
@@ -19555,12 +19742,12 @@
}
},
"@jest/types": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz",
- "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
"dev": true,
"requires": {
- "@jest/schemas": "^29.6.0",
+ "@jest/schemas": "^29.6.3",
"@types/istanbul-lib-coverage": "^2.0.0",
"@types/istanbul-reports": "^3.0.0",
"@types/node": "*",
@@ -19673,12 +19860,6 @@
"resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz",
"integrity": "sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q=="
},
- "@nicolo-ribaudo/semver-v6": {
- "version": "6.3.3",
- "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
- "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
- "dev": true
- },
"@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -19921,12 +20102,6 @@
"@types/node": "*"
}
},
- "@types/prettier": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
- "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==",
- "dev": true
- },
"@types/responselike": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
@@ -20553,6 +20728,16 @@
"sprintf-js": "~1.0.2"
}
},
+ "array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ }
+ },
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -20571,6 +20756,19 @@
"is-string": "^1.0.7"
}
},
+ "array.prototype.findlastindex": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz",
+ "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.1.3"
+ }
+ },
"array.prototype.flat": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
@@ -20595,6 +20793,20 @@
"es-shim-unscopables": "^1.0.0"
}
},
+ "arraybuffer.prototype.slice": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz",
+ "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==",
+ "dev": true,
+ "requires": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "get-intrinsic": "^1.2.1",
+ "is-array-buffer": "^3.0.2",
+ "is-shared-array-buffer": "^1.0.2"
+ }
+ },
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -20684,13 +20896,13 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"autoprefixer": {
- "version": "10.4.14",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
- "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
+ "version": "10.4.15",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz",
+ "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==",
"dev": true,
"requires": {
- "browserslist": "^4.21.5",
- "caniuse-lite": "^1.0.30001464",
+ "browserslist": "^4.21.10",
+ "caniuse-lite": "^1.0.30001520",
"fraction.js": "^4.2.0",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
@@ -20713,15 +20925,15 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"babel-jest": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz",
- "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.3.tgz",
+ "integrity": "sha512-1Ne93zZZEy5XmTa4Q+W5+zxBrDpExX8E3iy+xJJ+24ewlfo/T3qHfQJCzi/MMVFmBQDNxtRR/Gfd2dwb/0yrQw==",
"dev": true,
"requires": {
- "@jest/transform": "^29.6.1",
+ "@jest/transform": "^29.6.3",
"@types/babel__core": "^7.1.14",
"babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^29.5.0",
+ "babel-preset-jest": "^29.6.3",
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
"slash": "^3.0.0"
@@ -20799,12 +21011,27 @@
"@istanbuljs/schema": "^0.1.2",
"istanbul-lib-instrument": "^5.0.4",
"test-exclude": "^6.0.0"
+ },
+ "dependencies": {
+ "istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "requires": {
+ "@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"
+ }
+ }
}
},
"babel-plugin-jest-hoist": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz",
- "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
"dev": true,
"requires": {
"@babel/template": "^7.3.3",
@@ -20824,19 +21051,19 @@
}
},
"babel-plugin-polyfill-corejs3": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz",
- "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==",
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz",
+ "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==",
"dev": true,
"requires": {
- "@babel/helper-define-polyfill-provider": "^0.4.1",
+ "@babel/helper-define-polyfill-provider": "^0.4.2",
"core-js-compat": "^3.31.0"
},
"dependencies": {
"@babel/helper-define-polyfill-provider": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz",
- "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==",
+ "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==",
"dev": true,
"requires": {
"@babel/helper-compilation-targets": "^7.22.6",
@@ -20893,12 +21120,12 @@
}
},
"babel-preset-jest": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz",
- "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
"dev": true,
"requires": {
- "babel-plugin-jest-hoist": "^29.5.0",
+ "babel-plugin-jest-hoist": "^29.6.3",
"babel-preset-current-node-syntax": "^1.0.0"
}
},
@@ -21120,13 +21347,13 @@
}
},
"browserslist": {
- "version": "4.21.9",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
- "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
+ "version": "4.21.10",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
+ "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
"requires": {
- "caniuse-lite": "^1.0.30001503",
- "electron-to-chromium": "^1.4.431",
- "node-releases": "^2.0.12",
+ "caniuse-lite": "^1.0.30001517",
+ "electron-to-chromium": "^1.4.477",
+ "node-releases": "^2.0.13",
"update-browserslist-db": "^1.0.11"
}
},
@@ -21317,9 +21544,9 @@
}
},
"caniuse-lite": {
- "version": "1.0.30001512",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
- "integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw=="
+ "version": "1.0.30001520",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz",
+ "integrity": "sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA=="
},
"caseless": {
"version": "0.12.0",
@@ -21356,9 +21583,9 @@
"dev": true
},
"chart.js": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.2.tgz",
- "integrity": "sha512-pvQNyFOY1QmbmIr8oDORL16/FFivfxj8V26VFpFilMo4cNvkV5WXLJetDio365pd9gKUHGdirUTbqJfw8tr+Dg==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz",
+ "integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==",
"requires": {
"@kurkle/color": "^0.3.0"
}
@@ -21653,9 +21880,9 @@
}
},
"core-js": {
- "version": "3.31.1",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.1.tgz",
- "integrity": "sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ=="
+ "version": "3.32.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.1.tgz",
+ "integrity": "sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ=="
},
"core-js-compat": {
"version": "3.31.0",
@@ -22109,10 +22336,11 @@
}
},
"dedent": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
- "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
- "dev": true
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
+ "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==",
+ "dev": true,
+ "requires": {}
},
"deep-eql": {
"version": "3.0.1",
@@ -22148,9 +22376,9 @@
}
},
"define-properties": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
- "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
"requires": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
@@ -22197,9 +22425,9 @@
"dev": true
},
"diff-sequences": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
- "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
"dev": true
},
"diffie-hellman": {
@@ -22313,9 +22541,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
"electron-to-chromium": {
- "version": "1.4.450",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz",
- "integrity": "sha512-BLG5HxSELlrMx7dJ2s+8SFlsCtJp37Zpk2VAxyC6CZtbc+9AJeZHfYHbrlSgdXp6saQ8StMqOTEDaBKgA7u1sw=="
+ "version": "1.4.490",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz",
+ "integrity": "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A=="
},
"elliptic": {
"version": "6.5.4",
@@ -22431,18 +22659,19 @@
}
},
"es-abstract": {
- "version": "1.21.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz",
- "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==",
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz",
+ "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==",
"dev": true,
"requires": {
+ "array-buffer-byte-length": "^1.0.0",
+ "arraybuffer.prototype.slice": "^1.0.1",
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-set-tostringtag": "^2.0.1",
"es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
"function.prototype.name": "^1.1.5",
- "get-intrinsic": "^1.1.3",
+ "get-intrinsic": "^1.2.1",
"get-symbol-description": "^1.0.0",
"globalthis": "^1.0.3",
"gopd": "^1.0.1",
@@ -22450,8 +22679,8 @@
"has-property-descriptors": "^1.0.0",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
- "internal-slot": "^1.0.4",
- "is-array-buffer": "^3.0.1",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
"is-callable": "^1.2.7",
"is-negative-zero": "^2.0.2",
"is-regex": "^1.1.4",
@@ -22459,16 +22688,21 @@
"is-string": "^1.0.7",
"is-typed-array": "^1.1.10",
"is-weakref": "^1.0.2",
- "object-inspect": "^1.12.2",
+ "object-inspect": "^1.12.3",
"object-keys": "^1.1.1",
"object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.4.3",
+ "regexp.prototype.flags": "^1.5.0",
+ "safe-array-concat": "^1.0.0",
"safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
"string.prototype.trimend": "^1.0.6",
"string.prototype.trimstart": "^1.0.6",
+ "typed-array-buffer": "^1.0.0",
+ "typed-array-byte-length": "^1.0.0",
+ "typed-array-byte-offset": "^1.0.0",
"typed-array-length": "^1.0.4",
"unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.9"
+ "which-typed-array": "^1.1.10"
}
},
"es-module-lexer": {
@@ -22623,27 +22857,27 @@
}
},
"eslint": {
- "version": "8.45.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz",
- "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==",
+ "version": "8.47.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz",
+ "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==",
"dev": true,
"requires": {
"@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.4.0",
- "@eslint/eslintrc": "^2.1.0",
- "@eslint/js": "8.44.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.2",
+ "@eslint/js": "^8.47.0",
"@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
- "ajv": "^6.10.0",
+ "ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.3.2",
"doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.0",
- "eslint-visitor-keys": "^3.4.1",
- "espree": "^9.6.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -22714,9 +22948,9 @@
"dev": true
},
"eslint-scope": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
- "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
"dev": true,
"requires": {
"esrecurse": "^4.3.0",
@@ -22834,9 +23068,9 @@
}
},
"eslint-module-utils": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
- "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
+ "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
"dev": true,
"requires": {
"debug": "^3.2.7"
@@ -22865,26 +23099,28 @@
}
},
"eslint-plugin-import": {
- "version": "2.27.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
- "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
+ "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==",
"dev": true,
"requires": {
"array-includes": "^3.1.6",
+ "array.prototype.findlastindex": "^1.2.2",
"array.prototype.flat": "^1.3.1",
"array.prototype.flatmap": "^1.3.1",
"debug": "^3.2.7",
"doctrine": "^2.1.0",
"eslint-import-resolver-node": "^0.3.7",
- "eslint-module-utils": "^2.7.4",
+ "eslint-module-utils": "^2.8.0",
"has": "^1.0.3",
- "is-core-module": "^2.11.0",
+ "is-core-module": "^2.13.0",
"is-glob": "^4.0.3",
"minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.6",
+ "object.groupby": "^1.0.0",
"object.values": "^1.1.6",
- "resolve": "^1.22.1",
- "semver": "^6.3.0",
- "tsconfig-paths": "^3.14.1"
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.14.2"
},
"dependencies": {
"debug": {
@@ -23014,15 +23250,15 @@
}
},
"eslint-visitor-keys": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
- "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true
},
"espree": {
- "version": "9.6.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
- "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
"dev": true,
"requires": {
"acorn": "^8.9.0",
@@ -23625,17 +23861,16 @@
"dev": true
},
"expect": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz",
- "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.3.tgz",
+ "integrity": "sha512-x1vY4LlEMWUYVZQrFi4ZANXFwqYbJ/JNQspLVvzhW2BNY28aNcXMQH6imBbt+RBf5sVRTodYHXtSP/TLEU0Dxw==",
"dev": true,
"requires": {
- "@jest/expect-utils": "^29.6.1",
- "@types/node": "*",
- "jest-get-type": "^29.4.3",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1"
+ "@jest/expect-utils": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3"
}
},
"express": {
@@ -24069,12 +24304,13 @@
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
},
"get-intrinsic": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
- "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
+ "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
+ "has-proto": "^1.0.1",
"has-symbols": "^1.0.3"
}
},
@@ -24271,8 +24507,7 @@
"has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "dev": true
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
},
"has-symbols": {
"version": "1.0.3",
@@ -24523,12 +24758,12 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"internal-slot": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz",
- "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
"dev": true,
"requires": {
- "get-intrinsic": "^1.1.3",
+ "get-intrinsic": "^1.2.0",
"has": "^1.0.3",
"side-channel": "^1.0.4"
}
@@ -24554,13 +24789,13 @@
}
},
"is-array-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz",
- "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
+ "get-intrinsic": "^1.2.0",
"is-typed-array": "^1.1.10"
}
},
@@ -24604,9 +24839,9 @@
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="
},
"is-core-module": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
- "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
+ "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
"requires": {
"has": "^1.0.3"
}
@@ -24819,26 +25054,37 @@
"dev": true
},
"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.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz",
+ "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==",
"dev": true,
"requires": {
"@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"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
}
},
"istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
"requires": {
"istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^3.0.0",
+ "make-dir": "^4.0.0",
"supports-color": "^7.1.0"
},
"dependencies": {
@@ -24871,9 +25117,9 @@
}
},
"istanbul-reports": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
- "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz",
+ "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==",
"dev": true,
"requires": {
"html-escaper": "^2.0.0",
@@ -24881,50 +25127,51 @@
}
},
"jest": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz",
- "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.3.tgz",
+ "integrity": "sha512-alueLuoPCDNHFcFGmgETR4KpQ+0ff3qVaiJwxQM4B5sC0CvXcgg4PEi7xrDkxuItDmdz/FVc7SSit4KEu8GRvw==",
"dev": true,
"requires": {
- "@jest/core": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/core": "^29.6.3",
+ "@jest/types": "^29.6.3",
"import-local": "^3.0.2",
- "jest-cli": "^29.6.1"
+ "jest-cli": "^29.6.3"
}
},
"jest-changed-files": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz",
- "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz",
+ "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==",
"dev": true,
"requires": {
"execa": "^5.0.0",
+ "jest-util": "^29.6.3",
"p-limit": "^3.1.0"
}
},
"jest-circus": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz",
- "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.3.tgz",
+ "integrity": "sha512-p0R5YqZEMnOpHqHLWRSjm2z/0p6RNsrNE/GRRT3eli8QGOAozj6Ys/3Tv+Ej+IfltJoSPwcQ6/hOCRkNlxLLCw==",
"dev": true,
"requires": {
- "@jest/environment": "^29.6.1",
- "@jest/expect": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/environment": "^29.6.3",
+ "@jest/expect": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@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": "^29.6.1",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-each": "^29.6.3",
+ "jest-matcher-utils": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-runtime": "^29.6.3",
+ "jest-snapshot": "^29.6.3",
+ "jest-util": "^29.6.3",
"p-limit": "^3.1.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"pure-rand": "^6.0.0",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
@@ -24982,21 +25229,21 @@
}
},
"jest-cli": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz",
- "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.3.tgz",
+ "integrity": "sha512-KuPdXUPXQIf0t6DvmG8MV4QyhcjR1a6ruKl3YL7aGn/AQ8JkROwFkWzEpDIpt11Qy188dHbRm8WjwMsV/4nmnQ==",
"dev": true,
"requires": {
- "@jest/core": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/core": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/types": "^29.6.3",
"chalk": "^4.0.0",
"exit": "^0.1.2",
"graceful-fs": "^4.2.9",
"import-local": "^3.0.2",
- "jest-config": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-config": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
"prompts": "^2.0.1",
"yargs": "^17.3.1"
},
@@ -25053,31 +25300,31 @@
}
},
"jest-config": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz",
- "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.3.tgz",
+ "integrity": "sha512-nb9bOq2aEqogbyL4F9mLkAeQGAgNt7Uz6U59YtQDIxFPiL7Ejgq0YIrp78oyEHD6H4CIV/k7mFrK7eFDzUJ69w==",
"dev": true,
"requires": {
"@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.6.1",
- "@jest/types": "^29.6.1",
- "babel-jest": "^29.6.1",
+ "@jest/test-sequencer": "^29.6.3",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.6.3",
"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.6.1",
- "jest-environment-node": "^29.6.1",
- "jest-get-type": "^29.4.3",
- "jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-runner": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-circus": "^29.6.3",
+ "jest-environment-node": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-runner": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
"micromatch": "^4.0.4",
"parse-json": "^5.2.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"slash": "^3.0.0",
"strip-json-comments": "^3.1.1"
},
@@ -25134,15 +25381,15 @@
}
},
"jest-diff": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz",
- "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.3.tgz",
+ "integrity": "sha512-3sw+AdWnwH9sSNohMRKA7JiYUJSRr/WS6+sEFfBuhxU5V5GlEVKfvUn8JuMHE0wqKowemR1C2aHy8VtXbaV8dQ==",
"dev": true,
"requires": {
"chalk": "^4.0.0",
- "diff-sequences": "^29.4.3",
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.6.3"
},
"dependencies": {
"ansi-styles": {
@@ -25197,25 +25444,25 @@
}
},
"jest-docblock": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz",
- "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz",
+ "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==",
"dev": true,
"requires": {
"detect-newline": "^3.0.0"
}
},
"jest-each": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz",
- "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz",
+ "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==",
"dev": true,
"requires": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"chalk": "^4.0.0",
- "jest-get-type": "^29.4.3",
- "jest-util": "^29.6.1",
- "pretty-format": "^29.6.1"
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "pretty-format": "^29.6.3"
},
"dependencies": {
"ansi-styles": {
@@ -25270,57 +25517,57 @@
}
},
"jest-environment-jsdom": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.1.tgz",
- "integrity": "sha512-PoY+yLaHzVRhVEjcVKSfJ7wXmJW4UqPYNhR05h7u/TK0ouf6DmRNZFBL/Z00zgQMyWGMBXn69/FmOvhEJu8cIw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.3.tgz",
+ "integrity": "sha512-nMJz/i27Moit9bv8Z323/13Melj4FEQH93yRu7GnilvBmPBMH4EGEkEfBTJXYuubyzhMO7w/VHzljIDV+Q/SeQ==",
"dev": true,
"requires": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/environment": "^29.6.3",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/jsdom": "^20.0.0",
"@types/node": "*",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-mock": "^29.6.3",
+ "jest-util": "^29.6.3",
"jsdom": "^20.0.0"
}
},
"jest-environment-node": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz",
- "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.3.tgz",
+ "integrity": "sha512-PKl7upfPJXMYbWpD+60o4HP86KvFO2c9dZ+Zr6wUzsG5xcPx/65o3ArNgHW5M0RFvLYdW4/aieR4JSooD0a2ew==",
"dev": true,
"requires": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/environment": "^29.6.3",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-mock": "^29.6.1",
- "jest-util": "^29.6.1"
+ "jest-mock": "^29.6.3",
+ "jest-util": "^29.6.3"
}
},
"jest-get-type": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
- "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
"dev": true
},
"jest-haste-map": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz",
- "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.3.tgz",
+ "integrity": "sha512-GecR5YavfjkhOytEFHAeI6aWWG3f/cOKNB1YJvj/B76xAmeVjy4zJUYobGF030cRmKaO1FBw3V8CZZ6KVh9ZSw==",
"dev": true,
"requires": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@types/graceful-fs": "^4.1.3",
"@types/node": "*",
"anymatch": "^3.0.3",
"fb-watchman": "^2.0.0",
"fsevents": "^2.3.2",
"graceful-fs": "^4.2.9",
- "jest-regex-util": "^29.4.3",
- "jest-util": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-worker": "^29.6.3",
"micromatch": "^4.0.4",
"walker": "^1.0.8"
},
@@ -25332,13 +25579,13 @@
"dev": true
},
"jest-worker": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
- "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz",
+ "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==",
"dev": true,
"requires": {
"@types/node": "*",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
}
@@ -25355,25 +25602,25 @@
}
},
"jest-leak-detector": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz",
- "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz",
+ "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==",
"dev": true,
"requires": {
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.6.3"
}
},
"jest-matcher-utils": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz",
- "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.3.tgz",
+ "integrity": "sha512-6ZrMYINZdwduSt5Xu18/n49O1IgXdjsfG7NEZaQws9k69eTKWKcVbJBw/MZsjOZe2sSyJFmuzh8042XWwl54Zg==",
"dev": true,
"requires": {
"chalk": "^4.0.0",
- "jest-diff": "^29.6.1",
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.6.1"
+ "jest-diff": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.6.3"
},
"dependencies": {
"ansi-styles": {
@@ -25428,18 +25675,18 @@
}
},
"jest-message-util": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz",
- "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz",
+ "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
- "@jest/types": "^29.6.1",
+ "@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.6.1",
+ "pretty-format": "^29.6.3",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
},
@@ -25496,14 +25743,14 @@
}
},
"jest-mock": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz",
- "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz",
+ "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==",
"dev": true,
"requires": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-util": "^29.6.1"
+ "jest-util": "^29.6.3"
}
},
"jest-pnp-resolver": {
@@ -25514,23 +25761,23 @@
"requires": {}
},
"jest-regex-util": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz",
- "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==",
+ "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
},
"jest-resolve": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz",
- "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.3.tgz",
+ "integrity": "sha512-WMXwxhvzDeA/J+9jz1i8ZKGmbw/n+s988EiUvRI4egM+eTn31Hb5v10Re3slG3/qxntkBt2/6GkQVDGu6Bwyhw==",
"dev": true,
"requires": {
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
"jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.6.1",
- "jest-validate": "^29.6.1",
+ "jest-util": "^29.6.3",
+ "jest-validate": "^29.6.3",
"resolve": "^1.20.0",
"resolve.exports": "^2.0.0",
"slash": "^3.0.0"
@@ -25588,40 +25835,40 @@
}
},
"jest-resolve-dependencies": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz",
- "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.3.tgz",
+ "integrity": "sha512-iah5nhSPTwtUV7yzpTc9xGg8gP3Ch2VNsuFMsKoCkNCrQSbFtx5KRPemmPJ32AUhTSDqJXB6djPN6zAaUGV53g==",
"dev": true,
"requires": {
- "jest-regex-util": "^29.4.3",
- "jest-snapshot": "^29.6.1"
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.6.3"
}
},
"jest-runner": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz",
- "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.3.tgz",
+ "integrity": "sha512-E4zsMhQnjhirFPhDTJgoLMWUrVCDij/KGzWlbslDHGuO8Hl2pVUfOiygMzVZtZq+BzmlqwEr7LYmW+WFLlmX8w==",
"dev": true,
"requires": {
- "@jest/console": "^29.6.1",
- "@jest/environment": "^29.6.1",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/console": "^29.6.3",
+ "@jest/environment": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
"graceful-fs": "^4.2.9",
- "jest-docblock": "^29.4.3",
- "jest-environment-node": "^29.6.1",
- "jest-haste-map": "^29.6.1",
- "jest-leak-detector": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-resolve": "^29.6.1",
- "jest-runtime": "^29.6.1",
- "jest-util": "^29.6.1",
- "jest-watcher": "^29.6.1",
- "jest-worker": "^29.6.1",
+ "jest-docblock": "^29.6.3",
+ "jest-environment-node": "^29.6.3",
+ "jest-haste-map": "^29.6.3",
+ "jest-leak-detector": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-runtime": "^29.6.3",
+ "jest-util": "^29.6.3",
+ "jest-watcher": "^29.6.3",
+ "jest-worker": "^29.6.3",
"p-limit": "^3.1.0",
"source-map-support": "0.5.13"
},
@@ -25667,13 +25914,13 @@
"dev": true
},
"jest-worker": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
- "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.3.tgz",
+ "integrity": "sha512-wacANXecZ/GbQakpf2CClrqrlwsYYDSXFd4fIGdL+dXpM2GWoJ+6bhQ7vR3TKi3+gkSfBkjy1/khH/WrYS4Q6g==",
"dev": true,
"requires": {
"@types/node": "*",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@@ -25711,31 +25958,31 @@
}
},
"jest-runtime": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz",
- "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.6.1",
- "@jest/fake-timers": "^29.6.1",
- "@jest/globals": "^29.6.1",
- "@jest/source-map": "^29.6.0",
- "@jest/test-result": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.3.tgz",
+ "integrity": "sha512-VM0Z3a9xaqizGpEKwCOIhImkrINYzxgwk8oQAvrmAiXX8LNrJrRjyva30RkuRY0ETAotHLlUcd2moviCA1hgsQ==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^29.6.3",
+ "@jest/fake-timers": "^29.6.3",
+ "@jest/globals": "^29.6.3",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@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.6.1",
- "jest-message-util": "^29.6.1",
- "jest-mock": "^29.6.1",
- "jest-regex-util": "^29.4.3",
- "jest-resolve": "^29.6.1",
- "jest-snapshot": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-haste-map": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-mock": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.6.3",
+ "jest-snapshot": "^29.6.3",
+ "jest-util": "^29.6.3",
"slash": "^3.0.0",
"strip-bom": "^4.0.0"
},
@@ -25792,9 +26039,9 @@
}
},
"jest-snapshot": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz",
- "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.3.tgz",
+ "integrity": "sha512-66Iu7H1ojiveQMGFnKecHIZPPPBjZwfQEnF6wxqpxGf57sV3YSUtAb5/sTKM5TPa3OndyxZp1wxHFbmgVhc53w==",
"dev": true,
"requires": {
"@babel/core": "^7.11.6",
@@ -25802,21 +26049,20 @@
"@babel/plugin-syntax-jsx": "^7.7.2",
"@babel/plugin-syntax-typescript": "^7.7.2",
"@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.6.1",
- "@jest/transform": "^29.6.1",
- "@jest/types": "^29.6.1",
- "@types/prettier": "^2.1.5",
+ "@jest/expect-utils": "^29.6.3",
+ "@jest/transform": "^29.6.3",
+ "@jest/types": "^29.6.3",
"babel-preset-current-node-syntax": "^1.0.0",
"chalk": "^4.0.0",
- "expect": "^29.6.1",
+ "expect": "^29.6.3",
"graceful-fs": "^4.2.9",
- "jest-diff": "^29.6.1",
- "jest-get-type": "^29.4.3",
- "jest-matcher-utils": "^29.6.1",
- "jest-message-util": "^29.6.1",
- "jest-util": "^29.6.1",
+ "jest-diff": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.6.3",
+ "jest-message-util": "^29.6.3",
+ "jest-util": "^29.6.3",
"natural-compare": "^1.4.0",
- "pretty-format": "^29.6.1",
+ "pretty-format": "^29.6.3",
"semver": "^7.5.3"
},
"dependencies": {
@@ -25861,9 +26107,9 @@
"dev": true
},
"semver": {
- "version": "7.5.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
- "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
+ "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,
"requires": {
"lru-cache": "^6.0.0"
@@ -25881,12 +26127,12 @@
}
},
"jest-util": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz",
- "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz",
+ "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==",
"dev": true,
"requires": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
"ci-info": "^3.2.0",
@@ -25946,17 +26192,17 @@
}
},
"jest-validate": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz",
- "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz",
+ "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==",
"dev": true,
"requires": {
- "@jest/types": "^29.6.1",
+ "@jest/types": "^29.6.3",
"camelcase": "^6.2.0",
"chalk": "^4.0.0",
- "jest-get-type": "^29.4.3",
+ "jest-get-type": "^29.6.3",
"leven": "^3.1.0",
- "pretty-format": "^29.6.1"
+ "pretty-format": "^29.6.3"
},
"dependencies": {
"ansi-styles": {
@@ -26017,18 +26263,18 @@
}
},
"jest-watcher": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz",
- "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.3.tgz",
+ "integrity": "sha512-NgpFjZ2U2MKusjidbi4Oiu7tfs+nrgdIxIEVROvH1cFmOei9Uj25lwkMsakqLnH/s0nEcvxO1ck77FiRlcnpZg==",
"dev": true,
"requires": {
- "@jest/test-result": "^29.6.1",
- "@jest/types": "^29.6.1",
+ "@jest/test-result": "^29.6.3",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"ansi-escapes": "^4.2.1",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
- "jest-util": "^29.6.1",
+ "jest-util": "^29.6.3",
"string-length": "^4.0.1"
},
"dependencies": {
@@ -26657,17 +26903,28 @@
"integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU="
},
"luxon": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz",
- "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg=="
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.1.tgz",
+ "integrity": "sha512-2USspxOCXWGIKHwuQ9XElxPPYrDOJHDQ5DQ870CoD+CxJbBnRDIBCfhioUJJjct7BKOy80Ia8cVstIcIMb/0+Q=="
},
"make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
"requires": {
- "semver": "^6.0.0"
+ "semver": "^7.5.3"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
}
},
"makeerror": {
@@ -27099,9 +27356,9 @@
"dev": true
},
"node-releases": {
- "version": "2.0.12",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
- "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ=="
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
},
"normalize-path": {
"version": "3.0.0",
@@ -27206,6 +27463,29 @@
"object-keys": "^1.1.1"
}
},
+ "object.fromentries": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz",
+ "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "object.groupby": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz",
+ "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.21.2",
+ "get-intrinsic": "^1.2.1"
+ }
+ },
"object.values": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
@@ -27533,9 +27813,9 @@
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
},
"postcss": {
- "version": "8.4.26",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz",
- "integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==",
+ "version": "8.4.28",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
+ "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
"dev": true,
"requires": {
"nanoid": "^3.3.6",
@@ -27883,12 +28163,12 @@
"dev": true
},
"pretty-format": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
- "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz",
+ "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==",
"dev": true,
"requires": {
- "@jest/schemas": "^29.6.0",
+ "@jest/schemas": "^29.6.3",
"ansi-styles": "^5.0.0",
"react-is": "^18.0.0"
},
@@ -28291,23 +28571,23 @@
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"regenerator-transform": {
- "version": "0.15.1",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz",
- "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==",
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
+ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.8.4"
}
},
"regexp.prototype.flags": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
- "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
+ "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "functions-have-names": "^1.2.2"
+ "define-properties": "^1.2.0",
+ "functions-have-names": "^1.2.3"
}
},
"regexpp": {
@@ -28408,11 +28688,11 @@
"dev": true
},
"resolve": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "version": "1.22.3",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
+ "integrity": "sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==",
"requires": {
- "is-core-module": "^2.9.0",
+ "is-core-module": "^2.12.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
}
@@ -28512,6 +28792,26 @@
"resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz",
"integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA=="
},
+ "safe-array-concat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz",
+ "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ }
+ }
+ },
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -28542,9 +28842,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sass": {
- "version": "1.64.1",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz",
- "integrity": "sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==",
+ "version": "1.66.1",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.66.1.tgz",
+ "integrity": "sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -28972,6 +29272,17 @@
"strip-ansi": "^6.0.1"
}
},
+ "string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
"string.prototype.trimend": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
@@ -29161,9 +29472,9 @@
}
},
"sweetalert2": {
- "version": "11.7.20",
- "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.7.20.tgz",
- "integrity": "sha512-GdU1TkiLpGGC0mcPV8bKmS7G0MR7caxambPkEU8zyepRSNR9EaEvIjNhX5QNkL0VFVzHbI3l12NtuEklkJ0D4Q=="
+ "version": "11.7.27",
+ "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.7.27.tgz",
+ "integrity": "sha512-QbRXGQn1sb7HEhzA/K2xtWIwQHh/qkSbb1w6jYcTql2xy17876lTREEt1D4X6Q0x2wHtfUjKJ+Cb8IVkRoq7DQ=="
},
"symbol-tree": {
"version": "3.2.4",
@@ -29344,13 +29655,13 @@
}
},
"tsconfig-paths": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
- "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==",
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+ "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
"dev": true,
"requires": {
"@types/json5": "^0.0.29",
- "json5": "^1.0.1",
+ "json5": "^1.0.2",
"minimist": "^1.2.6",
"strip-bom": "^3.0.0"
},
@@ -29424,6 +29735,42 @@
"mime-types": "~2.1.24"
}
},
+ "typed-array-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
+ "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "typed-array-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+ "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "typed-array-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "dev": true,
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ }
+ },
"typed-array-length": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
@@ -30279,16 +30626,15 @@
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q=="
},
"which-typed-array": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
- "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
+ "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0",
- "is-typed-array": "^1.1.10"
+ "has-tostringtag": "^1.0.0"
}
},
"wildcard": {
diff --git a/apps/block_scout_web/assets/package.json b/apps/block_scout_web/assets/package.json
index 53436e8d65dc..030c75b07638 100644
--- a/apps/block_scout_web/assets/package.json
+++ b/apps/block_scout_web/assets/package.json
@@ -19,17 +19,17 @@
"eslint": "eslint js/**"
},
"dependencies": {
- "@fortawesome/fontawesome-free": "^6.4.0",
- "@amplitude/analytics-browser": "^2.1.2",
+ "@fortawesome/fontawesome-free": "^6.4.2",
+ "@amplitude/analytics-browser": "^2.2.0",
"@tarekraafat/autocomplete.js": "^10.2.7",
"@walletconnect/web3-provider": "^1.8.0",
"assert": "^2.0.0",
"bignumber.js": "^9.1.1",
"bootstrap": "^4.6.0",
- "chart.js": "^4.3.2",
+ "chart.js": "^4.3.3",
"chartjs-adapter-luxon": "^1.3.1",
"clipboard": "^2.0.11",
- "core-js": "^3.31.1",
+ "core-js": "^3.32.1",
"crypto-browserify": "^3.12.0",
"dropzone": "^5.9.3",
"eth-net-props": "^1.0.41",
@@ -56,7 +56,7 @@
"lodash.omit": "^4.5.0",
"lodash.rangeright": "^4.2.0",
"lodash.reduce": "^4.6.0",
- "luxon": "^3.3.0",
+ "luxon": "^3.4.1",
"malihu-custom-scrollbar-plugin": "3.1.5",
"mixpanel-browser": "^2.47.0",
"moment": "^2.29.4",
@@ -73,7 +73,7 @@
"redux": "^4.2.1",
"stream-browserify": "^3.0.0",
"stream-http": "^3.1.1",
- "sweetalert2": "^11.7.20",
+ "sweetalert2": "^11.7.27",
"urijs": "^1.19.11",
"url": "^0.11.1",
"util": "^0.12.5",
@@ -83,25 +83,25 @@
"xss": "^1.0.14"
},
"devDependencies": {
- "@babel/core": "^7.22.9",
- "@babel/preset-env": "^7.22.9",
- "autoprefixer": "^10.4.14",
+ "@babel/core": "^7.22.10",
+ "@babel/preset-env": "^7.22.10",
+ "autoprefixer": "^10.4.15",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^5.2.7",
"css-minimizer-webpack-plugin": "^5.0.1",
- "eslint": "^8.45.0",
+ "eslint": "^8.47.0",
"eslint-config-standard": "^17.1.0",
- "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-import": "^2.28.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"file-loader": "^6.2.0",
- "jest": "^29.6.1",
- "jest-environment-jsdom": "^29.6.1",
+ "jest": "^29.6.3",
+ "jest-environment-jsdom": "^29.6.3",
"mini-css-extract-plugin": "^2.7.6",
- "postcss": "^8.4.26",
+ "postcss": "^8.4.28",
"postcss-loader": "^7.3.3",
- "sass": "^1.64.1",
+ "sass": "^1.66.1",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"webpack": "^5.88.2",
diff --git a/apps/block_scout_web/lib/block_scout_web/api_router.ex b/apps/block_scout_web/lib/block_scout_web/api_router.ex
index 12245a9d9bd5..c422faed4620 100644
--- a/apps/block_scout_web/lib/block_scout_web/api_router.ex
+++ b/apps/block_scout_web/lib/block_scout_web/api_router.ex
@@ -13,7 +13,7 @@ defmodule BlockScoutWeb.ApiRouter do
Router for API
"""
use BlockScoutWeb, :router
- alias BlockScoutWeb.{APIKeyV2Router, SmartContractsApiV2Router}
+ alias BlockScoutWeb.{AddressTransactionController, APIKeyV2Router, SmartContractsApiV2Router}
alias BlockScoutWeb.Plug.{CheckAccountAPI, CheckApiV2, RateLimit}
forward("/v2/smart-contracts", SmartContractsApiV2Router)
@@ -124,6 +124,7 @@ defmodule BlockScoutWeb.ApiRouter do
scope "/search" do
get("/", V2.SearchController, :search)
get("/check-redirect", V2.SearchController, :check_redirect)
+ get("/quick", V2.SearchController, :quick_search)
end
scope "/config" do
@@ -134,12 +135,12 @@ defmodule BlockScoutWeb.ApiRouter do
scope "/transactions" do
get("/", V2.TransactionController, :transactions)
get("/watchlist", V2.TransactionController, :watchlist_transactions)
- get("/:transaction_hash", V2.TransactionController, :transaction)
- get("/:transaction_hash/token-transfers", V2.TransactionController, :token_transfers)
- get("/:transaction_hash/internal-transactions", V2.TransactionController, :internal_transactions)
- get("/:transaction_hash/logs", V2.TransactionController, :logs)
- get("/:transaction_hash/raw-trace", V2.TransactionController, :raw_trace)
- get("/:transaction_hash/state-changes", V2.TransactionController, :state_changes)
+ get("/:transaction_hash_param", V2.TransactionController, :transaction)
+ get("/:transaction_hash_param/token-transfers", V2.TransactionController, :token_transfers)
+ get("/:transaction_hash_param/internal-transactions", V2.TransactionController, :internal_transactions)
+ get("/:transaction_hash_param/logs", V2.TransactionController, :logs)
+ get("/:transaction_hash_param/raw-trace", V2.TransactionController, :raw_trace)
+ get("/:transaction_hash_param/state-changes", V2.TransactionController, :state_changes)
end
scope "/blocks" do
@@ -151,31 +152,32 @@ defmodule BlockScoutWeb.ApiRouter do
scope "/addresses" do
get("/", V2.AddressController, :addresses_list)
- get("/:address_hash", V2.AddressController, :address)
- get("/:address_hash/counters", V2.AddressController, :counters)
- get("/:address_hash/token-balances", V2.AddressController, :token_balances)
- get("/:address_hash/tokens", V2.AddressController, :tokens)
- get("/:address_hash/transactions", V2.AddressController, :transactions)
- get("/:address_hash/token-transfers", V2.AddressController, :token_transfers)
- get("/:address_hash/internal-transactions", V2.AddressController, :internal_transactions)
- get("/:address_hash/logs", V2.AddressController, :logs)
- get("/:address_hash/blocks-validated", V2.AddressController, :blocks_validated)
- get("/:address_hash/coin-balance-history", V2.AddressController, :coin_balance_history)
- get("/:address_hash/coin-balance-history-by-day", V2.AddressController, :coin_balance_history_by_day)
- get("/:address_hash/withdrawals", V2.AddressController, :withdrawals)
+ get("/:address_hash_param", V2.AddressController, :address)
+ get("/:address_hash_param/tabs-counters", V2.AddressController, :tabs_counters)
+ get("/:address_hash_param/counters", V2.AddressController, :counters)
+ get("/:address_hash_param/token-balances", V2.AddressController, :token_balances)
+ get("/:address_hash_param/tokens", V2.AddressController, :tokens)
+ get("/:address_hash_param/transactions", V2.AddressController, :transactions)
+ get("/:address_hash_param/token-transfers", V2.AddressController, :token_transfers)
+ get("/:address_hash_param/internal-transactions", V2.AddressController, :internal_transactions)
+ get("/:address_hash_param/logs", V2.AddressController, :logs)
+ get("/:address_hash_param/blocks-validated", V2.AddressController, :blocks_validated)
+ get("/:address_hash_param/coin-balance-history", V2.AddressController, :coin_balance_history)
+ get("/:address_hash_param/coin-balance-history-by-day", V2.AddressController, :coin_balance_history_by_day)
+ get("/:address_hash_param/withdrawals", V2.AddressController, :withdrawals)
end
scope "/tokens" do
get("/", V2.TokenController, :tokens_list)
- get("/:address_hash", V2.TokenController, :token)
- get("/:address_hash/counters", V2.TokenController, :counters)
- get("/:address_hash/transfers", V2.TokenController, :transfers)
- get("/:address_hash/holders", V2.TokenController, :holders)
- get("/:address_hash/instances", V2.TokenController, :instances)
- get("/:address_hash/instances/:token_id", V2.TokenController, :instance)
- get("/:address_hash/instances/:token_id/transfers", V2.TokenController, :transfers_by_instance)
- get("/:address_hash/instances/:token_id/holders", V2.TokenController, :holders_by_instance)
- get("/:address_hash/instances/:token_id/transfers-count", V2.TokenController, :transfers_count_by_instance)
+ get("/:address_hash_param", V2.TokenController, :token)
+ get("/:address_hash_param/counters", V2.TokenController, :counters)
+ get("/:address_hash_param/transfers", V2.TokenController, :transfers)
+ get("/:address_hash_param/holders", V2.TokenController, :holders)
+ get("/:address_hash_param/instances", V2.TokenController, :instances)
+ get("/:address_hash_param/instances/:token_id", V2.TokenController, :instance)
+ get("/:address_hash_param/instances/:token_id/transfers", V2.TokenController, :transfers_by_instance)
+ get("/:address_hash_param/instances/:token_id/holders", V2.TokenController, :holders_by_instance)
+ get("/:address_hash_param/instances/:token_id/transfers-count", V2.TokenController, :transfers_count_by_instance)
end
scope "/main-page" do
@@ -209,6 +211,22 @@ defmodule BlockScoutWeb.ApiRouter do
# leave the same endpoint in v1 in order to keep backward compatibility
get("/search", SearchController, :search)
+ @max_complexity 200
+
+ forward("/graphql", Absinthe.Plug,
+ schema: BlockScoutWeb.Schema,
+ analyze_complexity: true,
+ max_complexity: @max_complexity
+ )
+
+ get("/transactions-csv", AddressTransactionController, :transactions_csv)
+
+ get("/token-transfers-csv", AddressTransactionController, :token_transfers_csv)
+
+ get("/internal-transactions-csv", AddressTransactionController, :internal_transactions_csv)
+
+ get("/logs-csv", AddressTransactionController, :logs_csv)
+
scope "/health" do
get("/", HealthController, :health)
get("/liveness", HealthController, :liveness)
diff --git a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
index ba808cc16f2b..35a5ea606c07 100644
--- a/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
+++ b/apps/block_scout_web/lib/block_scout_web/channels/address_channel.ex
@@ -28,11 +28,13 @@ defmodule BlockScoutWeb.AddressChannel do
"transaction",
"verification_result",
"token_transfer",
- "pending_transaction"
+ "pending_transaction",
+ "address_current_token_balances"
])
{:ok, burn_address_hash} = Chain.string_to_address_hash("0x0000000000000000000000000000000000000000")
@burn_address_hash burn_address_hash
+ @current_token_balances_limit 50
def join("addresses:" <> address_hash, _params, socket) do
{:ok, %{}, assign(socket, :address_hash, address_hash)}
@@ -225,6 +227,34 @@ defmodule BlockScoutWeb.AddressChannel do
def handle_out("pending_transaction", data, socket), do: handle_transaction(data, socket, "transaction")
+ def handle_out(
+ "address_current_token_balances",
+ %{address_current_token_balances: address_current_token_balances},
+ %Phoenix.Socket{handler: BlockScoutWeb.UserSocketV2} = socket
+ ) do
+ push_current_token_balances(socket, address_current_token_balances, "erc_20", "ERC-20")
+ push_current_token_balances(socket, address_current_token_balances, "erc_721", "ERC-721")
+ push_current_token_balances(socket, address_current_token_balances, "erc_1155", "ERC-1155")
+
+ {:noreply, socket}
+ end
+
+ def handle_out("address_current_token_balances", _, socket) do
+ {:noreply, socket}
+ end
+
+ defp push_current_token_balances(socket, address_current_token_balances, event_postfix, token_type) do
+ filtered_ctbs = address_current_token_balances |> Enum.filter(fn ctb -> ctb.token_type == token_type end)
+
+ push(socket, "updated_token_balances_" <> event_postfix, %{
+ token_balances:
+ AddressViewAPI.render("token_balances.json", %{
+ token_balances: Enum.take(filtered_ctbs, @current_token_balances_limit)
+ }),
+ overflow: Enum.count(filtered_ctbs) > @current_token_balances_limit
+ })
+ end
+
def push_current_coin_balance(
%Phoenix.Socket{handler: BlockScoutWeb.UserSocketV2} = socket,
block_number,
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
index 9e37382e12a7..c352cb8e783b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
@@ -15,6 +15,7 @@ defmodule BlockScoutWeb.AddressController do
}
alias Explorer.{Chain, Market}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.Wei
alias Indexer.Fetcher.CoinBalanceOnDemand
alias Phoenix.View
@@ -82,7 +83,7 @@ defmodule BlockScoutWeb.AddressController do
render(conn, "index.html",
current_path: Controller.current_full_path(conn),
- address_count: Chain.address_estimated_count(),
+ address_count: Counters.address_estimated_count(),
total_supply: total_supply
)
end
@@ -146,7 +147,7 @@ defmodule BlockScoutWeb.AddressController do
def address_counters(conn, %{"id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
- {validation_count} = Chain.address_counters(address)
+ {validation_count} = Counters.address_counters(address)
transactions_from_db = address.transactions_count || 0
token_transfers_from_db = address.token_transfers_count || 0
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex
index 2013c7bcaad5..5899458fd887 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_token_balance_controller.ex
@@ -9,12 +9,8 @@ defmodule BlockScoutWeb.AddressTokenBalanceController do
def index(conn, %{"address_id" => address_hash_string} = params) do
with true <- ajax?(conn),
{:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string) do
- token_balances =
- address_hash
- |> Chain.fetch_last_token_balances()
-
Task.start_link(fn ->
- TokenBalanceOnDemand.trigger_fetch(address_hash, token_balances)
+ TokenBalanceOnDemand.trigger_fetch(address_hash)
end)
case AccessHelper.restricted_access?(address_hash_string, params) do
@@ -24,7 +20,7 @@ defmodule BlockScoutWeb.AddressTokenBalanceController do
|> put_layout(false)
|> render("_token_balances.html",
address_hash: Address.checksum(address_hash),
- token_balances: token_balances,
+ token_balances: Chain.fetch_last_token_balances(address_hash),
conn: conn
)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex
index 53a5ec3add25..b27554eed39b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/rpc_translator.ex
@@ -29,7 +29,7 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
end
def call(%Conn{params: %{"module" => module, "action" => action}} = conn, translations) do
- with true <- valid_api_request_path(conn),
+ with {:valid_api_request, true} <- {:valid_api_request, valid_api_request_path(conn)},
{:ok, {controller, write_actions}} <- translate_module(translations, module),
{:ok, action} <- translate_action(action),
true <- action_accessed?(action, write_actions),
@@ -58,6 +58,13 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
:rate_limit_reached ->
AccessHelper.handle_rate_limit_deny(conn)
+ {:valid_api_request, false} ->
+ conn
+ |> put_status(404)
+ |> put_view(RPCView)
+ |> Controller.render(:error, error: "Not found")
+ |> halt()
+
_ ->
conn
|> put_status(500)
@@ -119,7 +126,8 @@ defmodule BlockScoutWeb.API.RPC.RPCTranslator do
end
defp valid_api_request_path(conn) do
- if conn.request_path == "/api" || conn.request_path == "/api/v1" do
+ if conn.request_path == "/api" || conn.request_path == "/api/" || conn.request_path == "/api/v1" ||
+ conn.request_path == "/api/v1/" do
true
else
false
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/address_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/address_controller.ex
index c8062039c870..160fd28cf60d 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/address_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/address_controller.ex
@@ -17,6 +17,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
alias BlockScoutWeb.AccessHelper
alias BlockScoutWeb.API.V2.{BlockView, TransactionView, WithdrawalView}
alias Explorer.{Chain, Market}
+ alias Explorer.Chain.Address.Counters
alias Indexer.Fetcher.{CoinBalanceOnDemand, TokenBalanceOnDemand}
@transaction_necessity_by_association [
@@ -57,7 +58,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
action_fallback(BlockScoutWeb.API.V2.FallbackController)
- def address(conn, %{"address_hash" => address_hash_string} = params) do
+ def address(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, address}} <- {:not_found, Chain.hash_to_address(address_hash, @address_options)} do
@@ -69,11 +70,11 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def counters(conn, %{"address_hash" => address_hash_string} = params) do
+ def counters(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
- {validation_count} = Chain.address_counters(address, @api_true)
+ {validation_count} = Counters.address_counters(address, @api_true)
transactions_from_db = address.transactions_count || 0
token_transfers_from_db = address.token_transfers_count || 0
@@ -88,7 +89,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def token_balances(conn, %{"address_hash" => address_hash_string} = params) do
+ def token_balances(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -97,7 +98,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
|> Chain.fetch_last_token_balances(@api_true)
Task.start_link(fn ->
- TokenBalanceOnDemand.trigger_fetch(address_hash, token_balances)
+ TokenBalanceOnDemand.trigger_fetch(address_hash)
end)
conn
@@ -106,7 +107,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def transactions(conn, %{"address_hash" => address_hash_string} = params) do
+ def transactions(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -118,8 +119,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
results_plus_one = Chain.address_to_transactions_without_rewards(address_hash, options, false)
{transactions, next_page} = split_list_by_page(results_plus_one)
- next_page_params =
- next_page |> next_page_params(transactions, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(transactions, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -130,7 +130,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
def token_transfers(
conn,
- %{"address_hash" => address_hash_string, "token" => token_address_hash_string} = params
+ %{"address_hash_param" => address_hash_string, "token" => token_address_hash_string} = params
) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:format, {:ok, token_address_hash}} <- {:format, Chain.string_to_address_hash(token_address_hash_string)},
@@ -166,8 +166,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
next_page_params =
next_page
- |> token_transfers_next_page_params(token_transfers, params)
- |> delete_parameters_from_next_page_params()
+ |> token_transfers_next_page_params(token_transfers, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -176,7 +175,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def token_transfers(conn, %{"address_hash" => address_hash_string} = params) do
+ def token_transfers(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -198,8 +197,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
next_page_params =
next_page
- |> token_transfers_next_page_params(token_transfers, params)
- |> delete_parameters_from_next_page_params()
+ |> token_transfers_next_page_params(token_transfers, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -208,7 +206,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def internal_transactions(conn, %{"address_hash" => address_hash_string} = params) do
+ def internal_transactions(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -231,7 +229,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
{internal_transactions, next_page} = split_list_by_page(results_plus_one)
next_page_params =
- next_page |> next_page_params(internal_transactions, params) |> delete_parameters_from_next_page_params()
+ next_page |> next_page_params(internal_transactions, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -243,7 +241,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def logs(conn, %{"address_hash" => address_hash_string, "topic" => topic} = params) do
+ def logs(conn, %{"address_hash_param" => address_hash_string, "topic" => topic} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -257,7 +255,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
{logs, next_page} = split_list_by_page(results_plus_one)
- next_page_params = next_page |> next_page_params(logs, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(logs, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -266,7 +264,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def logs(conn, %{"address_hash" => address_hash_string} = params) do
+ def logs(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -276,7 +274,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
{logs, next_page} = split_list_by_page(results_plus_one)
- next_page_params = next_page |> next_page_params(logs, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(logs, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -285,7 +283,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def blocks_validated(conn, %{"address_hash" => address_hash_string} = params) do
+ def blocks_validated(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -304,7 +302,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
results_plus_one = Chain.get_blocks_validated_by_address(full_options, address_hash)
{blocks, next_page} = split_list_by_page(results_plus_one)
- next_page_params = next_page |> next_page_params(blocks, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(blocks, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -313,7 +311,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def coin_balance_history(conn, %{"address_hash" => address_hash_string} = params) do
+ def coin_balance_history(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -323,8 +321,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
{coin_balances, next_page} = split_list_by_page(results_plus_one)
- next_page_params =
- next_page |> next_page_params(coin_balances, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(coin_balances, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -332,7 +329,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def coin_balance_history_by_day(conn, %{"address_hash" => address_hash_string} = params) do
+ def coin_balance_history_by_day(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -346,7 +343,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def tokens(conn, %{"address_hash" => address_hash_string} = params) do
+ def tokens(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -354,20 +351,18 @@ defmodule BlockScoutWeb.API.V2.AddressController do
address_hash
|> Chain.fetch_paginated_last_token_balances(
params
- |> delete_parameters_from_next_page_params()
|> paging_options()
|> Keyword.merge(token_transfers_types_options(params))
|> Keyword.merge(@api_true)
)
Task.start_link(fn ->
- TokenBalanceOnDemand.trigger_fetch(address_hash, results_plus_one)
+ TokenBalanceOnDemand.trigger_fetch(address_hash)
end)
{tokens, next_page} = split_list_by_page(results_plus_one)
- next_page_params =
- next_page |> next_page_params(tokens, params, true) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(tokens, delete_parameters_from_next_page_params(params), true)
conn
|> put_status(200)
@@ -375,7 +370,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
end
end
- def withdrawals(conn, %{"address_hash" => address_hash_string} = params) do
+ def withdrawals(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
@@ -383,7 +378,7 @@ defmodule BlockScoutWeb.API.V2.AddressController do
withdrawals_plus_one = address_hash |> Chain.address_hash_to_withdrawals(options)
{withdrawals, next_page} = split_list_by_page(withdrawals_plus_one)
- next_page_params = next_page |> next_page_params(withdrawals, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(withdrawals, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -414,4 +409,26 @@ defmodule BlockScoutWeb.API.V2.AddressController do
total_supply: total_supply
})
end
+
+ def tabs_counters(conn, %{"address_hash_param" => address_hash_string} = params) do
+ with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
+ {:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
+ {:not_found, {:ok, _address}} <- {:not_found, Chain.hash_to_address(address_hash, @api_true, false)} do
+ {validations, transactions, token_transfers, token_balances, logs, withdrawals, internal_txs, coin_balances} =
+ Counters.address_limited_counters(address_hash_string, @api_true)
+
+ conn
+ |> put_status(200)
+ |> json(%{
+ validations_count: validations,
+ transactions_count: transactions,
+ token_transfers_count: token_transfers,
+ token_balances_count: token_balances,
+ logs_count: logs,
+ withdrawals_count: withdrawals,
+ internal_txs_count: internal_txs,
+ coin_balances_count: coin_balances
+ })
+ end
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/block_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/block_controller.ex
index 865127d756a0..a680d7616d40 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/block_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/block_controller.ex
@@ -77,7 +77,7 @@ defmodule BlockScoutWeb.API.V2.BlockController do
{blocks, next_page} = split_list_by_page(blocks_plus_one)
- next_page_params = next_page |> next_page_params(blocks, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(blocks, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -98,8 +98,7 @@ defmodule BlockScoutWeb.API.V2.BlockController do
next_page_params =
next_page
- |> next_page_params(transactions, params)
- |> delete_parameters_from_next_page_params()
+ |> next_page_params(transactions, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -118,7 +117,7 @@ defmodule BlockScoutWeb.API.V2.BlockController do
withdrawals_plus_one = Chain.block_to_withdrawals(block.hash, full_options)
{withdrawals, next_page} = split_list_by_page(withdrawals_plus_one)
- next_page_params = next_page |> next_page_params(withdrawals, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(withdrawals, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/fallback_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/fallback_controller.ex
index 78ef0980d2c5..79cad2ebffed 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/fallback_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/fallback_controller.ex
@@ -1,134 +1,235 @@
defmodule BlockScoutWeb.API.V2.FallbackController do
use Phoenix.Controller
+ require Logger
+
alias BlockScoutWeb.API.V2.ApiView
- def call(conn, {:format, _}) do
+ @verification_failed "API v2 smart-contract verification failed"
+ @invalid_parameters "Invalid parameter(s)"
+ @invalid_address_hash "Invalid address hash"
+ @invalid_hash "Invalid hash"
+ @invalid_number "Invalid number"
+ @invalid_url "Invalid URL"
+ @not_found "Not found"
+ @contract_interaction_disabled "Contract interaction disabled"
+ @restricted_access "Restricted access"
+ @already_verified "Already verified"
+ @json_not_found "JSON files not found"
+ @error_while_reading_json "Error while reading JSON file"
+ @error_in_libraries "Libraries are not valid JSON map"
+ @block_lost_consensus "Block lost consensus"
+ @invalid_captcha_resp "Invalid reCAPTCHA response"
+ @unauthorized "Unauthorized"
+ @not_configured_api_key "API key not configured on the server"
+ @wrong_api_key "Wrong API key"
+
+ def call(conn, {:format, _params}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@invalid_parameters}"]
+ end)
+
conn
|> put_status(:unprocessable_entity)
|> put_view(ApiView)
- |> render(:message, %{message: "Invalid parameter(s)"})
+ |> render(:message, %{message: @invalid_parameters})
end
def call(conn, {:format_address, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@invalid_address_hash}"]
+ end)
+
conn
|> put_status(:unprocessable_entity)
|> put_view(ApiView)
- |> render(:message, %{message: "Invalid address hash"})
+ |> render(:message, %{message: @invalid_address_hash})
end
def call(conn, {:format_url, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@invalid_url}"]
+ end)
+
conn
|> put_status(:unprocessable_entity)
|> put_view(ApiView)
- |> render(:message, %{message: "Invalid URL"})
+ |> render(:message, %{message: @invalid_url})
end
def call(conn, {:not_found, _, :empty_items_with_next_page_params}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: :empty_items_with_next_page_params"]
+ end)
+
conn
|> json(%{"items" => [], "next_page_params" => nil})
end
def call(conn, {:not_found, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@not_found}"]
+ end)
+
conn
|> put_status(:not_found)
|> put_view(ApiView)
- |> render(:message, %{message: "Not found"})
+ |> render(:message, %{message: @not_found})
end
def call(conn, {:contract_interaction_disabled, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@contract_interaction_disabled}"]
+ end)
+
conn
|> put_status(:forbidden)
|> put_view(ApiView)
- |> render(:message, %{message: "Contract interaction disabled"})
+ |> render(:message, %{message: @contract_interaction_disabled})
end
def call(conn, {:error, {:invalid, :hash}}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@invalid_hash}"]
+ end)
+
conn
|> put_status(:unprocessable_entity)
|> put_view(ApiView)
- |> render(:message, %{message: "Invalid hash"})
+ |> render(:message, %{message: @invalid_hash})
end
def call(conn, {:error, {:invalid, :number}}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@invalid_number}"]
+ end)
+
conn
|> put_status(:unprocessable_entity)
|> put_view(ApiView)
- |> render(:message, %{message: "Invalid number"})
+ |> render(:message, %{message: @invalid_number})
end
def call(conn, {:error, :not_found}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: :not_found"]
+ end)
+
conn
|> call({:not_found, nil})
end
def call(conn, {:restricted_access, true}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@restricted_access}"]
+ end)
+
conn
|> put_status(:forbidden)
|> put_view(ApiView)
- |> render(:message, %{message: "Restricted access"})
+ |> render(:message, %{message: @restricted_access})
end
def call(conn, {:already_verified, true}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@already_verified}"]
+ end)
+
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Already verified"})
+ |> render(:message, %{message: @already_verified})
end
def call(conn, {:no_json_file, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@json_not_found}"]
+ end)
+
conn
|> put_view(ApiView)
- |> render(:message, %{message: "JSON files not found"})
+ |> render(:message, %{message: @json_not_found})
end
def call(conn, {:file_error, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@error_while_reading_json}"]
+ end)
+
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Error while reading JSON file"})
+ |> render(:message, %{message: @error_while_reading_json})
end
def call(conn, {:libs_format, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@error_in_libraries}"]
+ end)
+
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Libraries are not valid JSON map"})
+ |> render(:message, %{message: @error_in_libraries})
end
def call(conn, {:lost_consensus, {:ok, block}}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@block_lost_consensus}"]
+ end)
+
conn
|> put_status(:not_found)
- |> json(%{message: "Block lost consensus", hash: to_string(block.hash)})
+ |> json(%{message: @block_lost_consensus, hash: to_string(block.hash)})
end
def call(conn, {:lost_consensus, {:error, :not_found}}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@block_lost_consensus}"]
+ end)
+
conn
|> call({:not_found, nil})
end
def call(conn, {:recaptcha, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@invalid_captcha_resp}"]
+ end)
+
conn
|> put_status(:forbidden)
|> put_view(ApiView)
- |> render(:message, %{message: "Invalid reCAPTCHA response"})
+ |> render(:message, %{message: @invalid_captcha_resp})
end
def call(conn, {:auth, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@unauthorized}"]
+ end)
+
conn
|> put_status(:unauthorized)
|> put_view(ApiView)
- |> render(:message, %{message: "Unauthorized"})
+ |> render(:message, %{message: @unauthorized})
end
def call(conn, {:sensitive_endpoints_api_key, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@not_configured_api_key}"]
+ end)
+
conn
|> put_status(:forbidden)
|> put_view(ApiView)
- |> render(:message, %{message: "API key not configured on the server"})
+ |> render(:message, %{message: @not_configured_api_key})
end
def call(conn, {:api_key, _}) do
+ Logger.error(fn ->
+ ["#{@verification_failed}: #{@wrong_api_key}"]
+ end)
+
conn
|> put_status(:unauthorized)
|> put_view(ApiView)
- |> render(:message, %{message: "Wrong API key"})
+ |> render(:message, %{message: @wrong_api_key})
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/import_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/import_controller.ex
index 29175a1ad697..a89cbb323e74 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/import_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/import_controller.ex
@@ -18,7 +18,7 @@ defmodule BlockScoutWeb.API.V2.ImportController do
{:format_address, Chain.string_to_address_hash(token_address_hash_string)},
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)},
{:format_url, true} <- {:format_url, valid_url?(icon_url)} do
- case token |> Token.changeset(%{icon_url: icon_url}) |> Repo.update() do
+ case token |> Token.changeset(%{icon_url: icon_url, is_verified_via_admin_panel: true}) |> Repo.update() do
{:ok, _} ->
conn
|> put_view(ApiView)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/search_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/search_controller.ex
index e76b4408e2f0..abe0aca31486 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/search_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/search_controller.ex
@@ -3,7 +3,10 @@ defmodule BlockScoutWeb.API.V2.SearchController do
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1, from_param: 1]
- alias Explorer.Chain
+ alias Explorer.Chain.Search
+ alias Explorer.PagingOptions
+
+ @api_true [api?: true]
def search(conn, %{"q" => query} = params) do
[paging_options: paging_options] = paging_options(params)
@@ -11,7 +14,7 @@ defmodule BlockScoutWeb.API.V2.SearchController do
search_results_plus_one =
paging_options
- |> Chain.joint_search(offset, query, api?: true)
+ |> Search.joint_search(offset, query, @api_true)
{search_results, next_page} = split_list_by_page(search_results_plus_one)
@@ -32,4 +35,12 @@ defmodule BlockScoutWeb.API.V2.SearchController do
|> put_status(200)
|> render(:search_results, %{result: result})
end
+
+ def quick_search(conn, %{"q" => query}) do
+ search_results = Search.balanced_unpaginated_search(%PagingOptions{page_size: 50}, query, @api_true)
+
+ conn
+ |> put_status(200)
+ |> render(:search_results, %{search_results: search_results})
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex
index 8d016c404714..34ad68ca255c 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/smart_contract_controller.ex
@@ -82,7 +82,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do
{:not_found, true} <- {:not_found, AddressView.check_custom_abi_for_having_write_functions(custom_abi)} do
conn
|> put_status(200)
- |> json(Writer.filter_write_functions(custom_abi.abi))
+ |> json(custom_abi.abi |> Writer.filter_write_functions() |> Reader.get_abi_with_method_id())
end
end
@@ -95,7 +95,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do
{:not_found, false} <- {:not_found, is_nil(smart_contract)} do
conn
|> put_status(200)
- |> json(Writer.write_functions(smart_contract))
+ |> json(smart_contract |> Writer.write_functions() |> Reader.get_abi_with_method_id())
end
end
@@ -135,7 +135,11 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do
conn
|> put_status(200)
- |> json(Writer.write_functions_proxy(implementation_address_hash_string, @api_true))
+ |> json(
+ implementation_address_hash_string
+ |> Writer.write_functions_proxy(@api_true)
+ |> Reader.get_abi_with_method_id()
+ )
end
end
@@ -200,8 +204,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractController do
next_page_params =
next_page
- |> next_page_params(smart_contracts, params)
- |> delete_parameters_from_next_page_params()
+ |> next_page_params(smart_contracts, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex
index 6ffbd0c6bbfe..098b05f7e9c8 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/stats_controller.ex
@@ -4,6 +4,7 @@ defmodule BlockScoutWeb.API.V2.StatsController do
alias BlockScoutWeb.API.V2.Helper
alias BlockScoutWeb.Chain.MarketHistoryChartController
alias Explorer.{Chain, Market}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.Cache.Block, as: BlockCache
alias Explorer.Chain.Cache.{GasPriceOracle, GasUsage}
alias Explorer.Chain.Cache.Transaction, as: TransactionCache
@@ -43,7 +44,7 @@ defmodule BlockScoutWeb.API.V2.StatsController do
conn,
%{
"total_blocks" => BlockCache.estimated_count() |> to_string(),
- "total_addresses" => @api_true |> Chain.address_estimated_count() |> to_string(),
+ "total_addresses" => @api_true |> Counters.address_estimated_count() |> to_string(),
"total_transactions" => TransactionCache.estimated_count() |> to_string(),
"average_block_time" => AverageBlockTime.average_block_time() |> Duration.to_milliseconds(),
"coin_price" => exchange_rate.usd_value,
@@ -94,7 +95,7 @@ defmodule BlockScoutWeb.API.V2.StatsController do
exchange_rate = Market.get_coin_exchange_rate()
recent_market_history = Market.fetch_recent_history()
- current_total_supply = available_supply(Chain.supply_for_days(), exchange_rate)
+ current_total_supply = MarketHistoryChartController.available_supply(Chain.supply_for_days(), exchange_rate)
price_history_data =
recent_market_history
@@ -122,8 +123,4 @@ defmodule BlockScoutWeb.API.V2.StatsController do
available_supply: current_total_supply
})
end
-
- defp available_supply(:ok, exchange_rate), do: exchange_rate.available_supply || 0
-
- defp available_supply({:ok, supply_for_days}, _exchange_rate), do: supply_for_days
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/token_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/token_controller.ex
index 647e38ab6283..1ec2a32a3e0b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/token_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/token_controller.ex
@@ -23,7 +23,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
@api_true [api?: true]
- def token(conn, %{"address_hash" => address_hash_string} = params) do
+ def token(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)} do
@@ -35,7 +35,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def counters(conn, %{"address_hash" => address_hash_string} = params) do
+ def counters(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, true} <- {:not_found, Chain.token_from_address_hash_exists?(address_hash, @api_true)} do
@@ -45,7 +45,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def transfers(conn, %{"address_hash" => address_hash_string} = params) do
+ def transfers(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, true} <- {:not_found, Chain.token_from_address_hash_exists?(address_hash, @api_true)} do
@@ -61,8 +61,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
next_page_params =
next_page
- |> token_transfers_next_page_params(token_transfers, params)
- |> delete_parameters_from_next_page_params()
+ |> token_transfers_next_page_params(token_transfers, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -71,7 +70,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def holders(conn, %{"address_hash" => address_hash_string} = params) do
+ def holders(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)} do
@@ -80,8 +79,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
{token_balances, next_page} = split_list_by_page(results_plus_one)
- next_page_params =
- next_page |> next_page_params(token_balances, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(token_balances, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -89,7 +87,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def instances(conn, %{"address_hash" => address_hash_string} = params) do
+ def instances(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)} do
@@ -102,7 +100,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
{token_instances, next_page} = split_list_by_page(results_plus_one)
next_page_params =
- next_page |> unique_tokens_next_page(token_instances, params) |> delete_parameters_from_next_page_params()
+ next_page |> unique_tokens_next_page(token_instances, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -110,7 +108,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def instance(conn, %{"address_hash" => address_hash_string, "token_id" => token_id_str} = params) do
+ def instance(conn, %{"address_hash_param" => address_hash_string, "token_id" => token_id_str} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)},
@@ -131,7 +129,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def transfers_by_instance(conn, %{"address_hash" => address_hash_string, "token_id" => token_id_str} = params) do
+ def transfers_by_instance(conn, %{"address_hash_param" => address_hash_string, "token_id" => token_id_str} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)},
@@ -149,8 +147,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
next_page_params =
next_page
- |> token_transfers_next_page_params(token_transfers, params)
- |> delete_parameters_from_next_page_params()
+ |> token_transfers_next_page_params(token_transfers, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -159,7 +156,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def holders_by_instance(conn, %{"address_hash" => address_hash_string, "token_id" => token_id_str} = params) do
+ def holders_by_instance(conn, %{"address_hash_param" => address_hash_string, "token_id" => token_id_str} = params) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)},
@@ -178,8 +175,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
next_page_params =
next_page
- |> next_page_params(token_holders, params)
- |> delete_parameters_from_next_page_params()
+ |> next_page_params(token_holders, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -187,7 +183,10 @@ defmodule BlockScoutWeb.API.V2.TokenController do
end
end
- def transfers_count_by_instance(conn, %{"address_hash" => address_hash_string, "token_id" => token_id_str} = params) do
+ def transfers_count_by_instance(
+ conn,
+ %{"address_hash_param" => address_hash_string, "token_id" => token_id_str} = params
+ ) do
with {:format, {:ok, address_hash}} <- {:format, Chain.string_to_address_hash(address_hash_string)},
{:ok, false} <- AccessHelper.restricted_access?(address_hash_string, params),
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)},
@@ -213,7 +212,7 @@ defmodule BlockScoutWeb.API.V2.TokenController do
{tokens, next_page} = filter |> Chain.list_top_tokens(options) |> split_list_by_page()
- next_page_params = next_page |> next_page_params(tokens, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(tokens, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/transaction_controller.ex
index 94d060f918ad..973fdc7094dd 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/transaction_controller.ex
@@ -62,7 +62,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
@api_true [api?: true]
- def transaction(conn, %{"transaction_hash" => transaction_hash_string} = params) do
+ def transaction(conn, %{"transaction_hash_param" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found,
@@ -97,14 +97,14 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
{transactions, next_page} = split_list_by_page(transactions_plus_one)
- next_page_params = next_page |> next_page_params(transactions, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(transactions, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
|> render(:transactions, %{transactions: transactions, next_page_params: next_page_params})
end
- def raw_trace(conn, %{"transaction_hash" => transaction_hash_string} = params) do
+ def raw_trace(conn, %{"transaction_hash_param" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash, @api_true)},
@@ -133,7 +133,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
end
end
- def token_transfers(conn, %{"transaction_hash" => transaction_hash_string} = params) do
+ def token_transfers(conn, %{"transaction_hash_param" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash, @api_true)},
@@ -157,8 +157,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
next_page_params =
next_page
- |> token_transfers_next_page_params(token_transfers, params)
- |> delete_parameters_from_next_page_params()
+ |> token_transfers_next_page_params(token_transfers, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -166,7 +165,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
end
end
- def internal_transactions(conn, %{"transaction_hash" => transaction_hash_string} = params) do
+ def internal_transactions(conn, %{"transaction_hash_param" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash, @api_true)},
@@ -183,8 +182,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
next_page_params =
next_page
- |> next_page_params(internal_transactions, params)
- |> delete_parameters_from_next_page_params()
+ |> next_page_params(internal_transactions, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -195,7 +193,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
end
end
- def logs(conn, %{"transaction_hash" => transaction_hash_string} = params) do
+ def logs(conn, %{"transaction_hash_param" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found, Chain.hash_to_transaction(transaction_hash, @api_true)},
@@ -218,8 +216,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
next_page_params =
next_page
- |> next_page_params(logs, params)
- |> delete_parameters_from_next_page_params()
+ |> next_page_params(logs, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -231,7 +228,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
end
end
- def state_changes(conn, %{"transaction_hash" => transaction_hash_string} = params) do
+ def state_changes(conn, %{"transaction_hash_param" => transaction_hash_string} = params) do
with {:format, {:ok, transaction_hash}} <- {:format, Chain.string_to_transaction_hash(transaction_hash_string)},
{:not_found, {:ok, transaction}} <-
{:not_found,
@@ -249,8 +246,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
next_page_params =
next_page
- |> next_page_params(state_changes, params)
- |> delete_parameters_from_next_page_params()
+ |> next_page_params(state_changes, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
@@ -271,8 +267,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
{transactions, next_page} = split_list_by_page(transactions_plus_one)
- next_page_params =
- next_page |> next_page_params(transactions, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(transactions, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
index 49c98c5153ee..b2bbb07d3189 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/verification_controller.ex
@@ -3,6 +3,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
import Explorer.SmartContract.Solidity.Verifier, only: [parse_boolean: 1]
+ require Logger
+
alias BlockScoutWeb.AccessHelper
alias BlockScoutWeb.API.V2.ApiView
alias Explorer.Chain
@@ -14,6 +16,7 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
action_fallback(BlockScoutWeb.API.V2.FallbackController)
@api_true [api?: true]
+ @sc_verification_started "Smart-contract verification started"
def config(conn, _params) do
solidity_compiler_versions = CompilerVersion.fetch_version_list(:solc)
@@ -46,6 +49,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
%{"address_hash" => address_hash_string, "compiler_version" => compiler_version, "source_code" => source_code} =
params
) do
+ Logger.info("API v2 smart-contract #{address_hash_string} verification via flattened file")
+
with :validated <- validate_address(params) do
verification_params =
%{
@@ -65,11 +70,12 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
|> Map.put("external_libraries", Map.get(params, "libraries", %{}))
|> Map.put("is_yul", Map.get(params, "is_yul_contract", false))
+ log_sc_verification_started(address_hash_string)
Que.add(SolidityPublisherWorker, {"flattened_api_v2", verification_params})
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Verification started"})
+ |> render(:message, %{message: @sc_verification_started})
end
end
@@ -77,6 +83,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
conn,
%{"address_hash" => address_hash_string, "files" => _files, "compiler_version" => compiler_version} = params
) do
+ Logger.info("API v2 smart-contract #{address_hash_string} verification via standard json input")
+
with {:json_input, json_input} <- validate_params_standard_json_input(params) do
verification_params =
%{
@@ -87,15 +95,18 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
|> Map.put("constructor_arguments", Map.get(params, "constructor_args", ""))
|> Map.put("name", Map.get(params, "contract_name", ""))
+ log_sc_verification_started(address_hash_string)
Que.add(SolidityPublisherWorker, {"json_api_v2", verification_params, json_input})
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Verification started"})
+ |> render(:message, %{message: @sc_verification_started})
end
end
def verification_via_sourcify(conn, %{"address_hash" => address_hash_string, "files" => files} = params) do
+ Logger.info("API v2 smart-contract #{address_hash_string} verification via Sourcify")
+
with {:not_found, true} <-
{:not_found, Application.get_env(:explorer, Explorer.ThirdPartyIntegrations.Sourcify)[:enabled]},
:validated <- validate_address(params),
@@ -105,6 +116,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
files_content <- PublishHelper.read_files(files_array) do
chosen_contract = params["chosen_contract_index"]
+ log_sc_verification_started(address_hash_string)
+
Que.add(
SolidityPublisherWorker,
{"sourcify_api_v2", String.downcase(address_hash_string), files_content, conn, chosen_contract}
@@ -112,7 +125,7 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Verification started"})
+ |> render(:message, %{message: @sc_verification_started})
end
end
@@ -120,6 +133,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
conn,
%{"address_hash" => address_hash_string, "compiler_version" => compiler_version, "files" => files} = params
) do
+ Logger.info("API v2 smart-contract #{address_hash_string} verification via multipart")
+
with :verifier_enabled <- check_microservice(),
:validated <- validate_address(params),
libraries <- Map.get(params, "libraries", "{}"),
@@ -142,11 +157,12 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
|> PublishHelper.prepare_files_array()
|> PublishHelper.read_files()
+ log_sc_verification_started(address_hash_string)
Que.add(SolidityPublisherWorker, {"multipart_api_v2", verification_params, files_array})
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Verification started"})
+ |> render(:message, %{message: @sc_verification_started})
end
end
@@ -166,11 +182,12 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
|> Map.put("name", Map.get(params, "contract_name", "Vyper_contract"))
|> Map.put("evm_version", Map.get(params, "evm_version"))
+ log_sc_verification_started(address_hash_string)
Que.add(VyperPublisherWorker, {"vyper_flattened", verification_params})
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Verification started"})
+ |> render(:message, %{message: @sc_verification_started})
end
end
@@ -178,6 +195,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
conn,
%{"address_hash" => address_hash_string, "compiler_version" => compiler_version, "files" => files} = params
) do
+ Logger.info("API v2 vyper smart-contract #{address_hash_string} verification")
+
with :verifier_enabled <- check_microservice(),
:validated <- validate_address(params) do
interfaces = parse_interfaces(params["interfaces"])
@@ -195,11 +214,12 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
|> PublishHelper.prepare_files_array()
|> PublishHelper.read_files()
+ log_sc_verification_started(address_hash_string)
Que.add(VyperPublisherWorker, {"vyper_multipart", verification_params, files_array})
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Verification started"})
+ |> render(:message, %{message: @sc_verification_started})
end
end
@@ -207,6 +227,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
conn,
%{"address_hash" => address_hash_string, "files" => _files, "compiler_version" => compiler_version} = params
) do
+ Logger.info("API v2 vyper smart-contract #{address_hash_string} verification via standard json input")
+
with :verifier_enabled <- check_microservice(),
{:json_input, json_input} <- validate_params_standard_json_input(params) do
verification_params = %{
@@ -215,11 +237,12 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
"input" => json_input
}
+ log_sc_verification_started(address_hash_string)
Que.add(VyperPublisherWorker, {"vyper_standard_json", verification_params})
conn
|> put_view(ApiView)
- |> render(:message, %{message: "Verification started"})
+ |> render(:message, %{message: @sc_verification_started})
end
end
@@ -269,4 +292,8 @@ defmodule BlockScoutWeb.API.V2.VerificationController do
:verifier_enabled
end
end
+
+ defp log_sc_verification_started(address_hash_string) do
+ Logger.info("API v2 smart-contract #{address_hash_string} verification request sent to the microservice")
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/withdrawal_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/withdrawal_controller.ex
index 396e66712a54..fc26823e5211 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/withdrawal_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/api/v2/withdrawal_controller.ex
@@ -16,7 +16,7 @@ defmodule BlockScoutWeb.API.V2.WithdrawalController do
withdrawals_plus_one = Chain.list_withdrawals(full_options)
{withdrawals, next_page} = split_list_by_page(withdrawals_plus_one)
- next_page_params = next_page |> next_page_params(withdrawals, params) |> delete_parameters_from_next_page_params()
+ next_page_params = next_page |> next_page_params(withdrawals, delete_parameters_from_next_page_params(params))
conn
|> put_status(200)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex
index 5ab997f4a91e..a9816adcbd04 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/chain/market_history_chart_controller.ex
@@ -29,16 +29,22 @@ defmodule BlockScoutWeb.Chain.MarketHistoryChartController do
end
end
- defp available_supply(:ok, exchange_rate) do
- to_string(exchange_rate.available_supply || 0)
- end
+ def available_supply(:ok, exchange_rate), do: exchange_rate.available_supply || 0
- defp available_supply({:ok, supply_for_days}, _exchange_rate) do
+ def available_supply({:ok, supply_for_days}, _exchange_rate) do
supply_for_days
|> Jason.encode()
|> case do
- {:ok, data} -> data
- _ -> []
+ {:ok, _data} ->
+ current_date =
+ supply_for_days
+ |> Map.keys()
+ |> Enum.max(Date)
+
+ Map.get(supply_for_days, current_date)
+
+ _ ->
+ nil
end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
index afa8143329b3..eabc844c7d01 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
@@ -6,10 +6,12 @@ defmodule BlockScoutWeb.ChainController do
alias BlockScoutWeb.API.V2.Helper
alias BlockScoutWeb.{ChainView, Controller}
alias Explorer.{Chain, PagingOptions, Repo}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.{Address, Block, Transaction}
alias Explorer.Chain.Cache.Block, as: BlockCache
alias Explorer.Chain.Cache.GasUsage
alias Explorer.Chain.Cache.Transaction, as: TransactionCache
+ alias Explorer.Chain.Search
alias Explorer.Chain.Supply.RSK
alias Explorer.Counters.AverageBlockTime
alias Explorer.Market
@@ -19,7 +21,7 @@ defmodule BlockScoutWeb.ChainController do
transaction_estimated_count = TransactionCache.estimated_count()
total_gas_usage = GasUsage.total()
block_count = BlockCache.estimated_count()
- address_count = Chain.address_estimated_count()
+ address_count = Counters.address_estimated_count()
market_cap_calculation =
case Application.get_env(:explorer, :supply) do
@@ -90,7 +92,7 @@ defmodule BlockScoutWeb.ChainController do
results =
paging_options
- |> Chain.joint_search(offset, term)
+ |> Search.joint_search(offset, term)
encoded_results =
results
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/search_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/search_controller.ex
index b2f639a6e3a9..937c4b2603a6 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/search_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/search_controller.ex
@@ -4,7 +4,7 @@ defmodule BlockScoutWeb.SearchController do
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias BlockScoutWeb.{Controller, SearchView}
- alias Explorer.Chain
+ alias Explorer.Chain.Search
alias Phoenix.View
def search_results(conn, %{"q" => query, "type" => "JSON"} = params) do
@@ -13,7 +13,7 @@ defmodule BlockScoutWeb.SearchController do
search_results_plus_one =
paging_options
- |> Chain.joint_search(offset, query)
+ |> Search.joint_search(offset, query)
{search_results, next_page} = split_list_by_page(search_results_plus_one)
diff --git a/apps/block_scout_web/lib/block_scout_web/notifier.ex b/apps/block_scout_web/lib/block_scout_web/notifier.ex
index fc69ceb3e27d..a82202c4acdc 100644
--- a/apps/block_scout_web/lib/block_scout_web/notifier.ex
+++ b/apps/block_scout_web/lib/block_scout_web/notifier.ex
@@ -3,6 +3,8 @@ defmodule BlockScoutWeb.Notifier do
Responds to events by sending appropriate channel updates to front-end.
"""
+ require Logger
+
alias Absinthe.Subscription
alias BlockScoutWeb.API.V2, as: API_V2
@@ -17,6 +19,7 @@ defmodule BlockScoutWeb.Notifier do
}
alias Explorer.{Chain, Market, Repo}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.{Address, InternalTransaction, Transaction}
alias Explorer.Chain.Supply.RSK
alias Explorer.Chain.Transaction.History.TransactionStats
@@ -27,7 +30,7 @@ defmodule BlockScoutWeb.Notifier do
@check_broadcast_sequence_period 500
def handle_event({:chain_event, :addresses, type, addresses}) when type in [:realtime, :on_demand] do
- Endpoint.broadcast("addresses:new_address", "count", %{count: Chain.address_estimated_count()})
+ Endpoint.broadcast("addresses:new_address", "count", %{count: Counters.address_estimated_count()})
addresses
|> Stream.reject(fn %Address{fetched_coin_balance: fetched_coin_balance} -> is_nil(fetched_coin_balance) end)
@@ -44,14 +47,11 @@ defmodule BlockScoutWeb.Notifier do
Enum.each(address_token_balances, &broadcast_address_token_balance/1)
end
- def handle_event({:chain_event, :address_current_token_balances, type, address_current_token_balances})
- when type in [:realtime, :on_demand] do
- Enum.each(address_current_token_balances, &broadcast_address_token_balance/1)
- end
-
def handle_event(
{:chain_event, :contract_verification_result, :on_demand, {address_hash, contract_verification_result}}
) do
+ log_broadcast_verification_results_for_address(address_hash)
+
Endpoint.broadcast(
"addresses:#{address_hash}",
"verification_result",
@@ -64,6 +64,7 @@ defmodule BlockScoutWeb.Notifier do
def handle_event(
{:chain_event, :contract_verification_result, :on_demand, {address_hash, contract_verification_result, conn}}
) do
+ log_broadcast_verification_results_for_address(address_hash)
%{view: view, compiler: compiler} = select_contract_type_and_form_view(conn.params)
contract_verification_result =
@@ -222,10 +223,20 @@ defmodule BlockScoutWeb.Notifier do
end
def handle_event({:chain_event, :smart_contract_was_verified, :on_demand, [address_hash]}) do
+ log_broadcast_smart_contract_was_verified(address_hash)
Endpoint.broadcast("addresses:#{to_string(address_hash)}", "smart_contract_was_verified", %{})
end
- def handle_event(_), do: nil
+ def handle_event({:chain_event, :address_current_token_balances, :on_demand, address_current_token_balances}) do
+ Endpoint.broadcast("addresses:#{address_current_token_balances.address_hash}", "address_current_token_balances", %{
+ address_current_token_balances: address_current_token_balances.address_current_token_balances
+ })
+ end
+
+ def handle_event(event) do
+ Logger.warning("Unknown broadcasted event #{inspect(event)}.")
+ nil
+ end
def fetch_compiler_version(compiler) do
case CompilerVersion.fetch_versions(compiler) do
@@ -479,4 +490,12 @@ defmodule BlockScoutWeb.Notifier do
Endpoint.broadcast("addresses:#{address_hash}", event, %{map_key => elements})
end
end
+
+ defp log_broadcast_verification_results_for_address(address_hash) do
+ Logger.info("Broadcast smart-contract #{address_hash} verification results")
+ end
+
+ defp log_broadcast_smart_contract_was_verified(address_hash) do
+ Logger.info("Broadcast smart-contract #{address_hash} was verified")
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/paging_helper.ex b/apps/block_scout_web/lib/block_scout_web/paging_helper.ex
index bcbbc9b0a274..860a8f7d4a15 100644
--- a/apps/block_scout_web/lib/block_scout_web/paging_helper.ex
+++ b/apps/block_scout_web/lib/block_scout_web/paging_helper.ex
@@ -129,12 +129,11 @@ defmodule BlockScoutWeb.PagingHelper do
params
|> Map.drop([
"block_hash_or_number",
- "transaction_hash",
- "address_hash",
+ "transaction_hash_param",
+ "address_hash_param",
"type",
"method",
"filter",
- "token_address_hash",
"q",
"sort",
"order"
diff --git a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
index 7c0a05969912..47c9289f8301 100644
--- a/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
+++ b/apps/block_scout_web/lib/block_scout_web/realtime_event_handler.ex
@@ -26,6 +26,7 @@ defmodule BlockScoutWeb.RealtimeEventHandler do
Subscriber.to(:transactions, :realtime)
Subscriber.to(:addresses, :on_demand)
Subscriber.to(:address_coin_balances, :on_demand)
+ Subscriber.to(:address_current_token_balances, :on_demand)
Subscriber.to(:address_token_balances, :on_demand)
Subscriber.to(:contract_verification_result, :on_demand)
Subscriber.to(:token_total_supply, :on_demand)
diff --git a/apps/block_scout_web/lib/block_scout_web/router.ex b/apps/block_scout_web/lib/block_scout_web/router.ex
index 8b7421b2773b..ff9d5afcc609 100644
--- a/apps/block_scout_web/lib/block_scout_web/router.ex
+++ b/apps/block_scout_web/lib/block_scout_web/router.ex
@@ -28,12 +28,6 @@ defmodule BlockScoutWeb.Router do
# Needs to be 200 to support the schema introspection for graphiql
@max_complexity 200
- forward("/graphql", Absinthe.Plug,
- schema: BlockScoutWeb.Schema,
- analyze_complexity: true,
- max_complexity: @max_complexity
- )
-
forward("/graphiql", Absinthe.Plug.GraphiQL,
schema: BlockScoutWeb.Schema,
interface: :advanced,
diff --git a/apps/block_scout_web/lib/block_scout_web/schema/types.ex b/apps/block_scout_web/lib/block_scout_web/schema/types.ex
index 426d9909f59b..99f47a29163b 100644
--- a/apps/block_scout_web/lib/block_scout_web/schema/types.ex
+++ b/apps/block_scout_web/lib/block_scout_web/schema/types.ex
@@ -22,10 +22,14 @@ defmodule BlockScoutWeb.Schema.Types do
A stored representation of a Web3 address.
"""
object :address do
- field(:hash, :address_hash)
field(:fetched_coin_balance, :wei)
field(:fetched_coin_balance_block_number, :integer)
+ field(:hash, :address_hash)
field(:contract_code, :data)
+ field(:nonce, :integer)
+ field(:gas_used, :integer)
+ field(:transactions_count, :integer)
+ field(:token_transfers_count, :integer)
field :smart_contract, :smart_contract do
resolve(dataloader(:db, :smart_contract))
@@ -36,16 +40,7 @@ defmodule BlockScoutWeb.Schema.Types do
arg(:order, type: :sort_order, default_value: :desc)
resolve(&Transaction.get_by/3)
- complexity(fn
- %{first: first}, child_complexity ->
- first * child_complexity
-
- %{last: last}, child_complexity ->
- last * child_complexity
-
- %{}, _child_complexity ->
- 0
- end)
+ complexity(fn params, child_complexity -> process_complexity(params, child_complexity) end)
end
end
@@ -55,18 +50,20 @@ defmodule BlockScoutWeb.Schema.Types do
structure that they form is called a "blockchain".
"""
object :block do
- field(:hash, :full_hash)
field(:consensus, :boolean)
field(:difficulty, :decimal)
field(:gas_limit, :decimal)
field(:gas_used, :decimal)
+ field(:hash, :full_hash)
+ field(:miner_hash, :address_hash)
field(:nonce, :nonce_hash)
field(:number, :integer)
+ field(:parent_hash, :full_hash)
field(:size, :integer)
field(:timestamp, :datetime)
field(:total_difficulty, :decimal)
- field(:miner_hash, :address_hash)
- field(:parent_hash, :full_hash)
+ field(:base_fee_per_gas, :wei)
+ field(:is_empty, :boolean)
end
@desc """
@@ -85,12 +82,14 @@ defmodule BlockScoutWeb.Schema.Types do
field(:trace_address, :json)
field(:type, :type)
field(:value, :wei)
- field(:block_number, :integer)
- field(:transaction_index, :integer)
field(:created_contract_address_hash, :address_hash)
field(:from_address_hash, :address_hash)
field(:to_address_hash, :address_hash)
field(:transaction_hash, :full_hash)
+ field(:block_number, :integer)
+ field(:transaction_index, :integer)
+ field(:block_hash, :full_hash)
+ field(:block_index, :integer)
end
@desc """
@@ -108,6 +107,19 @@ defmodule BlockScoutWeb.Schema.Types do
field(:contract_source_code, :string)
field(:abi, :json)
field(:address_hash, :address_hash)
+ field(:constructor_arguments, :string)
+ field(:optimization_runs, :integer)
+ field(:evm_version, :string)
+ field(:external_libraries, :json)
+ field(:verified_via_sourcify, :boolean)
+ field(:partially_verified, :boolean)
+ field(:file_path, :string)
+ field(:is_vyper_contract, :boolean)
+ field(:is_changed_bytecode, :boolean)
+ field(:implementation_name, :string)
+ field(:implementation_address_hash, :address_hash)
+ field(:compiler_settings, :json)
+ field(:verified_via_eth_bytecode_db, :boolean)
end
@desc """
@@ -130,13 +142,12 @@ defmodule BlockScoutWeb.Schema.Types do
Models a Web3 transaction.
"""
node object(:transaction, id_fetcher: &transaction_id_fetcher/2) do
- field(:hash, :full_hash)
- field(:block_number, :integer)
field(:cumulative_gas_used, :decimal)
field(:error, :string)
field(:gas, :decimal)
field(:gas_price, :wei)
field(:gas_used, :decimal)
+ field(:hash, :full_hash)
field(:index, :integer)
field(:input, :string)
field(:nonce, :nonce_hash)
@@ -145,24 +156,23 @@ defmodule BlockScoutWeb.Schema.Types do
field(:status, :status)
field(:v, :decimal)
field(:value, :wei)
+ field(:block_hash, :full_hash)
+ field(:block_number, :integer)
field(:from_address_hash, :address_hash)
field(:to_address_hash, :address_hash)
field(:created_contract_address_hash, :address_hash)
+ field(:earliest_processing_start, :datetime)
+ field(:revert_reason, :string)
+ field(:max_priority_fee_per_gas, :wei)
+ field(:max_fee_per_gas, :wei)
+ field(:type, :integer)
+ field(:has_error_in_internal_txs, :boolean)
connection field(:internal_transactions, node_type: :internal_transaction) do
arg(:count, :integer)
resolve(&InternalTransaction.get_by/3)
- complexity(fn
- %{first: first}, child_complexity ->
- first * child_complexity
-
- %{last: last}, child_complexity ->
- last * child_complexity
-
- %{}, _child_complexity ->
- 0
- end)
+ complexity(fn params, child_complexity -> process_complexity(params, child_complexity) end)
end
end
@@ -175,4 +185,17 @@ defmodule BlockScoutWeb.Schema.Types do
def internal_transaction_id_fetcher(%{transaction_hash: transaction_hash, index: index}, _) do
Jason.encode!(%{transaction_hash: to_string(transaction_hash), index: index})
end
+
+ defp process_complexity(params, child_complexity) do
+ case params do
+ %{first: first} ->
+ first * child_complexity
+
+ %{last: last} ->
+ last * child_complexity
+
+ %{} ->
+ 0
+ end
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex
index de29c7e7fd9d..a4060c9485d9 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex
@@ -8,7 +8,7 @@
class: "card-tab #{tab_status("transactions", @conn.request_path)}",
to: AccessHelper.get_path(@conn, :address_transaction_path, :index, @address.hash)
) %>
- <%= if Chain.check_if_token_transfers_at_address(@address.hash) do %>
+ <%= if Counters.check_if_token_transfers_at_address(@address.hash) do %>
<%= link(
gettext("Token Transfers"),
class: "card-tab #{tab_status("token-transfers", @conn.request_path)}",
@@ -16,7 +16,7 @@
to: AccessHelper.get_path(@conn, :address_token_transfers_path, :index, @address.hash)
) %>
<% end %>
- <%= if Chain.check_if_tokens_at_address(@address.hash) do %>
+ <%= if Counters.check_if_tokens_at_address(@address.hash) do %>
<%= link(
gettext("Tokens"),
class: "card-tab #{tab_status("tokens", @conn.request_path)}",
@@ -24,7 +24,7 @@
"data-test": "tokens_tab_link"
) %>
<% end %>
- <%= if Chain.check_if_withdrawals_at_address(@address.hash) do %>
+ <%= if Counters.check_if_withdrawals_at_address(@address.hash) do %>
<%= link(
gettext("Withdrawals"),
class: "card-tab #{tab_status("withdrawals", @conn.request_path)}",
@@ -44,14 +44,14 @@
"data-test": "coin_balance_tab_link",
to: AccessHelper.get_path(@conn, :address_coin_balance_path, :index, @address.hash)
) %>
- <%= if Chain.check_if_logs_at_address(@address.hash) do %>
+ <%= if Counters.check_if_logs_at_address(@address.hash) do %>
<%= link(
gettext("Logs"),
class: "card-tab #{tab_status("logs", @conn.request_path)}",
to: AccessHelper.get_path(@conn, :address_logs_path, :index, @address.hash)
) %>
<% end %>
- <%= if Chain.check_if_validated_blocks_at_address(@address.hash) do %>
+ <%= if Counters.check_if_validated_blocks_at_address(@address.hash) do %>
<%= link(
gettext("Blocks Validated"),
class: "card-tab #{tab_status("validations", @conn.request_path)}",
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
index 658acfd417b4..77c96739cb5d 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_contract/index.html.eex
@@ -43,7 +43,7 @@
<% end %>
<%= if smart_contract_verified || (!smart_contract_verified && metadata_for_verification) do %>
<% target_contract = if smart_contract_verified, do: @address.smart_contract, else: metadata_for_verification %>
- <%= if @address.smart_contract.partially_verified && smart_contract_verified do %>
+ <%= if @address.smart_contract.verified_via_sourcify && @address.smart_contract.partially_verified && smart_contract_verified do %>
<%= gettext("This contract has been partially verified via Sourcify.") %>
<% else %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/csv_export/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/csv_export/index.html.eex
index f0484d83d28e..979926300cf6 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/csv_export/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/csv_export/index.html.eex
@@ -27,7 +27,7 @@
id="export-csv-button"
class="button button-primary"
style="padding: 10px 25px;"
- data-link=<%= address_transaction_path(@conn, type_download_path(@type)) %>
+ data-link=<%= BlockScoutWebController.full_path("/api/v1/#{type_download_path(@type)}") %>
data-address-hash=<%= address_checksum(@address_hash_string) %>
data-type=<%= @type %>
><%= gettext("Download") %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/page_not_found/index.json.eex b/apps/block_scout_web/lib/block_scout_web/templates/page_not_found/index.json.eex
new file mode 100644
index 000000000000..98b8502d5f4f
--- /dev/null
+++ b/apps/block_scout_web/lib/block_scout_web/templates/page_not_found/index.json.eex
@@ -0,0 +1 @@
+Page not found
\ No newline at end of file
diff --git a/apps/block_scout_web/lib/block_scout_web/views/abi_encoded_value_view.ex b/apps/block_scout_web/lib/block_scout_web/views/abi_encoded_value_view.ex
index a4a7fc66bebb..c25dbbf5392e 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/abi_encoded_value_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/abi_encoded_value_view.ex
@@ -192,23 +192,21 @@ defmodule BlockScoutWeb.ABIEncodedValueView do
end
defp base_value_json(_, {:dynamic, value}) do
- hex(value)
+ hex_for_json(value)
end
defp base_value_json(:address, value) do
- hex(value)
- end
-
- defp base_value_json(:address_text, value) do
- hex(value)
+ hex_for_json(value)
end
defp base_value_json(:bytes, value) do
- hex(value)
+ hex_for_json(value)
end
defp base_value_json(_, value), do: to_string(value)
defp hex("0x" <> value), do: "0x" <> value
defp hex(value), do: "0x" <> Base.encode16(value, case: :lower)
+
+ defp hex_for_json(value), do: "0x" <> Base.encode16(value, case: :lower)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/address_view.ex b/apps/block_scout_web/lib/block_scout_web/views/address_view.ex
index 3f60d4c7eadc..41ebf80976d6 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/address_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/address_view.ex
@@ -6,6 +6,7 @@ defmodule BlockScoutWeb.AddressView do
alias BlockScoutWeb.{AccessHelper, LayoutView}
alias Explorer.Account.CustomABI
alias Explorer.{Chain, CustomContractsHelper, Repo}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.{Address, Hash, InternalTransaction, Log, SmartContract, Token, TokenTransfer, Transaction, Wei}
alias Explorer.Chain.Block.Reward
alias Explorer.ExchangeRates.Token, as: TokenExchangeRate
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/v2/address_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/v2/address_view.ex
index 4f1601f23481..9cdf88abb2f9 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api/v2/address_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api/v2/address_view.ex
@@ -7,6 +7,7 @@ defmodule BlockScoutWeb.API.V2.AddressView do
alias BlockScoutWeb.API.V2.{ApiView, Helper, TokenView}
alias BlockScoutWeb.API.V2.Helper
alias Explorer.{Chain, Market}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.{Address, SmartContract}
@api_true [api?: true]
@@ -102,12 +103,12 @@ defmodule BlockScoutWeb.API.V2.AddressView do
"has_methods_read_proxy" => is_proxy,
"has_methods_write_proxy" => AddressView.smart_contract_with_write_functions?(address) && is_proxy,
"has_decompiled_code" => AddressView.has_decompiled_code?(address),
- "has_validated_blocks" => Chain.check_if_validated_blocks_at_address(address.hash, @api_true),
- "has_logs" => Chain.check_if_logs_at_address(address.hash, @api_true),
- "has_tokens" => Chain.check_if_tokens_at_address(address.hash, @api_true),
- "has_token_transfers" => Chain.check_if_token_transfers_at_address(address.hash, @api_true),
+ "has_validated_blocks" => Counters.check_if_validated_blocks_at_address(address.hash, @api_true),
+ "has_logs" => Counters.check_if_logs_at_address(address.hash, @api_true),
+ "has_tokens" => Counters.check_if_tokens_at_address(address.hash, @api_true),
+ "has_token_transfers" => Counters.check_if_token_transfers_at_address(address.hash, @api_true),
"watchlist_address_id" => Chain.select_watchlist_address_id(get_watchlist_id(conn), address.hash),
- "has_beacon_chain_withdrawals" => Chain.check_if_withdrawals_at_address(address.hash, @api_true)
+ "has_beacon_chain_withdrawals" => Counters.check_if_withdrawals_at_address(address.hash, @api_true)
})
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/v2/block_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/v2/block_view.ex
index 9c022d364e52..8da05d3b686a 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api/v2/block_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api/v2/block_view.ex
@@ -50,9 +50,9 @@ defmodule BlockScoutWeb.API.V2.BlockView do
"base_fee_per_gas" => block.base_fee_per_gas,
"burnt_fees" => burned_fee,
"priority_fee" => priority_fee,
- "extra_data" => "TODO",
+ # "extra_data" => "TODO",
"uncles_hashes" => prepare_uncles(block.uncle_relations),
- "state_root" => "TODO",
+ # "state_root" => "TODO",
"rewards" => prepare_rewards(block.rewards, block, single_block?),
"gas_target_percentage" => gas_target(block),
"gas_used_percentage" => gas_used_percentage(block),
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
index 7b4f45cbb2da..3663e2f96e80 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api/v2/search_view.ex
@@ -2,12 +2,16 @@ defmodule BlockScoutWeb.API.V2.SearchView do
use BlockScoutWeb, :view
alias BlockScoutWeb.Endpoint
- alias Explorer.Chain.{Address, Block, Transaction}
+ alias Explorer.Chain.{Address, Block, Hash, Transaction}
def render("search_results.json", %{search_results: search_results, next_page_params: next_page_params}) do
%{"items" => Enum.map(search_results, &prepare_search_result/1), "next_page_params" => next_page_params}
end
+ def render("search_results.json", %{search_results: search_results}) do
+ Enum.map(search_results, &prepare_search_result/1)
+ end
+
def render("search_results.json", %{result: {:ok, result}}) do
Map.merge(%{"redirect" => true}, redirect_search_results(result))
end
@@ -30,7 +34,8 @@ defmodule BlockScoutWeb.API.V2.SearchView do
"exchange_rate" => search_result.exchange_rate && to_string(search_result.exchange_rate),
"total_supply" => search_result.total_supply,
"circulating_market_cap" =>
- search_result.circulating_market_cap && to_string(search_result.circulating_market_cap)
+ search_result.circulating_market_cap && to_string(search_result.circulating_market_cap),
+ "is_verified_via_admin_panel" => search_result.is_verified_via_admin_panel
}
end
@@ -68,6 +73,7 @@ defmodule BlockScoutWeb.API.V2.SearchView do
}
end
+ defp hash_to_string(%Hash{bytes: bytes}), do: hash_to_string(bytes)
defp hash_to_string(hash), do: "0x" <> Base.encode16(hash, case: :lower)
defp redirect_search_results(%Address{} = item) do
diff --git a/apps/block_scout_web/lib/block_scout_web/views/api/v2/token_view.ex b/apps/block_scout_web/lib/block_scout_web/views/api/v2/token_view.ex
index fe60782eb14b..7f983ed84b56 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/api/v2/token_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/api/v2/token_view.ex
@@ -13,7 +13,7 @@ defmodule BlockScoutWeb.API.V2.TokenView do
"name" => token.name,
"decimals" => token.decimals,
"type" => token.type,
- "holders" => token.holder_count && to_string(token.holder_count),
+ "holders" => prepare_holders_count(token.holder_count),
"exchange_rate" => exchange_rate(token),
"total_supply" => token.total_supply,
"icon_url" => token.icon_url,
@@ -80,4 +80,8 @@ defmodule BlockScoutWeb.API.V2.TokenView do
"is_unique" => is_unique
}
end
+
+ defp prepare_holders_count(nil), do: nil
+ defp prepare_holders_count(count) when count < 0, do: prepare_holders_count(0)
+ defp prepare_holders_count(count), do: to_string(count)
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/csv_export.ex b/apps/block_scout_web/lib/block_scout_web/views/csv_export.ex
index 34596956e45a..a076e1d00afe 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/csv_export.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/csv_export.ex
@@ -1,6 +1,7 @@
defmodule BlockScoutWeb.CsvExportView do
use BlockScoutWeb, :view
+ alias BlockScoutWeb.Controller, as: BlockScoutWebController
alias Explorer.Chain
alias Explorer.Chain.Address
alias Explorer.Chain.CSVExport.Helper
@@ -15,14 +16,10 @@ defmodule BlockScoutWeb.CsvExportView do
end
end
+ defp type_download_path(nil), do: ""
+
defp type_download_path(type) do
- case type do
- "internal-transactions" -> :internal_transactions_csv
- "transactions" -> :transactions_csv
- "token-transfers" -> :token_transfers_csv
- "logs" -> :logs_csv
- _ -> ""
- end
+ type <> "-csv"
end
defp address_checksum(address_hash_string) do
diff --git a/apps/block_scout_web/lib/block_scout_web/web_router.ex b/apps/block_scout_web/lib/block_scout_web/web_router.ex
index 4b3f7a20ae74..3f3dbed7d10e 100644
--- a/apps/block_scout_web/lib/block_scout_web/web_router.ex
+++ b/apps/block_scout_web/lib/block_scout_web/web_router.ex
@@ -493,16 +493,8 @@ defmodule BlockScoutWeb.WebRouter do
get("/csv-export", CsvExportController, :index)
- get("/transactions-csv", AddressTransactionController, :transactions_csv)
-
get("/token-autocomplete", ChainController, :token_autocomplete)
- get("/token-transfers-csv", AddressTransactionController, :token_transfers_csv)
-
- get("/internal-transactions-csv", AddressTransactionController, :internal_transactions_csv)
-
- get("/logs-csv", AddressTransactionController, :logs_csv)
-
get("/chain-blocks", ChainController, :chain_blocks, as: :chain_blocks)
get("/token-counters", Tokens.TokenController, :token_counters)
diff --git a/apps/block_scout_web/mix.exs b/apps/block_scout_web/mix.exs
index 03a852bd85b2..01efe54cadbf 100644
--- a/apps/block_scout_web/mix.exs
+++ b/apps/block_scout_web/mix.exs
@@ -23,7 +23,7 @@ defmodule BlockScoutWeb.Mixfile do
dialyzer: :test
],
start_permanent: Mix.env() == :prod,
- version: "5.2.1"
+ version: "5.2.2"
]
end
@@ -83,7 +83,7 @@ defmodule BlockScoutWeb.Mixfile do
# HTML CSS selectors for Phoenix controller tests
{:floki, "~> 0.31"},
{:flow, "~> 1.2"},
- {:gettext, "~> 0.22.0"},
+ {:gettext, "~> 0.23.1"},
{:hammer, "~> 6.0"},
{:httpoison, "~> 2.0"},
{:indexer, in_umbrella: true, runtime: false},
@@ -128,7 +128,7 @@ defmodule BlockScoutWeb.Mixfile do
{:wallaby, "~> 0.30", only: :test, runtime: false},
# `:cowboy` `~> 2.0` and Phoenix 1.4 compatibility
{:websocket_client, git: "https://github.com/blockscout/websocket_client.git", branch: "master", override: true},
- {:ex_json_schema, "~> 0.9.1"},
+ {:ex_json_schema, "~> 0.10.1"},
{:ueberauth, "~> 0.7"},
{:ueberauth_auth0, "~> 2.0"},
{:bureaucrat, "~> 0.2.9", only: :test}
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot
index 9e448f7f82a7..930e2348eca3 100644
--- a/apps/block_scout_web/priv/gettext/default.pot
+++ b/apps/block_scout_web/priv/gettext/default.pot
@@ -265,7 +265,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:20
#: lib/block_scout_web/templates/transaction_state/index.html.eex:34
#: lib/block_scout_web/templates/verified_contracts/index.html.eex:60
-#: lib/block_scout_web/views/address_view.ex:107
+#: lib/block_scout_web/views/address_view.ex:108
#, elixir-autogen, elixir-format
msgid "Address"
msgstr ""
@@ -556,7 +556,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:56
#: lib/block_scout_web/templates/address/overview.html.eex:275
#: lib/block_scout_web/templates/address_validation/index.html.eex:11
-#: lib/block_scout_web/views/address_view.ex:384
+#: lib/block_scout_web/views/address_view.ex:385
#, elixir-autogen, elixir-format
msgid "Blocks Validated"
msgstr ""
@@ -656,13 +656,13 @@ msgstr ""
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187
#: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:126
#: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:149
-#: lib/block_scout_web/views/address_view.ex:377
+#: lib/block_scout_web/views/address_view.ex:378
#, elixir-autogen, elixir-format
msgid "Code"
msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:42
-#: lib/block_scout_web/views/address_view.ex:383
+#: lib/block_scout_web/views/address_view.ex:384
#, elixir-autogen, elixir-format
msgid "Coin Balance History"
msgstr ""
@@ -771,14 +771,14 @@ msgstr ""
#: lib/block_scout_web/templates/account/custom_abi/form.html.eex:18
#: lib/block_scout_web/templates/account/custom_abi/index.html.eex:29
#: lib/block_scout_web/templates/address_contract_verification_common_fields/_contract_address_field.html.eex:3
-#: lib/block_scout_web/views/address_view.ex:105
+#: lib/block_scout_web/views/address_view.ex:106
#, elixir-autogen, elixir-format
msgid "Contract Address"
msgstr ""
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:16
-#: lib/block_scout_web/views/address_view.ex:45
-#: lib/block_scout_web/views/address_view.ex:79
+#: lib/block_scout_web/views/address_view.ex:46
+#: lib/block_scout_web/views/address_view.ex:80
#, elixir-autogen, elixir-format
msgid "Contract Address Pending"
msgstr ""
@@ -1084,7 +1084,7 @@ msgstr ""
msgid "Decoded"
msgstr ""
-#: lib/block_scout_web/views/address_view.ex:378
+#: lib/block_scout_web/views/address_view.ex:379
#, elixir-autogen, elixir-format
msgid "Decompiled Code"
msgstr ""
@@ -1601,7 +1601,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:17
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
-#: lib/block_scout_web/views/address_view.ex:374
+#: lib/block_scout_web/views/address_view.ex:375
#: lib/block_scout_web/views/transaction_view.ex:533
#, elixir-autogen, elixir-format
msgid "Internal Transactions"
@@ -1718,7 +1718,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_logs/index.html.eex:10
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
-#: lib/block_scout_web/views/address_view.ex:385
+#: lib/block_scout_web/views/address_view.ex:386
#: lib/block_scout_web/views/transaction_view.ex:534
#, elixir-autogen, elixir-format
msgid "Logs"
@@ -1732,7 +1732,7 @@ msgstr ""
#: lib/block_scout_web/templates/chain/show.html.eex:53
#: lib/block_scout_web/templates/layout/app.html.eex:50
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:85
-#: lib/block_scout_web/views/address_view.ex:145
+#: lib/block_scout_web/views/address_view.ex:146
#, elixir-autogen, elixir-format
msgid "Market Cap"
msgstr ""
@@ -2208,7 +2208,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:89
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:27
-#: lib/block_scout_web/views/address_view.ex:379
+#: lib/block_scout_web/views/address_view.ex:380
#: lib/block_scout_web/views/tokens/overview_view.ex:41
#, elixir-autogen, elixir-format
msgid "Read Contract"
@@ -2216,7 +2216,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:96
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:41
-#: lib/block_scout_web/views/address_view.ex:380
+#: lib/block_scout_web/views/address_view.ex:381
#, elixir-autogen, elixir-format
msgid "Read Proxy"
msgstr ""
@@ -2903,7 +2903,7 @@ msgstr ""
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:15
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
-#: lib/block_scout_web/views/address_view.ex:376
+#: lib/block_scout_web/views/address_view.ex:377
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:114
#: lib/block_scout_web/views/tokens/overview_view.ex:39
#: lib/block_scout_web/views/transaction_view.ex:532
@@ -2927,7 +2927,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:13
#: lib/block_scout_web/templates/layout/_topnav.html.eex:84
#: lib/block_scout_web/templates/tokens/index.html.eex:10
-#: lib/block_scout_web/views/address_view.ex:373
+#: lib/block_scout_web/views/address_view.ex:374
#, elixir-autogen, elixir-format
msgid "Tokens"
msgstr ""
@@ -3099,7 +3099,7 @@ msgstr ""
#: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/chain/show.html.eex:214
#: lib/block_scout_web/templates/layout/_topnav.html.eex:49
-#: lib/block_scout_web/views/address_view.ex:375
+#: lib/block_scout_web/views/address_view.ex:376
#, elixir-autogen, elixir-format
msgid "Transactions"
msgstr ""
@@ -3469,14 +3469,14 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:103
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:34
-#: lib/block_scout_web/views/address_view.ex:381
+#: lib/block_scout_web/views/address_view.ex:382
#, elixir-autogen, elixir-format
msgid "Write Contract"
msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:110
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:48
-#: lib/block_scout_web/views/address_view.ex:382
+#: lib/block_scout_web/views/address_view.ex:383
#, elixir-autogen, elixir-format
msgid "Write Proxy"
msgstr ""
diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
index d84b5aca859a..dd08664c4b1f 100644
--- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
+++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
@@ -265,7 +265,7 @@ msgstr ""
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:20
#: lib/block_scout_web/templates/transaction_state/index.html.eex:34
#: lib/block_scout_web/templates/verified_contracts/index.html.eex:60
-#: lib/block_scout_web/views/address_view.ex:107
+#: lib/block_scout_web/views/address_view.ex:108
#, elixir-autogen, elixir-format
msgid "Address"
msgstr ""
@@ -556,7 +556,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:56
#: lib/block_scout_web/templates/address/overview.html.eex:275
#: lib/block_scout_web/templates/address_validation/index.html.eex:11
-#: lib/block_scout_web/views/address_view.ex:384
+#: lib/block_scout_web/views/address_view.ex:385
#, elixir-autogen, elixir-format
msgid "Blocks Validated"
msgstr ""
@@ -656,13 +656,13 @@ msgstr ""
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187
#: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:126
#: lib/block_scout_web/templates/api_docs/_eth_rpc_item.html.eex:149
-#: lib/block_scout_web/views/address_view.ex:377
+#: lib/block_scout_web/views/address_view.ex:378
#, elixir-autogen, elixir-format
msgid "Code"
msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:42
-#: lib/block_scout_web/views/address_view.ex:383
+#: lib/block_scout_web/views/address_view.ex:384
#, elixir-autogen, elixir-format
msgid "Coin Balance History"
msgstr ""
@@ -771,14 +771,14 @@ msgstr ""
#: lib/block_scout_web/templates/account/custom_abi/form.html.eex:18
#: lib/block_scout_web/templates/account/custom_abi/index.html.eex:29
#: lib/block_scout_web/templates/address_contract_verification_common_fields/_contract_address_field.html.eex:3
-#: lib/block_scout_web/views/address_view.ex:105
+#: lib/block_scout_web/views/address_view.ex:106
#, elixir-autogen, elixir-format
msgid "Contract Address"
msgstr ""
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:16
-#: lib/block_scout_web/views/address_view.ex:45
-#: lib/block_scout_web/views/address_view.ex:79
+#: lib/block_scout_web/views/address_view.ex:46
+#: lib/block_scout_web/views/address_view.ex:80
#, elixir-autogen, elixir-format
msgid "Contract Address Pending"
msgstr ""
@@ -1084,7 +1084,7 @@ msgstr ""
msgid "Decoded"
msgstr ""
-#: lib/block_scout_web/views/address_view.ex:378
+#: lib/block_scout_web/views/address_view.ex:379
#, elixir-autogen, elixir-format
msgid "Decompiled Code"
msgstr ""
@@ -1601,7 +1601,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:17
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:11
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:6
-#: lib/block_scout_web/views/address_view.ex:374
+#: lib/block_scout_web/views/address_view.ex:375
#: lib/block_scout_web/views/transaction_view.ex:533
#, elixir-autogen, elixir-format
msgid "Internal Transactions"
@@ -1718,7 +1718,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_logs/index.html.eex:10
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8
-#: lib/block_scout_web/views/address_view.ex:385
+#: lib/block_scout_web/views/address_view.ex:386
#: lib/block_scout_web/views/transaction_view.ex:534
#, elixir-autogen, elixir-format
msgid "Logs"
@@ -1732,7 +1732,7 @@ msgstr ""
#: lib/block_scout_web/templates/chain/show.html.eex:53
#: lib/block_scout_web/templates/layout/app.html.eex:50
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:85
-#: lib/block_scout_web/views/address_view.ex:145
+#: lib/block_scout_web/views/address_view.ex:146
#, elixir-autogen, elixir-format
msgid "Market Cap"
msgstr ""
@@ -2208,7 +2208,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:89
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:27
-#: lib/block_scout_web/views/address_view.ex:379
+#: lib/block_scout_web/views/address_view.ex:380
#: lib/block_scout_web/views/tokens/overview_view.ex:41
#, elixir-autogen, elixir-format
msgid "Read Contract"
@@ -2216,7 +2216,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:96
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:41
-#: lib/block_scout_web/views/address_view.ex:380
+#: lib/block_scout_web/views/address_view.ex:381
#, elixir-autogen, elixir-format
msgid "Read Proxy"
msgstr ""
@@ -2903,7 +2903,7 @@ msgstr ""
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:15
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7
-#: lib/block_scout_web/views/address_view.ex:376
+#: lib/block_scout_web/views/address_view.ex:377
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:114
#: lib/block_scout_web/views/tokens/overview_view.ex:39
#: lib/block_scout_web/views/transaction_view.ex:532
@@ -2927,7 +2927,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:13
#: lib/block_scout_web/templates/layout/_topnav.html.eex:84
#: lib/block_scout_web/templates/tokens/index.html.eex:10
-#: lib/block_scout_web/views/address_view.ex:373
+#: lib/block_scout_web/views/address_view.ex:374
#, elixir-autogen, elixir-format
msgid "Tokens"
msgstr ""
@@ -3099,7 +3099,7 @@ msgstr ""
#: lib/block_scout_web/templates/block/overview.html.eex:80
#: lib/block_scout_web/templates/chain/show.html.eex:214
#: lib/block_scout_web/templates/layout/_topnav.html.eex:49
-#: lib/block_scout_web/views/address_view.ex:375
+#: lib/block_scout_web/views/address_view.ex:376
#, elixir-autogen, elixir-format
msgid "Transactions"
msgstr ""
@@ -3469,14 +3469,14 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:103
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:34
-#: lib/block_scout_web/views/address_view.ex:381
+#: lib/block_scout_web/views/address_view.ex:382
#, elixir-autogen, elixir-format
msgid "Write Contract"
msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:110
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:48
-#: lib/block_scout_web/views/address_view.ex:382
+#: lib/block_scout_web/views/address_view.ex:383
#, elixir-autogen, elixir-format
msgid "Write Proxy"
msgstr ""
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs
index 3e1434750870..ad86587530fc 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/address_transaction_controller_test.exs
@@ -176,7 +176,7 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
to_period = Timex.format!(Timex.now(), "%Y-%m-%d", :strftime)
conn =
- get(conn, "/token-transfers-csv", %{
+ get(conn, "/api/v1/token-transfers-csv", %{
"address_id" => Address.checksum(address.hash),
"from_period" => from_period,
"to_period" => to_period
@@ -203,7 +203,7 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
to_period = Timex.format!(Timex.now(), "%Y-%m-%d", :strftime)
conn =
- get(conn, "/token-transfers-csv", %{
+ get(conn, "/api/v1/token-transfers-csv", %{
"address_id" => Address.checksum(address.hash),
"from_period" => from_period,
"to_period" => to_period,
@@ -231,7 +231,7 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
to_period = Timex.format!(Timex.now(), "%Y-%m-%d", :strftime)
conn =
- get(conn, "/token-transfers-csv", %{
+ get(conn, "/api/v1/token-transfers-csv", %{
"address_id" => Address.checksum(address.hash),
"from_period" => from_period,
"to_period" => to_period
@@ -260,7 +260,7 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
to_period = Timex.format!(Timex.now(), "%Y-%m-%d", :strftime)
conn =
- get(conn, "/token-transfers-csv", %{
+ get(conn, "/api/v1/token-transfers-csv", %{
"address_id" => Address.checksum(address.hash),
"from_period" => from_period,
"to_period" => to_period,
@@ -290,7 +290,7 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
to_period = Timex.format!(Timex.now(), "%Y-%m-%d", :strftime)
conn =
- get(conn, "/transactions-csv", %{
+ get(conn, "/api/v1/transactions-csv", %{
"address_id" => Address.checksum(address.hash),
"from_period" => from_period,
"to_period" => to_period,
@@ -357,7 +357,7 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
to_period = Timex.format!(Timex.now(), "%Y-%m-%d", :strftime)
conn =
- get(conn, "/internal-transactions-csv", %{
+ get(conn, "/api/v1/internal-transactions-csv", %{
"address_id" => Address.checksum(address.hash),
"from_period" => from_period,
"to_period" => to_period,
@@ -418,7 +418,7 @@ defmodule BlockScoutWeb.AddressTransactionControllerTest do
to_period = Timex.format!(Timex.now(), "%Y-%m-%d", :strftime)
conn =
- get(conn, "/logs-csv", %{
+ get(conn, "/api/v1/logs-csv", %{
"address_id" => Address.checksum(address.hash),
"from_period" => from_period,
"to_period" => to_period,
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
index 0cd2b50bd390..752c393c4710 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/rpc/contract_controller_test.exs
@@ -712,7 +712,7 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
params = %{
"module" => "contract",
"action" => "verify_via_sourcify",
- "addressHash" => "0x18d89C12e9463Be6343c35C9990361bA4C42AfC2"
+ "addressHash" => "0xf26594F585De4EB0Ae9De865d9053FEe02ac6eF1"
}
response =
@@ -732,14 +732,14 @@ defmodule BlockScoutWeb.API.RPC.ContractControllerTest do
_created_contract_address =
insert(
:address,
- hash: "0x18d89C12e9463Be6343c35C9990361bA4C42AfC2",
+ hash: "0xf26594F585De4EB0Ae9De865d9053FEe02ac6eF1",
contract_code: smart_contract_bytecode
)
params = %{
"module" => "contract",
"action" => "verify_via_sourcify",
- "addressHash" => "0x18d89C12e9463Be6343c35C9990361bA4C42AfC2"
+ "addressHash" => "0xf26594F585De4EB0Ae9De865d9053FEe02ac6eF1"
}
get_implementation()
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/address_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/address_controller_test.exs
index 7073f491550a..adfba5247640 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/address_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/address_controller_test.exs
@@ -3,6 +3,7 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
alias BlockScoutWeb.Models.UserFromAuth
alias Explorer.{Chain, Repo}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.{
Address,
@@ -159,9 +160,9 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
insert(:block, miner: address)
- Chain.transaction_count(address)
- Chain.token_transfers_count(address)
- Chain.gas_usage_count(address)
+ Counters.transaction_count(address)
+ Counters.token_transfers_count(address)
+ Counters.gas_usage_count(address)
request = get(conn, "/api/v2/addresses/#{address.hash}/counters")
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/search_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/search_controller_test.exs
index e9dda32b848e..145963c99d32 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/search_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/search_controller_test.exs
@@ -135,6 +135,7 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
assert item["exchange_rate"] == (token.fiat_value && to_string(token.fiat_value))
assert item["total_supply"] == to_string(token.total_supply)
assert item["icon_url"] == token.icon_url
+ assert item["is_verified_via_admin_panel"] == token.is_verified_via_admin_panel
end
test "search transaction", %{conn: conn} do
@@ -287,4 +288,49 @@ defmodule BlockScoutWeb.API.V2.SearchControllerTest do
%{"redirect" => false, "type" => nil, "parameter" => nil} = json_response(request, 200)
end
end
+
+ describe "/search/quick" do
+ test "check that all categories are in response list", %{conn: conn} do
+ name = "156000"
+
+ tags =
+ for _ <- 0..50 do
+ insert(:address_to_tag, tag: build(:address_tag, display_name: name))
+ end
+
+ contracts = insert_list(50, :smart_contract, name: name)
+ tokens = insert_list(50, :token, name: name)
+ blocks = [insert(:block, number: name, consensus: false), insert(:block, number: name)]
+
+ request = get(conn, "/api/v2/search/quick?q=#{name}")
+ assert response = json_response(request, 200)
+ assert Enum.count(response) == 50
+
+ assert response |> Enum.filter(fn x -> x["type"] == "label" end) |> Enum.map(fn x -> x["address"] end) ==
+ tags |> Enum.reverse() |> Enum.take(16) |> Enum.map(fn tag -> Address.checksum(tag.address.hash) end)
+
+ assert response |> Enum.filter(fn x -> x["type"] == "contract" end) |> Enum.map(fn x -> x["address"] end) ==
+ contracts
+ |> Enum.reverse()
+ |> Enum.take(16)
+ |> Enum.map(fn contract -> Address.checksum(contract.address_hash) end)
+
+ assert response |> Enum.filter(fn x -> x["type"] == "token" end) |> Enum.map(fn x -> x["address"] end) ==
+ tokens
+ |> Enum.reverse()
+ |> Enum.sort_by(fn x -> x.is_verified_via_admin_panel end, :desc)
+ |> Enum.take(16)
+ |> Enum.map(fn token -> Address.checksum(token.contract_address_hash) end)
+
+ block_hashes = response |> Enum.filter(fn x -> x["type"] == "block" end) |> Enum.map(fn x -> x["block_hash"] end)
+
+ assert block_hashes == blocks |> Enum.reverse() |> Enum.map(fn block -> to_string(block.hash) end) ||
+ block_hashes == blocks |> Enum.map(fn block -> to_string(block.hash) end)
+ end
+
+ test "returns empty list and don't crash", %{conn: conn} do
+ request = get(conn, "/api/v2/search/quick?q=qwertyuioiuytrewertyuioiuytrertyuio")
+ assert [] = json_response(request, 200)
+ end
+ end
end
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs
index 12dd8c8c5f4b..863345a9038a 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/smart_contract_controller_test.exs
@@ -1205,6 +1205,7 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
assert [
%{
+ "method_id" => "49ba1b49",
"type" => "function",
"stateMutability" => "nonpayable",
"outputs" => [],
@@ -1271,7 +1272,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"stateMutability" => "nonpayable",
"outputs" => [],
"name" => "disableWhitelist",
- "inputs" => [%{"type" => "bool", "name" => "disable", "internalType" => "bool"}]
+ "inputs" => [%{"type" => "bool", "name" => "disable", "internalType" => "bool"}],
+ "method_id" => "49ba1b49"
}
] == response
end
@@ -1912,7 +1914,8 @@ defmodule BlockScoutWeb.API.V2.SmartContractControllerTest do
"stateMutability" => "nonpayable",
"outputs" => [],
"name" => "disableWhitelist",
- "inputs" => [%{"type" => "bool", "name" => "disable", "internalType" => "bool"}]
+ "inputs" => [%{"type" => "bool", "name" => "disable", "internalType" => "bool"}],
+ "method_id" => "49ba1b49"
}
] == response
end
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/token_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/token_controller_test.exs
index fbed9880a6ec..05b7009487c4 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/token_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/token_controller_test.exs
@@ -390,6 +390,30 @@ defmodule BlockScoutWeb.API.V2.TokenControllerTest do
check_paginated_response(response, response_2nd_page, token_balances)
end
+
+ test "check pagination with the same values", %{conn: conn} do
+ token = insert(:token)
+
+ token_balances =
+ for _ <- 0..50 do
+ insert(
+ :address_current_token_balance,
+ token_contract_address_hash: token.contract_address_hash,
+ value: 1000
+ )
+ end
+ |> Enum.sort_by(fn x -> x.address_hash end, :asc)
+
+ request = get(conn, "/api/v2/tokens/#{token.contract_address.hash}/holders")
+ assert response = json_response(request, 200)
+
+ request_2nd_page =
+ get(conn, "/api/v2/tokens/#{token.contract_address.hash}/holders", response["next_page_params"])
+
+ assert response_2nd_page = json_response(request_2nd_page, 200)
+
+ check_paginated_response(response, response_2nd_page, token_balances)
+ end
end
describe "/tokens" do
diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/verification_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/verification_controller_test.exs
index 4ff1545377bd..bd471e8d771f 100644
--- a/apps/block_scout_web/test/block_scout_web/controllers/api/v2/verification_controller_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v2/verification_controller_test.exs
@@ -75,7 +75,7 @@ defmodule BlockScoutWeb.API.V2.VerificationControllerTest do
request = post(conn, "/api/v2/smart-contracts/#{contract_address.hash}/verification/via/flattened-code", params)
- assert %{"message" => "Verification started"} = json_response(request, 200)
+ assert %{"message" => "Smart-contract verification started"} = json_response(request, 200)
assert_receive %Phoenix.Socket.Message{
payload: %{status: "success"},
@@ -118,7 +118,7 @@ defmodule BlockScoutWeb.API.V2.VerificationControllerTest do
request = post(conn, "/api/v2/smart-contracts/#{contract_address.hash}/verification/via/flattened-code", params)
- assert %{"message" => "Verification started"} = json_response(request, 200)
+ assert %{"message" => "Smart-contract verification started"} = json_response(request, 200)
assert_receive %Phoenix.Socket.Message{
payload: %{status: "error", errors: %{name: ["Wrong contract name, please try again."]}},
@@ -198,7 +198,7 @@ defmodule BlockScoutWeb.API.V2.VerificationControllerTest do
body
)
- assert %{"message" => "Verification started"} = json_response(request, 200)
+ assert %{"message" => "Smart-contract verification started"} = json_response(request, 200)
assert_receive %Phoenix.Socket.Message{
payload: %{status: "success"},
@@ -222,7 +222,7 @@ defmodule BlockScoutWeb.API.V2.VerificationControllerTest do
end
test "verify contract from sourcify repo", %{conn: conn} do
- address = "0x18d89C12e9463Be6343c35C9990361bA4C42AfC2"
+ address = "0xf26594F585De4EB0Ae9De865d9053FEe02ac6eF1"
_contract = insert(:address, hash: address, contract_code: "0x01")
@@ -259,7 +259,7 @@ defmodule BlockScoutWeb.API.V2.VerificationControllerTest do
body
)
- assert %{"message" => "Verification started"} = json_response(request, 200)
+ assert %{"message" => "Smart-contract verification started"} = json_response(request, 200)
assert_receive %Phoenix.Socket.Message{
payload: %{status: "success"},
@@ -329,7 +329,7 @@ defmodule BlockScoutWeb.API.V2.VerificationControllerTest do
request = post(conn, "/api/v2/smart-contracts/#{contract_address.hash}/verification/via/vyper-code", params)
- assert %{"message" => "Verification started"} = json_response(request, 200)
+ assert %{"message" => "Smart-contract verification started"} = json_response(request, 200)
assert_receive %Phoenix.Socket.Message{
payload: %{status: "success"},
diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs
index ea1f5579f01c..f4526bc31454 100644
--- a/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/schema/query/address_test.exs
@@ -18,7 +18,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
variables = %{"hash" => to_string(address.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -45,7 +45,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
variables = %{"hash" => to_string(address.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -78,7 +78,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
variables = %{"hash" => to_string(address.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -110,7 +110,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
variables = %{"hash" => to_string(address.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] =~ ~s(Address not found.)
@@ -127,7 +127,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
variables = %{}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] == ~s(In argument "hash": Expected type "AddressHash!", found null.)
@@ -144,7 +144,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
variables = %{"hash" => "someInvalidHash"}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] =~ ~s(Argument "hash" has invalid value)
@@ -193,7 +193,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"first" => 1
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -251,7 +251,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"first" => 1
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -304,7 +304,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"first" => 3
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
%{
"data" => %{
@@ -366,7 +366,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"first" => 3
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
%{
"data" => %{
@@ -410,7 +410,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"first" => 67
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error1, error2, error3]} = json_response(conn, 200)
assert error1["message"] =~ ~s(Field transactions is too complex)
@@ -465,7 +465,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"count" => 9
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
%{
"data" => %{
@@ -525,7 +525,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"first" => 3
}
- conn = post(conn, "/graphql", query: query1, variables: variables1)
+ conn = post(conn, "/api/v1/graphql", query: query1, variables: variables1)
%{"data" => %{"address" => %{"transactions" => page1}}} = json_response(conn, 200)
@@ -564,7 +564,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"after" => last_cursor_page1
}
- conn = post(conn, "/graphql", query: query2, variables: variables2)
+ conn = post(conn, "/api/v1/graphql", query: query2, variables: variables2)
%{"data" => %{"address" => %{"transactions" => page2}}} = json_response(conn, 200)
@@ -583,7 +583,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressTest do
"after" => last_cursor_page2
}
- conn = post(conn, "/graphql", query: query2, variables: variables3)
+ conn = post(conn, "/api/v1/graphql", query: query2, variables: variables3)
%{"data" => %{"address" => %{"transactions" => page3}}} = json_response(conn, 200)
diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs
index f6145a4afc1d..e3ca744f4937 100644
--- a/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/schema/query/addresses_test.exs
@@ -18,7 +18,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do
variables = %{"hashes" => to_string(address.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -47,7 +47,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do
variables = %{"hashes" => to_string(address.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -82,7 +82,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do
variables = %{"hashes" => to_string(address.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -116,7 +116,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do
variables = %{"hashes" => [to_string(address.hash)]}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] =~ ~s(Addresses not found.)
@@ -133,7 +133,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do
variables = %{}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] == ~s(In argument "hashes": Expected type "[AddressHash!]!", found null.)
@@ -150,7 +150,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do
variables = %{"hashes" => ["someInvalidHash"]}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] =~ ~s(Argument "hashes" has invalid value)
@@ -175,7 +175,7 @@ defmodule BlockScoutWeb.Schema.Query.AddressesTest do
variables = %{"hashes" => hashes}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error1, error2]} = json_response(conn, 200)
assert error1["message"] =~ ~s(Field addresses is too complex)
diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/block_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/block_test.exs
index d601e3dd1005..26c612b344ce 100644
--- a/apps/block_scout_web/test/block_scout_web/schema/query/block_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/schema/query/block_test.exs
@@ -27,7 +27,7 @@ defmodule BlockScoutWeb.Schema.Query.BlockTest do
variables = %{"number" => block.number}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -63,7 +63,7 @@ defmodule BlockScoutWeb.Schema.Query.BlockTest do
variables = %{"number" => non_existent_block_number}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] =~ ~s(Block number #{non_existent_block_number} was not found)
@@ -80,7 +80,7 @@ defmodule BlockScoutWeb.Schema.Query.BlockTest do
}
"""
- conn = get(conn, "/graphql", query: query)
+ conn = get(conn, "/api/v1/graphql", query: query)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] == ~s(In argument "number": Expected type "Int!", found null.)
@@ -99,7 +99,7 @@ defmodule BlockScoutWeb.Schema.Query.BlockTest do
variables = %{"number" => "invalid"}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] =~ ~s(Argument "number" has invalid value)
diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/node_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/node_test.exs
index 4638e2f1c379..75e6aacd1ac6 100644
--- a/apps/block_scout_web/test/block_scout_web/schema/query/node_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/schema/query/node_test.exs
@@ -20,7 +20,7 @@ defmodule BlockScoutWeb.Schema.Query.NodeTest do
variables = %{"id" => id}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -50,7 +50,7 @@ defmodule BlockScoutWeb.Schema.Query.NodeTest do
variables = %{"id" => id}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
%{"errors" => [error]} = json_response(conn, 200)
@@ -88,7 +88,7 @@ defmodule BlockScoutWeb.Schema.Query.NodeTest do
variables = %{"id" => id}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -132,7 +132,7 @@ defmodule BlockScoutWeb.Schema.Query.NodeTest do
variables = %{"id" => id}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
%{"errors" => [error]} = json_response(conn, 200)
@@ -163,7 +163,7 @@ defmodule BlockScoutWeb.Schema.Query.NodeTest do
variables = %{"id" => id}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -199,7 +199,7 @@ defmodule BlockScoutWeb.Schema.Query.NodeTest do
variables = %{"id" => id}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
%{"errors" => [error]} = json_response(conn, 200)
diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/token_transfers_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/token_transfers_test.exs
index aef875fe3e16..ea20aa4f4ede 100644
--- a/apps/block_scout_web/test/block_scout_web/schema/query/token_transfers_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/schema/query/token_transfers_test.exs
@@ -33,7 +33,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
"first" => 1
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -86,7 +86,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
"first" => 10
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -121,7 +121,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
response1 =
conn
- |> post("/graphql", query: query1, variables: variables1)
+ |> post("/api/v1/graphql", query: query1, variables: variables1)
|> json_response(200)
%{"errors" => [response1_error1, response1_error2]} = response1
@@ -150,7 +150,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
response2 =
conn
- |> post("/graphql", query: query2, variables: variables2)
+ |> post("/api/v1/graphql", query: query2, variables: variables2)
|> json_response(200)
%{"errors" => [response2_error1, response2_error2]} = response2
@@ -212,7 +212,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
[token_transfer] =
conn
- |> post("/graphql", query: query, variables: variables)
+ |> post("/api/v1/graphql", query: query, variables: variables)
|> json_response(200)
|> get_in(["data", "token_transfers", "edges"])
@@ -264,7 +264,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
"first" => 1
}
- conn = post(conn, "/graphql", query: query1, variables: variables1)
+ conn = post(conn, "/api/v1/graphql", query: query1, variables: variables1)
%{"data" => %{"token_transfers" => page1}} = json_response(conn, 200)
@@ -300,7 +300,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
"after" => last_cursor_page1
}
- conn = post(conn, "/graphql", query: query2, variables: variables2)
+ conn = post(conn, "/api/v1/graphql", query: query2, variables: variables2)
%{"data" => %{"token_transfers" => page2}} = json_response(conn, 200)
@@ -319,7 +319,7 @@ defmodule BlockScoutWeb.Schema.Query.TokenTransfersTest do
"after" => last_cursor_page2
}
- conn = post(conn, "/graphql", query: query2, variables: variables3)
+ conn = post(conn, "/api/v1/graphql", query: query2, variables: variables3)
%{"data" => %{"token_transfers" => page3}} = json_response(conn, 200)
diff --git a/apps/block_scout_web/test/block_scout_web/schema/query/transaction_test.exs b/apps/block_scout_web/test/block_scout_web/schema/query/transaction_test.exs
index 66b31d676c72..6212ca89a788 100644
--- a/apps/block_scout_web/test/block_scout_web/schema/query/transaction_test.exs
+++ b/apps/block_scout_web/test/block_scout_web/schema/query/transaction_test.exs
@@ -37,7 +37,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
variables = %{"hash" => to_string(transaction.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -78,7 +78,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
variables = %{"hash" => to_string(transaction.hash)}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] == "Transaction not found."
@@ -93,7 +93,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
}
"""
- conn = get(conn, "/graphql", query: query)
+ conn = get(conn, "/api/v1/graphql", query: query)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] == ~s(In argument "hash": Expected type "FullHash!", found null.)
@@ -110,7 +110,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
variables = %{"hash" => "0x000"}
- conn = get(conn, "/graphql", query: query, variables: variables)
+ conn = get(conn, "/api/v1/graphql", query: query, variables: variables)
assert %{"errors" => [error]} = json_response(conn, 200)
assert error["message"] =~ ~s(Argument "hash" has invalid value)
@@ -180,7 +180,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
"first" => 1
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -247,7 +247,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
"first" => 1
}
- conn = post(conn, "/graphql", query: query, variables: variables)
+ conn = post(conn, "/api/v1/graphql", query: query, variables: variables)
assert json_response(conn, 200) == %{
"data" => %{
@@ -306,7 +306,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
response =
conn
- |> post("/graphql", query: query, variables: variables)
+ |> post("/api/v1/graphql", query: query, variables: variables)
|> json_response(200)
internal_transactions = get_in(response, ["data", "transaction", "internal_transactions", "edges"])
@@ -341,7 +341,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
response1 =
conn
- |> post("/graphql", query: query1, variables: variables1)
+ |> post("/api/v1/graphql", query: query1, variables: variables1)
|> json_response(200)
assert %{"errors" => [error1, error2, error3]} = response1
@@ -372,7 +372,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
response2 =
conn
- |> post("/graphql", query: query2, variables: variables2)
+ |> post("/api/v1/graphql", query: query2, variables: variables2)
|> json_response(200)
assert %{"errors" => [error1, error2, error3]} = response2
@@ -435,7 +435,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
[internal_transaction] =
conn
- |> post("/graphql", query: query, variables: variables)
+ |> post("/api/v1/graphql", query: query, variables: variables)
|> json_response(200)
|> get_in(["data", "transaction", "internal_transactions", "edges"])
@@ -479,7 +479,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
"first" => 2
}
- conn = post(conn, "/graphql", query: query1, variables: variables1)
+ conn = post(conn, "/api/v1/graphql", query: query1, variables: variables1)
%{"data" => %{"transaction" => %{"internal_transactions" => page1}}} = json_response(conn, 200)
@@ -520,7 +520,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
page2 =
conn
- |> post("/graphql", query: query2, variables: variables2)
+ |> post("/api/v1/graphql", query: query2, variables: variables2)
|> json_response(200)
|> get_in(["data", "transaction", "internal_transactions"])
@@ -541,7 +541,7 @@ defmodule BlockScoutWeb.Schema.Query.TransactionTest do
page3 =
conn
- |> post("/graphql", query: query2, variables: variables3)
+ |> post("/api/v1/graphql", query: query2, variables: variables3)
|> json_response(200)
|> get_in(["data", "transaction", "internal_transactions"])
diff --git a/apps/ethereum_jsonrpc/config/config.exs b/apps/ethereum_jsonrpc/config/config.exs
index e578ffbea78a..503b7a3828ed 100644
--- a/apps/ethereum_jsonrpc/config/config.exs
+++ b/apps/ethereum_jsonrpc/config/config.exs
@@ -6,7 +6,6 @@ config :ethereum_jsonrpc, EthereumJSONRPC.RequestCoordinator,
duration: :timer.minutes(1),
table: EthereumJSONRPC.RequestCoordinator.TimeoutCounter
],
- wait_per_timeout: :timer.seconds(20),
max_jitter: :timer.seconds(2)
# Add this configuration to add global RPC request throttling.
diff --git a/apps/ethereum_jsonrpc/config/runtime/test.exs b/apps/ethereum_jsonrpc/config/runtime/test.exs
index e2043f6c1435..081c952dfc9d 100644
--- a/apps/ethereum_jsonrpc/config/runtime/test.exs
+++ b/apps/ethereum_jsonrpc/config/runtime/test.exs
@@ -2,6 +2,8 @@ import Config
alias EthereumJSONRPC.Variant
+config :ethereum_jsonrpc, EthereumJSONRPC.RequestCoordinator, wait_per_timeout: 2
+
variant = Variant.get()
Code.require_file("#{variant}.exs", "#{__DIR__}/../../../explorer/config/test")
diff --git a/apps/ethereum_jsonrpc/config/test.exs b/apps/ethereum_jsonrpc/config/test.exs
index 0ed3de28b282..61e5f67398a0 100644
--- a/apps/ethereum_jsonrpc/config/test.exs
+++ b/apps/ethereum_jsonrpc/config/test.exs
@@ -6,7 +6,6 @@ config :ethereum_jsonrpc, EthereumJSONRPC.RequestCoordinator,
duration: :timer.seconds(6),
table: EthereumJSONRPC.RequestCoordinator.TimeoutCounter
],
- wait_per_timeout: 2,
max_jitter: 1,
# This should not actually limit anything in tests, but it is here to enable the relevant code for testing
throttle_rate_limit: 10_000,
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex
index 2a6ebeeb397d..4a59a80e9c7d 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex
@@ -275,6 +275,16 @@ defmodule EthereumJSONRPC do
|> fetch_blocks_by_params(&Block.ByNumber.request/1, json_rpc_named_arguments)
end
+ @doc """
+ Fetches block by "t:tag/0".
+ """
+ @spec fetch_block_by_tag(tag(), json_rpc_named_arguments) ::
+ {:ok, Blocks.t()} | {:error, reason :: :invalid_tag | :not_found | term()}
+ def fetch_block_by_tag(tag, json_rpc_named_arguments) when tag in ~w(earliest latest pending) do
+ [%{tag: tag}]
+ |> fetch_blocks_by_params(&Block.ByTag.request/1, json_rpc_named_arguments)
+ end
+
@doc """
Fetches uncle blocks by nephew hashes and indices.
"""
@@ -310,9 +320,8 @@ defmodule EthereumJSONRPC do
@spec fetch_block_number_by_tag(tag(), json_rpc_named_arguments) ::
{:ok, non_neg_integer()} | {:error, reason :: :invalid_tag | :not_found | term()}
def fetch_block_number_by_tag(tag, json_rpc_named_arguments) when tag in ~w(earliest latest pending) do
- %{id: 0, tag: tag}
- |> Block.ByTag.request()
- |> json_rpc(json_rpc_named_arguments)
+ tag
+ |> fetch_block_by_tag(json_rpc_named_arguments)
|> Block.ByTag.number_from_result()
end
diff --git a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block/by_tag.ex b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block/by_tag.ex
index fa4a9b83c990..d257f4e506c5 100644
--- a/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block/by_tag.ex
+++ b/apps/ethereum_jsonrpc/lib/ethereum_jsonrpc/block/by_tag.ex
@@ -5,6 +5,7 @@ defmodule EthereumJSONRPC.Block.ByTag do
"""
import EthereumJSONRPC, only: [quantity_to_integer: 1]
+ alias EthereumJSONRPC.Blocks
def request(%{id: id, tag: tag}) when is_binary(tag) do
EthereumJSONRPC.request(%{id: id, method: "eth_getBlockByNumber", params: [tag, false]})
@@ -16,6 +17,10 @@ defmodule EthereumJSONRPC.Block.ByTag do
{:ok, quantity_to_integer(quantity)}
end
+ def number_from_result({:ok, %Blocks{blocks_params: []}}), do: {:error, :not_found}
+
+ def number_from_result({:ok, %Blocks{blocks_params: [%{number: number}]}}), do: {:ok, number}
+
def number_from_result({:ok, nil}), do: {:error, :not_found}
def number_from_result({:error, %{"code" => -32602}}), do: {:error, :invalid_tag}
diff --git a/apps/ethereum_jsonrpc/mix.exs b/apps/ethereum_jsonrpc/mix.exs
index 752c6465f656..5c4003d17880 100644
--- a/apps/ethereum_jsonrpc/mix.exs
+++ b/apps/ethereum_jsonrpc/mix.exs
@@ -23,7 +23,7 @@ defmodule EthereumJsonrpc.MixProject do
dialyzer: :test
],
start_permanent: Mix.env() == :prod,
- version: "5.2.1"
+ version: "5.2.2"
]
end
diff --git a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/mox_test.exs b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/mox_test.exs
index 2ad5b8f52c20..f0c4fbaf2d65 100644
--- a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/mox_test.exs
+++ b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc/mox_test.exs
@@ -21,8 +21,15 @@ defmodule EthereumJSONRPC.MoxTest do
describe "fetch_block_number_by_tag/2" do
test "with pending with null result", %{json_rpc_named_arguments: json_rpc_named_arguments} do
- expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options ->
- {:ok, nil}
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [
+ %{
+ id: id,
+ method: "eth_getBlockByNumber",
+ params: ["pending", false]
+ }
+ ],
+ _options ->
+ {:ok, [%{id: id, result: nil}]}
end)
assert {:error, :not_found} = EthereumJSONRPC.fetch_block_number_by_tag("pending", json_rpc_named_arguments)
diff --git a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc_test.exs b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc_test.exs
index bc77cabd5c6a..7299d48478fb 100644
--- a/apps/ethereum_jsonrpc/test/ethereum_jsonrpc_test.exs
+++ b/apps/ethereum_jsonrpc/test/ethereum_jsonrpc_test.exs
@@ -2,6 +2,7 @@ defmodule EthereumJSONRPCTest do
use EthereumJSONRPC.Case, async: true
import EthereumJSONRPC.Case
+ import EthereumJSONRPC, only: [quantity_to_integer: 1]
import Mox
alias EthereumJSONRPC.{Blocks, FetchedBalances, FetchedBeneficiaries, FetchedCodes, Subscription}
@@ -543,61 +544,92 @@ defmodule EthereumJSONRPCTest do
end
end
- describe "fetch_block_number_by_tag" do
- @tag capture_log: false
- test "with earliest", %{json_rpc_named_arguments: json_rpc_named_arguments} do
- if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
- expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options ->
- {:ok, %{"number" => "0x0"}}
- end)
- end
+ describe "fetch_block_by_tag/2" do
+ @supported_tags ~w(earliest latest pending)
- log_bad_gateway(
- fn -> EthereumJSONRPC.fetch_block_number_by_tag("earliest", json_rpc_named_arguments) end,
- fn result ->
- assert {:ok, 0} = result
+ @tag capture_log: false
+ test "with all supported tags", %{json_rpc_named_arguments: json_rpc_named_arguments} do
+ for tag <- @supported_tags do
+ if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [
+ %{
+ id: id,
+ method: "eth_getBlockByNumber",
+ params: [^tag, false]
+ }
+ ],
+ _options ->
+ block_response(id, tag == "pending", "0x1")
+ end)
end
- )
- end
- @tag capture_log: false
- test "with latest", %{json_rpc_named_arguments: json_rpc_named_arguments} do
- if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
- expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options ->
- {:ok, %{"number" => "0x1"}}
- end)
+ log_bad_gateway(
+ fn -> EthereumJSONRPC.fetch_block_by_tag(tag, json_rpc_named_arguments) end,
+ fn result ->
+ {:ok, %Blocks{blocks_params: [_ | _], transactions_params: []}} = result
+ end
+ )
end
+ end
- log_bad_gateway(
- fn -> EthereumJSONRPC.fetch_block_number_by_tag("latest", json_rpc_named_arguments) end,
- fn result ->
- assert {:ok, number} = result
- assert number > 0
- end
- )
+ test "unknown errors are returned", %{json_rpc_named_arguments: json_rpc_named_arguments} do
+ # Can't be faked reliably on real chain
+ moxed_json_rpc_named_arguments = Keyword.put(json_rpc_named_arguments, :transport, EthereumJSONRPC.Mox)
+
+ unknown_error = %{"code" => 500, "message" => "Unknown error"}
+
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options ->
+ {:error, unknown_error}
+ end)
+
+ assert {:error, ^unknown_error} = EthereumJSONRPC.fetch_block_by_tag("latest", moxed_json_rpc_named_arguments)
end
+ end
- @tag capture_log: false
- test "with pending", %{json_rpc_named_arguments: json_rpc_named_arguments} do
- if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
- expect(EthereumJSONRPC.Mox, :json_rpc, fn _json, _options ->
- {:ok, nil}
- end)
- end
+ describe "fetch_block_number_by_tag" do
+ @supported_tags %{"earliest" => "0x0", "latest" => "0x1", "pending" => nil}
- log_bad_gateway(
- fn -> EthereumJSONRPC.fetch_block_number_by_tag("pending", json_rpc_named_arguments) end,
- fn
- # Parity after https://github.com/paritytech/parity-ethereum/pull/8281 and anything spec-compliant
- {:error, reason} ->
- assert reason == :not_found
-
- # Parity before https://github.com/paritytech/parity-ethereum/pull/8281
- {:ok, number} ->
- assert is_integer(number)
- assert number > 0
+ @tag capture_log: false
+ test "with all supported tags", %{json_rpc_named_arguments: json_rpc_named_arguments} do
+ for {tag, expected_result} <- @supported_tags do
+ if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [
+ %{
+ id: id,
+ method: "eth_getBlockByNumber",
+ params: [^tag, false]
+ }
+ ],
+ _options ->
+ if tag == "pending" do
+ {:ok, [%{id: id, result: nil}]}
+ else
+ block_response(id, false, expected_result)
+ end
+ end)
end
- )
+
+ log_bad_gateway(
+ fn -> EthereumJSONRPC.fetch_block_number_by_tag(tag, json_rpc_named_arguments) end,
+ if tag == "pending" do
+ fn
+ # Parity after https://github.com/paritytech/parity-ethereum/pull/8281 and anything spec-compliant
+ {:error, reason} ->
+ assert reason == :not_found
+
+ # Parity before https://github.com/paritytech/parity-ethereum/pull/8281
+ {:ok, number} ->
+ assert is_integer(number)
+ assert number > 0
+ end
+ else
+ fn result ->
+ integer_result = expected_result && quantity_to_integer(expected_result)
+ assert {:ok, ^integer_result} = result
+ end
+ end
+ )
+ end
end
test "unknown errors are returned", %{json_rpc_named_arguments: json_rpc_named_arguments} do
@@ -912,12 +944,43 @@ defmodule EthereumJSONRPCTest do
:ok
end
end
+
+ defp block_response(id, pending, block_number) do
+ block_hash = "0x29c850324e357f3c0c836d79860c5af55f7b651e5d7ee253c1af1b14908af49c"
+ transaction_hash = "0xa2e81bb56b55ba3dab2daf76501b50dfaad240cccb905dbf89d65c7a84a4a48e"
+
+ {:ok,
+ [
+ %{
+ id: id,
+ result: %{
+ "difficulty" => "0x0",
+ "gasLimit" => "0x0",
+ "gasUsed" => "0x0",
+ "hash" => if(pending, do: nil, else: block_hash),
+ "extraData" => "0x0",
+ "logsBloom" => "0x0",
+ "miner" => "0x0",
+ "number" => block_number,
+ "parentHash" => "0x0",
+ "receiptsRoot" => "0x0",
+ "size" => "0x0",
+ "sha3Uncles" => "0x0",
+ "stateRoot" => "0x0",
+ "timestamp" => "0x0",
+ "totalDifficulty" => "0x0",
+ "transactions" => [transaction_hash],
+ "transactionsRoot" => "0x0",
+ "uncles" => []
+ }
+ }
+ ]}
+ end
end
defmodule EthereumJSONRPCSyncTest do
use EthereumJSONRPC.Case, async: false
- import EthereumJSONRPC.Case
import Mox
alias EthereumJSONRPC.FetchedBalances
diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex
index dd4200d0f0c0..264ce9d67b1d 100644
--- a/apps/explorer/lib/explorer/chain.ex
+++ b/apps/explorer/lib/explorer/chain.ex
@@ -55,6 +55,7 @@ defmodule Explorer.Chain do
InternalTransaction,
Log,
PendingBlockOperation,
+ Search,
SmartContract,
SmartContractAdditionalSource,
Token,
@@ -81,24 +82,15 @@ defmodule Explorer.Chain do
}
alias Explorer.Chain.Cache.Block, as: BlockCache
- alias Explorer.Chain.Cache.Helper, as: CacheHelper
alias Explorer.Chain.Cache.PendingBlockOperation, as: PendingBlockOperationCache
alias Explorer.Chain.Fetcher.{CheckBytecodeMatchingOnDemand, LookUpSmartContractSourcesOnDemand}
alias Explorer.Chain.Import.Runner
alias Explorer.Chain.InternalTransaction.{CallType, Type}
- alias Explorer.Counters.{
- AddressesCounter,
- AddressesWithBalanceCounter,
- AddressTokenTransfersCounter,
- AddressTransactionsCounter,
- AddressTransactionsGasUsageCounter
- }
-
alias Explorer.Market.MarketHistoryCache
alias Explorer.{PagingOptions, Repo}
alias Explorer.SmartContract.Helper
- alias Explorer.Tags.{AddressTag, AddressToTag}
+ alias Explorer.SmartContract.Solidity.Verifier
alias Dataloader.Ecto, as: DataloaderEcto
@@ -121,8 +113,6 @@ defmodule Explorer.Chain do
"commit" => "f14fcbc8"
}
- @max_incoming_transactions_count 10_000
-
@revert_msg_prefix_1 "Revert: "
@revert_msg_prefix_2 "revert: "
@revert_msg_prefix_3 "reverted "
@@ -178,56 +168,7 @@ defmodule Explorer.Chain do
@typep necessity_by_association_option :: {:necessity_by_association, necessity_by_association}
@typep paging_options :: {:paging_options, PagingOptions.t()}
@typep balance_by_day :: %{date: String.t(), value: Wei.t()}
- @typep api? :: {:api?, true | false}
-
- @doc """
- Gets from the cache the count of `t:Explorer.Chain.Address.t/0`'s where the `fetched_coin_balance` is > 0
- """
- @spec count_addresses_with_balance_from_cache :: non_neg_integer()
- def count_addresses_with_balance_from_cache do
- AddressesWithBalanceCounter.fetch()
- end
-
- @doc """
- Estimated count of `t:Explorer.Chain.Address.t/0`.
-
- Estimated count of addresses.
- """
- @spec address_estimated_count() :: non_neg_integer()
- def address_estimated_count(options \\ []) do
- cached_value = AddressesCounter.fetch()
-
- if is_nil(cached_value) || cached_value == 0 do
- count = CacheHelper.estimated_count_from("addresses", options)
-
- max(count, 0)
- else
- cached_value
- end
- end
-
- @doc """
- Counts the number of addresses with fetched coin balance > 0.
-
- This function should be used with caution. In larger databases, it may take a
- while to have the return back.
- """
- def count_addresses_with_balance do
- Repo.one(
- Address.count_with_fetched_coin_balance(),
- timeout: :infinity
- )
- end
-
- @doc """
- Counts the number of all addresses.
-
- This function should be used with caution. In larger databases, it may take a
- while to have the return back.
- """
- def count_addresses do
- Repo.aggregate(Address, :count, timeout: :infinity)
- end
+ @type api? :: {:api?, true | false}
@doc """
`t:Explorer.Chain.InternalTransaction/0`s from the address with the given `hash`.
@@ -326,25 +267,6 @@ defmodule Explorer.Chain do
)
end
- @doc """
- Get the total number of transactions sent by the address with the given hash according to the last block indexed.
-
- We have to increment +1 in the last nonce result because it works like an array position, the first
- nonce has the value 0. When last nonce is nil, it considers that the given address has 0 transactions.
- """
- @spec total_transactions_sent_by_address(Hash.Address.t()) :: non_neg_integer()
- def total_transactions_sent_by_address(address_hash) do
- last_nonce =
- address_hash
- |> Transaction.last_nonce_by_address_query()
- |> Repo.one(timeout: :infinity)
-
- case last_nonce do
- nil -> 0
- value -> value + 1
- end
- end
-
@doc """
Fetches the transactions related to the address with the given hash, including
transactions that only have the address in the `token_transfers` related table
@@ -1027,53 +949,6 @@ defmodule Explorer.Chain do
|> select_repo(options).exists?()
end
- @spec address_to_incoming_transaction_count(Hash.Address.t()) :: non_neg_integer()
- def address_to_incoming_transaction_count(address_hash) do
- to_address_query =
- from(
- transaction in Transaction,
- where: transaction.to_address_hash == ^address_hash
- )
-
- Repo.aggregate(to_address_query, :count, :hash, timeout: :infinity)
- end
-
- @spec address_hash_to_transaction_count(Hash.Address.t()) :: non_neg_integer()
- def address_hash_to_transaction_count(address_hash) do
- query =
- from(
- transaction in Transaction,
- where: transaction.to_address_hash == ^address_hash or transaction.from_address_hash == ^address_hash
- )
-
- Repo.aggregate(query, :count, :hash, timeout: :infinity)
- end
-
- @spec address_to_incoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil
- def address_to_incoming_transaction_gas_usage(address_hash) do
- to_address_query =
- from(
- transaction in Transaction,
- where: transaction.to_address_hash == ^address_hash
- )
-
- Repo.aggregate(to_address_query, :sum, :gas_used, timeout: :infinity)
- end
-
- @spec address_to_outcoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil
- def address_to_outcoming_transaction_gas_usage(address_hash) do
- to_address_query =
- from(
- transaction in Transaction,
- where: transaction.from_address_hash == ^address_hash
- )
-
- Repo.aggregate(to_address_query, :sum, :gas_used, timeout: :infinity)
- end
-
- @spec max_incoming_transactions_count() :: non_neg_integer()
- def max_incoming_transactions_count, do: @max_incoming_transactions_count
-
@doc """
How many blocks have confirmed `block` based on the current `max_block_number`
@@ -1472,328 +1347,6 @@ defmodule Explorer.Chain do
end
end
- defp prepare_search_term(string) do
- case Regex.scan(~r/[a-zA-Z0-9]+/, string) do
- [_ | _] = words ->
- term_final =
- words
- |> Enum.map_join(" & ", fn [word] -> word <> ":*" end)
-
- {:some, term_final}
-
- _ ->
- :none
- end
- end
-
- def search_label_query(term) do
- inner_query =
- from(tag in AddressTag,
- where: fragment("to_tsvector('english', ?) @@ to_tsquery(?)", tag.display_name, ^term),
- select: tag
- )
-
- from(att in AddressToTag,
- inner_join: at in subquery(inner_query),
- on: att.tag_id == at.id,
- left_join: smart_contract in SmartContract,
- on: att.address_hash == smart_contract.address_hash,
- select: %{
- address_hash: att.address_hash,
- tx_hash: fragment("CAST(NULL AS bytea)"),
- block_hash: fragment("CAST(NULL AS bytea)"),
- type: "label",
- name: at.display_name,
- symbol: ^nil,
- holder_count: ^nil,
- inserted_at: att.inserted_at,
- block_number: 0,
- icon_url: nil,
- token_type: nil,
- timestamp: fragment("NULL::timestamp without time zone"),
- verified: not is_nil(smart_contract),
- exchange_rate: nil,
- total_supply: nil,
- circulating_market_cap: nil,
- priority: 1
- }
- )
- end
-
- defp search_token_query(term) do
- from(token in Token,
- left_join: smart_contract in SmartContract,
- on: token.contract_address_hash == smart_contract.address_hash,
- where: fragment("to_tsvector('english', ? || ' ' || ?) @@ to_tsquery(?)", token.symbol, token.name, ^term),
- select: %{
- address_hash: token.contract_address_hash,
- tx_hash: fragment("CAST(NULL AS bytea)"),
- block_hash: fragment("CAST(NULL AS bytea)"),
- type: "token",
- name: token.name,
- symbol: token.symbol,
- holder_count: token.holder_count,
- inserted_at: token.inserted_at,
- block_number: 0,
- icon_url: token.icon_url,
- token_type: token.type,
- timestamp: fragment("NULL::timestamp without time zone"),
- verified: not is_nil(smart_contract),
- exchange_rate: token.fiat_value,
- total_supply: token.total_supply,
- circulating_market_cap: token.circulating_market_cap,
- priority: 0
- }
- )
- end
-
- defp search_contract_query(term) do
- from(smart_contract in SmartContract,
- left_join: address in Address,
- on: smart_contract.address_hash == address.hash,
- where: fragment("to_tsvector('english', ?) @@ to_tsquery(?)", smart_contract.name, ^term),
- select: %{
- address_hash: smart_contract.address_hash,
- tx_hash: fragment("CAST(NULL AS bytea)"),
- block_hash: fragment("CAST(NULL AS bytea)"),
- type: "contract",
- name: smart_contract.name,
- symbol: ^nil,
- holder_count: ^nil,
- inserted_at: address.inserted_at,
- block_number: 0,
- icon_url: nil,
- token_type: nil,
- timestamp: fragment("NULL::timestamp without time zone"),
- verified: true,
- exchange_rate: nil,
- total_supply: nil,
- circulating_market_cap: nil,
- priority: 0
- }
- )
- end
-
- defp search_address_query(term) do
- case Chain.string_to_address_hash(term) do
- {:ok, address_hash} ->
- from(address in Address,
- left_join:
- address_name in subquery(
- from(name in Address.Name,
- where: name.address_hash == ^address_hash,
- order_by: [desc: name.primary],
- limit: 1
- )
- ),
- on: address.hash == address_name.address_hash,
- where: address.hash == ^address_hash,
- select: %{
- address_hash: address.hash,
- tx_hash: fragment("CAST(NULL AS bytea)"),
- block_hash: fragment("CAST(NULL AS bytea)"),
- type: "address",
- name: address_name.name,
- symbol: ^nil,
- holder_count: ^nil,
- inserted_at: address.inserted_at,
- block_number: 0,
- icon_url: nil,
- token_type: nil,
- timestamp: fragment("NULL::timestamp without time zone"),
- verified: address.verified,
- exchange_rate: nil,
- total_supply: nil,
- circulating_market_cap: nil,
- priority: 0
- }
- )
-
- _ ->
- nil
- end
- end
-
- defp search_tx_query(term) do
- case Chain.string_to_transaction_hash(term) do
- {:ok, tx_hash} ->
- from(transaction in Transaction,
- left_join: block in Block,
- on: transaction.block_hash == block.hash,
- where: transaction.hash == ^tx_hash,
- select: %{
- address_hash: fragment("CAST(NULL AS bytea)"),
- tx_hash: transaction.hash,
- block_hash: fragment("CAST(NULL AS bytea)"),
- type: "transaction",
- name: ^nil,
- symbol: ^nil,
- holder_count: ^nil,
- inserted_at: transaction.inserted_at,
- block_number: 0,
- icon_url: nil,
- token_type: nil,
- timestamp: block.timestamp,
- verified: nil,
- exchange_rate: nil,
- total_supply: nil,
- circulating_market_cap: nil,
- priority: 0
- }
- )
-
- _ ->
- nil
- end
- end
-
- defp search_block_query(term) do
- case Chain.string_to_block_hash(term) do
- {:ok, block_hash} ->
- from(block in Block,
- where: block.hash == ^block_hash,
- select: %{
- address_hash: fragment("CAST(NULL AS bytea)"),
- tx_hash: fragment("CAST(NULL AS bytea)"),
- block_hash: block.hash,
- type: "block",
- name: ^nil,
- symbol: ^nil,
- holder_count: ^nil,
- inserted_at: block.inserted_at,
- block_number: block.number,
- icon_url: nil,
- token_type: nil,
- timestamp: block.timestamp,
- verified: nil,
- exchange_rate: nil,
- total_supply: nil,
- circulating_market_cap: nil,
- priority: 0
- }
- )
-
- _ ->
- case Integer.parse(term) do
- {block_number, ""} ->
- from(block in Block,
- where: block.number == ^block_number,
- select: %{
- address_hash: fragment("CAST(NULL AS bytea)"),
- tx_hash: fragment("CAST(NULL AS bytea)"),
- block_hash: block.hash,
- type: "block",
- name: ^nil,
- symbol: ^nil,
- holder_count: ^nil,
- inserted_at: block.inserted_at,
- block_number: block.number,
- icon_url: nil,
- token_type: nil,
- timestamp: block.timestamp,
- verified: nil,
- exchange_rate: nil,
- total_supply: nil,
- circulating_market_cap: nil,
- priority: 0
- }
- )
-
- _ ->
- nil
- end
- end
- end
-
- def joint_search(paging_options, offset, raw_string, options \\ []) do
- string = String.trim(raw_string)
-
- case prepare_search_term(string) do
- {:some, term} ->
- tokens_query = search_token_query(term)
- contracts_query = search_contract_query(term)
- labels_query = search_label_query(term)
- tx_query = search_tx_query(string)
- address_query = search_address_query(string)
- block_query = search_block_query(string)
-
- basic_query =
- from(
- tokens in subquery(tokens_query),
- union: ^contracts_query,
- union: ^labels_query
- )
-
- query =
- cond do
- address_query ->
- basic_query
- |> union(^address_query)
-
- tx_query ->
- basic_query
- |> union(^tx_query)
- |> union(^block_query)
-
- block_query ->
- basic_query
- |> union(^block_query)
-
- true ->
- basic_query
- end
-
- ordered_query =
- from(items in subquery(query),
- order_by: [
- desc: items.priority,
- desc_nulls_last: items.circulating_market_cap,
- desc_nulls_last: items.exchange_rate,
- desc_nulls_last: items.holder_count,
- asc: items.name,
- desc: items.inserted_at
- ],
- limit: ^paging_options.page_size,
- offset: ^offset
- )
-
- paginated_ordered_query =
- ordered_query
- |> page_search_results(paging_options)
-
- search_results = select_repo(options).all(paginated_ordered_query)
-
- search_results
- |> Enum.map(fn result ->
- result
- |> compose_result_checksummed_address_hash()
- |> format_timestamp()
- end)
-
- _ ->
- []
- end
- end
-
- defp compose_result_checksummed_address_hash(result) do
- if result.address_hash do
- result
- |> Map.put(:address_hash, Address.checksum(result.address_hash))
- else
- result
- end
- end
-
- # For some reasons timestamp for blocks and txs returns as ~N[2023-06-25 19:39:47.339493]
- defp format_timestamp(result) do
- if result.timestamp do
- result
- |> Map.put(:timestamp, DateTime.from_naive!(result.timestamp, "Etc/UTC"))
- else
- result
- end
- end
-
@doc """
Converts `t:Explorer.Chain.Address.t/0` `hash` to the `t:Explorer.Chain.Address.t/0` with that `hash`.
@@ -1913,7 +1466,7 @@ defmodule Explorer.Chain do
if smart_contract do
CheckBytecodeMatchingOnDemand.trigger_check(address_result, smart_contract)
LookUpSmartContractSourcesOnDemand.trigger_fetch(address_result, smart_contract)
- address_result
+ check_and_update_constructor_args(address_result)
else
LookUpSmartContractSourcesOnDemand.trigger_fetch(address_result, nil)
@@ -1936,6 +1489,36 @@ defmodule Explorer.Chain do
end
end
+ defp check_and_update_constructor_args(
+ %SmartContract{address_hash: address_hash, constructor_arguments: nil, verified_via_sourcify: true} =
+ smart_contract
+ ) do
+ if args = Verifier.parse_constructor_arguments_for_sourcify_contract(address_hash, smart_contract.abi) do
+ smart_contract |> SmartContract.changeset(%{constructor_arguments: args}) |> Repo.update()
+ %SmartContract{smart_contract | constructor_arguments: args}
+ else
+ smart_contract
+ end
+ end
+
+ defp check_and_update_constructor_args(
+ %Address{
+ hash: address_hash,
+ contract_code: deployed_bytecode,
+ smart_contract: %SmartContract{constructor_arguments: nil, verified_via_sourcify: true} = smart_contract
+ } = address
+ ) do
+ if args =
+ Verifier.parse_constructor_arguments_for_sourcify_contract(address_hash, smart_contract.abi, deployed_bytecode) do
+ smart_contract |> SmartContract.changeset(%{constructor_arguments: args}) |> Repo.update()
+ %Address{address | smart_contract: %SmartContract{smart_contract | constructor_arguments: args}}
+ else
+ address
+ end
+ end
+
+ defp check_and_update_constructor_args(other), do: other
+
defp add_twin_info_to_contract(address_result, address_verified_twin_contract, _hash)
when is_nil(address_verified_twin_contract),
do: address_result
@@ -2510,7 +2093,7 @@ defmodule Explorer.Chain do
query =
if filter && filter !== "" do
- case prepare_search_term(filter) do
+ case Search.prepare_search_term(filter) do
{:some, filter_term} ->
base_query_with_paging
|> where(fragment("to_tsvector('english', symbol || ' ' || name) @@ to_tsquery(?)", ^filter_term))
@@ -2574,56 +2157,6 @@ defmodule Explorer.Chain do
|> select_repo(options).all()
end
- def check_if_validated_blocks_at_address(address_hash, options \\ []) do
- select_repo(options).exists?(from(b in Block, where: b.miner_hash == ^address_hash))
- end
-
- def check_if_logs_at_address(address_hash, options \\ []) do
- select_repo(options).exists?(from(l in Log, where: l.address_hash == ^address_hash))
- end
-
- def check_if_internal_transactions_at_address(address_hash) do
- internal_transactions_exists_by_created_contract_address_hash =
- Repo.exists?(from(it in InternalTransaction, where: it.created_contract_address_hash == ^address_hash))
-
- internal_transactions_exists_by_from_address_hash =
- Repo.exists?(from(it in InternalTransaction, where: it.from_address_hash == ^address_hash))
-
- internal_transactions_exists_by_to_address_hash =
- Repo.exists?(from(it in InternalTransaction, where: it.to_address_hash == ^address_hash))
-
- internal_transactions_exists_by_created_contract_address_hash || internal_transactions_exists_by_from_address_hash ||
- internal_transactions_exists_by_to_address_hash
- end
-
- def check_if_token_transfers_at_address(address_hash, options \\ []) do
- token_transfers_exists_by_from_address_hash =
- select_repo(options).exists?(from(tt in TokenTransfer, where: tt.from_address_hash == ^address_hash))
-
- token_transfers_exists_by_to_address_hash =
- select_repo(options).exists?(from(tt in TokenTransfer, where: tt.to_address_hash == ^address_hash))
-
- token_transfers_exists_by_from_address_hash ||
- token_transfers_exists_by_to_address_hash
- end
-
- def check_if_tokens_at_address(address_hash, options \\ []) do
- select_repo(options).exists?(
- from(
- tb in CurrentTokenBalance,
- where: tb.address_hash == ^address_hash,
- where: tb.value > 0
- )
- )
- end
-
- @spec check_if_withdrawals_at_address(Hash.Address.t()) :: boolean()
- def check_if_withdrawals_at_address(address_hash, options \\ []) do
- address_hash
- |> Withdrawal.address_hash_to_withdrawals_unordered_query()
- |> select_repo(options).exists?()
- end
-
@doc """
Counts all of the block validations and groups by the `miner_hash`.
"""
@@ -2640,53 +2173,6 @@ defmodule Explorer.Chain do
Repo.stream_each(query, fun)
end
- @doc """
- Counts the number of `t:Explorer.Chain.Block.t/0` validated by the address with the given `hash`.
- """
- @spec address_to_validation_count(Hash.Address.t(), [api?]) :: non_neg_integer()
- def address_to_validation_count(hash, options) do
- query = from(block in Block, where: block.miner_hash == ^hash, select: fragment("COUNT(*)"))
-
- select_repo(options).one(query)
- end
-
- @spec address_to_transaction_count(Address.t()) :: non_neg_integer()
- def address_to_transaction_count(address) do
- address_hash_to_transaction_count(address.hash)
- end
-
- @spec address_to_token_transfer_count(Address.t()) :: non_neg_integer()
- def address_to_token_transfer_count(address) do
- query =
- from(
- token_transfer in TokenTransfer,
- where: token_transfer.to_address_hash == ^address.hash,
- or_where: token_transfer.from_address_hash == ^address.hash
- )
-
- Repo.aggregate(query, :count, timeout: :infinity)
- end
-
- @spec address_to_gas_usage_count(Address.t()) :: Decimal.t() | nil
- def address_to_gas_usage_count(address) do
- if contract?(address) do
- incoming_transaction_gas_usage = address_to_incoming_transaction_gas_usage(address.hash)
-
- cond do
- !incoming_transaction_gas_usage ->
- address_to_outcoming_transaction_gas_usage(address.hash)
-
- Decimal.compare(incoming_transaction_gas_usage, 0) == :eq ->
- address_to_outcoming_transaction_gas_usage(address.hash)
-
- true ->
- incoming_transaction_gas_usage
- end
- else
- address_to_outcoming_transaction_gas_usage(address.hash)
- end
- end
-
@doc """
Return the balance in usd corresponding to this token. Return nil if the fiat_value of the token is not present.
"""
@@ -2703,9 +2189,9 @@ defmodule Explorer.Chain do
Decimal.mult(tokens, fiat_value)
end
- defp contract?(%{contract_code: nil}), do: false
+ def contract?(%{contract_code: nil}), do: false
- defp contract?(%{contract_code: _}), do: true
+ def contract?(%{contract_code: _}), do: true
@doc """
Returns a stream of unfetched `t:Explorer.Chain.Address.CoinBalance.t/0`.
@@ -4310,7 +3796,7 @@ defmodule Explorer.Chain do
verified_contract_twin_additional_sources = get_contract_additional_sources(verified_contract_twin, options)
%{
- :verified_contract => verified_contract_twin,
+ :verified_contract => check_and_update_constructor_args(verified_contract_twin),
:additional_sources => verified_contract_twin_additional_sources
}
else
@@ -4772,37 +4258,6 @@ defmodule Explorer.Chain do
where(query, [transaction], transaction.index < ^index)
end
- defp page_search_results(query, %PagingOptions{key: nil}), do: query
-
- defp page_search_results(query, %PagingOptions{
- key: {_address_hash, _tx_hash, _block_hash, holder_count, name, inserted_at, item_type}
- })
- when holder_count in [nil, ""] do
- where(
- query,
- [item],
- (item.name > ^name and item.type == ^item_type) or
- (item.name == ^name and item.inserted_at < ^inserted_at and
- item.type == ^item_type) or
- item.type != ^item_type
- )
- end
-
- # credo:disable-for-next-line
- defp page_search_results(query, %PagingOptions{
- key: {_address_hash, _tx_hash, _block_hash, holder_count, name, inserted_at, item_type}
- }) do
- where(
- query,
- [item],
- (item.holder_count < ^holder_count and item.type == ^item_type) or
- (item.holder_count == ^holder_count and item.name > ^name and item.type == ^item_type) or
- (item.holder_count == ^holder_count and item.name == ^name and item.inserted_at < ^inserted_at and
- item.type == ^item_type) or
- item.type != ^item_type
- )
- end
-
def page_token_balances(query, %PagingOptions{key: nil}), do: query
def page_token_balances(query, %PagingOptions{key: {value, address_hash}}) do
@@ -5295,6 +4750,13 @@ defmodule Explorer.Chain do
end
end
+ @spec fetch_last_token_balances_include_unfetched(Hash.Address.t(), [api?]) :: []
+ def fetch_last_token_balances_include_unfetched(address_hash, options \\ []) do
+ address_hash
+ |> CurrentTokenBalance.last_token_balances_include_unfetched()
+ |> select_repo(options).all()
+ end
+
@spec fetch_last_token_balances(Hash.Address.t(), [api?]) :: []
def fetch_last_token_balances(address_hash, options \\ []) do
address_hash
@@ -5578,7 +5040,7 @@ defmodule Explorer.Chain do
def count_token_holders_from_token_hash(contract_address_hash) do
query =
from(ctb in CurrentTokenBalance.token_holders_query_for_count(contract_address_hash),
- select: fragment("COUNT(DISTINCT(address_hash))")
+ select: fragment("COUNT(DISTINCT(?))", ctb.address_hash)
)
Repo.one!(query, timeout: :infinity)
@@ -6650,55 +6112,6 @@ defmodule Explorer.Chain do
NewContractsCounter.fetch(options)
end
- def address_counters(address, options \\ []) do
- validation_count_task =
- Task.async(fn ->
- address_to_validation_count(address.hash, options)
- end)
-
- Task.start_link(fn ->
- transaction_count(address)
- end)
-
- Task.start_link(fn ->
- token_transfers_count(address)
- end)
-
- Task.start_link(fn ->
- gas_usage_count(address)
- end)
-
- [
- validation_count_task
- ]
- |> Task.yield_many(:infinity)
- |> Enum.map(fn {_task, res} ->
- case res do
- {:ok, result} ->
- result
-
- {:exit, reason} ->
- raise "Query fetching address counters terminated: #{inspect(reason)}"
-
- nil ->
- raise "Query fetching address counters timed out."
- end
- end)
- |> List.to_tuple()
- end
-
- def transaction_count(address) do
- AddressTransactionsCounter.fetch(address)
- end
-
- def token_transfers_count(address) do
- AddressTokenTransfersCounter.fetch(address)
- end
-
- def gas_usage_count(address) do
- AddressTransactionsGasUsageCounter.fetch(address)
- end
-
def fetch_token_counters(address_hash, timeout) do
total_token_transfers_task =
Task.async(fn ->
diff --git a/apps/explorer/lib/explorer/chain/address/coin_balance.ex b/apps/explorer/lib/explorer/chain/address/coin_balance.ex
index bab4a62b6291..b2e5a46f263e 100644
--- a/apps/explorer/lib/explorer/chain/address/coin_balance.ex
+++ b/apps/explorer/lib/explorer/chain/address/coin_balance.ex
@@ -155,7 +155,6 @@ defmodule Explorer.Chain.Address.CoinBalance do
balance
|> cast(params, @allowed_fields)
|> validate_required(@required_fields)
- |> foreign_key_constraint(:address_hash)
|> unique_constraint(:block_number, name: :address_coin_balances_address_hash_block_number_index)
end
end
diff --git a/apps/explorer/lib/explorer/chain/address/coin_balance_daily.ex b/apps/explorer/lib/explorer/chain/address/coin_balance_daily.ex
index 0aab03e3619a..cc881d9c471d 100644
--- a/apps/explorer/lib/explorer/chain/address/coin_balance_daily.ex
+++ b/apps/explorer/lib/explorer/chain/address/coin_balance_daily.ex
@@ -69,7 +69,6 @@ defmodule Explorer.Chain.Address.CoinBalanceDaily do
balance
|> cast(params, @allowed_fields)
|> validate_required(@required_fields)
- |> foreign_key_constraint(:address_hash)
|> unique_constraint(:day, name: :address_coin_balances_daily_address_hash_day_index)
end
end
diff --git a/apps/explorer/lib/explorer/chain/address/counters.ex b/apps/explorer/lib/explorer/chain/address/counters.ex
new file mode 100644
index 000000000000..a8d2b78b6d69
--- /dev/null
+++ b/apps/explorer/lib/explorer/chain/address/counters.ex
@@ -0,0 +1,543 @@
+defmodule Explorer.Chain.Address.Counters do
+ @moduledoc """
+ Functions related to Explorer.Chain.Address counters
+ """
+ import Ecto.Query, only: [from: 2, limit: 2, select: 3, subquery: 1, union: 2, where: 3]
+
+ import Explorer.Chain,
+ only: [select_repo: 1, wrapped_union_subquery: 1]
+
+ alias Explorer.{Chain, Repo}
+
+ alias Explorer.Counters.{
+ AddressesCounter,
+ AddressesWithBalanceCounter,
+ AddressTokenTransfersCounter,
+ AddressTransactionsCounter,
+ AddressTransactionsGasUsageCounter
+ }
+
+ alias Explorer.Chain.{
+ Address,
+ Address.CoinBalance,
+ Address.CurrentTokenBalance,
+ Block,
+ Hash,
+ InternalTransaction,
+ Log,
+ TokenTransfer,
+ Transaction,
+ Withdrawal
+ }
+
+ alias Explorer.Chain.Cache.Helper, as: CacheHelper
+
+ require Logger
+
+ defp address_hash_to_logs_query(address_hash) do
+ from(l in Log, where: l.address_hash == ^address_hash)
+ end
+
+ defp address_hash_to_validated_blocks_query(address_hash) do
+ from(b in Block, where: b.miner_hash == ^address_hash)
+ end
+
+ def check_if_validated_blocks_at_address(address_hash, options \\ []) do
+ select_repo(options).exists?(address_hash_to_validated_blocks_query(address_hash))
+ end
+
+ def check_if_logs_at_address(address_hash, options \\ []) do
+ select_repo(options).exists?(address_hash_to_logs_query(address_hash))
+ end
+
+ defp address_hash_to_coin_balances(address_hash) do
+ query =
+ from(
+ cb in CoinBalance,
+ where: cb.address_hash == ^address_hash,
+ where: not is_nil(cb.value),
+ select_merge: %{
+ delta: fragment("? - coalesce(lead(?, 1) over (order by ? desc), 0)", cb.value, cb.value, cb.block_number)
+ }
+ )
+
+ from(balance in subquery(query),
+ where: balance.delta != 0
+ )
+ end
+
+ def check_if_token_transfers_at_address(address_hash, options \\ []) do
+ select_repo(options).exists?(from(tt in TokenTransfer, where: tt.from_address_hash == ^address_hash)) ||
+ select_repo(options).exists?(from(tt in TokenTransfer, where: tt.to_address_hash == ^address_hash))
+ end
+
+ def check_if_tokens_at_address(address_hash, options \\ []) do
+ select_repo(options).exists?(address_hash_to_token_balances_query(address_hash))
+ end
+
+ @spec check_if_withdrawals_at_address(Hash.Address.t()) :: boolean()
+ def check_if_withdrawals_at_address(address_hash, options \\ []) do
+ address_hash
+ |> Withdrawal.address_hash_to_withdrawals_unordered_query()
+ |> select_repo(options).exists?()
+ end
+
+ @doc """
+ Gets from the cache the count of `t:Explorer.Chain.Address.t/0`'s where the `fetched_coin_balance` is > 0
+ """
+ @spec count_addresses_with_balance_from_cache :: non_neg_integer()
+ def count_addresses_with_balance_from_cache do
+ AddressesWithBalanceCounter.fetch()
+ end
+
+ @doc """
+ Estimated count of `t:Explorer.Chain.Address.t/0`.
+
+ Estimated count of addresses.
+ """
+ @spec address_estimated_count() :: non_neg_integer()
+ def address_estimated_count(options \\ []) do
+ cached_value = AddressesCounter.fetch()
+
+ if is_nil(cached_value) || cached_value == 0 do
+ count = CacheHelper.estimated_count_from("addresses", options)
+
+ max(count, 0)
+ else
+ cached_value
+ end
+ end
+
+ @doc """
+ Counts the number of all addresses.
+
+ This function should be used with caution. In larger databases, it may take a
+ while to have the return back.
+ """
+ def count_addresses do
+ Repo.aggregate(Address, :count, timeout: :infinity)
+ end
+
+ @doc """
+ Get the total number of transactions sent by the address with the given hash according to the last block indexed.
+
+ We have to increment +1 in the last nonce result because it works like an array position, the first
+ nonce has the value 0. When last nonce is nil, it considers that the given address has 0 transactions.
+ """
+ @spec total_transactions_sent_by_address(Hash.Address.t()) :: non_neg_integer()
+ def total_transactions_sent_by_address(address_hash) do
+ last_nonce =
+ address_hash
+ |> Transaction.last_nonce_by_address_query()
+ |> Repo.one(timeout: :infinity)
+
+ case last_nonce do
+ nil -> 0
+ value -> value + 1
+ end
+ end
+
+ def address_hash_to_transaction_count_query(address_hash) do
+ from(
+ transaction in Transaction,
+ where: transaction.to_address_hash == ^address_hash or transaction.from_address_hash == ^address_hash
+ )
+ end
+
+ @spec address_hash_to_transaction_count(Hash.Address.t()) :: non_neg_integer()
+ def address_hash_to_transaction_count(address_hash) do
+ query = address_hash_to_transaction_count_query(address_hash)
+
+ Repo.aggregate(query, :count, :hash, timeout: :infinity)
+ end
+
+ @spec address_to_transaction_count(Address.t()) :: non_neg_integer()
+ def address_to_transaction_count(address) do
+ address_hash_to_transaction_count(address.hash)
+ end
+
+ @doc """
+ Counts the number of `t:Explorer.Chain.Block.t/0` validated by the address with the given `hash`.
+ """
+ @spec address_to_validation_count(Hash.Address.t(), [Chain.api?()]) :: non_neg_integer()
+ def address_to_validation_count(hash, options) do
+ query = from(block in Block, where: block.miner_hash == ^hash, select: fragment("COUNT(*)"))
+
+ select_repo(options).one(query)
+ end
+
+ @doc """
+ Counts the number of addresses with fetched coin balance > 0.
+
+ This function should be used with caution. In larger databases, it may take a
+ while to have the return back.
+ """
+ def count_addresses_with_balance do
+ Repo.one(
+ Address.count_with_fetched_coin_balance(),
+ timeout: :infinity
+ )
+ end
+
+ @spec address_to_incoming_transaction_count(Hash.Address.t()) :: non_neg_integer()
+ def address_to_incoming_transaction_count(address_hash) do
+ to_address_query =
+ from(
+ transaction in Transaction,
+ where: transaction.to_address_hash == ^address_hash
+ )
+
+ Repo.aggregate(to_address_query, :count, :hash, timeout: :infinity)
+ end
+
+ @spec address_to_incoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil
+ def address_to_incoming_transaction_gas_usage(address_hash) do
+ to_address_query =
+ from(
+ transaction in Transaction,
+ where: transaction.to_address_hash == ^address_hash
+ )
+
+ Repo.aggregate(to_address_query, :sum, :gas_used, timeout: :infinity)
+ end
+
+ @spec address_to_outcoming_transaction_gas_usage(Hash.Address.t()) :: Decimal.t() | nil
+ def address_to_outcoming_transaction_gas_usage(address_hash) do
+ to_address_query =
+ from(
+ transaction in Transaction,
+ where: transaction.from_address_hash == ^address_hash
+ )
+
+ Repo.aggregate(to_address_query, :sum, :gas_used, timeout: :infinity)
+ end
+
+ def address_to_token_transfer_count_query(address_hash) do
+ from(
+ token_transfer in TokenTransfer,
+ where: token_transfer.to_address_hash == ^address_hash,
+ or_where: token_transfer.from_address_hash == ^address_hash
+ )
+ end
+
+ @spec address_to_token_transfer_count(Address.t()) :: non_neg_integer()
+ def address_to_token_transfer_count(address) do
+ query = address_to_token_transfer_count_query(address.hash)
+
+ Repo.aggregate(query, :count, timeout: :infinity)
+ end
+
+ def address_hash_to_token_balances_query(address_hash) do
+ from(
+ tb in CurrentTokenBalance,
+ where: tb.address_hash == ^address_hash,
+ where: tb.value > 0
+ )
+ end
+
+ @spec address_to_gas_usage_count(Address.t()) :: Decimal.t() | nil
+ def address_to_gas_usage_count(address) do
+ if Chain.contract?(address) do
+ incoming_transaction_gas_usage = address_to_incoming_transaction_gas_usage(address.hash)
+
+ cond do
+ !incoming_transaction_gas_usage ->
+ address_to_outcoming_transaction_gas_usage(address.hash)
+
+ Decimal.compare(incoming_transaction_gas_usage, 0) == :eq ->
+ address_to_outcoming_transaction_gas_usage(address.hash)
+
+ true ->
+ incoming_transaction_gas_usage
+ end
+ else
+ address_to_outcoming_transaction_gas_usage(address.hash)
+ end
+ end
+
+ def address_counters(address, options \\ []) do
+ validation_count_task =
+ Task.async(fn ->
+ address_to_validation_count(address.hash, options)
+ end)
+
+ Task.start_link(fn ->
+ transaction_count(address)
+ end)
+
+ Task.start_link(fn ->
+ token_transfers_count(address)
+ end)
+
+ Task.start_link(fn ->
+ gas_usage_count(address)
+ end)
+
+ [
+ validation_count_task
+ ]
+ |> Task.yield_many(:infinity)
+ |> Enum.map(fn {_task, res} ->
+ case res do
+ {:ok, result} ->
+ result
+
+ {:exit, reason} ->
+ raise "Query fetching address counters terminated: #{inspect(reason)}"
+
+ nil ->
+ raise "Query fetching address counters timed out."
+ end
+ end)
+ |> List.to_tuple()
+ end
+
+ def transaction_count(address) do
+ AddressTransactionsCounter.fetch(address)
+ end
+
+ def token_transfers_count(address) do
+ AddressTokenTransfersCounter.fetch(address)
+ end
+
+ def gas_usage_count(address) do
+ AddressTransactionsGasUsageCounter.fetch(address)
+ end
+
+ @counters_limit 51
+
+ def address_limited_counters(address_hash, options) do
+ start = Time.utc_now()
+
+ validations_count_task =
+ Task.async(fn ->
+ result =
+ address_hash
+ |> address_hash_to_validated_blocks_query()
+ |> limit(@counters_limit)
+ |> select_repo(options).aggregate(:count)
+
+ Logger.info(
+ "Time consumed for validations_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ transactions_from_count_task =
+ Task.async(fn ->
+ result =
+ Transaction
+ |> where([t], t.from_address_hash == ^address_hash)
+ |> Transaction.not_dropped_or_replaced_transactions()
+ |> select([t], t.hash)
+ |> limit(@counters_limit)
+ |> select_repo(options).all()
+
+ Logger.info(
+ "Time consumed for transactions_from_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ transactions_to_count_task =
+ Task.async(fn ->
+ result =
+ Transaction
+ |> where([t], t.to_address_hash == ^address_hash)
+ |> Transaction.not_dropped_or_replaced_transactions()
+ |> select([t], t.hash)
+ |> limit(@counters_limit)
+ |> select_repo(options).all()
+
+ Logger.info(
+ "Time consumed for transactions_to_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ transactions_created_contract_count_task =
+ Task.async(fn ->
+ result =
+ Transaction
+ |> where([t], t.created_contract_address_hash == ^address_hash)
+ |> Transaction.not_dropped_or_replaced_transactions()
+ |> select([t], t.hash)
+ |> limit(@counters_limit)
+ |> select_repo(options).all()
+
+ Logger.info(
+ "Time consumed for transactions_created_contract_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ token_transfer_count_task =
+ Task.async(fn ->
+ result =
+ address_hash
+ |> address_to_token_transfer_count_query()
+ |> limit(@counters_limit)
+ |> select_repo(options).aggregate(:count)
+
+ Logger.info(
+ "Time consumed for token_transfer_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ token_balances_count_task =
+ Task.async(fn ->
+ result =
+ address_hash
+ |> address_hash_to_token_balances_query()
+ |> limit(@counters_limit)
+ |> select_repo(options).aggregate(:count)
+
+ Logger.info(
+ "Time consumed for token_balances_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ logs_count_task =
+ Task.async(fn ->
+ result =
+ address_hash
+ |> address_hash_to_logs_query()
+ |> limit(@counters_limit)
+ |> select_repo(options).aggregate(:count)
+
+ Logger.info(
+ "Time consumed for logs_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ withdrawals_count_task =
+ Task.async(fn ->
+ result =
+ address_hash
+ |> Withdrawal.address_hash_to_withdrawals_unordered_query()
+ |> limit(@counters_limit)
+ |> select_repo(options).aggregate(:count)
+
+ Logger.info(
+ "Time consumed for withdrawals_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ internal_txs_count_task =
+ Task.async(fn ->
+ query_to_address_hash_wrapped =
+ InternalTransaction
+ |> InternalTransaction.where_nonpending_block()
+ |> InternalTransaction.where_address_fields_match(address_hash, :to_address_hash)
+ |> InternalTransaction.where_is_different_from_parent_transaction()
+ |> limit(@counters_limit)
+ |> wrapped_union_subquery()
+
+ query_from_address_hash_wrapped =
+ InternalTransaction
+ |> InternalTransaction.where_nonpending_block()
+ |> InternalTransaction.where_address_fields_match(address_hash, :from_address_hash)
+ |> InternalTransaction.where_is_different_from_parent_transaction()
+ |> limit(@counters_limit)
+ |> wrapped_union_subquery()
+
+ query_created_contract_address_hash_wrapped =
+ InternalTransaction
+ |> InternalTransaction.where_nonpending_block()
+ |> InternalTransaction.where_address_fields_match(address_hash, :created_contract_address_hash)
+ |> InternalTransaction.where_is_different_from_parent_transaction()
+ |> limit(@counters_limit)
+ |> wrapped_union_subquery()
+
+ result =
+ query_to_address_hash_wrapped
+ |> union(^query_from_address_hash_wrapped)
+ |> union(^query_created_contract_address_hash_wrapped)
+ |> wrapped_union_subquery()
+ |> InternalTransaction.where_is_different_from_parent_transaction()
+ |> limit(@counters_limit)
+ |> select_repo(options).aggregate(:count)
+
+ Logger.info(
+ "Time consumed for internal_txs_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ coin_balances_count_task =
+ Task.async(fn ->
+ result =
+ address_hash
+ |> address_hash_to_coin_balances()
+ |> limit(@counters_limit)
+ |> select_repo(options).aggregate(:count)
+
+ Logger.info(
+ "Time consumed for coin_balances_count_task for #{address_hash} is #{Time.diff(Time.utc_now(), start, :millisecond)}ms"
+ )
+
+ result
+ end)
+
+ {validations, txs_from, txs_to, txs_contract, token_transfers, token_balances, logs, withdrawals, internal_txs,
+ coin_balances} =
+ [
+ validations_count_task,
+ transactions_from_count_task,
+ transactions_to_count_task,
+ transactions_created_contract_count_task,
+ token_transfer_count_task,
+ token_balances_count_task,
+ logs_count_task,
+ withdrawals_count_task,
+ internal_txs_count_task,
+ coin_balances_count_task
+ ]
+ |> Task.yield_many(:timer.seconds(30))
+ |> Enum.map(fn {_task, res} ->
+ case res do
+ {:ok, result} ->
+ result
+
+ {:exit, reason} ->
+ Logger.warn(fn ->
+ [
+ "Query fetching address counters terminated: #{inspect(reason)}"
+ ]
+ end)
+
+ nil
+
+ nil ->
+ Logger.warn(fn ->
+ [
+ "Query fetching address counters timed out."
+ ]
+ end)
+
+ nil
+ end
+ end)
+ |> List.to_tuple()
+
+ {validations,
+ (sanitize_list(txs_from) ++ sanitize_list(txs_to) ++ sanitize_list(txs_contract)) |> Enum.dedup() |> Enum.count(),
+ token_transfers, token_balances, logs, withdrawals, internal_txs, coin_balances}
+ end
+
+ defp sanitize_list(nil), do: []
+ defp sanitize_list(other), do: other
+end
diff --git a/apps/explorer/lib/explorer/chain/address/current_token_balance.ex b/apps/explorer/lib/explorer/chain/address/current_token_balance.ex
index 4b4574598a72..88c4594a3a7b 100644
--- a/apps/explorer/lib/explorer/chain/address/current_token_balance.ex
+++ b/apps/explorer/lib/explorer/chain/address/current_token_balance.ex
@@ -74,7 +74,6 @@ defmodule Explorer.Chain.Address.CurrentTokenBalance do
token_balance
|> cast(attrs, @allowed_fields)
|> validate_required(@required_fields)
- |> foreign_key_constraint(:address_hash)
|> foreign_key_constraint(:token_contract_address_hash)
end
@@ -158,6 +157,25 @@ defmodule Explorer.Chain.Address.CurrentTokenBalance do
dynamic([ctb, t], ctb.value * t.fiat_value / fragment("10 ^ ?", t.decimals))
end
+ @doc """
+ Builds an `t:Ecto.Query.t/0` to fetch the current token balances of the given address (include unfetched).
+ """
+ def last_token_balances_include_unfetched(address_hash) do
+ fiat_balance = fiat_value_query()
+
+ from(
+ ctb in __MODULE__,
+ where: ctb.address_hash == ^address_hash,
+ left_join: t in assoc(ctb, :token),
+ on: ctb.token_contract_address_hash == t.contract_address_hash,
+ preload: [token: t],
+ select: ctb,
+ select_merge: ^%{fiat_value: fiat_balance},
+ order_by: ^[desc_nulls_last: fiat_balance],
+ order_by: [desc: ctb.value, desc: ctb.id]
+ )
+ end
+
@doc """
Builds an `t:Ecto.Query.t/0` to fetch the current token balances of the given address.
"""
diff --git a/apps/explorer/lib/explorer/chain/address/token_balance.ex b/apps/explorer/lib/explorer/chain/address/token_balance.ex
index bdf7d42293b9..24b8dfb1c856 100644
--- a/apps/explorer/lib/explorer/chain/address/token_balance.ex
+++ b/apps/explorer/lib/explorer/chain/address/token_balance.ex
@@ -65,7 +65,6 @@ defmodule Explorer.Chain.Address.TokenBalance do
token_balance
|> cast(attrs, @allowed_fields)
|> validate_required(@required_fields)
- |> foreign_key_constraint(:address_hash)
|> foreign_key_constraint(:token_contract_address_hash)
|> unique_constraint(:block_number, name: :token_balances_address_hash_block_number_index)
end
diff --git a/apps/explorer/lib/explorer/chain/cache/gas_price_oracle.ex b/apps/explorer/lib/explorer/chain/cache/gas_price_oracle.ex
index 4315bd7b5d1a..60111725e142 100644
--- a/apps/explorer/lib/explorer/chain/cache/gas_price_oracle.ex
+++ b/apps/explorer/lib/explorer/chain/cache/gas_price_oracle.ex
@@ -10,6 +10,8 @@ defmodule Explorer.Chain.Cache.GasPriceOracle do
from: 2
]
+ alias EthereumJSONRPC.Blocks
+
alias Explorer.Chain.{
Block,
Wei
@@ -25,8 +27,17 @@ defmodule Explorer.Chain.Cache.GasPriceOracle do
ttl_check_interval: :timer.seconds(1),
callback: &async_task_on_deletion(&1)
+ @doc """
+ Get `safelow`, `average` and `fast` percentile of transactions gas prices among the last `num_of_blocks` blocks
+ """
+ @spec get_average_gas_price(pos_integer(), pos_integer(), pos_integer(), pos_integer()) ::
+ {:error, any} | {:ok, %{String.t() => nil | float, String.t() => nil | float, String.t() => nil | float}}
def get_average_gas_price(num_of_blocks, safelow_percentile, average_percentile, fast_percentile) do
- latest_gas_price_query =
+ safelow_percentile_fraction = safelow_percentile / 100
+ average_percentile_fraction = average_percentile / 100
+ fast_percentile_fraction = fast_percentile / 100
+
+ fee_query =
from(
block in Block,
left_join: transaction in assoc(block, :transactions),
@@ -35,27 +46,48 @@ defmodule Explorer.Chain.Cache.GasPriceOracle do
where: transaction.gas_price > ^0,
group_by: block.number,
order_by: [desc: block.number],
- select: min(transaction.gas_price),
+ select: %{
+ slow_gas_price:
+ fragment(
+ "percentile_disc(?) within group ( order by ? )",
+ ^safelow_percentile_fraction,
+ transaction.gas_price
+ ),
+ average_gas_price:
+ fragment(
+ "percentile_disc(?) within group ( order by ? )",
+ ^average_percentile_fraction,
+ transaction.gas_price
+ ),
+ fast_gas_price:
+ fragment(
+ "percentile_disc(?) within group ( order by ? )",
+ ^fast_percentile_fraction,
+ transaction.gas_price
+ ),
+ slow:
+ fragment(
+ "percentile_disc(?) within group ( order by ? )",
+ ^safelow_percentile_fraction,
+ transaction.max_priority_fee_per_gas
+ ),
+ average:
+ fragment(
+ "percentile_disc(?) within group ( order by ? )",
+ ^average_percentile_fraction,
+ transaction.max_priority_fee_per_gas
+ ),
+ fast:
+ fragment(
+ "percentile_disc(?) within group ( order by ? )",
+ ^fast_percentile_fraction,
+ transaction.max_priority_fee_per_gas
+ )
+ },
limit: ^num_of_blocks
)
- latest_gas_prices =
- latest_gas_price_query
- |> Repo.all(timeout: :infinity)
-
- latest_ordered_gas_prices =
- latest_gas_prices
- |> Enum.map(fn %Wei{value: gas_price} -> Decimal.to_integer(gas_price) end)
-
- safelow_gas_price = gas_price_percentile_to_gwei(latest_ordered_gas_prices, safelow_percentile)
- average_gas_price = gas_price_percentile_to_gwei(latest_ordered_gas_prices, average_percentile)
- fast_gas_price = gas_price_percentile_to_gwei(latest_ordered_gas_prices, fast_percentile)
-
- gas_prices = %{
- "slow" => safelow_gas_price,
- "average" => average_gas_price,
- "fast" => fast_gas_price
- }
+ gas_prices = fee_query |> Repo.all(timeout: :infinity) |> process_fee_data_from_db()
{:ok, gas_prices}
catch
@@ -63,6 +95,69 @@ defmodule Explorer.Chain.Cache.GasPriceOracle do
{:error, error}
end
+ defp process_fee_data_from_db([]) do
+ %{
+ "slow" => nil,
+ "average" => nil,
+ "fast" => nil
+ }
+ end
+
+ defp process_fee_data_from_db(fees) do
+ fees_length = Enum.count(fees)
+
+ %{
+ slow_gas_price: slow_gas_price,
+ average_gas_price: average_gas_price,
+ fast_gas_price: fast_gas_price,
+ slow: slow,
+ average: average,
+ fast: fast
+ } =
+ fees
+ |> Enum.reduce(
+ &Map.merge(&1, &2, fn
+ _, v1, v2 when nil not in [v1, v2] -> Decimal.add(v1, v2)
+ _, v1, v2 -> v1 || v2
+ end)
+ )
+ |> Map.new(fn
+ {key, nil} -> {key, nil}
+ {key, value} -> {key, Decimal.div(value, fees_length)}
+ end)
+
+ json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
+
+ {slow_fee, average_fee, fast_fee} =
+ case {nil not in [slow, average, fast], EthereumJSONRPC.fetch_block_by_tag("pending", json_rpc_named_arguments)} do
+ {true, {:ok, %Blocks{blocks_params: [%{base_fee_per_gas: base_fee}]}}} when not is_nil(base_fee) ->
+ base_fee_wei = base_fee |> Decimal.new() |> Wei.from(:wei)
+
+ {
+ priority_with_base_fee(slow, base_fee_wei),
+ priority_with_base_fee(average, base_fee_wei),
+ priority_with_base_fee(fast, base_fee_wei)
+ }
+
+ _ ->
+ {gas_price(slow_gas_price), gas_price(average_gas_price), gas_price(fast_gas_price)}
+ end
+
+ %{
+ "slow" => slow_fee,
+ "average" => average_fee,
+ "fast" => fast_fee
+ }
+ end
+
+ defp priority_with_base_fee(priority, base_fee) do
+ priority |> Wei.from(:wei) |> Wei.sum(base_fee) |> Wei.to(:gwei) |> Decimal.to_float() |> Float.ceil(2)
+ end
+
+ defp gas_price(value) do
+ value |> Wei.from(:wei) |> Wei.to(:gwei) |> Decimal.to_float() |> Float.ceil(2)
+ end
+
defp num_of_blocks, do: Application.get_env(:explorer, __MODULE__)[:num_of_blocks]
defp safelow, do: Application.get_env(:explorer, __MODULE__)[:safelow_percentile]
@@ -102,40 +197,6 @@ defmodule Explorer.Chain.Cache.GasPriceOracle do
{:update, task}
end
- defp gas_price_percentile_to_gwei(gas_prices, percentile) do
- gas_price_wei = percentile(gas_prices, percentile)
-
- if gas_price_wei do
- gas_price_gwei = Wei.to(%Wei{value: Decimal.from_float(gas_price_wei)}, :gwei)
-
- gas_price_gwei_float = gas_price_gwei |> Decimal.to_float()
-
- if gas_price_gwei_float > 0.01 do
- gas_price_gwei_float
- |> Float.ceil(2)
- else
- gas_price_gwei_float
- end
- else
- nil
- end
- end
-
- @spec percentile(list, number) :: number | nil
- defp percentile([], _), do: nil
- defp percentile([x], _), do: x
- defp percentile(list, 0), do: Enum.min(list)
- defp percentile(list, 100), do: Enum.max(list)
-
- defp percentile(list, n) when is_list(list) and is_number(n) do
- s = Enum.sort(list)
- r = n / 100.0 * (length(list) - 1)
- f = :erlang.trunc(r)
- lower = Enum.at(s, f)
- upper = Enum.at(s, f + 1)
- lower + (upper - lower) * (r - f)
- end
-
# By setting this as a `callback` an async task will be started each time the
# `gas_prices` expires (unless there is one already running)
defp async_task_on_deletion({:delete, _, :gas_prices}), do: get_async_task()
diff --git a/apps/explorer/lib/explorer/chain/events/publisher.ex b/apps/explorer/lib/explorer/chain/events/publisher.ex
index 92f01bfc844d..8d47f337ec64 100644
--- a/apps/explorer/lib/explorer/chain/events/publisher.ex
+++ b/apps/explorer/lib/explorer/chain/events/publisher.ex
@@ -3,7 +3,7 @@ defmodule Explorer.Chain.Events.Publisher do
Publishes events related to the Chain context.
"""
- @allowed_events ~w(addresses address_coin_balances address_token_balances blocks block_rewards internal_transactions last_block_number token_transfers transactions contract_verification_result token_total_supply changed_bytecode smart_contract_was_verified)a
+ @allowed_events ~w(addresses address_coin_balances address_token_balances address_current_token_balances blocks block_rewards internal_transactions last_block_number token_transfers transactions contract_verification_result token_total_supply changed_bytecode smart_contract_was_verified)a
def broadcast(_data, false), do: :ok
diff --git a/apps/explorer/lib/explorer/chain/events/subscriber.ex b/apps/explorer/lib/explorer/chain/events/subscriber.ex
index 9862e2e6c043..fa0203cbaf90 100644
--- a/apps/explorer/lib/explorer/chain/events/subscriber.ex
+++ b/apps/explorer/lib/explorer/chain/events/subscriber.ex
@@ -3,7 +3,7 @@ defmodule Explorer.Chain.Events.Subscriber do
Subscribes to events related to the Chain context.
"""
- @allowed_broadcast_events ~w(addresses address_coin_balances address_token_balances blocks block_rewards internal_transactions last_block_number token_transfers transactions contract_verification_result token_total_supply changed_bytecode smart_contract_was_verified)a
+ @allowed_broadcast_events ~w(addresses address_coin_balances address_token_balances address_current_token_balances blocks block_rewards internal_transactions last_block_number token_transfers transactions contract_verification_result token_total_supply changed_bytecode smart_contract_was_verified)a
@allowed_broadcast_types ~w(catchup realtime on_demand contract_verification_result)a
diff --git a/apps/explorer/lib/explorer/chain/import/runner/address/current_token_balances.ex b/apps/explorer/lib/explorer/chain/import/runner/address/current_token_balances.ex
index 0903c70cb876..cc51fb87376c 100644
--- a/apps/explorer/lib/explorer/chain/import/runner/address/current_token_balances.ex
+++ b/apps/explorer/lib/explorer/chain/import/runner/address/current_token_balances.ex
@@ -273,11 +273,12 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalances do
]
],
where:
- fragment("? < EXCLUDED.block_number", current_token_balance.block_number) or
- (fragment("? = EXCLUDED.block_number", current_token_balance.block_number) and
- fragment("EXCLUDED.value IS NOT NULL") and
- (is_nil(current_token_balance.value_fetched_at) or
- fragment("? < EXCLUDED.value_fetched_at", current_token_balance.value_fetched_at)))
+ fragment("EXCLUDED.value_fetched_at IS NOT NULL") and
+ (fragment("? < EXCLUDED.block_number", current_token_balance.block_number) or
+ (fragment("? = EXCLUDED.block_number", current_token_balance.block_number) and
+ fragment("EXCLUDED.value IS NOT NULL") and
+ (is_nil(current_token_balance.value_fetched_at) or
+ fragment("? < EXCLUDED.value_fetched_at", current_token_balance.value_fetched_at))))
)
end
diff --git a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex
index a3d99c65d6a5..3839dd58341c 100644
--- a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex
+++ b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex
@@ -374,6 +374,7 @@ defmodule Explorer.Chain.Import.Runner.Blocks do
removed_consensus_block_hashes
|> Enum.map(fn {number, _hash} -> number end)
+ |> Enum.reject(&Enum.member?(consensus_block_numbers, &1))
|> MissingRangesManipulator.add_ranges_by_block_numbers()
{:ok, removed_consensus_block_hashes}
diff --git a/apps/explorer/lib/explorer/chain/internal_transaction.ex b/apps/explorer/lib/explorer/chain/internal_transaction.ex
index b91509a3dcf9..2d0c6ae2da02 100644
--- a/apps/explorer/lib/explorer/chain/internal_transaction.ex
+++ b/apps/explorer/lib/explorer/chain/internal_transaction.ex
@@ -444,8 +444,6 @@ defmodule Explorer.Chain.InternalTransaction do
|> validate_call_error_or_result()
|> check_constraint(:call_type, message: ~S|can't be blank when type is 'call'|, name: :call_has_call_type)
|> check_constraint(:input, message: ~S|can't be blank when type is 'call'|, name: :call_has_call_type)
- |> foreign_key_constraint(:from_address_hash)
- |> foreign_key_constraint(:to_address_hash)
|> foreign_key_constraint(:transaction_hash)
|> unique_constraint(:index)
end
@@ -460,8 +458,6 @@ defmodule Explorer.Chain.InternalTransaction do
|> validate_required(@create_required_fields)
|> validate_create_error_or_result()
|> check_constraint(:init, message: ~S|can't be blank when type is 'create'|, name: :create_has_init)
- |> foreign_key_constraint(:created_contract_address_hash)
- |> foreign_key_constraint(:from_address_hash)
|> foreign_key_constraint(:transaction_hash)
|> unique_constraint(:index)
end
@@ -474,8 +470,6 @@ defmodule Explorer.Chain.InternalTransaction do
changeset
|> cast(attrs, @selfdestruct_allowed_fields)
|> validate_required(@selfdestruct_required_fields)
- |> foreign_key_constraint(:from_address_hash)
- |> foreign_key_constraint(:to_address_hash)
|> unique_constraint(:index)
end
diff --git a/apps/explorer/lib/explorer/chain/search.ex b/apps/explorer/lib/explorer/chain/search.ex
new file mode 100644
index 000000000000..b2439545a424
--- /dev/null
+++ b/apps/explorer/lib/explorer/chain/search.ex
@@ -0,0 +1,523 @@
+defmodule Explorer.Chain.Search do
+ @moduledoc """
+ Search related functions
+ """
+ import Ecto.Query,
+ only: [
+ from: 2,
+ limit: 2,
+ order_by: 3,
+ subquery: 1,
+ union: 2,
+ where: 3
+ ]
+
+ import Explorer.Chain, only: [select_repo: 1]
+
+ alias Explorer.{Chain, PagingOptions}
+ alias Explorer.Tags.{AddressTag, AddressToTag}
+
+ alias Explorer.Chain.{
+ Address,
+ Block,
+ SmartContract,
+ Token,
+ Transaction
+ }
+
+ @doc """
+ Search function used in web interface. Returns paginated search results
+ """
+ @spec joint_search(PagingOptions.t(), integer(), binary(), [Chain.api?()] | []) :: list
+ def joint_search(paging_options, offset, raw_string, options \\ []) do
+ string = String.trim(raw_string)
+
+ case prepare_search_term(string) do
+ {:some, term} ->
+ tokens_query = search_token_query(term)
+ contracts_query = search_contract_query(term)
+ labels_query = search_label_query(term)
+ tx_query = search_tx_query(string)
+ address_query = search_address_query(string)
+ block_query = search_block_query(string)
+
+ basic_query =
+ from(
+ tokens in subquery(tokens_query),
+ union: ^contracts_query,
+ union: ^labels_query
+ )
+
+ query =
+ cond do
+ address_query ->
+ basic_query
+ |> union(^address_query)
+
+ tx_query ->
+ basic_query
+ |> union(^tx_query)
+ |> union(^block_query)
+
+ block_query ->
+ basic_query
+ |> union(^block_query)
+
+ true ->
+ basic_query
+ end
+
+ ordered_query =
+ from(items in subquery(query),
+ order_by: [
+ desc: items.priority,
+ desc_nulls_last: items.circulating_market_cap,
+ desc_nulls_last: items.exchange_rate,
+ desc_nulls_last: items.is_verified_via_admin_panel,
+ desc_nulls_last: items.holder_count,
+ asc: items.name,
+ desc: items.inserted_at
+ ],
+ limit: ^paging_options.page_size,
+ offset: ^offset
+ )
+
+ paginated_ordered_query =
+ ordered_query
+ |> page_search_results(paging_options)
+
+ search_results = select_repo(options).all(paginated_ordered_query)
+
+ search_results
+ |> Enum.map(fn result ->
+ result
+ |> compose_result_checksummed_address_hash()
+ |> format_timestamp()
+ end)
+
+ _ ->
+ []
+ end
+ end
+
+ @doc """
+ Search function. Differences from joint_search/4:
+ 1. Returns all the found categories (amount of results up to `paging_options.page_size`).
+ For example if was found 50 tokens, 50 smart-contracts, 50 labels, 1 address, 1 transaction and 2 blocks (impossible, just example) and page_size=50. Then function will return:
+ [1 address, 1 transaction, 2 blocks, 16 tokens, 15 smart-contracts, 15 labels]
+ 2. Results couldn't be paginated
+ """
+ @spec balanced_unpaginated_search(PagingOptions.t(), binary(), [Chain.api?()] | []) :: list
+ def balanced_unpaginated_search(paging_options, raw_search_query, options \\ []) do
+ search_query = String.trim(raw_search_query)
+
+ case prepare_search_term(search_query) do
+ {:some, term} ->
+ tokens_result =
+ term
+ |> search_token_query()
+ |> order_by([token],
+ desc_nulls_last: token.circulating_market_cap,
+ desc_nulls_last: token.fiat_value,
+ desc_nulls_last: token.is_verified_via_admin_panel,
+ desc_nulls_last: token.holder_count,
+ asc: token.name,
+ desc: token.inserted_at
+ )
+ |> limit(^paging_options.page_size)
+ |> select_repo(options).all()
+
+ contracts_result =
+ term
+ |> search_contract_query()
+ |> order_by([items], asc: items.name, desc: items.inserted_at)
+ |> limit(^paging_options.page_size)
+ |> select_repo(options).all()
+
+ labels_result =
+ term
+ |> search_label_query()
+ |> order_by([att, at], asc: at.display_name, desc: att.inserted_at)
+ |> limit(^paging_options.page_size)
+ |> select_repo(options).all()
+
+ tx_result =
+ if query = search_tx_query(search_query) do
+ query
+ |> select_repo(options).all()
+ else
+ []
+ end
+
+ address_result =
+ if query = search_address_query(search_query) do
+ query
+ |> select_repo(options).all()
+ else
+ []
+ end
+
+ blocks_result =
+ if query = search_block_query(search_query) do
+ query
+ |> limit(^paging_options.page_size)
+ |> select_repo(options).all()
+ else
+ []
+ end
+
+ non_empty_lists =
+ [tokens_result, contracts_result, labels_result, tx_result, address_result, blocks_result]
+ |> Enum.filter(fn list -> Enum.count(list) > 0 end)
+ |> Enum.sort_by(fn list -> Enum.count(list) end, :asc)
+
+ to_take =
+ non_empty_lists
+ |> Enum.map(fn list -> Enum.count(list) end)
+ |> take_all_categories(List.duplicate(0, Enum.count(non_empty_lists)), paging_options.page_size)
+
+ non_empty_lists
+ |> Enum.zip_reduce(to_take, [], fn x, y, acc -> acc ++ Enum.take(x, y) end)
+ |> Enum.map(fn result ->
+ result
+ |> compose_result_checksummed_address_hash()
+ |> format_timestamp()
+ end)
+
+ _ ->
+ []
+ end
+ end
+
+ def prepare_search_term(string) do
+ case Regex.scan(~r/[a-zA-Z0-9]+/, string) do
+ [_ | _] = words ->
+ term_final =
+ words
+ |> Enum.map_join(" & ", fn [word] -> word <> ":*" end)
+
+ {:some, term_final}
+
+ _ ->
+ :none
+ end
+ end
+
+ defp search_label_query(term) do
+ inner_query =
+ from(tag in AddressTag,
+ where: fragment("to_tsvector('english', ?) @@ to_tsquery(?)", tag.display_name, ^term),
+ select: tag
+ )
+
+ from(att in AddressToTag,
+ inner_join: at in subquery(inner_query),
+ on: att.tag_id == at.id,
+ left_join: smart_contract in SmartContract,
+ on: att.address_hash == smart_contract.address_hash,
+ select: %{
+ address_hash: att.address_hash,
+ tx_hash: fragment("CAST(NULL AS bytea)"),
+ block_hash: fragment("CAST(NULL AS bytea)"),
+ type: "label",
+ name: at.display_name,
+ symbol: ^nil,
+ holder_count: ^nil,
+ inserted_at: att.inserted_at,
+ block_number: 0,
+ icon_url: nil,
+ token_type: nil,
+ timestamp: fragment("NULL::timestamp without time zone"),
+ verified: not is_nil(smart_contract),
+ exchange_rate: nil,
+ total_supply: nil,
+ circulating_market_cap: nil,
+ priority: 1,
+ is_verified_via_admin_panel: nil
+ }
+ )
+ end
+
+ defp search_token_query(term) do
+ from(token in Token,
+ left_join: smart_contract in SmartContract,
+ on: token.contract_address_hash == smart_contract.address_hash,
+ where: fragment("to_tsvector('english', ? || ' ' || ?) @@ to_tsquery(?)", token.symbol, token.name, ^term),
+ select: %{
+ address_hash: token.contract_address_hash,
+ tx_hash: fragment("CAST(NULL AS bytea)"),
+ block_hash: fragment("CAST(NULL AS bytea)"),
+ type: "token",
+ name: token.name,
+ symbol: token.symbol,
+ holder_count: token.holder_count,
+ inserted_at: token.inserted_at,
+ block_number: 0,
+ icon_url: token.icon_url,
+ token_type: token.type,
+ timestamp: fragment("NULL::timestamp without time zone"),
+ verified: not is_nil(smart_contract),
+ exchange_rate: token.fiat_value,
+ total_supply: token.total_supply,
+ circulating_market_cap: token.circulating_market_cap,
+ priority: 0,
+ is_verified_via_admin_panel: token.is_verified_via_admin_panel
+ }
+ )
+ end
+
+ defp search_contract_query(term) do
+ from(smart_contract in SmartContract,
+ left_join: address in Address,
+ on: smart_contract.address_hash == address.hash,
+ where: fragment("to_tsvector('english', ?) @@ to_tsquery(?)", smart_contract.name, ^term),
+ select: %{
+ address_hash: smart_contract.address_hash,
+ tx_hash: fragment("CAST(NULL AS bytea)"),
+ block_hash: fragment("CAST(NULL AS bytea)"),
+ type: "contract",
+ name: smart_contract.name,
+ symbol: ^nil,
+ holder_count: ^nil,
+ inserted_at: address.inserted_at,
+ block_number: 0,
+ icon_url: nil,
+ token_type: nil,
+ timestamp: fragment("NULL::timestamp without time zone"),
+ verified: true,
+ exchange_rate: nil,
+ total_supply: nil,
+ circulating_market_cap: nil,
+ priority: 0,
+ is_verified_via_admin_panel: nil
+ }
+ )
+ end
+
+ defp search_address_query(term) do
+ case Chain.string_to_address_hash(term) do
+ {:ok, address_hash} ->
+ from(address in Address,
+ left_join:
+ address_name in subquery(
+ from(name in Address.Name,
+ where: name.address_hash == ^address_hash,
+ order_by: [desc: name.primary],
+ limit: 1
+ )
+ ),
+ on: address.hash == address_name.address_hash,
+ where: address.hash == ^address_hash,
+ select: %{
+ address_hash: address.hash,
+ tx_hash: fragment("CAST(NULL AS bytea)"),
+ block_hash: fragment("CAST(NULL AS bytea)"),
+ type: "address",
+ name: address_name.name,
+ symbol: ^nil,
+ holder_count: ^nil,
+ inserted_at: address.inserted_at,
+ block_number: 0,
+ icon_url: nil,
+ token_type: nil,
+ timestamp: fragment("NULL::timestamp without time zone"),
+ verified: address.verified,
+ exchange_rate: nil,
+ total_supply: nil,
+ circulating_market_cap: nil,
+ priority: 0,
+ is_verified_via_admin_panel: nil
+ }
+ )
+
+ _ ->
+ nil
+ end
+ end
+
+ defp search_tx_query(term) do
+ case Chain.string_to_transaction_hash(term) do
+ {:ok, tx_hash} ->
+ from(transaction in Transaction,
+ left_join: block in Block,
+ on: transaction.block_hash == block.hash,
+ where: transaction.hash == ^tx_hash,
+ select: %{
+ address_hash: fragment("CAST(NULL AS bytea)"),
+ tx_hash: transaction.hash,
+ block_hash: fragment("CAST(NULL AS bytea)"),
+ type: "transaction",
+ name: ^nil,
+ symbol: ^nil,
+ holder_count: ^nil,
+ inserted_at: transaction.inserted_at,
+ block_number: 0,
+ icon_url: nil,
+ token_type: nil,
+ timestamp: block.timestamp,
+ verified: nil,
+ exchange_rate: nil,
+ total_supply: nil,
+ circulating_market_cap: nil,
+ priority: 0,
+ is_verified_via_admin_panel: nil
+ }
+ )
+
+ _ ->
+ nil
+ end
+ end
+
+ defp search_block_query(term) do
+ case Chain.string_to_block_hash(term) do
+ {:ok, block_hash} ->
+ from(block in Block,
+ where: block.hash == ^block_hash,
+ select: %{
+ address_hash: fragment("CAST(NULL AS bytea)"),
+ tx_hash: fragment("CAST(NULL AS bytea)"),
+ block_hash: block.hash,
+ type: "block",
+ name: ^nil,
+ symbol: ^nil,
+ holder_count: ^nil,
+ inserted_at: block.inserted_at,
+ block_number: block.number,
+ icon_url: nil,
+ token_type: nil,
+ timestamp: block.timestamp,
+ verified: nil,
+ exchange_rate: nil,
+ total_supply: nil,
+ circulating_market_cap: nil,
+ priority: 0,
+ is_verified_via_admin_panel: nil
+ }
+ )
+
+ _ ->
+ case Integer.parse(term) do
+ {block_number, ""} ->
+ from(block in Block,
+ where: block.number == ^block_number,
+ select: %{
+ address_hash: fragment("CAST(NULL AS bytea)"),
+ tx_hash: fragment("CAST(NULL AS bytea)"),
+ block_hash: block.hash,
+ type: "block",
+ name: ^nil,
+ symbol: ^nil,
+ holder_count: ^nil,
+ inserted_at: block.inserted_at,
+ block_number: block.number,
+ icon_url: nil,
+ token_type: nil,
+ timestamp: block.timestamp,
+ verified: nil,
+ exchange_rate: nil,
+ total_supply: nil,
+ circulating_market_cap: nil,
+ priority: 0,
+ is_verified_via_admin_panel: nil
+ }
+ )
+
+ _ ->
+ nil
+ end
+ end
+ end
+
+ defp page_search_results(query, %PagingOptions{key: nil}), do: query
+
+ defp page_search_results(query, %PagingOptions{
+ key: {_address_hash, _tx_hash, _block_hash, holder_count, name, inserted_at, item_type}
+ })
+ when holder_count in [nil, ""] do
+ where(
+ query,
+ [item],
+ (item.name > ^name and item.type == ^item_type) or
+ (item.name == ^name and item.inserted_at < ^inserted_at and
+ item.type == ^item_type) or
+ item.type != ^item_type
+ )
+ end
+
+ # credo:disable-for-next-line
+ defp page_search_results(query, %PagingOptions{
+ key: {_address_hash, _tx_hash, _block_hash, holder_count, name, inserted_at, item_type}
+ }) do
+ where(
+ query,
+ [item],
+ (item.holder_count < ^holder_count and item.type == ^item_type) or
+ (item.holder_count == ^holder_count and item.name > ^name and item.type == ^item_type) or
+ (item.holder_count == ^holder_count and item.name == ^name and item.inserted_at < ^inserted_at and
+ item.type == ^item_type) or
+ item.type != ^item_type
+ )
+ end
+
+ defp take_all_categories([], taken_lengths, _remained), do: taken_lengths
+
+ defp take_all_categories(lengths, taken_lengths, remained) do
+ non_zero_count = count_non_zero(lengths)
+
+ target = if(remained < non_zero_count, do: 1, else: div(remained, non_zero_count))
+
+ {lengths_updated, %{result: taken_lengths_reversed}} =
+ Enum.map_reduce(lengths, %{result: [], sum: 0}, fn el, acc ->
+ taken =
+ cond do
+ acc[:sum] >= remained ->
+ 0
+
+ el < target ->
+ el
+
+ true ->
+ target
+ end
+
+ {el - taken, %{result: [taken | acc[:result]], sum: acc[:sum] + taken}}
+ end)
+
+ taken_lengths =
+ taken_lengths
+ |> Enum.zip_reduce(Enum.reverse(taken_lengths_reversed), [], fn x, y, acc -> [x + y | acc] end)
+ |> Enum.reverse()
+
+ remained = remained - Enum.sum(taken_lengths_reversed)
+
+ if remained > 0 and count_non_zero(lengths_updated) > 0 do
+ take_all_categories(lengths_updated, taken_lengths, remained)
+ else
+ taken_lengths
+ end
+ end
+
+ defp count_non_zero(list) do
+ Enum.reduce(list, 0, fn el, acc -> acc + if el > 0, do: 1, else: 0 end)
+ end
+
+ defp compose_result_checksummed_address_hash(result) do
+ if result.address_hash do
+ result
+ |> Map.put(:address_hash, Address.checksum(result.address_hash))
+ else
+ result
+ end
+ end
+
+ # For some reasons timestamp for blocks and txs returns as ~N[2023-06-25 19:39:47.339493]
+ defp format_timestamp(result) do
+ if result.timestamp do
+ result
+ |> Map.put(:timestamp, DateTime.from_naive!(result.timestamp, "Etc/UTC"))
+ else
+ result
+ end
+ end
+end
diff --git a/apps/explorer/lib/explorer/chain/smart_contract.ex b/apps/explorer/lib/explorer/chain/smart_contract.ex
index c1cb17f1022e..6b3696d28259 100644
--- a/apps/explorer/lib/explorer/chain/smart_contract.ex
+++ b/apps/explorer/lib/explorer/chain/smart_contract.ex
@@ -424,30 +424,53 @@ defmodule Explorer.Chain.SmartContract do
defp upsert_contract_methods(changeset), do: changeset
- defp error_message(:compilation), do: "There was an error compiling your contract."
- defp error_message(:compiler_version), do: "Compiler version does not match, please try again."
- defp error_message(:generated_bytecode), do: "Bytecode does not match, please try again."
- defp error_message(:constructor_arguments), do: "Constructor arguments do not match, please try again."
- defp error_message(:name), do: "Wrong contract name, please try again."
- defp error_message(:json), do: "Invalid JSON file."
+ defp error_message(:compilation), do: error_message_with_log("There was an error compiling your contract.")
+
+ defp error_message(:compiler_version),
+ do: error_message_with_log("Compiler version does not match, please try again.")
+
+ defp error_message(:generated_bytecode), do: error_message_with_log("Bytecode does not match, please try again.")
+
+ defp error_message(:constructor_arguments),
+ do: error_message_with_log("Constructor arguments do not match, please try again.")
+
+ defp error_message(:name), do: error_message_with_log("Wrong contract name, please try again.")
+ defp error_message(:json), do: error_message_with_log("Invalid JSON file.")
defp error_message(:autodetect_constructor_arguments_failed),
- do: "Autodetection of constructor arguments failed. Please try to input constructor arguments manually."
+ do:
+ error_message_with_log(
+ "Autodetection of constructor arguments failed. Please try to input constructor arguments manually."
+ )
defp error_message(:no_creation_data),
- do: "The contract creation transaction has not been indexed yet. Please wait a few minutes and try again."
+ do:
+ error_message_with_log(
+ "The contract creation transaction has not been indexed yet. Please wait a few minutes and try again."
+ )
- defp error_message(:unknown_error), do: "Unable to verify: unknown error."
- defp error_message(:deployed_bytecode), do: "Deployed bytecode does not correspond to contract creation code."
+ defp error_message(:unknown_error), do: error_message_with_log("Unable to verify: unknown error.")
- defp error_message(string) when is_binary(string), do: string
+ defp error_message(:deployed_bytecode),
+ do: error_message_with_log("Deployed bytecode does not correspond to contract creation code.")
+
+ defp error_message(:contract_source_code), do: error_message_with_log("Empty contract source code.")
+
+ defp error_message(string) when is_binary(string), do: error_message_with_log(string)
+ defp error_message(%{"message" => string} = error) when is_map(error), do: error_message_with_log(string)
defp error_message(error) do
Logger.warn(fn -> ["Unknown verifier error: ", inspect(error)] end)
"There was an error validating your contract, please try again."
end
- defp error_message(:compilation, error_message), do: "There was an error compiling your contract: #{error_message}"
+ defp error_message(:compilation, error_message),
+ do: error_message_with_log("There was an error compiling your contract: #{error_message}")
+
+ defp error_message_with_log(error_string) do
+ Logger.error("Smart-contract verification error: #{error_string}")
+ error_string
+ end
defp select_error_field(:no_creation_data), do: :address_hash
defp select_error_field(:compiler_version), do: :compiler_version
diff --git a/apps/explorer/lib/explorer/chain/supply/rsk.ex b/apps/explorer/lib/explorer/chain/supply/rsk.ex
index 1037dd4cf79e..2eb9caa93350 100644
--- a/apps/explorer/lib/explorer/chain/supply/rsk.ex
+++ b/apps/explorer/lib/explorer/chain/supply/rsk.ex
@@ -5,7 +5,7 @@ defmodule Explorer.Chain.Supply.RSK do
use Explorer.Chain.Supply
- import Ecto.Query, only: [from: 2]
+ import Ecto.Query, only: [from: 2, subquery: 1]
import EthereumJSONRPC, only: [integer_to_quantity: 1]
alias EthereumJSONRPC.FetchedBalances
@@ -16,7 +16,9 @@ defmodule Explorer.Chain.Supply.RSK do
@cache_name :rsk_balance
@balance_key :balance
+ @rsk_bridge_contract_address "0x0000000000000000000000000000000001000006"
+ @spec market_cap(any()) :: Decimal.t()
def market_cap(%{usd_value: usd_value}) when not is_nil(usd_value) do
btc = circulating()
@@ -25,31 +27,32 @@ defmodule Explorer.Chain.Supply.RSK do
def market_cap(_), do: Decimal.new(0)
- @doc "Equivalent to getting the circulating value "
+ @doc "Equivalent to getting the circulating value"
def supply_for_days(days) do
now = Timex.now()
- balances_query =
+ base_query =
from(balance in CoinBalance,
join: block in Block,
on: block.number == balance.block_number,
where: block.consensus == true,
- where: balance.address_hash == ^"0x0000000000000000000000000000000001000006",
- where: block.timestamp > ^Timex.shift(now, days: -days),
- distinct: fragment("date_trunc('day', ?)", block.timestamp),
- select: {block.timestamp, balance.value}
+ where: balance.address_hash == ^@rsk_bridge_contract_address,
+ select: %{timestamp: block.timestamp, value: balance.value}
+ )
+
+ balances_query =
+ from(q in subquery(base_query),
+ where: q.timestamp > ^Timex.shift(now, days: -days),
+ distinct: fragment("date_trunc('day', ?)", q.timestamp),
+ select: {q.timestamp, q.value}
)
balance_before_query =
- from(balance in CoinBalance,
- join: block in Block,
- on: block.number == balance.block_number,
- where: block.consensus == true,
- where: balance.address_hash == ^"0x0000000000000000000000000000000001000006",
- where: block.timestamp <= ^Timex.shift(Timex.now(), days: -days),
- order_by: [desc: block.timestamp],
+ from(q in subquery(base_query),
+ where: q.timestamp <= ^Timex.shift(Timex.now(), days: -days),
+ order_by: [desc: q.timestamp],
limit: 1,
- select: balance.value
+ select: q.value
)
by_day =
@@ -105,7 +108,7 @@ defmodule Explorer.Chain.Supply.RSK do
max_number = BlockNumber.get_max()
params = [
- %{block_quantity: integer_to_quantity(max_number), hash_data: "0x0000000000000000000000000000000001000006"}
+ %{block_quantity: integer_to_quantity(max_number), hash_data: @rsk_bridge_contract_address}
]
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
@@ -116,7 +119,7 @@ defmodule Explorer.Chain.Supply.RSK do
errors: [],
params_list: [
%{
- address_hash: "0x0000000000000000000000000000000001000006",
+ address_hash: @rsk_bridge_contract_address,
value: value
}
]
diff --git a/apps/explorer/lib/explorer/chain/token.ex b/apps/explorer/lib/explorer/chain/token.ex
index b59f6ef2de5d..3b9eb2e95e18 100644
--- a/apps/explorer/lib/explorer/chain/token.ex
+++ b/apps/explorer/lib/explorer/chain/token.ex
@@ -41,6 +41,7 @@ defmodule Explorer.Chain.Token do
* `fiat_value` - The price of a token in a configured currency (USD by default).
* `circulating_market_cap` - The circulating market cap of a token in a configured currency (USD by default).
* `icon_url` - URL of the token's icon.
+ * `is_verified_via_admin_panel` - is token verified via admin panel.
"""
@type t :: %Token{
name: String.t(),
@@ -56,7 +57,8 @@ defmodule Explorer.Chain.Token do
total_supply_updated_at_block: non_neg_integer() | nil,
fiat_value: Decimal.t() | nil,
circulating_market_cap: Decimal.t() | nil,
- icon_url: String.t()
+ icon_url: String.t(),
+ is_verified_via_admin_panel: boolean()
}
@derive {Poison.Encoder,
@@ -89,6 +91,7 @@ defmodule Explorer.Chain.Token do
field(:fiat_value, :decimal)
field(:circulating_market_cap, :decimal)
field(:icon_url, :string)
+ field(:is_verified_via_admin_panel, :boolean)
belongs_to(
:contract_address,
@@ -103,14 +106,13 @@ defmodule Explorer.Chain.Token do
end
@required_attrs ~w(contract_address_hash type)a
- @optional_attrs ~w(cataloged decimals name symbol total_supply skip_metadata total_supply_updated_at_block updated_at fiat_value circulating_market_cap icon_url)a
+ @optional_attrs ~w(cataloged decimals name symbol total_supply skip_metadata total_supply_updated_at_block updated_at fiat_value circulating_market_cap icon_url is_verified_via_admin_panel)a
@doc false
def changeset(%Token{} = token, params \\ %{}) do
token
|> cast(params, @required_attrs ++ @optional_attrs)
|> validate_required(@required_attrs)
- |> foreign_key_constraint(:contract_address)
|> trim_name()
|> sanitize_token_input(:name)
|> sanitize_token_input(:symbol)
diff --git a/apps/explorer/lib/explorer/chain/token_transfer.ex b/apps/explorer/lib/explorer/chain/token_transfer.ex
index d1abd9971e74..ff17c0f768cb 100644
--- a/apps/explorer/lib/explorer/chain/token_transfer.ex
+++ b/apps/explorer/lib/explorer/chain/token_transfer.ex
@@ -136,9 +136,6 @@ defmodule Explorer.Chain.TokenTransfer do
struct
|> cast(params, @required_attrs ++ @optional_attrs)
|> validate_required(@required_attrs)
- |> foreign_key_constraint(:from_address)
- |> foreign_key_constraint(:to_address)
- |> foreign_key_constraint(:token_contract_address)
|> foreign_key_constraint(:transaction)
end
diff --git a/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex b/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex
index 5ca1520cb2b5..573ab8a988a5 100644
--- a/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex
+++ b/apps/explorer/lib/explorer/counters/address_gas_usage_counter.ex
@@ -5,8 +5,9 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
use GenServer
alias Ecto.Changeset
- alias Explorer.{Chain, Repo}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Counters.Helper
+ alias Explorer.Repo
@cache_name :address_transactions_gas_usage_counter
@last_update_key "last_update"
@@ -67,7 +68,7 @@ defmodule Explorer.Counters.AddressTransactionsGasUsageCounter do
defp update_cache(address) do
address_hash_string = to_string(address.hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", Helper.current_time())
- new_data = Chain.address_to_gas_usage_count(address)
+ new_data = Counters.address_to_gas_usage_count(address)
put_into_cache("hash_#{address_hash_string}", new_data)
put_into_db(address, new_data)
end
diff --git a/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex b/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex
index ffec588f3131..db3c82da3b48 100644
--- a/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex
+++ b/apps/explorer/lib/explorer/counters/address_token_transfers_counter.ex
@@ -5,8 +5,9 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do
use GenServer
alias Ecto.Changeset
- alias Explorer.{Chain, Repo}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Counters.Helper
+ alias Explorer.Repo
@cache_name :address_token_transfers_counter
@last_update_key "last_update"
@@ -67,7 +68,7 @@ defmodule Explorer.Counters.AddressTokenTransfersCounter do
defp update_cache(address) do
address_hash_string = to_string(address.hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", Helper.current_time())
- new_data = Chain.address_to_token_transfer_count(address)
+ new_data = Counters.address_to_token_transfer_count(address)
put_into_cache("hash_#{address_hash_string}", new_data)
put_into_db(address, new_data)
end
diff --git a/apps/explorer/lib/explorer/counters/address_transactions_counter.ex b/apps/explorer/lib/explorer/counters/address_transactions_counter.ex
index e3c6dfffb690..7b2c912335fa 100644
--- a/apps/explorer/lib/explorer/counters/address_transactions_counter.ex
+++ b/apps/explorer/lib/explorer/counters/address_transactions_counter.ex
@@ -5,8 +5,9 @@ defmodule Explorer.Counters.AddressTransactionsCounter do
use GenServer
alias Ecto.Changeset
- alias Explorer.{Chain, Repo}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Counters.Helper
+ alias Explorer.Repo
@cache_name :address_transactions_counter
@last_update_key "last_update"
@@ -67,7 +68,7 @@ defmodule Explorer.Counters.AddressTransactionsCounter do
defp update_cache(address) do
address_hash_string = to_string(address.hash)
put_into_cache("hash_#{address_hash_string}_#{@last_update_key}", Helper.current_time())
- new_data = Chain.address_to_transaction_count(address)
+ new_data = Counters.address_to_transaction_count(address)
put_into_cache("hash_#{address_hash_string}", new_data)
put_into_db(address, new_data)
end
diff --git a/apps/explorer/lib/explorer/counters/addresses_counter.ex b/apps/explorer/lib/explorer/counters/addresses_counter.ex
index 820d96a9152f..51fb845bb945 100644
--- a/apps/explorer/lib/explorer/counters/addresses_counter.ex
+++ b/apps/explorer/lib/explorer/counters/addresses_counter.ex
@@ -7,7 +7,7 @@ defmodule Explorer.Counters.AddressesCounter do
use GenServer
- alias Explorer.Chain
+ alias Explorer.Chain.Address.Counters
@table :addresses_counter
@@ -104,7 +104,7 @@ defmodule Explorer.Counters.AddressesCounter do
Consolidates the info by populating the `:ets` table with the current database information.
"""
def consolidate do
- counter = Chain.count_addresses()
+ counter = Counters.count_addresses()
insert_counter({cache_key(), counter})
end
diff --git a/apps/explorer/lib/explorer/counters/addresses_with_balance_counter.ex b/apps/explorer/lib/explorer/counters/addresses_with_balance_counter.ex
index 1358e52a21e8..53621029afd7 100644
--- a/apps/explorer/lib/explorer/counters/addresses_with_balance_counter.ex
+++ b/apps/explorer/lib/explorer/counters/addresses_with_balance_counter.ex
@@ -7,7 +7,7 @@ defmodule Explorer.Counters.AddressesWithBalanceCounter do
use GenServer
- alias Explorer.Chain
+ alias Explorer.Chain.Address.Counters
@table :addresses_with_balance_counter
@@ -104,7 +104,7 @@ defmodule Explorer.Counters.AddressesWithBalanceCounter do
Consolidates the info by populating the `:ets` table with the current database information.
"""
def consolidate do
- counter = Chain.count_addresses_with_balance()
+ counter = Counters.count_addresses_with_balance()
insert_counter({cache_key(), counter})
end
diff --git a/apps/explorer/lib/explorer/eth_rpc.ex b/apps/explorer/lib/explorer/eth_rpc.ex
index ed7e6830802b..889fdabbba6e 100644
--- a/apps/explorer/lib/explorer/eth_rpc.ex
+++ b/apps/explorer/lib/explorer/eth_rpc.ex
@@ -296,17 +296,14 @@ defmodule Explorer.EthRPC do
defp paging_options(%{
"paging_options" => %{
"logIndex" => log_index,
- "transactionIndex" => transaction_index,
"blockNumber" => block_number
}
- })
- when is_integer(transaction_index) do
+ }) do
with {:ok, parsed_block_number} <- to_number(block_number, "invalid block number"),
{:ok, parsed_log_index} <- to_number(log_index, "invalid log index") do
{:ok,
%{
log_index: parsed_log_index,
- transaction_index: transaction_index,
block_number: parsed_block_number
}}
end
diff --git a/apps/explorer/lib/explorer/etherscan/logs.ex b/apps/explorer/lib/explorer/etherscan/logs.ex
index 006c0a2e191b..c7ae91e34732 100644
--- a/apps/explorer/lib/explorer/etherscan/logs.ex
+++ b/apps/explorer/lib/explorer/etherscan/logs.ex
@@ -248,16 +248,14 @@ defmodule Explorer.Etherscan.Logs do
defp where_multiple_topics_match(query, _, _, _), do: query
- defp page_logs(query, %{block_number: nil, transaction_index: nil, log_index: nil}) do
+ defp page_logs(query, %{block_number: nil, log_index: nil}) do
query
end
- defp page_logs(query, %{block_number: block_number, transaction_index: transaction_index, log_index: log_index}) do
+ defp page_logs(query, %{block_number: block_number, log_index: log_index}) do
from(
data in query,
- where:
- data.index > ^log_index and data.block_number >= ^block_number and
- data.transaction_index >= ^transaction_index
+ where: data.index > ^log_index and data.block_number >= ^block_number
)
end
diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/publisher.ex b/apps/explorer/lib/explorer/smart_contract/solidity/publisher.ex
index 96455e7c327c..045766198150 100644
--- a/apps/explorer/lib/explorer/smart_contract/solidity/publisher.ex
+++ b/apps/explorer/lib/explorer/smart_contract/solidity/publisher.ex
@@ -3,6 +3,8 @@ defmodule Explorer.SmartContract.Solidity.Publisher do
Module responsible to control the contract verification.
"""
+ require Logger
+
import Explorer.SmartContract.Helper, only: [cast_libraries: 1]
alias Explorer.Chain
@@ -10,6 +12,10 @@ defmodule Explorer.SmartContract.Solidity.Publisher do
alias Explorer.SmartContract.{CompilerVersion, Helper}
alias Explorer.SmartContract.Solidity.Verifier
+ @sc_verification_via_flattened_file_started "Smart-contract verification via flattened file started"
+ @sc_verification_via_standard_json_input_started "Smart-contract verification via standard json input started"
+ @sc_verification_via_multipart_files_started "Smart-contract verification via multipart files started"
+
@doc """
Evaluates smart contract authenticity and saves its details.
@@ -27,6 +33,7 @@ defmodule Explorer.SmartContract.Solidity.Publisher do
"""
def publish(address_hash, params, external_libraries \\ %{}) do
+ Logger.info(@sc_verification_via_flattened_file_started)
params_with_external_libraries = add_external_libraries(params, external_libraries)
case Verifier.evaluate_authenticity(address_hash, params_with_external_libraries) do
@@ -65,6 +72,8 @@ defmodule Explorer.SmartContract.Solidity.Publisher do
end
def publish_with_standard_json_input(%{"address_hash" => address_hash} = params, json_input) do
+ Logger.info(@sc_verification_via_standard_json_input_started)
+
case Verifier.evaluate_authenticity_via_standard_json_input(address_hash, params, json_input) do
{:ok,
%{
@@ -102,6 +111,7 @@ defmodule Explorer.SmartContract.Solidity.Publisher do
end
def publish_with_multi_part_files(%{"address_hash" => address_hash} = params, external_libraries \\ %{}, files) do
+ Logger.info(@sc_verification_via_multipart_files_started)
params_with_external_libraries = add_external_libraries(params, external_libraries)
case Verifier.evaluate_authenticity_via_multi_part_files(address_hash, params_with_external_libraries, files) do
@@ -187,6 +197,8 @@ defmodule Explorer.SmartContract.Solidity.Publisher do
end
defp create_or_update_smart_contract(address_hash, attrs) do
+ Logger.info("Publish successfully verified Solidity smart-contract #{address_hash} into the DB")
+
if Chain.smart_contract_verified?(address_hash) do
Chain.update_smart_contract(attrs, attrs.external_libraries, attrs.secondary_sources)
else
@@ -209,6 +221,8 @@ defmodule Explorer.SmartContract.Solidity.Publisher do
verification_with_files?
)
+ Logger.error("Solidity smart-contract verification #{address_hash} failed because of the error #{error}")
+
%{changeset | action: :insert}
end
diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/publisher_worker.ex b/apps/explorer/lib/explorer/smart_contract/solidity/publisher_worker.ex
index b8dbc3f81dba..b9ae134d54cb 100644
--- a/apps/explorer/lib/explorer/smart_contract/solidity/publisher_worker.ex
+++ b/apps/explorer/lib/explorer/smart_contract/solidity/publisher_worker.ex
@@ -3,6 +3,8 @@ defmodule Explorer.SmartContract.Solidity.PublisherWorker do
Background smart contract verification worker.
"""
+ require Logger
+
use Que.Worker, concurrency: 5
alias Explorer.Chain.Events.Publisher, as: EventsPublisher
@@ -68,6 +70,8 @@ defmodule Explorer.SmartContract.Solidity.PublisherWorker do
{:error, changeset}
end
+ Logger.info("Smart-contract #{address_hash} verification: broadcast verification results")
+
if conn do
EventsPublisher.broadcast([{:contract_verification_result, {address_hash, result, conn}}], :on_demand)
else
diff --git a/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex b/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
index 57c11709abd5..ee5554a0361d 100644
--- a/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
+++ b/apps/explorer/lib/explorer/smart_contract/solidity/verifier.ex
@@ -11,8 +11,10 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
import Explorer.SmartContract.Helper,
only: [cast_libraries: 1, prepare_bytecode_for_microservice: 3, contract_creation_input: 1]
+ # import Explorer.Chain.SmartContract, only: [:function_description]
alias ABI.{FunctionSelector, TypeDecoder}
alias Explorer.Chain
+ alias Explorer.Chain.{Data, Hash, SmartContract}
alias Explorer.SmartContract.RustVerifierInterface
alias Explorer.SmartContract.Solidity.CodeCompiler
@@ -533,4 +535,53 @@ defmodule Explorer.SmartContract.Solidity.Verifier do
def parse_boolean(false), do: false
def parse_boolean(_), do: false
+
+ @doc """
+ Function tries to parse constructor args from smart contract creation input.
+ 1. using `extract_meta_from_deployed_bytecode/1` we derive CBOR metadata string
+ 2. using metadata we split creation_tx_input and try to decode resulting constructor arguments
+ 2.1. if we successfully decoded args using constructor's abi, then return constructor args
+ 2.2 otherwise return nil
+ """
+ @spec parse_constructor_arguments_for_sourcify_contract(Hash.Address.t(), SmartContract.abi()) :: nil | binary
+ def parse_constructor_arguments_for_sourcify_contract(address_hash, abi) do
+ parse_constructor_arguments_for_sourcify_contract(address_hash, abi, Chain.smart_contract_bytecode(address_hash))
+ end
+
+ @doc """
+ Clause for cases when we already can pass deployed bytecode to this function (in order to avoid excessive read DB accesses)
+ """
+ @spec parse_constructor_arguments_for_sourcify_contract(
+ Hash.Address.t(),
+ SmartContract.abi(),
+ binary | Explorer.Chain.Data.t()
+ ) :: nil | binary
+ def parse_constructor_arguments_for_sourcify_contract(address_hash, abi, deployed_bytecode)
+ when is_binary(deployed_bytecode) do
+ creation_tx_input =
+ case Chain.smart_contract_creation_tx_bytecode(address_hash) do
+ %{init: init, created_contract_code: _created_contract_code} ->
+ "0x" <> init_without_0x = init
+ init_without_0x
+
+ _ ->
+ nil
+ end
+
+ with true <- has_constructor_with_params?(abi),
+ check_function <- parse_constructor_and_return_check_function(abi),
+ false <- is_nil(creation_tx_input) || deployed_bytecode == "0x",
+ {meta, meta_length} <- extract_meta_from_deployed_bytecode(deployed_bytecode),
+ [_bytecode, constructor_args] <- String.split(creation_tx_input, meta <> meta_length),
+ ^constructor_args <- check_function.(constructor_args) do
+ constructor_args
+ else
+ _ ->
+ nil
+ end
+ end
+
+ def parse_constructor_arguments_for_sourcify_contract(address_hash, abi, deployed_bytecode) do
+ parse_constructor_arguments_for_sourcify_contract(address_hash, abi, Data.to_string(deployed_bytecode))
+ end
end
diff --git a/apps/explorer/lib/explorer/smart_contract/vyper/publisher.ex b/apps/explorer/lib/explorer/smart_contract/vyper/publisher.ex
index 64f91345f787..e5c38116d06f 100644
--- a/apps/explorer/lib/explorer/smart_contract/vyper/publisher.ex
+++ b/apps/explorer/lib/explorer/smart_contract/vyper/publisher.ex
@@ -5,6 +5,8 @@ defmodule Explorer.SmartContract.Vyper.Publisher do
import Explorer.SmartContract.Helper, only: [cast_libraries: 1]
+ require Logger
+
alias Explorer.Chain
alias Explorer.Chain.SmartContract
alias Explorer.SmartContract.CompilerVersion
@@ -119,6 +121,7 @@ defmodule Explorer.SmartContract.Vyper.Publisher do
end
def publish_smart_contract(address_hash, params, abi) do
+ Logger.info("Publish successfully verified Vyper smart-contract #{address_hash} into the DB")
attrs = address_hash |> attributes(params, abi)
Chain.create_smart_contract(attrs, attrs.external_libraries, attrs.secondary_sources)
@@ -136,6 +139,8 @@ defmodule Explorer.SmartContract.Vyper.Publisher do
verification_with_files?
)
+ Logger.error("Vyper smart-contract verification #{address_hash} failed because of the error #{error}")
+
%{changeset | action: :insert}
end
diff --git a/apps/explorer/lib/explorer/smart_contract/vyper/publisher_worker.ex b/apps/explorer/lib/explorer/smart_contract/vyper/publisher_worker.ex
index 45b8feccffa9..690efc346635 100644
--- a/apps/explorer/lib/explorer/smart_contract/vyper/publisher_worker.ex
+++ b/apps/explorer/lib/explorer/smart_contract/vyper/publisher_worker.ex
@@ -3,6 +3,8 @@ defmodule Explorer.SmartContract.Vyper.PublisherWorker do
Background smart contract verification worker.
"""
+ require Logger
+
use Que.Worker, concurrency: 5
alias Explorer.Chain.Events.Publisher, as: EventsPublisher
@@ -34,6 +36,8 @@ defmodule Explorer.SmartContract.Vyper.PublisherWorker do
{:error, changeset}
end
+ Logger.info("Smart-contract #{address_hash} verification: broadcast verification results")
+
if conn do
EventsPublisher.broadcast([{:contract_verification_result, {address_hash, result, conn}}], :on_demand)
else
diff --git a/apps/explorer/lib/explorer/utility/missing_block_range.ex b/apps/explorer/lib/explorer/utility/missing_block_range.ex
index b9355d0c6192..4892334d5fd5 100644
--- a/apps/explorer/lib/explorer/utility/missing_block_range.ex
+++ b/apps/explorer/lib/explorer/utility/missing_block_range.ex
@@ -61,6 +61,7 @@ defmodule Explorer.Utility.MissingBlockRange do
update_range(range_1, %{from_number: range_2.from_number})
_ ->
+ delete_ranges_between(max_number, min_number)
insert_range(%{from_number: max_number, to_number: min_number})
end
end
diff --git a/apps/explorer/mix.exs b/apps/explorer/mix.exs
index fb2cb75bfa64..7bf6eb62cc2d 100644
--- a/apps/explorer/mix.exs
+++ b/apps/explorer/mix.exs
@@ -24,7 +24,7 @@ defmodule Explorer.Mixfile do
dialyzer: :test
],
start_permanent: Mix.env() == :prod,
- version: "5.2.1",
+ version: "5.2.2",
xref: [exclude: [BlockScoutWeb.WebRouter.Helpers]]
]
end
diff --git a/apps/explorer/priv/repo/migrations/20230809134253_add_is_verified_via_admin_panel.exs b/apps/explorer/priv/repo/migrations/20230809134253_add_is_verified_via_admin_panel.exs
new file mode 100644
index 000000000000..1cfa57cb6fca
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20230809134253_add_is_verified_via_admin_panel.exs
@@ -0,0 +1,9 @@
+defmodule Explorer.Repo.Migrations.AddIsVerifiedViaAdminPanel do
+ use Ecto.Migration
+
+ def change do
+ alter table(:tokens) do
+ add(:is_verified_via_admin_panel, :boolean, null: true, default: false)
+ end
+ end
+end
diff --git a/apps/explorer/priv/repo/migrations/20230815131151_drop_logs_address_hash_foreign_key.exs b/apps/explorer/priv/repo/migrations/20230815131151_drop_logs_address_hash_foreign_key.exs
new file mode 100644
index 000000000000..e847cb14d74f
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20230815131151_drop_logs_address_hash_foreign_key.exs
@@ -0,0 +1,8 @@
+# cspell:ignore fkey
+defmodule Explorer.Repo.Migrations.DropLogsAddressHashForeignKey do
+ use Ecto.Migration
+
+ def change do
+ drop_if_exists(constraint(:logs, :logs_address_hash_fkey))
+ end
+end
diff --git a/apps/explorer/priv/repo/migrations/20230816061723_drop_token_transfers_and_transactions_address_foreign_key.exs b/apps/explorer/priv/repo/migrations/20230816061723_drop_token_transfers_and_transactions_address_foreign_key.exs
new file mode 100644
index 000000000000..1cfe0a5fb3d7
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20230816061723_drop_token_transfers_and_transactions_address_foreign_key.exs
@@ -0,0 +1,13 @@
+# cspell:ignore fkey
+defmodule Explorer.Repo.Migrations.DropTokenTransfersAndTransactionsAddressForeignKey do
+ use Ecto.Migration
+
+ def change do
+ drop_if_exists(constraint(:token_transfers, :token_transfers_from_address_hash_fkey))
+ drop_if_exists(constraint(:token_transfers, :token_transfers_to_address_hash_fkey))
+ drop_if_exists(constraint(:token_transfers, :token_transfers_token_contract_address_hash_fkey))
+ drop_if_exists(constraint(:transactions, :transactions_created_contract_address_hash_fkey))
+ drop_if_exists(constraint(:transactions, :transactions_from_address_hash_fkey))
+ drop_if_exists(constraint(:transactions, :transactions_to_address_hash_fkey))
+ end
+end
diff --git a/apps/explorer/priv/repo/migrations/20230817061317_drop_address_foreign_keys.exs b/apps/explorer/priv/repo/migrations/20230817061317_drop_address_foreign_keys.exs
new file mode 100644
index 000000000000..f10c301b76e3
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20230817061317_drop_address_foreign_keys.exs
@@ -0,0 +1,14 @@
+# cspell:ignore fkey
+defmodule Explorer.Repo.Migrations.DropAddressForeignKeys do
+ use Ecto.Migration
+
+ def change do
+ drop_if_exists(constraint(:address_coin_balances, :address_coin_balances_address_hash_fkey))
+ drop_if_exists(constraint(:address_token_balances, :address_token_balances_address_hash_fkey))
+ drop_if_exists(constraint(:address_current_token_balances, :address_current_token_balances_address_hash_fkey))
+ drop_if_exists(constraint(:tokens, :tokens_contract_address_hash_fkey))
+ drop_if_exists(constraint(:internal_transactions, :internal_transactions_created_contract_address_hash_fkey))
+ drop_if_exists(constraint(:internal_transactions, :internal_transactions_from_address_hash_fkey))
+ drop_if_exists(constraint(:internal_transactions, :internal_transactions_to_address_hash_fkey))
+ end
+end
diff --git a/apps/explorer/priv/repo/migrations/20230821120625_drop_rest_address_foreign_keys.exs b/apps/explorer/priv/repo/migrations/20230821120625_drop_rest_address_foreign_keys.exs
new file mode 100644
index 000000000000..36cdd2353fa5
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20230821120625_drop_rest_address_foreign_keys.exs
@@ -0,0 +1,14 @@
+# cspell:ignore fkey
+defmodule Explorer.Repo.Migrations.DropRestAddressForeignKeys do
+ use Ecto.Migration
+
+ def change do
+ drop_if_exists(constraint(:address_coin_balances_daily, :address_coin_balances_daily_address_hash_fkey))
+ drop_if_exists(constraint(:address_to_tags, :address_to_tags_address_hash_fkey))
+ drop_if_exists(constraint(:block_rewards, :block_rewards_address_hash_fkey))
+ drop_if_exists(constraint(:decompiled_smart_contracts, :decompiled_smart_contracts_address_hash_fkey))
+ drop_if_exists(constraint(:smart_contracts, :smart_contracts_address_hash_fkey))
+ drop_if_exists(constraint(:withdrawals, :withdrawals_address_hash_fkey))
+ drop_if_exists(constraint(:blocks, :blocks_miner_hash_fkey))
+ end
+end
diff --git a/apps/explorer/test/explorer/chain/cache/gas_price_oracle_test.exs b/apps/explorer/test/explorer/chain/cache/gas_price_oracle_test.exs
index 630301488aad..d7004d11d0ed 100644
--- a/apps/explorer/test/explorer/chain/cache/gas_price_oracle_test.exs
+++ b/apps/explorer/test/explorer/chain/cache/gas_price_oracle_test.exs
@@ -1,10 +1,53 @@
defmodule Explorer.Chain.Cache.GasPriceOracleTest do
use Explorer.DataCase
+ import Mox
+
alias Explorer.Chain.Cache.GasPriceOracle
+ @block %{
+ "difficulty" => "0x0",
+ "gasLimit" => "0x0",
+ "gasUsed" => "0x0",
+ "hash" => "0x29c850324e357f3c0c836d79860c5af55f7b651e5d7ee253c1af1b14908af49c",
+ "extraData" => "0x0",
+ "logsBloom" => "0x0",
+ "miner" => "0x0",
+ "number" => "0x1",
+ "parentHash" => "0x0",
+ "receiptsRoot" => "0x0",
+ "size" => "0x0",
+ "sha3Uncles" => "0x0",
+ "stateRoot" => "0x0",
+ "timestamp" => "0x0",
+ "baseFeePerGas" => "0x1DCD6500",
+ "totalDifficulty" => "0x0",
+ "transactions" => [
+ %{
+ "blockHash" => "0x29c850324e357f3c0c836d79860c5af55f7b651e5d7ee253c1af1b14908af49c",
+ "blockNumber" => "0x1",
+ "from" => "0x0",
+ "gas" => "0x0",
+ "gasPrice" => "0x0",
+ "hash" => "0xa2e81bb56b55ba3dab2daf76501b50dfaad240cccb905dbf89d65c7a84a4a48e",
+ "input" => "0x",
+ "nonce" => "0x0",
+ "r" => "0x0",
+ "s" => "0x0",
+ "to" => "0x0",
+ "transactionIndex" => "0x0",
+ "v" => "0x0",
+ "value" => "0x0"
+ }
+ ],
+ "transactionsRoot" => "0x0",
+ "uncles" => []
+ }
+
describe "get_average_gas_price/4" do
test "returns nil percentile values if no blocks in the DB" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
assert {:ok,
%{
"slow" => nil,
@@ -14,6 +57,8 @@ defmodule Explorer.Chain.Cache.GasPriceOracleTest do
end
test "returns nil percentile values if blocks are empty in the DB" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
insert(:block)
insert(:block)
insert(:block)
@@ -27,6 +72,8 @@ defmodule Explorer.Chain.Cache.GasPriceOracleTest do
end
test "returns nil percentile values for blocks with failed txs in the DB" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
block = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
:transaction
@@ -51,6 +98,8 @@ defmodule Explorer.Chain.Cache.GasPriceOracleTest do
end
test "returns nil percentile values for transactions with 0 gas price aka 'whitelisted transactions' in the DB" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
block1 = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
block2 = insert(:block, number: 101, hash: "0x76c3da57334fffdc66c0d954dce1a910fcff13ec889a13b2d8b0b6e9440ce729")
@@ -87,6 +136,8 @@ defmodule Explorer.Chain.Cache.GasPriceOracleTest do
end
test "returns the same percentile values if gas price is the same over transactions" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
block1 = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
block2 = insert(:block, number: 101, hash: "0x76c3da57334fffdc66c0d954dce1a910fcff13ec889a13b2d8b0b6e9440ce729")
@@ -123,6 +174,8 @@ defmodule Explorer.Chain.Cache.GasPriceOracleTest do
end
test "returns correct min gas price from the block" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
block1 = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
block2 = insert(:block, number: 101, hash: "0x76c3da57334fffdc66c0d954dce1a910fcff13ec889a13b2d8b0b6e9440ce729")
@@ -165,12 +218,14 @@ defmodule Explorer.Chain.Cache.GasPriceOracleTest do
assert {:ok,
%{
"slow" => 1.0,
- "average" => 1.0,
- "fast" => 1.0
+ "average" => 2.0,
+ "fast" => 2.0
}} = GasPriceOracle.get_average_gas_price(3, 35, 60, 90)
end
test "returns correct average percentile" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
block1 = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
block2 = insert(:block, number: 101, hash: "0x76c3da57334fffdc66c0d954dce1a910fcff13ec889a13b2d8b0b6e9440ce729")
block3 = insert(:block, number: 102, hash: "0x659b2a1cc4dd1a5729900cf0c81c471d1c7891b2517bf9466f7fba56ead2fca0")
@@ -213,7 +268,64 @@ defmodule Explorer.Chain.Cache.GasPriceOracleTest do
assert {:ok,
%{
- "average" => 4.0
+ "average" => 3.34
+ }} = GasPriceOracle.get_average_gas_price(3, 35, 60, 90)
+ end
+
+ test "returns correct gas price for EIP-1559 transactions" do
+ expect(EthereumJSONRPC.Mox, :json_rpc, fn [%{id: id}], _options -> {:ok, [%{id: id, result: @block}]} end)
+
+ block1 = insert(:block, number: 100, hash: "0x3e51328bccedee581e8ba35190216a61a5d67fd91ca528f3553142c0c7d18391")
+ block2 = insert(:block, number: 101, hash: "0x76c3da57334fffdc66c0d954dce1a910fcff13ec889a13b2d8b0b6e9440ce729")
+
+ :transaction
+ |> insert(
+ status: :ok,
+ block_hash: block1.hash,
+ block_number: block1.number,
+ cumulative_gas_used: 884_322,
+ gas_used: 106_025,
+ index: 0,
+ gas_price: 1_000_000_000,
+ max_priority_fee_per_gas: 1_000_000_000,
+ max_fee_per_gas: 1_000_000_000,
+ hash: "0xac2a7dab94d965893199e7ee01649e2d66f0787a4c558b3118c09e80d4df8269"
+ )
+
+ :transaction
+ |> insert(
+ status: :ok,
+ block_hash: block2.hash,
+ block_number: block2.number,
+ cumulative_gas_used: 884_322,
+ gas_used: 106_025,
+ index: 0,
+ gas_price: 1_000_000_000,
+ max_priority_fee_per_gas: 1_000_000_000,
+ max_fee_per_gas: 1_000_000_000,
+ hash: "0x5d5c2776f96704e7845f7d3c1fbba6685ab6efd6f82b6cd11d549f3b3a46bd03"
+ )
+
+ :transaction
+ |> insert(
+ status: :ok,
+ block_hash: block2.hash,
+ block_number: block2.number,
+ cumulative_gas_used: 884_322,
+ gas_used: 106_025,
+ index: 1,
+ gas_price: 3_000_000_000,
+ max_priority_fee_per_gas: 3_000_000_000,
+ max_fee_per_gas: 3_000_000_000,
+ hash: "0x906b80861b4a0921acfbb91a7b527227b0d32adabc88bc73e8c52ff714e55016"
+ )
+
+ assert {:ok,
+ %{
+ # including base fee
+ "slow" => 1.5,
+ "average" => 2.5,
+ "fast" => 2.5
}} = GasPriceOracle.get_average_gas_price(3, 35, 60, 90)
end
end
diff --git a/apps/explorer/test/explorer/chain/csv_export/address_log_csv_exporter_test.exs b/apps/explorer/test/explorer/chain/csv_export/address_log_csv_exporter_test.exs
index b863792f8165..bff1ca818d33 100644
--- a/apps/explorer/test/explorer/chain/csv_export/address_log_csv_exporter_test.exs
+++ b/apps/explorer/test/explorer/chain/csv_export/address_log_csv_exporter_test.exs
@@ -1,6 +1,7 @@
defmodule Explorer.Chain.AddressLogCsvExporterTest do
use Explorer.DataCase
+ alias Explorer.Chain.Address
alias Explorer.Chain.CSVExport.AddressLogCsvExporter
describe "export/3" do
@@ -74,7 +75,7 @@ defmodule Explorer.Chain.AddressLogCsvExporterTest do
assert result.index == to_string(log.index)
assert result.block_number == to_string(log.block_number)
assert result.block_hash == to_string(log.block_hash)
- assert result.address == String.downcase(to_string(log.address))
+ assert result.address == Address.checksum(log.address.hash)
assert result.data == to_string(log.data)
assert result.first_topic == to_string(log.first_topic)
assert result.second_topic == to_string(log.second_topic)
diff --git a/apps/explorer/test/explorer/chain/import/runner/address/current_token_balances_test.exs b/apps/explorer/test/explorer/chain/import/runner/address/current_token_balances_test.exs
index 31eba0553de0..fa8d97e0a5c2 100644
--- a/apps/explorer/test/explorer/chain/import/runner/address/current_token_balances_test.exs
+++ b/apps/explorer/test/explorer/chain/import/runner/address/current_token_balances_test.exs
@@ -218,7 +218,8 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalancesTest do
address_hash: address.hash,
block_number: 2,
token_contract_address_hash: token.contract_address_hash,
- value: Decimal.new(200)
+ value: Decimal.new(200),
+ value_fetched_at: DateTime.utc_now()
},
options
)
@@ -300,7 +301,8 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalancesTest do
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
- value: value
+ value: value,
+ value_fetched_at: DateTime.utc_now()
},
options
)
@@ -344,7 +346,8 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalancesTest do
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
- value: value
+ value: value,
+ value_fetched_at: DateTime.utc_now()
},
options
)
@@ -404,13 +407,15 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalancesTest do
address_hash: non_holder_becomes_holder_address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
- value: non_holder_becomes_holder_value
+ value: non_holder_becomes_holder_value,
+ value_fetched_at: DateTime.utc_now()
},
%{
address_hash: holder_becomes_non_holder_address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
- value: holder_becomes_non_holder_value
+ value: holder_becomes_non_holder_value,
+ value_fetched_at: DateTime.utc_now()
}
],
options
diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs
index fbfc00668853..728d7adc2971 100644
--- a/apps/explorer/test/explorer/chain_test.exs
+++ b/apps/explorer/test/explorer/chain_test.exs
@@ -28,6 +28,7 @@ defmodule Explorer.ChainTest do
}
alias Explorer.{Chain, Etherscan}
+ alias Explorer.Chain.Address.Counters
alias Explorer.Chain.Cache.Block, as: BlockCache
alias Explorer.Chain.Cache.Transaction, as: TransactionCache
alias Explorer.Chain.Cache.PendingBlockOperation, as: PendingBlockOperationCache
@@ -84,7 +85,7 @@ defmodule Explorer.ChainTest do
start_supervised!(AddressesWithBalanceCounter)
AddressesWithBalanceCounter.consolidate()
- addresses_with_balance = Chain.count_addresses_with_balance_from_cache()
+ addresses_with_balance = Counters.count_addresses_with_balance_from_cache()
assert is_integer(addresses_with_balance)
assert addresses_with_balance == 2
@@ -100,7 +101,7 @@ defmodule Explorer.ChainTest do
start_supervised!(AddressesCounter)
AddressesCounter.consolidate()
- addresses_with_balance = Chain.address_estimated_count()
+ addresses_with_balance = Counters.address_estimated_count()
assert is_integer(addresses_with_balance)
assert addresses_with_balance == 3
@@ -108,7 +109,7 @@ defmodule Explorer.ChainTest do
test "returns 0 on empty table" do
start_supervised!(AddressesCounter)
- assert 0 == Chain.address_estimated_count()
+ assert 0 == Counters.address_estimated_count()
end
end
@@ -875,7 +876,7 @@ defmodule Explorer.ChainTest do
|> insert(nonce: 100, from_address: address)
|> with_block(insert(:block, number: 1000))
- assert Chain.total_transactions_sent_by_address(address.hash) == 101
+ assert Counters.total_transactions_sent_by_address(address.hash) == 101
end
test "returns 0 when the address did not send transactions" do
@@ -885,7 +886,7 @@ defmodule Explorer.ChainTest do
|> insert(nonce: 100, to_address: address)
|> with_block(insert(:block, number: 1000))
- assert Chain.total_transactions_sent_by_address(address.hash) == 0
+ assert Counters.total_transactions_sent_by_address(address.hash) == 0
end
end
@@ -1099,13 +1100,13 @@ defmodule Explorer.ChainTest do
test "without transactions" do
%Address{hash: address_hash} = insert(:address)
- assert Chain.address_to_incoming_transaction_count(address_hash) == 0
+ assert Counters.address_to_incoming_transaction_count(address_hash) == 0
end
test "with transactions" do
%Transaction{to_address: to_address} = insert(:transaction)
- assert Chain.address_to_incoming_transaction_count(to_address.hash) == 1
+ assert Counters.address_to_incoming_transaction_count(to_address.hash) == 1
end
end
diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex
index 9c33824972eb..28093d950e19 100644
--- a/apps/explorer/test/support/factory.ex
+++ b/apps/explorer/test/support/factory.ex
@@ -142,14 +142,18 @@ defmodule Explorer.Factory do
def address_to_tag_factory do
%AddressToTag{
- tag: %AddressTag{
- label: sequence("label"),
- display_name: sequence("display_name")
- },
+ tag: build(:address_tag),
address: build(:address)
}
end
+ def address_tag_factory do
+ %AddressTag{
+ label: sequence("label"),
+ display_name: sequence("display_name")
+ }
+ end
+
def account_watchlist_address_factory do
hash = build(:address).hash
@@ -656,7 +660,8 @@ defmodule Explorer.Factory do
type: "ERC-20",
cataloged: true,
icon_url: sequence("https://example.com/icon"),
- fiat_value: 10.1
+ fiat_value: 10.1,
+ is_verified_via_admin_panel: Enum.random([true, false])
}
end
diff --git a/apps/indexer/lib/indexer/block/catchup/fetcher.ex b/apps/indexer/lib/indexer/block/catchup/fetcher.ex
index 6a7d63e8710d..740d788a251a 100644
--- a/apps/indexer/lib/indexer/block/catchup/fetcher.ex
+++ b/apps/indexer/lib/indexer/block/catchup/fetcher.ex
@@ -55,7 +55,9 @@ defmodule Indexer.Block.Catchup.Fetcher do
shrunk: false
}
- missing_ranges ->
+ latest_missing_ranges ->
+ missing_ranges = filter_consensus_blocks(latest_missing_ranges)
+
first.._ = List.first(missing_ranges)
_..last = List.last(missing_ranges)
@@ -85,6 +87,21 @@ defmodule Indexer.Block.Catchup.Fetcher do
end
end
+ defp filter_consensus_blocks(ranges) do
+ filtered_ranges =
+ ranges
+ |> Enum.map(&Chain.missing_block_number_ranges(&1))
+ |> List.flatten()
+
+ consensus_blocks = ranges_to_numbers(ranges) -- ranges_to_numbers(filtered_ranges)
+
+ consensus_blocks
+ |> numbers_to_ranges()
+ |> MissingRangesManipulator.clear_batch()
+
+ filtered_ranges
+ end
+
@doc """
The number of blocks to request in one call to the JSONRPC. Defaults to
10. Block requests also include the transactions for those blocks. *These transactions
@@ -306,6 +323,12 @@ defmodule Indexer.Block.Catchup.Fetcher do
)
end
+ defp ranges_to_numbers(ranges) do
+ ranges
+ |> Enum.map(&Enum.to_list/1)
+ |> List.flatten()
+ end
+
defp put_memory_monitor(sequence_options, %__MODULE__{memory_monitor: nil}) when is_list(sequence_options),
do: sequence_options
diff --git a/apps/indexer/lib/indexer/block/fetcher.ex b/apps/indexer/lib/indexer/block/fetcher.ex
index d7b9be8d31e7..cffd739843bf 100644
--- a/apps/indexer/lib/indexer/block/fetcher.ex
+++ b/apps/indexer/lib/indexer/block/fetcher.ex
@@ -29,7 +29,7 @@ defmodule Indexer.Block.Fetcher do
UncleBlock
}
- alias Indexer.{Prometheus, Tracer}
+ alias Indexer.{Prometheus, TokenBalances, Tracer}
alias Indexer.Transform.{
AddressCoinBalances,
@@ -182,6 +182,9 @@ defmodule Indexer.Block.Fetcher do
address_coin_balances: %{params: coin_balances_params_set},
address_coin_balances_daily: %{params: coin_balances_params_daily_set},
address_token_balances: %{params: address_token_balances},
+ address_current_token_balances: %{
+ params: address_token_balances |> MapSet.to_list() |> TokenBalances.to_address_current_token_balances()
+ },
blocks: %{params: blocks},
block_second_degree_relations: %{params: block_second_degree_relations_params},
block_rewards: %{errors: beneficiaries_errors, params: beneficiaries_with_gas_payment},
diff --git a/apps/indexer/lib/indexer/block/realtime/fetcher.ex b/apps/indexer/lib/indexer/block/realtime/fetcher.ex
index 720672987370..1b3a8fcb74fc 100644
--- a/apps/indexer/lib/indexer/block/realtime/fetcher.ex
+++ b/apps/indexer/lib/indexer/block/realtime/fetcher.ex
@@ -30,6 +30,7 @@ defmodule Indexer.Block.Realtime.Fetcher do
alias Explorer.Chain.Cache.Accounts
alias Explorer.Chain.Events.Publisher
alias Explorer.Counters.AverageBlockTime
+ alias Explorer.Utility.MissingRangesManipulator
alias Indexer.{Block, Tracer}
alias Indexer.Block.Realtime.TaskSupervisor
alias Indexer.Fetcher.CoinBalance
@@ -310,6 +311,7 @@ defmodule Indexer.Block.Realtime.Fetcher do
case result do
{:ok, %{inserted: inserted, errors: []}} ->
log_import_timings(inserted, fetch_duration, time_before)
+ MissingRangesManipulator.clear_batch([block_number_to_fetch..block_number_to_fetch])
Logger.debug("Fetched and imported.")
{:ok, %{inserted: _, errors: [_ | _] = errors}} ->
diff --git a/apps/indexer/lib/indexer/fetcher/token.ex b/apps/indexer/lib/indexer/fetcher/token.ex
index 57b815a03e54..9d4b0dd253f3 100644
--- a/apps/indexer/lib/indexer/fetcher/token.ex
+++ b/apps/indexer/lib/indexer/fetcher/token.ex
@@ -14,12 +14,7 @@ defmodule Indexer.Fetcher.Token do
@behaviour BufferedTask
- @defaults [
- flush_interval: 300,
- max_batch_size: 1,
- max_concurrency: 10,
- task_supervisor: Indexer.Fetcher.Token.TaskSupervisor
- ]
+ @default_max_concurrency 10
@doc false
def child_spec([init_options, gen_server_options]) do
@@ -32,7 +27,7 @@ defmodule Indexer.Fetcher.Token do
end
merged_init_opts =
- @defaults
+ defaults()
|> Keyword.merge(mergeable_init_options)
|> Keyword.put(:state, state)
@@ -81,4 +76,13 @@ defmodule Indexer.Fetcher.Token do
{:ok, _} = Chain.update_token(token, token_params)
:ok
end
+
+ defp defaults do
+ [
+ flush_interval: 300,
+ max_batch_size: 1,
+ max_concurrency: Application.get_env(:indexer, __MODULE__)[:concurrency] || @default_max_concurrency,
+ task_supervisor: Indexer.Fetcher.Token.TaskSupervisor
+ ]
+ end
end
diff --git a/apps/indexer/lib/indexer/fetcher/token_balance.ex b/apps/indexer/lib/indexer/fetcher/token_balance.ex
index 9a40d88e6f0b..93add63827d2 100644
--- a/apps/indexer/lib/indexer/fetcher/token_balance.ex
+++ b/apps/indexer/lib/indexer/fetcher/token_balance.ex
@@ -26,6 +26,7 @@ defmodule Indexer.Fetcher.TokenBalance do
@behaviour BufferedTask
@default_max_batch_size 100
+ @default_max_concurrency 10
@max_retries 3
@@ -75,8 +76,7 @@ defmodule Indexer.Fetcher.TokenBalance do
token_balance
|> entry()
|> reducer.(acc)
- end,
- true
+ end
)
final
@@ -235,7 +235,7 @@ defmodule Indexer.Fetcher.TokenBalance do
[
flush_interval: 300,
max_batch_size: Application.get_env(:indexer, __MODULE__)[:batch_size] || @default_max_batch_size,
- max_concurrency: 10,
+ max_concurrency: Application.get_env(:indexer, __MODULE__)[:concurrency] || @default_max_concurrency,
task_supervisor: Indexer.Fetcher.TokenBalance.TaskSupervisor
]
end
diff --git a/apps/indexer/lib/indexer/fetcher/token_balance_on_demand.ex b/apps/indexer/lib/indexer/fetcher/token_balance_on_demand.ex
index 3f3c05bb7932..d1dfcf6d3364 100644
--- a/apps/indexer/lib/indexer/fetcher/token_balance_on_demand.ex
+++ b/apps/indexer/lib/indexer/fetcher/token_balance_on_demand.ex
@@ -9,15 +9,18 @@ defmodule Indexer.Fetcher.TokenBalanceOnDemand do
alias Explorer.Chain
alias Explorer.Chain.Address.CurrentTokenBalance
alias Explorer.Chain.Cache.BlockNumber
+ alias Explorer.Chain.Events.Publisher
alias Explorer.Chain.Hash
alias Explorer.Counters.AverageBlockTime
alias Explorer.Token.BalanceReader
alias Timex.Duration
+ require Logger
+
## Interface
- @spec trigger_fetch(Hash.t(), [CurrentTokenBalance.t()]) :: :ok
- def trigger_fetch(address_hash, current_token_balances) do
+ @spec trigger_fetch(Hash.t()) :: :ok
+ def trigger_fetch(address_hash) do
latest_block_number = latest_block_number()
case stale_balance_window(latest_block_number) do
@@ -25,7 +28,7 @@ defmodule Indexer.Fetcher.TokenBalanceOnDemand do
:current
stale_balance_window ->
- do_trigger_fetch(address_hash, current_token_balances, latest_block_number, stale_balance_window)
+ do_trigger_fetch(address_hash, latest_block_number, stale_balance_window)
end
end
@@ -36,7 +39,6 @@ defmodule Indexer.Fetcher.TokenBalanceOnDemand do
Decimal.t() | nil,
non_neg_integer()
) :: {:ok, pid}
-
def trigger_historic_fetch(address_hash, contract_address_hash, token_type, token_id, block_number) do
Task.start(fn ->
do_trigger_historic_fetch(address_hash, contract_address_hash, token_type, token_id, block_number)
@@ -45,10 +47,11 @@ defmodule Indexer.Fetcher.TokenBalanceOnDemand do
## Implementation
- defp do_trigger_fetch(address_hash, current_token_balances, latest_block_number, stale_balance_window)
+ defp do_trigger_fetch(address_hash, latest_block_number, stale_balance_window)
when not is_nil(address_hash) do
stale_current_token_balances =
- current_token_balances
+ address_hash
+ |> Chain.fetch_last_token_balances_include_unfetched()
|> Enum.filter(fn current_token_balance -> current_token_balance.block_number < stale_balance_window end)
if Enum.count(stale_current_token_balances) > 0 do
@@ -61,51 +64,101 @@ defmodule Indexer.Fetcher.TokenBalanceOnDemand do
end
defp fetch_and_update(block_number, address_hash, stale_current_token_balances) do
- current_token_balances_update_params =
+ %{erc_1155: erc_1155_ctbs, other: other_ctbs, tokens: tokens} =
stale_current_token_balances
- |> Enum.map(fn %{token_id: token_id} = stale_current_token_balance ->
- stale_current_token_balances_to_fetch = [
- %{
- token_contract_address_hash:
- "0x" <> Base.encode16(stale_current_token_balance.token.contract_address_hash.bytes),
- address_hash: "0x" <> Base.encode16(address_hash.bytes),
- block_number: block_number,
- token_id: token_id && Decimal.to_integer(token_id)
- }
- ]
-
- balance_response =
- case stale_current_token_balance.token_type do
- "ERC-1155" -> BalanceReader.get_balances_of_erc_1155(stale_current_token_balances_to_fetch)
- _ -> BalanceReader.get_balances_of(stale_current_token_balances_to_fetch)
+ |> Enum.reduce(%{erc_1155: [], other: [], tokens: %{}}, fn %{token_id: token_id} = stale_current_token_balance,
+ acc ->
+ prepared_ctb = %{
+ token_contract_address_hash:
+ "0x" <> Base.encode16(stale_current_token_balance.token.contract_address_hash.bytes),
+ address_hash: "0x" <> Base.encode16(address_hash.bytes),
+ block_number: block_number,
+ token_id: token_id && Decimal.to_integer(token_id),
+ token_type: stale_current_token_balance.token_type
+ }
+
+ updated_tokens =
+ Map.put_new(
+ acc[:tokens],
+ stale_current_token_balance.token.contract_address_hash.bytes,
+ stale_current_token_balance.token
+ )
+
+ result =
+ if stale_current_token_balance.token_type == "ERC-1155" do
+ Map.put(acc, :erc_1155, [prepared_ctb | acc[:erc_1155]])
+ else
+ Map.put(acc, :other, [prepared_ctb | acc[:other]])
end
- updated_balance = balance_response[:ok]
-
- if updated_balance do
- %{}
- |> Map.put(:address_hash, stale_current_token_balance.address_hash)
- |> Map.put(:token_contract_address_hash, stale_current_token_balance.token.contract_address_hash)
- |> Map.put(:token_type, stale_current_token_balance.token.type)
- |> Map.put(:token_id, token_id)
- |> Map.put(:block_number, block_number)
- |> Map.put(:value, Decimal.new(updated_balance))
- |> Map.put(:value_fetched_at, DateTime.utc_now())
- else
- nil
- end
+ Map.put(result, :tokens, updated_tokens)
end)
+ erc_1155_ctbs_reversed = Enum.reverse(erc_1155_ctbs)
+ other_ctbs_reversed = Enum.reverse(other_ctbs)
+
+ updated_erc_1155_ctbs =
+ if Enum.count(erc_1155_ctbs_reversed) > 0 do
+ erc_1155_ctbs_reversed
+ |> BalanceReader.get_balances_of_erc_1155()
+ |> Enum.zip(erc_1155_ctbs_reversed)
+ |> Enum.map(&prepare_updated_balance(&1, block_number))
+ else
+ []
+ end
+
+ updated_other_ctbs =
+ if Enum.count(other_ctbs_reversed) > 0 do
+ other_ctbs_reversed
+ |> BalanceReader.get_balances_of()
+ |> Enum.zip(other_ctbs_reversed)
+ |> Enum.map(&prepare_updated_balance(&1, block_number))
+ else
+ []
+ end
+
filtered_current_token_balances_update_params =
- current_token_balances_update_params
+ (updated_erc_1155_ctbs ++ updated_other_ctbs)
|> Enum.filter(&(!is_nil(&1)))
- Chain.import(%{
- address_current_token_balances: %{
- params: filtered_current_token_balances_update_params
+ {:ok,
+ %{
+ address_current_token_balances: imported_ctbs
+ }} =
+ Chain.import(%{
+ address_current_token_balances: %{
+ params: filtered_current_token_balances_update_params
+ },
+ broadcast: false
+ })
+
+ Publisher.broadcast(
+ %{
+ address_current_token_balances: %{
+ address_hash: to_string(address_hash),
+ address_current_token_balances:
+ imported_ctbs
+ |> Enum.map(fn ctb -> %CurrentTokenBalance{ctb | token: tokens[ctb.token_contract_address_hash.bytes]} end)
+ }
},
- broadcast: :on_demand
- })
+ :on_demand
+ )
+ end
+
+ defp prepare_updated_balance({{:ok, updated_balance}, stale_current_token_balance}, block_number) do
+ %{}
+ |> Map.put(:address_hash, stale_current_token_balance.address_hash)
+ |> Map.put(:token_contract_address_hash, stale_current_token_balance.token_contract_address_hash)
+ |> Map.put(:token_type, stale_current_token_balance.token_type)
+ |> Map.put(:token_id, stale_current_token_balance.token_id)
+ |> Map.put(:block_number, block_number)
+ |> Map.put(:value, Decimal.new(updated_balance))
+ |> Map.put(:value_fetched_at, DateTime.utc_now())
+ end
+
+ defp prepare_updated_balance({{:error, error}, _ctb}, _block_number) do
+ Logger.warn(fn -> ["Error on updating current token balance: ", inspect(error)] end)
+ nil
end
defp do_trigger_historic_fetch(address_hash, contract_address_hash, token_type, token_id, block_number) do
diff --git a/apps/indexer/mix.exs b/apps/indexer/mix.exs
index b24c16733a2e..444a7a27e772 100644
--- a/apps/indexer/mix.exs
+++ b/apps/indexer/mix.exs
@@ -14,7 +14,7 @@ defmodule Indexer.MixProject do
elixirc_paths: elixirc_paths(Mix.env()),
lockfile: "../../mix.lock",
start_permanent: Mix.env() == :prod,
- version: "5.2.1"
+ version: "5.2.2"
]
end
diff --git a/apps/indexer/test/indexer/block/catchup/bound_interval_supervisor_test.exs b/apps/indexer/test/indexer/block/catchup/bound_interval_supervisor_test.exs
index 77f7a63512dc..774ebfe3a5ab 100644
--- a/apps/indexer/test/indexer/block/catchup/bound_interval_supervisor_test.exs
+++ b/apps/indexer/test/indexer/block/catchup/bound_interval_supervisor_test.exs
@@ -50,37 +50,42 @@ defmodule Indexer.Block.Catchup.BoundIntervalSupervisorTest do
EthereumJSONRPC.Mox
|> stub(:json_rpc, fn
# latest block number to seed starting block number for genesis and realtime tasks
- %{method: "eth_getBlockByNumber", params: ["latest", false]}, _options ->
+ [%{id: id, method: "eth_getBlockByNumber", params: ["latest", false]}], _options ->
{:ok,
- %{
- "author" => "0xe2ac1c6843a33f81ae4935e5ef1277a392990381",
- "difficulty" => "0xfffffffffffffffffffffffffffffffe",
- "extraData" => "0xd583010a068650617269747986312e32362e32826c69",
- "gasLimit" => "0x7a1200",
- "gasUsed" => "0x0",
- "hash" => "0x627baabf5a17c0cfc547b6903ac5e19eaa91f30d9141be1034e3768f6adbc94e",
- "logsBloom" =>
- "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner" => "0xe2ac1c6843a33f81ae4935e5ef1277a392990381",
- "number" => block_quantity,
- "parentHash" => "0x006edcaa1e6fde822908783bc4ef1ad3675532d542fce53537557391cfe34c3c",
- "receiptsRoot" => "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sealFields" => [
- "0x841240b30d",
- "0xb84158bc4fa5891934bc94c5dca0301867ce4f35925ef46ea187496162668210bba61b4cda09d7e0dca2f1dd041fad498ced6697aeef72656927f52c55b630f2591c01"
- ],
- "sha3Uncles" => "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "signature" =>
- "58bc4fa5891934bc94c5dca0301867ce4f35925ef46ea187496162668210bba61b4cda09d7e0dca2f1dd041fad498ced6697aeef72656927f52c55b630f2591c01",
- "size" => "0x243",
- "stateRoot" => "0x9a8111062667f7b162851a1cbbe8aece5ff12e761b3dcee93b787fcc12548cf7",
- "step" => "306230029",
- "timestamp" => "0x5b437f41",
- "totalDifficulty" => "0x342337ffffffffffffffffffffffffed8d29bb",
- "transactions" => [],
- "transactionsRoot" => "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "uncles" => []
- }}
+ [
+ %{
+ id: id,
+ result: %{
+ "author" => "0xe2ac1c6843a33f81ae4935e5ef1277a392990381",
+ "difficulty" => "0xfffffffffffffffffffffffffffffffe",
+ "extraData" => "0xd583010a068650617269747986312e32362e32826c69",
+ "gasLimit" => "0x7a1200",
+ "gasUsed" => "0x0",
+ "hash" => "0x627baabf5a17c0cfc547b6903ac5e19eaa91f30d9141be1034e3768f6adbc94e",
+ "logsBloom" =>
+ "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner" => "0xe2ac1c6843a33f81ae4935e5ef1277a392990381",
+ "number" => block_quantity,
+ "parentHash" => "0x006edcaa1e6fde822908783bc4ef1ad3675532d542fce53537557391cfe34c3c",
+ "receiptsRoot" => "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sealFields" => [
+ "0x841240b30d",
+ "0xb84158bc4fa5891934bc94c5dca0301867ce4f35925ef46ea187496162668210bba61b4cda09d7e0dca2f1dd041fad498ced6697aeef72656927f52c55b630f2591c01"
+ ],
+ "sha3Uncles" => "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "signature" =>
+ "58bc4fa5891934bc94c5dca0301867ce4f35925ef46ea187496162668210bba61b4cda09d7e0dca2f1dd041fad498ced6697aeef72656927f52c55b630f2591c01",
+ "size" => "0x243",
+ "stateRoot" => "0x9a8111062667f7b162851a1cbbe8aece5ff12e761b3dcee93b787fcc12548cf7",
+ "step" => "306230029",
+ "timestamp" => "0x5b437f41",
+ "totalDifficulty" => "0x342337ffffffffffffffffffffffffed8d29bb",
+ "transactions" => [],
+ "transactionsRoot" => "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncles" => []
+ }
+ }
+ ]}
[%{method: "trace_block"} | _] = requests, _options ->
{:ok, Enum.map(requests, fn %{id: id} -> %{id: id, result: []} end)}
diff --git a/config/runtime.exs b/config/runtime.exs
index abf72d6e81ab..94b5b6abd17c 100644
--- a/config/runtime.exs
+++ b/config/runtime.exs
@@ -168,6 +168,9 @@ config :ethereum_jsonrpc, EthereumJSONRPC.Geth,
config :ethereum_jsonrpc, EthereumJSONRPC.PendingTransaction,
type: System.get_env("ETHEREUM_JSONRPC_PENDING_TRANSACTIONS_TYPE", "default")
+config :ethereum_jsonrpc, EthereumJSONRPC.RequestCoordinator,
+ wait_per_timeout: ConfigHelper.parse_time_env_var("ETHEREUM_JSONRPC_WAIT_PER_TIMEOUT", "20s")
+
################
### Explorer ###
################
@@ -449,8 +452,11 @@ config :indexer, Indexer.Fetcher.PendingTransaction.Supervisor,
System.get_env("ETHEREUM_JSONRPC_VARIANT") == "besu" ||
ConfigHelper.parse_bool_env_var("INDEXER_DISABLE_PENDING_TRANSACTIONS_FETCHER")
+config :indexer, Indexer.Fetcher.Token, concurrency: ConfigHelper.parse_integer_env_var("INDEXER_TOKEN_CONCURRENCY", 10)
+
config :indexer, Indexer.Fetcher.TokenBalance,
- batch_size: ConfigHelper.parse_integer_env_var("INDEXER_TOKEN_BALANCES_BATCH_SIZE", 100)
+ batch_size: ConfigHelper.parse_integer_env_var("INDEXER_TOKEN_BALANCES_BATCH_SIZE", 100),
+ concurrency: ConfigHelper.parse_integer_env_var("INDEXER_TOKEN_BALANCES_CONCURRENCY", 10)
config :indexer, Indexer.Fetcher.TokenBalanceOnDemand,
threshold: ConfigHelper.parse_time_env_var("TOKEN_BALANCE_ON_DEMAND_FETCHER_THRESHOLD", "1h"),
diff --git a/cspell.json b/cspell.json
index 2c733cb6d8ad..c35c242239f4 100644
--- a/cspell.json
+++ b/cspell.json
@@ -519,7 +519,8 @@
"erts",
"Asfpp",
"Nerg",
- "secp"
+ "secp",
+ "qwertyuioiuytrewertyuioiuytrertyuio"
],
"enableFiletypes": [
"dotenv",
diff --git a/docker-compose/docker-compose-no-build-external-backend.yml b/docker-compose/docker-compose-no-build-external-backend.yml
new file mode 100644
index 000000000000..3e1726bf846e
--- /dev/null
+++ b/docker-compose/docker-compose-no-build-external-backend.yml
@@ -0,0 +1,52 @@
+version: '3.8'
+
+services:
+ redis_db:
+ extends:
+ file: ./services/docker-compose-redis.yml
+ service: redis_db
+
+ db:
+ extends:
+ file: ./services/docker-compose-db.yml
+ service: db
+
+ smart-contract-verifier:
+ extends:
+ file: ./services/docker-compose-smart-contract-verifier.yml
+ service: smart-contract-verifier
+
+ visualizer:
+ extends:
+ file: ./services/docker-compose-visualizer.yml
+ service: visualizer
+
+ sig-provider:
+ extends:
+ file: ./services/docker-compose-sig-provider.yml
+ service: sig-provider
+
+ frontend:
+ extends:
+ file: ./services/docker-compose-frontend.yml
+ service: frontend
+
+ stats-db:
+ extends:
+ file: ./services/docker-compose-stats.yml
+ service: stats-db
+
+ stats:
+ depends_on:
+ - stats-db
+ extends:
+ file: ./services/docker-compose-stats.yml
+ service: stats
+
+ proxy:
+ depends_on:
+ - frontend
+ - stats
+ extends:
+ file: ./services/docker-compose-nginx.yml
+ service: proxy
diff --git a/docker-compose/docker-compose-no-build-external-frontend.yml b/docker-compose/docker-compose-no-build-external-frontend.yml
new file mode 100644
index 000000000000..bc96e61f854d
--- /dev/null
+++ b/docker-compose/docker-compose-no-build-external-frontend.yml
@@ -0,0 +1,85 @@
+version: '3.8'
+
+services:
+ redis_db:
+ extends:
+ file: ./services/docker-compose-redis.yml
+ service: redis_db
+
+ db:
+ extends:
+ file: ./services/docker-compose-db.yml
+ service: db
+
+ backend:
+ depends_on:
+ - db
+ - smart-contract-verifier
+ - redis_db
+ image: blockscout/blockscout:${DOCKER_TAG:-master}
+ pull_policy: always
+ restart: always
+ stop_grace_period: 5m
+ container_name: 'blockscout'
+ links:
+ - db:database
+ command: sh -c "bin/blockscout eval \"Elixir.Explorer.ReleaseTasks.create_and_migrate()\" && bin/blockscout start"
+ extra_hosts:
+ - 'host.docker.internal:host-gateway'
+ env_file:
+ - ./envs/common-blockscout.env
+ environment:
+ ETHEREUM_JSONRPC_VARIANT: 'ganache'
+ ETHEREUM_JSONRPC_HTTP_URL: http://host.docker.internal:8545/
+ ETHEREUM_JSONRPC_TRACE_URL: http://host.docker.internal:8545/
+ ETHEREUM_JSONRPC_WS_URL: ws://host.docker.internal:8545/
+ INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER: 'true'
+ INDEXER_DISABLE_PENDING_TRANSACTIONS_FETCHER: 'true'
+ DATABASE_URL: postgresql://postgres:@host.docker.internal:7432/blockscout?ssl=false
+ ECTO_USE_SSL: 'false'
+ SECRET_KEY_BASE: '56NtB48ear7+wMSf0IQuWDAAazhpb31qyc7GiyspBP2vh7t5zlCsF5QDv76chXeN'
+ CHAIN_ID: '1337'
+ API_V2_ENABLED: 'true'
+ MIX_ENV: 'prod'
+ ACCOUNT_ENABLED: 'false'
+ ports:
+ - 4000:4000
+ volumes:
+ - ./logs/:/app/logs/
+
+ smart-contract-verifier:
+ extends:
+ file: ./services/docker-compose-smart-contract-verifier.yml
+ service: smart-contract-verifier
+
+ visualizer:
+ extends:
+ file: ./services/docker-compose-visualizer.yml
+ service: visualizer
+
+ sig-provider:
+ extends:
+ file: ./services/docker-compose-sig-provider.yml
+ service: sig-provider
+
+ stats-db:
+ depends_on:
+ - backend
+ extends:
+ file: ./services/docker-compose-stats.yml
+ service: stats-db
+
+ stats:
+ depends_on:
+ - stats-db
+ extends:
+ file: ./services/docker-compose-stats.yml
+ service: stats
+
+ proxy:
+ depends_on:
+ - backend
+ - stats
+ extends:
+ file: ./services/docker-compose-nginx.yml
+ service: proxy
\ No newline at end of file
diff --git a/docker-compose/docker-compose-no-build-frontend.yml b/docker-compose/docker-compose-no-build-frontend.yml
index e52017c7f78b..663d580398dc 100644
--- a/docker-compose/docker-compose-no-build-frontend.yml
+++ b/docker-compose/docker-compose-no-build-frontend.yml
@@ -31,6 +31,7 @@ services:
environment:
ETHEREUM_JSONRPC_VARIANT: 'ganache'
ETHEREUM_JSONRPC_HTTP_URL: http://host.docker.internal:8545/
+ ETHEREUM_JSONRPC_TRACE_URL: http://host.docker.internal:8545/
ETHEREUM_JSONRPC_WS_URL: ws://host.docker.internal:8545/
INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER: 'true'
INDEXER_DISABLE_PENDING_TRANSACTIONS_FETCHER: 'true'
@@ -76,14 +77,16 @@ services:
stats:
depends_on:
- - backend
+ - stats-db
extends:
file: ./services/docker-compose-stats.yml
service: stats
proxy:
depends_on:
+ - backend
- frontend
+ - stats
extends:
file: ./services/docker-compose-nginx.yml
service: proxy
diff --git a/docker-compose/docker-compose-no-build-geth-clique-consensus.yml b/docker-compose/docker-compose-no-build-geth-clique-consensus.yml
index bfcb31cb9d27..fb0924808f3e 100644
--- a/docker-compose/docker-compose-no-build-geth-clique-consensus.yml
+++ b/docker-compose/docker-compose-no-build-geth-clique-consensus.yml
@@ -32,6 +32,7 @@ services:
ETHEREUM_JSONRPC_VARIANT: 'geth'
BLOCK_TRANSFORMER: 'clique'
ETHEREUM_JSONRPC_HTTP_URL: http://host.docker.internal:8545/
+ ETHEREUM_JSONRPC_TRACE_URL: http://host.docker.internal:8545/
DATABASE_URL: postgresql://postgres:@host.docker.internal:7432/blockscout?ssl=false
ECTO_USE_SSL: 'false'
SECRET_KEY_BASE: '56NtB48ear7+wMSf0IQuWDAAazhpb31qyc7GiyspBP2vh7t5zlCsF5QDv76chXeN'
diff --git a/docker-compose/docker-compose-no-build-geth.yml b/docker-compose/docker-compose-no-build-geth.yml
index d8aa27370019..acd74b684871 100644
--- a/docker-compose/docker-compose-no-build-geth.yml
+++ b/docker-compose/docker-compose-no-build-geth.yml
@@ -31,6 +31,7 @@ services:
environment:
ETHEREUM_JSONRPC_VARIANT: 'geth'
ETHEREUM_JSONRPC_HTTP_URL: http://host.docker.internal:8545/
+ ETHEREUM_JSONRPC_TRACE_URL: http://host.docker.internal:8545/
DATABASE_URL: postgresql://postgres:@host.docker.internal:7432/blockscout?ssl=false
ECTO_USE_SSL: 'false'
SECRET_KEY_BASE: '56NtB48ear7+wMSf0IQuWDAAazhpb31qyc7GiyspBP2vh7t5zlCsF5QDv76chXeN'
diff --git a/docker-compose/docker-compose-no-rust-services.yml b/docker-compose/docker-compose-no-rust-services.yml
index a35253cd3279..af87b47c1c28 100644
--- a/docker-compose/docker-compose-no-rust-services.yml
+++ b/docker-compose/docker-compose-no-rust-services.yml
@@ -27,7 +27,7 @@ services:
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED: ""
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL: ""
ADMIN_PANEL_ENABLED: ""
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
restart: always
stop_grace_period: 5m
container_name: 'blockscout'
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index 9fdb484b9699..93552c9d9cac 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -28,7 +28,7 @@ services:
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED: ""
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL: ""
ADMIN_PANEL_ENABLED: ""
- RELEASE_VERSION: 5.2.1
+ RELEASE_VERSION: 5.2.2
restart: always
stop_grace_period: 5m
container_name: 'blockscout'
diff --git a/docker-compose/envs/common-blockscout.env b/docker-compose/envs/common-blockscout.env
index a1a94b46cdf9..2b93ad54fb44 100644
--- a/docker-compose/envs/common-blockscout.env
+++ b/docker-compose/envs/common-blockscout.env
@@ -13,6 +13,7 @@ LOGO=/images/blockscout_logo.svg
ETHEREUM_JSONRPC_TRANSPORT=http
ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES=false
# ETHEREUM_JSONRPC_HTTP_HEADERS=
+# ETHEREUM_JSONRPC_WAIT_PER_TIMEOUT=
IPC_PATH=
NETWORK_PATH=/
BLOCKSCOUT_HOST=
@@ -114,7 +115,9 @@ INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER=false
# INDEXER_COIN_BALANCES_CONCURRENCY=
# INDEXER_RECEIPTS_BATCH_SIZE=
# INDEXER_RECEIPTS_CONCURRENCY=
+# INDEXER_TOKEN_CONCURRENCY=
# INDEXER_TOKEN_BALANCES_BATCH_SIZE=
+# INDEXER_TOKEN_BALANCES_CONCURRENCY=
# INDEXER_TX_ACTIONS_ENABLE=
# INDEXER_TX_ACTIONS_MAX_TOKEN_CACHE_SIZE=
# INDEXER_TX_ACTIONS_REINDEX_FIRST_BLOCK=
diff --git a/docker-compose/envs/common-frontend.env b/docker-compose/envs/common-frontend.env
index 84da58952bc6..f1c77cdfa7ca 100644
--- a/docker-compose/envs/common-frontend.env
+++ b/docker-compose/envs/common-frontend.env
@@ -1,26 +1,20 @@
NEXT_PUBLIC_API_HOST=localhost
-NEXT_PUBLIC_API_PORT=81
NEXT_PUBLIC_API_PROTOCOL=http
-NEXT_PUBLIC_STATS_API_HOST=http://localhost:82
+NEXT_PUBLIC_STATS_API_HOST=http://localhost:8080
NEXT_PUBLIC_NETWORK_NAME=Göerli
NEXT_PUBLIC_NETWORK_SHORT_NAME=Göerli
-NEXT_PUBLIC_NETWORK_ASSETS_PATHNAME=ethereum
NEXT_PUBLIC_NETWORK_ID=5
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/eth-goerli.json
-NEXT_PUBLIC_FOOTER_GITHUB_LINK=https://github.com/blockscout/blockscout
-NEXT_PUBLIC_FOOTER_TWITTER_LINK=https://www.twitter.com/blockscoutcom
-NEXT_PUBLIC_APP_ENV=staging
-NEXT_PUBLIC_APP_INSTANCE=eth_goerli
NEXT_PUBLIC_APP_HOST=localhost
+NEXT_PUBLIC_APP_PROTOCOL=http
NEXT_PUBLIC_HOMEPAGE_CHARTS="['daily_txs']"
-NEXT_PUBLIC_VISUALIZE_API_HOST=http://visualizer:80
+NEXT_PUBLIC_VISUALIZE_API_HOST=http://localhost:8081
NEXT_PUBLIC_IS_TESTNET='true'
NEXT_PUBLIC_NETWORK_LOGO=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/goerli.svg
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg
-NEXT_PUBLIC_HOMEPAGE_PLATE_GRADIENT="radial-gradient(103.03% 103.03% at 0% 0%, rgba(183, 148, 244, 0.8) 0%, rgba(0, 163, 196, 0.8) 100%)"
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR="rgb(255, 255, 255)"
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL='ws'
diff --git a/docker-compose/envs/common-stats.env b/docker-compose/envs/common-stats.env
index aa1f48225e6b..f5eed636bab6 100644
--- a/docker-compose/envs/common-stats.env
+++ b/docker-compose/envs/common-stats.env
@@ -15,7 +15,6 @@ STATS__CREATE_DATABASE=false
STATS__RUN_MIGRATIONS=false
STATS__DEFAULT_SCHEDULE=0 0 1 * * * *
STATS__FORCE_UPDATE_ON_START=false
-STATS__CHARTS_CONFIG=config/charts.toml
STATS__METRICS__ENABLED=false
STATS__METRICS__ADDR=0.0.0.0:6060
diff --git a/docker-compose/proxy/default.conf.template b/docker-compose/proxy/default.conf.template
new file mode 100644
index 000000000000..1b20024c4d3a
--- /dev/null
+++ b/docker-compose/proxy/default.conf.template
@@ -0,0 +1,104 @@
+map $http_upgrade $connection_upgrade {
+
+ default upgrade;
+ '' close;
+}
+
+server {
+ listen 80;
+ server_name localhost;
+ proxy_http_version 1.1;
+
+ location / {
+ proxy_pass ${BACK_PROXY_PASS};
+ proxy_http_version 1.1;
+ proxy_set_header Host "$host";
+ proxy_set_header X-Real-IP "$remote_addr";
+ proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
+ proxy_set_header X-Forwarded-Proto "$scheme";
+ proxy_set_header Upgrade "$http_upgrade";
+ proxy_set_header Connection $connection_upgrade;
+ proxy_cache_bypass $http_upgrade;
+ }
+ location = / {
+ proxy_pass ${FRONT_PROXY_PASS};
+ proxy_http_version 1.1;
+ proxy_set_header Host "$host";
+ proxy_set_header X-Real-IP "$remote_addr";
+ proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
+ proxy_set_header X-Forwarded-Proto "$scheme";
+ proxy_set_header Upgrade "$http_upgrade";
+ proxy_set_header Connection $connection_upgrade;
+ proxy_cache_bypass $http_upgrade;
+ }
+ location ~ ^/(_next|node-api|apps|account|accounts|static|auth/profile|auth/unverified-email|txs|tx|blocks|block|login|address|stats|search-results|token|tokens|visualize|api-docs|csv-export|verified-contracts|graphiql|withdrawals) {
+ proxy_pass ${FRONT_PROXY_PASS};
+ proxy_http_version 1.1;
+ proxy_set_header Host "$host";
+ proxy_set_header X-Real-IP "$remote_addr";
+ proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
+ proxy_set_header X-Forwarded-Proto "$scheme";
+ proxy_set_header Upgrade "$http_upgrade";
+ proxy_set_header Connection $connection_upgrade;
+ proxy_cache_bypass $http_upgrade;
+ }
+}
+server {
+ listen 8080;
+ server_name localhost;
+ proxy_http_version 1.1;
+ proxy_hide_header Access-Control-Allow-Origin;
+ proxy_hide_header Access-Control-Allow-Methods;
+ add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
+ add_header 'Access-Control-Allow-Credentials' 'true' always;
+ add_header 'Access-Control-Allow-Methods' 'PUT, GET, POST, OPTIONS, DELETE, PATCH' always;
+
+ location / {
+ proxy_pass http://stats:8050/;
+ proxy_http_version 1.1;
+ proxy_set_header Host "$host";
+ proxy_set_header X-Real-IP "$remote_addr";
+ proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
+ proxy_set_header X-Forwarded-Proto "$scheme";
+ proxy_set_header Upgrade "$http_upgrade";
+ proxy_set_header Connection $connection_upgrade;
+ proxy_cache_bypass $http_upgrade;
+ }
+}
+server {
+ listen 8081;
+ server_name localhost;
+ proxy_http_version 1.1;
+ proxy_hide_header Access-Control-Allow-Origin;
+ proxy_hide_header Access-Control-Allow-Methods;
+ add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
+ add_header 'Access-Control-Allow-Credentials' 'true' always;
+ add_header 'Access-Control-Allow-Methods' 'PUT, GET, POST, OPTIONS, DELETE, PATCH' always;
+ add_header 'Access-Control-Allow-Headers' 'DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,x-csrf-token' always;
+
+ location / {
+ proxy_pass http://visualizer:8050/;
+ proxy_http_version 1.1;
+ proxy_buffering off;
+ proxy_set_header Host "$host";
+ proxy_set_header X-Real-IP "$remote_addr";
+ proxy_connect_timeout 30m;
+ proxy_read_timeout 30m;
+ proxy_send_timeout 30m;
+ proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
+ proxy_set_header X-Forwarded-Proto "$scheme";
+ proxy_set_header Upgrade "$http_upgrade";
+ proxy_set_header Connection $connection_upgrade;
+ proxy_cache_bypass $http_upgrade;
+ if ($request_method = 'OPTIONS') {
+ add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
+ add_header 'Access-Control-Allow-Credentials' 'true' always;
+ add_header 'Access-Control-Allow-Methods' 'PUT, GET, POST, OPTIONS, DELETE, PATCH' always;
+ add_header 'Access-Control-Allow-Headers' 'DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,x-csrf-token' always;
+ add_header 'Access-Control-Max-Age' 1728000;
+ add_header 'Content-Type' 'text/plain charset=UTF-8';
+ add_header 'Content-Length' 0;
+ return 204;
+ }
+ }
+}
\ No newline at end of file
diff --git a/docker-compose/proxy/nginx.conf b/docker-compose/proxy/nginx.conf
deleted file mode 100644
index d20a44c819eb..000000000000
--- a/docker-compose/proxy/nginx.conf
+++ /dev/null
@@ -1,62 +0,0 @@
-server {
- listen 80;
- server_name localhost;
- proxy_http_version 1.1;
- location / {
- proxy_pass http://frontend:3000;
- }
- location /socket/v2 {
- proxy_pass http://backend:4000;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_set_header Host $host;
- }
- location /api/ {
- proxy_pass http://backend:4000/api;
- }
-}
-
-server {
- listen 81;
- server_name localhost;
- proxy_http_version 1.1;
- proxy_hide_header Access-Control-Allow-Origin;
- proxy_hide_header Access-Control-Allow-Methods;
- add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
- add_header 'Access-Control-Allow-Methods' 'PUT, GET, POST, OPTIONS, DELETE, PATCH' always;
-
- location / {
- proxy_pass http://backend:4000;
- }
-
- location /socket {
- proxy_pass http://backend:4000;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_set_header Host $host;
- }
-}
-
-server {
- listen 82;
- server_name localhost;
- proxy_http_version 1.1;
- proxy_hide_header Access-Control-Allow-Origin;
- proxy_hide_header Access-Control-Allow-Methods;
- add_header 'Access-Control-Allow-Origin' 'http://localhost' always;
- add_header 'Access-Control-Allow-Credentials' 'true' always;
- add_header 'Access-Control-Allow-Methods' 'PUT, GET, POST, OPTIONS, DELETE, PATCH' always;
-
- location / {
- proxy_pass http://stats:8050;
- }
- location /socket/v2 {
- proxy_pass http://backend:4000;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- proxy_set_header Host $host;
- }
-}
\ No newline at end of file
diff --git a/docker-compose/services/docker-compose-nginx.yml b/docker-compose/services/docker-compose-nginx.yml
index 2d2bd87dc127..e54401d3f5ae 100644
--- a/docker-compose/services/docker-compose-nginx.yml
+++ b/docker-compose/services/docker-compose-nginx.yml
@@ -1,14 +1,17 @@
version: '3.8'
-services:
+services:
proxy:
image: nginx
+ container_name: proxy
+ extra_hosts:
+ - 'host.docker.internal:host-gateway'
volumes:
- - type: bind
- source: ../proxy/nginx.conf
- target: /etc/nginx/conf.d/default.conf
- read_only: true
+ - "../proxy:/etc/nginx/templates"
+ environment:
+ BACK_PROXY_PASS: ${BACK_PROXY_PASS:-http://backend:4000}
+ FRONT_PROXY_PASS: ${FRONT_PROXY_PASS:-http://frontend:3000}
ports:
- 80:80
- - 81:81
- - 82:82
\ No newline at end of file
+ - 8080:8080
+ - 8081:8081
diff --git a/docker-compose/services/docker-compose-stats.yml b/docker-compose/services/docker-compose-stats.yml
index 4b14419fa631..b6ea6552b1da 100644
--- a/docker-compose/services/docker-compose-stats.yml
+++ b/docker-compose/services/docker-compose-stats.yml
@@ -12,10 +12,10 @@ services:
POSTGRES_HOST_AUTH_METHOD: 'trust'
ports:
- 7433:5432
+ volumes:
+ - ./stats-db-data:/var/lib/postgresql/data/
stats:
- depends_on:
- - stats-db
image: ghcr.io/blockscout/stats:${STATS_DOCKER_TAG:-latest}
pull_policy: always
platform: linux/amd64
@@ -32,5 +32,3 @@ services:
- STATS__RUN_MIGRATIONS=true
ports:
- 8153:8050
- volumes:
- - ./stats-db-data:/var/lib/postgresql/data/
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 9b42fcbe71b2..9193b154aec7 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -37,7 +37,7 @@ RUN mix do deps.get, local.rebar --force, deps.compile
ADD apps ./apps
ADD config ./config
ADD rel ./rel
-ADD *.exs .
+ADD *.exs ./
RUN apk add --update nodejs npm
diff --git a/docker/Makefile b/docker/Makefile
index b9f15c84c0b4..3f948c710617 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -7,7 +7,7 @@ BS_CONTAINER_NAME := blockscout
PG_CONTAINER_IMAGE := postgres:14
PG_CONTAINER_NAME := db
THIS_FILE = $(lastword $(MAKEFILE_LIST))
-RELEASE_VERSION ?= '5.2.1'
+RELEASE_VERSION ?= '5.2.2'
PORT ?= '4000'
TAG := $(RELEASE_VERSION)-commit-$(shell git log -1 --pretty=format:"%h")
STABLE_TAG := $(RELEASE_VERSION)
@@ -63,6 +63,9 @@ endif
ifdef ETHEREUM_JSONRPC_HTTP_HEADERS
BLOCKSCOUT_CONTAINER_PARAMS += -e 'ETHEREUM_JSONRPC_HTTP_HEADERS=$(ETHEREUM_JSONRPC_HTTP_HEADERS)'
endif
+ifdef ETHEREUM_JSONRPC_WAIT_PER_TIMEOUT
+ BLOCKSCOUT_CONTAINER_PARAMS += -e 'ETHEREUM_JSONRPC_WAIT_PER_TIMEOUT=$(ETHEREUM_JSONRPC_WAIT_PER_TIMEOUT)'
+endif
ifdef IPC_PATH
BLOCKSCOUT_CONTAINER_PARAMS += -e 'IPC_PATH=$(IPC_PATH)'
endif
@@ -561,9 +564,15 @@ endif
ifdef INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE
BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE=$(INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE)'
endif
+ifdef INDEXER_TOKEN_CONCURRENCY
+ BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_TOKEN_CONCURRENCY=$(INDEXER_TOKEN_CONCURRENCY)'
+endif
ifdef INDEXER_TOKEN_BALANCES_BATCH_SIZE
BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_TOKEN_BALANCES_BATCH_SIZE=$(INDEXER_TOKEN_BALANCES_BATCH_SIZE)'
endif
+ifdef INDEXER_TOKEN_BALANCES_CONCURRENCY
+ BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_TOKEN_BALANCES_CONCURRENCY=$(INDEXER_TOKEN_BALANCES_CONCURRENCY)'
+endif
ifdef INDEXER_REALTIME_FETCHER_MAX_GAP
BLOCKSCOUT_CONTAINER_PARAMS += -e 'INDEXER_REALTIME_FETCHER_MAX_GAP=$(INDEXER_REALTIME_FETCHER_MAX_GAP)'
endif
diff --git a/mix.exs b/mix.exs
index 744ac916a089..9983272fe866 100644
--- a/mix.exs
+++ b/mix.exs
@@ -7,7 +7,7 @@ defmodule BlockScout.Mixfile do
[
# app: :block_scout,
# aliases: aliases(config_env()),
- version: "5.2.1",
+ version: "5.2.2",
apps_path: "apps",
deps: deps(),
dialyzer: dialyzer(),
diff --git a/mix.lock b/mix.lock
index 419fe5f791e7..48442769907c 100644
--- a/mix.lock
+++ b/mix.lock
@@ -38,7 +38,7 @@
"digital_token": {:hex, :digital_token, "0.6.0", "13e6de581f0b1f6c686f7c7d12ab11a84a7b22fa79adeb4b50eec1a2d278d258", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "2455d626e7c61a128b02a4a8caddb092548c3eb613ac6f6a85e4cbb6caddc4d1"},
"earmark_parser": {:hex, :earmark_parser, "1.4.33", "3c3fd9673bb5dcc9edc28dd90f50c87ce506d1f71b70e3de69aa8154bc695d44", [:mix], [], "hexpm", "2d526833729b59b9fdb85785078697c72ac5e5066350663e5be6a1182da61b8f"},
"ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"},
- "ecto_sql": {:hex, :ecto_sql, "3.10.1", "6ea6b3036a0b0ca94c2a02613fd9f742614b5cfe494c41af2e6571bb034dd94c", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f6a25bdbbd695f12c8171eaff0851fa4c8e72eec1e98c7364402dda9ce11c56b"},
+ "ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"},
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_abi": {:hex, :ex_abi, "0.6.0", "8cf1fef9490dea0834bc201d399635e72178df05dea87b1c933478762dede142", [:mix], [{:ex_keccak, "~> 0.7.1", [hex: :ex_keccak, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b03e5fe07371db3ceceb2d536cc32658dcba47b79952469e3e71d7690495e8d8"},
@@ -47,8 +47,8 @@
"ex_cldr_lists": {:hex, :ex_cldr_lists, "2.10.0", "4d4c9877da2d0417fd832907d69974e8328969f75fafc79b05ccf85f549f6281", [:mix], [{:ex_cldr_numbers, "~> 2.25", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_doc, "~> 0.18", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "adc040cde7b97f7fd7c0b35dd69ddb6fcf607303ae6355bb1851deae1f8b0652"},
"ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.31.3", "6ec8b18c395c0e8788d46da806f8f2abcbe4b0d809226d2a91363e9ccd85f2f5", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:digital_token, "~> 0.3 or ~> 1.0", [hex: :digital_token, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.37", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, ">= 2.14.2", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "b519de08ecc4a6402038f3aa75e8654f78ebd6fa714b7e585531504e648588fd"},
"ex_cldr_units": {:hex, :ex_cldr_units, "3.16.2", "dbad303fba819981c578234e2aaf19d72efca16ea8b1c6ee46b26232cb45e232", [:mix], [{:cldr_utils, "~> 2.24", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr_lists, "~> 2.10", [hex: :ex_cldr_lists, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.31", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_doc, "~> 0.18", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "851095319fb3205c1549619da742cd53a2804c1d9c204cf84014021e2a6ea7e5"},
- "ex_doc": {:hex, :ex_doc, "0.30.3", "bfca4d340e3b95f2eb26e72e4890da83e2b3a5c5b0e52607333bf5017284b063", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "fbc8702046c1d25edf79de376297e608ac78cdc3a29f075484773ad1718918b6"},
- "ex_json_schema": {:hex, :ex_json_schema, "0.9.3", "fc17c50d410fd99fa6e814e1aed60122d8ff2578b869d17a9db1ce1c621382b6", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "b79962d09cefd33001706255187bdb483a0c2b4442d5edc6822eb7574a8df0a8"},
+ "ex_doc": {:hex, :ex_doc, "0.30.5", "aa6da96a5c23389d7dc7c381eba862710e108cee9cfdc629b7ec021313900e9e", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "88a1e115dcb91cefeef7e22df4a6ebbe4634fbf98b38adcbc25c9607d6d9d8e6"},
+ "ex_json_schema": {:hex, :ex_json_schema, "0.10.1", "e03b746b6675a750c0bb1a5cc919f61353f7ab8450977e11ceede20e6180c560", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "66a64e60dadad89914d92f89c7e7906c57de75a8b79ac2480d0d53e1b8096fb0"},
"ex_keccak": {:hex, :ex_keccak, "0.7.1", "0169f4b0c5073c5df61581d6282b12f1a1b764dcfcda4eeb1c819b5194c9ced0", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.6.1", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "c18c19f66b6545b4b46b0c71c0cc0079de84e30b26365a92961e91697e8724ed"},
"ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
"ex_rlp": {:hex, :ex_rlp, "0.6.0", "985391d2356a7cb8712a4a9a2deb93f19f2fbca0323f5c1203fcaf64d077e31e", [:mix], [], "hexpm", "7135db93b861d9e76821039b60b00a6a22d2c4e751bf8c444bffe7a042f1abaf"},
@@ -57,13 +57,13 @@
"exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm", "1222419f706e01bfa1095aec9acf6421367dcfab798a6f67c54cf784733cd6b5"},
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"},
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
- "exvcr": {:hex, :exvcr, "0.14.1", "d9aacec631ed379e366bce5b3c68f6ec5b92b89142f9379425854e80a28c1107", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:finch, "~> 0.16", [hex: :finch, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "5f1e0854fbad0c4bb64ae8cdd289eeace90b8a0a209788c2f840d70f86a2d63c"},
+ "exvcr": {:hex, :exvcr, "0.14.3", "e7d93b3b25919fbb653b06bc015cab99f658400eae96ed8e59758f1bb12ae167", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:finch, "~> 0.16", [hex: :finch, repo: "hexpm", optional: true]}, {:httpoison, "~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "38fa7d918aeda0ecc8e70346225c1299d21d4c432061c832f23a421ac2ed791d"},
"file_info": {:hex, :file_info, "0.0.4", "2e0e77f211e833f38ead22cb29ce53761d457d80b3ffe0ffe0eb93880b0963b2", [:mix], [{:mimetype_parser, "~> 0.1.2", [hex: :mimetype_parser, repo: "hexpm", optional: false]}], "hexpm", "50e7ad01c2c8b9339010675fe4dc4a113b8d6ca7eddce24d1d74fd0e762781a5"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"floki": {:hex, :floki, "0.34.3", "5e2dcaec5d7c228ce5b1d3501502e308b2d79eb655e4191751a1fe491c37feac", [:mix], [], "hexpm", "9577440eea5b97924b4bf3c7ea55f7b8b6dce589f9b28b096cc294a8dc342341"},
"flow": {:hex, :flow, "1.2.4", "1dd58918287eb286656008777cb32714b5123d3855956f29aa141ebae456922d", [:mix], [{:gen_stage, "~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm", "874adde96368e71870f3510b91e35bc31652291858c86c0e75359cbdd35eb211"},
"gen_stage": {:hex, :gen_stage, "1.2.1", "19d8b5e9a5996d813b8245338a28246307fd8b9c99d1237de199d21efc4c76a1", [:mix], [], "hexpm", "83e8be657fa05b992ffa6ac1e3af6d57aa50aace8f691fcf696ff02f8335b001"},
- "gettext": {:hex, :gettext, "0.22.3", "c8273e78db4a0bb6fba7e9f0fd881112f349a3117f7f7c598fa18c66c888e524", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "935f23447713954a6866f1bb28c3a878c4c011e802bcd68a726f5e558e4b64bd"},
+ "gettext": {:hex, :gettext, "0.23.1", "821e619a240e6000db2fc16a574ef68b3bd7fe0167ccc264a81563cc93e67a31", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "19d744a36b809d810d610b57c27b934425859d158ebd56561bc41f7eeb8795db"},
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"hammer": {:hex, :hammer, "6.1.0", "f263e3c3e9946bd410ea0336b2abe0cb6260af4afb3a221e1027540706e76c55", [:make, :mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b47e415a562a6d072392deabcd58090d8a41182cf9044cdd6b0d0faaaf68ba57"},
"hammer_backend_redis": {:hex, :hammer_backend_redis, "6.1.2", "eb296bb4924928e24135308b2afc189201fd09411c870c6bbadea444a49b2f2c", [:mix], [{:hammer, "~> 6.0", [hex: :hammer, repo: "hexpm", optional: false]}, {:redix, "~> 1.1", [hex: :redix, repo: "hexpm", optional: false]}], "hexpm", "217ea066278910543a5e9b577d5bf2425419446b94fe76bdd9f255f39feec9fa"},
@@ -123,7 +123,7 @@
"redix": {:hex, :redix, "1.2.3", "3036e7c6080c42e1bbaa9168d1e28e367b01e8960a640a899b8ef8067273cb5e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:nimble_options, "~> 0.5.0 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "14e2bca8a03fad297a78a3d201032df260ee5f0e0ef9c173c0f9ca5b3e0331b7"},
"remote_ip": {:hex, :remote_ip, "1.1.0", "cb308841595d15df3f9073b7c39243a1dd6ca56e5020295cb012c76fbec50f2d", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "616ffdf66aaad6a72fc546dabf42eed87e2a99e97b09cbd92b10cc180d02ed74"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.6.1", "160b545bce8bf9a3f1b436b2c10f53574036a0db628e40f393328cbbe593602f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "0dd269fa261c4e3df290b12031c575fff07a542749f7b0e8b744d72d66c43600"},
- "sobelow": {:hex, :sobelow, "0.12.2", "45f4d500e09f95fdb5a7b94c2838d6b26625828751d9f1127174055a78542cf5", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "2f0b617dce551db651145662b84c8da4f158e7abe049a76daaaae2282df01c5d"},
+ "sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
"spandex": {:hex, :spandex, "3.2.0", "f8cd40146ea988c87f3c14054150c9a47ba17e53cd4515c00e1f93c29c45404d", [:mix], [{:decorator, "~> 1.2", [hex: :decorator, repo: "hexpm", optional: true]}, {:optimal, "~> 0.3.3", [hex: :optimal, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d0a7d5aef4c5af9cf5467f2003e8a5d8d2bdae3823a6cc95d776b9a2251d4d03"},
"spandex_datadog": {:hex, :spandex_datadog, "1.3.0", "cabe82980f55612a8befa6c12904b1a429bf17faf7271a94b9aae278af6362cf", [:mix], [{:msgpax, "~> 2.2.1 or ~> 2.3", [hex: :msgpax, repo: "hexpm", optional: false]}, {:spandex, "~> 3.0", [hex: :spandex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c826e4e29d1612e866b2c7bae2df3beeee84fc57351968c2772672afe59b789c"},
"spandex_ecto": {:hex, :spandex_ecto, "0.7.0", "259ad2feb7c834e774ec623f99c0fbacca8d60a73be212f92b75e37f853c81be", [:mix], [{:spandex, "~> 2.2 or ~> 3.0", [hex: :spandex, repo: "hexpm", optional: false]}], "hexpm", "c64784be79d95538013b7c60828830411c5c7aff1f4e8d66dfe564b3c83b500e"},
@@ -138,7 +138,7 @@
"ueberauth": {:hex, :ueberauth, "0.10.5", "806adb703df87e55b5615cf365e809f84c20c68aa8c08ff8a416a5a6644c4b02", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1"},
"ueberauth_auth0": {:hex, :ueberauth_auth0, "2.1.0", "0632d5844049fa2f26823f15e1120aa32f27df6f27ce515a4b04641736594bf4", [:mix], [{:oauth2, "~> 2.0", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.7", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm", "8d3b30fa27c95c9e82c30c4afb016251405706d2e9627e603c3c9787fd1314fc"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
- "wallaby": {:hex, :wallaby, "0.30.5", "c6a8dbb6f3195dbfe080b50ba707973983e32446f6f9fac514a43918682696bb", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.2.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "d759711983c90aaa5338b8b9dcff0c9eb0609ac0a45071f4ef9cbb298bb54077"},
+ "wallaby": {:hex, :wallaby, "0.30.6", "7dc4c1213f3b52c4152581d126632bc7e06892336d3a0f582853efeeabd45a71", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.2.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "50950c1d968549b54c20e16175c68c7fc0824138e2bb93feb11ef6add8eb23d4"},
"web_driver_client": {:hex, :web_driver_client, "0.2.0", "63b76cd9eb3b0716ec5467a0f8bead73d3d9612e63f7560d21357f03ad86e31a", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.3", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "83cc6092bc3e74926d1c8455f0ce927d5d1d36707b74d9a65e38c084aab0350f"},
"websocket_client": {:git, "https://github.com/blockscout/websocket_client.git", "0b4ecc5b1fb8a0bd1c8352728da787c20add53aa", [branch: "master"]},
}
diff --git a/rel/config.exs b/rel/config.exs
index 7d4f453589ca..3782a1b80d82 100644
--- a/rel/config.exs
+++ b/rel/config.exs
@@ -71,7 +71,7 @@ end
# will be used by default
release :blockscout do
- set version: "5.2.1-beta"
+ set version: "5.2.2-beta"
set applications: [
:runtime_tools,
block_scout_web: :permanent,