diff --git a/.env.example b/.env.example index 8719278c7..7556bead9 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,7 @@ FORK_URL= DEV_RPC= ## post-refactor pearl envs -GNOSIS_DEV_RPC= -ETHEREUM_DEV_RPC= -OPTIMISM_DEV_RPC= -BASE_DEV_RPC= \ No newline at end of file +GNOSIS_RPC= +ETHEREUM_RPC= +OPTIMISM_RPC= +BASE_RPC= \ No newline at end of file diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 124d9af95..242e2e8bb 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -14,6 +14,13 @@ jobs: with: node-version: "20.x" + # Configure Yarn network settings for timeout, retries, and reduced concurrency + - name: Configure Yarn network settings + run: | + yarn config set network-timeout 60000 # Set network timeout to 1 minute + yarn config set network-retries 10 # Retry up to 10 times + yarn config set network-concurrency 2 # Reduce concurrency to 2 connections + # Python - uses: actions/setup-python@v4 with: diff --git a/.github/workflows/common_checks.yml b/.github/workflows/common_checks.yml index df38258ba..f1bf4b9d5 100644 --- a/.github/workflows/common_checks.yml +++ b/.github/workflows/common_checks.yml @@ -48,3 +48,27 @@ jobs: # - name: License compatibility check # run: tox -e liccheck # tox -p -e vulture -e darglint + + test: + continue-on-error: True + needs: + - linter_checks + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ ubuntu-latest ] + python-version: [ "3.10.9" ] + + timeout-minutes: 30 + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Run unit tests + run: | + pip install tomte[tox]==0.2.15 + tox -e unit-tests diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 197e31749..e6a3654b5 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -15,6 +15,13 @@ jobs: with: node-version: "20.x" + # Configure Yarn network settings for timeout, retries, and reduced concurrency + - name: Configure Yarn network settings + run: | + yarn config set network-timeout 60000 # Set network timeout to 1 minute + yarn config set network-retries 10 # Retry up to 10 times + yarn config set network-concurrency 2 # Reduce concurrency to 2 connections + # Install dependencies - name: Install dependencies run: yarn install:frontend diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0cd5c1071..bd2842742 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,13 +12,15 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-14, macos-14-large] + os: [macos-14] + arch: [arm64, x64] steps: - uses: actions/checkout@v3 - # Setup Python - - uses: actions/setup-python@v4 + # Set up Python with setup-python action and add it to PATH + - uses: actions/setup-python@v5 + id: setup-python with: python-version: "3.10" @@ -32,10 +34,10 @@ jobs: virtualenvs-path: ~/my-custom-path installer-parallel: true - # Set architecture for macos-latest-large as x64 and arm64 for other versions + # Set OS_ARCH env - name: Set architecture environment variable - run: | - if [ "${{ matrix.os }}" == "macos-14-large" ]; then echo "OS_ARCH=x64" >> $GITHUB_ENV; else echo "OS_ARCH=arm64" >> $GITHUB_ENV; fi + run: + echo "OS_ARCH=${{ matrix.arch }}" >> $GITHUB_ENV; # Cache Poetry dependencies with unique key for each environment and architecture - name: Cache Poetry dependencies @@ -45,9 +47,9 @@ jobs: ~/.cache/pypoetry ~/.cache/pip ~/.venv - key: poetry-${{ env.OS_ARCH }}-${{ hashFiles('**/poetry.lock') }} + key: poetry-${{ matrix.arch }}-${{ hashFiles('**/poetry.lock') }} restore-keys: | - poetry-${{ env.OS_ARCH }}- + poetry-${{ matrix.arch }}- - name: Install dependencies run: poetry install @@ -55,24 +57,35 @@ jobs: # Download and build with PyInstaller - name: Get trader bin run: | - optimus_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/optimus.yaml')); print(config['service_version'])") - echo $optimus_version - mkdir dist && curl -L -o dist/aea_bin "https://github.com/valory-xyz/optimus/releases/download/${$optimus_version}/optimus_bin_${{ env.OS_ARCH }}" - + trader_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/trader.yaml')); print(config['service_version'])") + echo $trader_version + make ./dist/aea_bin + #instead of this one mwe use make; mkdir dist && curl -L -o dist/aea_bin "https://github.com/valory-xyz/trader/releases/download/${trader_version}/trader_bin_${{ env.OS_ARCH }}" + + # -- old optimus getter + # optimus_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/optimus.yaml')); print(config['service_version'])") + # echo $optimus_version + # mkdir dist && curl -L -o dist/aea_bin "https://github.com/valory-xyz/optimus/releases/download/${$optimus_version}/optimus_bin_${{ env.OS_ARCH }}" - name: Build with PyInstaller run: | poetry run pyinstaller operate/services/utils/tendermint.py --onefile + + # patch open aea in place + rm -fr ./open-aea + git clone https://github.com/valory-xyz/open-aea.git -b fix/1.5.2_encoding + poetry run pip install ./open-aea/ + poetry run pyinstaller --collect-data eth_account --collect-all aea --collect-all autonomy --collect-all operate --collect-all aea_ledger_ethereum --collect-all aea_ledger_cosmos --collect-all aea_ledger_ethereum_flashbots --hidden-import aea_ledger_ethereum --hidden-import aea_ledger_cosmos --hidden-import aea_ledger_ethereum_flashbots operate/pearl.py --add-binary dist/aea_bin:. --add-binary dist/tendermint:. --onefile --name pearl_${{ env.OS_ARCH }} - name: Upload Release Assets uses: actions/upload-artifact@v4 with: - name: pearl_${{ env.OS_ARCH }} - path: dist/pearl_${{ env.OS_ARCH }} + name: pearl_${{ matrix.arch }} + path: dist/pearl_${{ matrix.arch }} # Jobs for production and development, running separately for x64 and arm64 build-release: - runs-on: macos-latest + runs-on: macos-14 strategy: matrix: env: [production, development] @@ -86,10 +99,18 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "20.x" - registry-url: "https://registry.npmjs.org" + registry-url: "https://registry.npmjs.org" + + # Configure Yarn network settings for timeout, retries, and reduced concurrency + - name: Configure Yarn network settings + run: | + yarn config set network-timeout 60000 # Set network timeout to 1 minute + yarn config set network-retries 10 # Retry up to 10 times + yarn config set network-concurrency 2 # Reduce concurrency to 2 connections + # Download the appropriate architecture artifact - - name: Download Pearl (Optimus) binary for architecture + - name: Download Pearl binary for architecture uses: actions/download-artifact@v4 with: name: pearl_${{ matrix.arch }} @@ -130,10 +151,13 @@ jobs: if: matrix.env == 'production' run: yarn build:frontend env: - NODE_ENV: ${{ matrix.env }} - DEV_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + NODE_ENV: ${{ matrix.env }} IS_STAGING: ${{ github.ref != 'refs/heads/main' && 'true' || 'false' }} - FORK_URL: https://rpc-gate.autonolas.tech/gnosis-rpc/ + OPTIMISM_RPC: https://rpc-gate.autonolas.tech/optimism-rpc/ + BASE_RPC: https://rpc-gate.autonolas.tech/base-rpc/ + GNOSIS_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + ETHEREUM_RPC: https://rpc-gate.autonolas.tech/ethereum-rpc/ + # Build frontend for development - name: Build frontend for development @@ -141,9 +165,11 @@ jobs: run: yarn build:frontend env: NODE_ENV: ${{ matrix.env }} - DEV_RPC: https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0 IS_STAGING: ${{ github.ref != 'refs/heads/main' && 'true' || 'false' }} - FORK_URL: https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0 + OPTIMISM_RPC: https://rpc-gate.autonolas.tech/optimism-rpc/ + BASE_RPC: https://rpc-gate.autonolas.tech/base-rpc/ + GNOSIS_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + ETHEREUM_RPC: https://rpc-gate.autonolas.tech/ethereum-rpc/ # Run the build and notarization process for production - name: Build, notarize, and publish (Production) @@ -151,14 +177,16 @@ jobs: env: APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLEIDPASS }} APPLE_ID: ${{ secrets.APPLEID }} - APPLETEAMID: ${{ secrets.APPLETEAMID }} + APPLE_TEAM_ID: ${{ secrets.APPLETEAMID }} CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} CSC_LINK: ${{ secrets.CSC_LINK }} GH_TOKEN: ${{ secrets.github_token }} NODE_ENV: ${{ matrix.env }} ARCH: ${{ matrix.arch }} - DEV_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ - FORK_URL: https://rpc-gate.autonolas.tech/gnosis-rpc/ + OPTIMISM_RPC: https://rpc-gate.autonolas.tech/optimism-rpc/ + BASE_RPC: https://rpc-gate.autonolas.tech/base-rpc/ + GNOSIS_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + ETHEREUM_RPC: https://rpc-gate.autonolas.tech/ethereum-rpc/ run: node build.js # Run the build and notarization process for development @@ -167,15 +195,14 @@ jobs: env: APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLEIDPASS }} APPLE_ID: ${{ secrets.APPLEID }} - APPLETEAMID: ${{ secrets.APPLETEAMID }} + APPLE_TEAM_ID: ${{ secrets.APPLETEAMID }} CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} CSC_LINK: ${{ secrets.CSC_LINK }} GH_TOKEN: ${{ secrets.github_token }} NODE_ENV: ${{ matrix.env }} ARCH: ${{ matrix.arch }} - DEV_RPC: https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0 - FORK_URL: https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0 - run: | - echo "DEV_RPC=https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0" >> .env - echo "FORK_URL=https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0" >> .env - node build.js + OPTIMISM_RPC: https://rpc-gate.autonolas.tech/optimism-rpc/ + BASE_RPC: https://rpc-gate.autonolas.tech/base-rpc/ + GNOSIS_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + ETHEREUM_RPC: https://rpc-gate.autonolas.tech/ethereum-rpc/ + run: node build.js diff --git a/.github/workflows/release_win.yml b/.github/workflows/release_win.yml index 15676dfb7..609800a7d 100644 --- a/.github/workflows/release_win.yml +++ b/.github/workflows/release_win.yml @@ -12,10 +12,16 @@ jobs: matrix: include: - env: "production" - rpc: "https://rpc-gate.autonolas.tech/gnosis-rpc/" + OPTIMISM_RPC: "https://rpc-gate.autonolas.tech/optimism-rpc/" + BASE_RPC: "https://rpc-gate.autonolas.tech/base-rpc/" + GNOSIS_RPC: "https://rpc-gate.autonolas.tech/gnosis-rpc/" + ETHEREUM_RPC: "https://rpc-gate.autonolas.tech/ethereum-rpc/" arch: "x64" - env: "development" - rpc: "https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0" + OPTIMISM_RPC: "https://rpc-gate.autonolas.tech/optimism-rpc/" + BASE_RPC: "https://rpc-gate.autonolas.tech/base-rpc/" + GNOSIS_RPC: "https://virtual.gnosis.rpc.tenderly.co/80ff70d1-71fd-4c9e-9402-913f0c4c58b0" + ETHEREUM_RPC: "https://rpc-gate.autonolas.tech/ethereum-rpc/" arch: "x64" defaults: run: @@ -23,15 +29,27 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + # Set up Python with setup-python action and add it to PATH + - uses: actions/setup-python@v5 id: setup-python with: python-version: "3.10" + - name: Add Python to PATH + run: | + echo "${{ steps.setup-python.outputs.python-path }}" >> $GITHUB_PATH + - uses: actions/setup-node@v4 with: node-version: "20.x" - registry-url: "https://registry.npmjs.org" + registry-url: "https://registry.npmjs.org" + + # Configure Yarn network settings for timeout, retries, and reduced concurrency + - name: Configure Yarn network settings + run: | + yarn config set network-timeout 60000 # Set network timeout to 1 minute + yarn config set network-retries 10 # Retry up to 10 times + yarn config set network-concurrency 2 # Reduce concurrency to 2 connections - name: Install and configure Poetry uses: snok/install-poetry@v1 @@ -84,16 +102,20 @@ jobs: - name: set env vars to prod.env env: - NODE_ENV: ${{ matrix.env }} - DEV_RPC: ${{ matrix.rpc }} + NODE_ENV: ${{ matrix.env }} + GNOSIS_RPC: ${{ matrix.GNOSIS_RPC }} + BASE_RPC: ${{ matrix.BASE_RPC }} + ETHEREUM_RPC: ${{ matrix.ETHEREUM_RPC }} + OPTIMISM_RPC: ${{ matrix.OPTIMISM_RPC }} IS_STAGING: ${{ github.ref != 'refs/heads/main' && 'true' || 'false' }} - FORK_URL: ${{ matrix.rpc }} GH_TOKEN: ${{ secrets.github_token}} run: | echo NODE_ENV=$NODE_ENV >> prod.env - echo DEV_RPC=$DEV_RPC >> prod.env echo IS_STAGING=$IS_STAGING >> prod.env - echo FORK_URL=$FORK_URL >> prod.env + echo OPTIMISM_RPC=$OPTIMISM_RPC >> prod.env + echo BASE_RPC=$BASE_RPC >> prod.env + echo ETHEREUM_RPC=$ETHEREUM_RPC >> prod.env + echo GNOSIS_RPC=$GNOSIS_RPC >> prod.env cat prod.env echo GH_TOKEN=$GH_TOKEN >> prod.env - run: rm -rf /dist diff --git a/.gitleaksignore b/.gitleaksignore index 95964f4b2..de6f6c1d5 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -4,9 +4,9 @@ ada5590acaa13a35afb62c368b13c3601e658c0c:operate/services/manage.py:generic-api- ada5590acaa13a35afb62c368b13c3601e658c0c:operate/services/manage.py:generic-api-key:449 ef9ec7a111816282b6185e8268a460d02329fbe4:api.md:generic-api-key:13 ef9ec7a111816282b6185e8268a460d02329fbe4:api.md:generic-api-key:37 -44388a82d29ce4d96e554c828c3c2c12d6ee3b8a:operate/data/contracts/service_staking_token/contract.yaml:generic-api-key:10 -43bb67ace89a4a6e0eee84d3ee6495088288c528:backend/operate/data/contracts/service_staking_token/contract.yaml:generic-api-key:10 -19ecb1e59813c632971658183a9f2d9d88e0614b:backend/operate/data/contracts/service_staking_token/contract.yaml:generic-api-key:10 +44388a82d29ce4d96e554c828c3c2c12d6ee3b8a:operate/data/contracts/staking_token/contract.yaml:generic-api-key:10 +43bb67ace89a4a6e0eee84d3ee6495088288c528:backend/operate/data/contracts/staking_token/contract.yaml:generic-api-key:10 +19ecb1e59813c632971658183a9f2d9d88e0614b:backend/operate/data/contracts/staking_token/contract.yaml:generic-api-key:10 37847b0c322a0dbc8987df526a49df70301e44d4:backend/operate/ledger/profiles.py:generic-api-key:29 6834023917760bf7875cc7c107e0c59ad7925ef4:backend/operate/ledger/profiles.py:generic-api-key:32 4e8c1c21dffd9283195052117ad4c371f770e0b2:backend/operate/ledger/profiles.py:generic-api-key:28 @@ -17,7 +17,7 @@ daf41a143aa8c483db584ba1e7222e8eafec1d3b:backend/controller.py:generic-api-key:2 af77e930289cbc87987567bff0efc25936484df2:backend/controller.py:generic-api-key:354b04972639d66053109596d3b73a1d91688964ebb:electron/constants/publishOptions.js:github-fine-grained-pat:3 b04972639d66053109596d3b73a1d91688964ebb:electron/constants/publishOptions.js:github-fine-grained-pat:3 af77e930289cbc87987567bff0efc25936484df2:backend/controller.py:generic-api-key:354 -e7de9ce0b902ed6d68f8c5b033d044f39b08f5a1:operate/data/contracts/service_staking_token/contract.yaml:generic-api-key:10 +e7de9ce0b902ed6d68f8c5b033d044f39b08f5a1:operate/data/contracts/staking_token/contract.yaml:generic-api-key:10 d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-key:405 d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-key:406 d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-key:454 diff --git a/Makefile b/Makefile index 5a766bb51..ea7348c80 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ define setup_env @echo " - setup env $(ENV_FILE)" $(eval include $(1).env) $(eval export) + @cp $(ENV_FILE) .env endef @@ -13,11 +14,18 @@ endef ./dist/aea_win.exe: ./trader/ mkdir -p dist - cd trader && poetry install && poetry run pyinstaller --collect-data eth_account --collect-all aea --collect-all autonomy --collect-all operate --collect-all aea_ledger_ethereum --collect-all aea_ledger_cosmos --collect-all aea_ledger_ethereum_flashbots --hidden-import aea_ledger_ethereum --hidden-import aea_ledger_cosmos --hidden-import aea_ledger_ethereum_flashbots --hidden-import grpc --hidden-import openapi_core --collect-all google.protobuf --collect-all openapi_core --collect-all openapi_spec_validator --collect-all asn1crypto --hidden-import py_ecc --hidden-import pytz --onefile pyinstaller/trader_bin.py --name trader_win + cd trader && poetry install && rm -fr ./open-aea && git clone https://github.com/valory-xyz/open-aea.git -b fix/1.5.2_encoding && poetry run pip install ./open-aea/ && poetry run pyinstaller --collect-data eth_account --collect-all aea --collect-all autonomy --collect-all operate --collect-all aea_ledger_ethereum --collect-all aea_ledger_cosmos --collect-all aea_ledger_ethereum_flashbots --hidden-import aea_ledger_ethereum --hidden-import aea_ledger_cosmos --hidden-import aea_ledger_ethereum_flashbots --hidden-import grpc --hidden-import openapi_core --collect-all google.protobuf --collect-all openapi_core --collect-all openapi_spec_validator --collect-all asn1crypto --hidden-import py_ecc --hidden-import pytz --onefile pyinstaller/trader_bin.py --name trader_win cp -f trader/dist/trader_win.exe ./dist/aea_win.exe pwd +./dist/aea_bin: ./trader/ + mkdir -p dist + cd trader && poetry install && rm -fr ./open-aea && git clone https://github.com/valory-xyz/open-aea.git -b fix/1.5.2_encoding && poetry run pip install ./open-aea/ && poetry run pyinstaller --collect-data eth_account --collect-all aea --collect-all autonomy --collect-all operate --collect-all aea_ledger_ethereum --collect-all aea_ledger_cosmos --collect-all aea_ledger_ethereum_flashbots --hidden-import aea_ledger_ethereum --hidden-import aea_ledger_cosmos --hidden-import aea_ledger_ethereum_flashbots --hidden-import grpc --hidden-import openapi_core --collect-all google.protobuf --collect-all openapi_core --collect-all openapi_spec_validator --collect-all asn1crypto --hidden-import py_ecc --hidden-import pytz --onefile pyinstaller/trader_bin.py --name trader_bin + cp -f trader/dist/trader_bin ./dist/aea_bin + pwd + + ./dist/tendermint_win.exe: ./operate/ pwd poetry install && poetry run pyinstaller operate/services/utils/tendermint.py --onefile --name tendermint_win @@ -25,7 +33,7 @@ endef ./dist/pearl_win.exe: ./operate/ ./dist/aea_win.exe ./dist/tendermint_win.exe pwd - poetry install && poetry run pyinstaller --collect-data eth_account --collect-all aea --collect-all coincurve --collect-all autonomy --collect-all operate --collect-all aea_ledger_ethereum --collect-all aea_ledger_cosmos --collect-all aea_ledger_ethereum_flashbots --hidden-import aea_ledger_ethereum --hidden-import aea_ledger_cosmos --hidden-import aea_ledger_ethereum_flashbots operate/pearl.py --add-binary dist/aea_win.exe:. --add-binary dist/tendermint_win.exe:. --onefile --name pearl_win + poetry install && rm -fr ./open-aea && git clone https://github.com/valory-xyz/open-aea.git -b fix/1.5.2_encoding && poetry run pip install ./open-aea/ && poetry run pyinstaller --collect-data eth_account --collect-all aea --collect-all coincurve --collect-all autonomy --collect-all operate --collect-all aea_ledger_ethereum --collect-all aea_ledger_cosmos --collect-all aea_ledger_ethereum_flashbots --hidden-import aea_ledger_ethereum --hidden-import aea_ledger_cosmos --hidden-import aea_ledger_ethereum_flashbots operate/pearl.py --add-binary dist/aea_win.exe:. --add-binary dist/tendermint_win.exe:. --onefile --name pearl_win ./electron/bins/: @@ -39,20 +47,14 @@ endef .PHONY: build build: ./dist/pearl_win.exe ./electron/bins/tendermint.exe $(call setup_env, prod) - echo ${DEV_RPC} cp -f dist/pearl_win.exe ./electron/bins/pearl_win.exe - echo ${NODE_ENV} - NODE_ENV=${NODE_ENV} DEV_RPC=${DEV_RPC} FORK_URL=${FORK_URL} yarn build:frontend - NODE_ENV=${NODE_ENV} DEV_RPC=${DEV_RPC} FORK_URL=${FORK_URL} GH_TOKEN=${GH_TOKEN} node build-win.js - - + NODE_ENV=${NODE_ENV} GNOSIS_RPC=${GNOSIS_RPC} OPTIMISM_RPC=${OPTIMISM_RPC} BASE_RPC=${BASE_RPC} ETHEREUM_RPC=${ETHEREUM_RPC} yarn build:frontend + NODE_ENV=${NODE_ENV} GNOSIS_RPC=${GNOSIS_RPC} OPTIMISM_RPC=${OPTIMISM_RPC} BASE_RPC=${BASE_RPC} ETHEREUM_RPC=${ETHEREUM_RPC} GH_TOKEN=${GH_TOKEN} node build-win.js .PHONY: build-tenderly build-tenderly: ./dist/pearl_win.exe $(call setup_env, dev-tenderly) - echo ${DEV_RPC} cp -f dist/pearl_win.exe ./electron/bins/pearl_win.exe - echo ${NODE_ENV} - NODE_ENV=${NODE_ENV} DEV_RPC=${DEV_RPC} FORK_URL=${FORK_URL} yarn build:frontend + NODE_ENV=${NODE_ENV} GNOSIS_RPC=${GNOSIS_RPC} OPTIMISM_RPC=${OPTIMISM_RPC} BASE_RPC=${BASE_RPC} ETHEREUM_RPC=${ETHEREUM_RPC} yarn build:frontend GH_TOKEN=${GH_TOKEN} node build-win-tenderly.js \ No newline at end of file diff --git a/api.md b/api.md index 675dc9896..c199f57fa 100644 --- a/api.md +++ b/api.md @@ -1,6 +1,10 @@ -#### `GET /api` +# Olas-Operate API reference -Returns information of the operate daemon +## General + +### `GET /api` + +Returns information of the operate daemon.
Response @@ -19,35 +23,39 @@ Returns information of the operate daemon
--- -#### `GET /api/account` -Returns account status +## Account + +### `GET /api/account` + +Returns account status.
- Before setup + Response -```json -{ - "is_setup": false -} -``` +- Before setup: -
+ ```json + { + "is_setup": false + } + ``` -
- After setup +- After setup: + + ```json + { + "is_setup": true + } + ``` -```json -{ - "is_setup": true -} -```
--- -#### `POST /api/account` -Create a local user account +### `POST /api/account` + +Create a local user account.
Request @@ -63,29 +71,29 @@ Create a local user account
Response -```json -{ - "error": null -} -``` -
+- If account did not exist: -If account already exists + ```json + { + "error": null + } + ``` -
- Response +- If account already exists: + + ```json + { + "error": "Account already exists" + } + ``` -```json -{ - "error": "Account already exists" -} -```
--- -#### `PUT /api/account` -Update password +### `PUT /api/account` + +Update account password.
Request @@ -102,30 +110,30 @@ Update password
Response -```json -{ - "error": null -} -``` -
+- If old password is valid: -Old password is not valid + ```json + { + "error": null + } + ``` -
- Response +- If old password is not valid: + + ```json + { + "error": "Old password is not valid", + "traceback": "..." + } + ``` -```json -{ - "error": "Old password is not valid", - "traceback": "..." -} -```
--- -#### `POST /api/account/login` -Login and create a session +### `POST /api/account/login` + +Login and create a session.
Request @@ -141,15 +149,29 @@ Login and create a session
Response -```json -{ - "message": "Login successful" -} -``` +- If password is valid: + + ```json + { + "message": "Login successful" + } + ``` + +- If password is not valid: + + ```json + { + "error": "Password is not valid" + } + ``` +
--- -#### `GET /api/wallet` + +## Wallet + +### `GET /api/wallet` Returns a list of available wallets @@ -161,27 +183,101 @@ Returns a list of available wallets { "address": "0xFafd5cb31a611C5e5aa65ea8c6226EB4328175E7", "safe_chains": [ - 2 + "gnosis" ], "ledger_type": 0, - "safe": "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23", + "safes": { + "gnosis": "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23" + }, "safe_nonce": 110558881674480320952254000342160989674913430251257716940579305238321962891821 } ] ``` + +
+ +--- + +### `GET /api/extended/wallet` + +Returns a list of available wallets with enriched information. It executes on-chain requests to populate the list of owners of each safe, and provides the attributes + +- `consistent_backup_owner`: This flag is `true` when all safes across the chains have exactly the same set of backup owner addresses. It ensures that ownership is identical across all safes, regardless of the number of owners. +- `consistent_backup_owner_count`: This flag is `true` when all safes have the same number of owners, and that number is either 0 (no backup owners) or 1 (exactly one backup owner). It checks for uniformity in the count of owners and restricts the count to these two cases. +- `consistent_safe_address`: This flag is `true` when all chains have the same safe address. It ensures there is a single safe address consistently used across all chains. + +
+ Response + +```json +[ + { + "address":"0xFafd5cb31a611C5e5aa65ea8c6226EB4328175E7", + "consistent_backup_owner": false, + "consistent_backup_owner_count": false, + "consistent_safe_address": true, + "ledger_type":"ethereum", + "safe_chains":[ + "gnosis", + "ethereum", + "base", + "optimistic" + ], + "safe_nonce":110558881674480320952254000342160989674913430251257716940579305238321962891821, + "safes":{ + "base":{ + "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23":{ + "backup_owners": [], // Empty = no backup owners + "balances": {...} + } + }, + "ethereum":{ + "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23":{ + "backup_owners":[ + "0x46eC2E77Fe3E367252f1A8a77470CE8eEd2A985b" + ], + "balances": {...} + } + }, + "gnosis":{ + "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23":{ + "backup_owners":[ + "0x46eC2E77Fe3E367252f1A8a77470CE8eEd2A985b" + ], + "balances": { + "0x0000000000000000000000000000000000000000": 995899999999999999998, // xDAI + "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83": 0, // USDC + "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f": 960000000000000000000 // OLAS + } + }, + "optimistic":{ + "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23":{ + "backup_owners":[ + "0x46eC2E77Fe3E367252f1A8a77470CE8eEd2A985b" + ], + "balances": {...} + } + } + }, + "single_backup_owner_per_safe":false + } +] +``` +
--- -#### `POST /api/wallet` -Creates a master key for given chain type. +### `POST /api/wallet` + +Creates a master wallet for a given ledger type. If a wallet already exists for a given ledger type, it returns the already existing wallet without creating an additional one.
Request -```js +```json { - "chain_type": ChainType, + "ledger_type": LedgerType, } ``` @@ -196,25 +292,27 @@ Creates a master key for given chain type. "address": "0xAafd5cb31a611C5e5aa65ea8c6226EB4328175E1", "safe_chains": [], "ledger_type": 0, - "safe": null, + "safes": {}, "safe_nonce": null }, - "mnemonic": [...] + "mnemonic": ["polar", "mail", "tattoo", "write", "track", ... ] } ``` +
--- -#### `PUT /api/wallet` -Creates a gnosis safe for given chain type. +### `POST /api/wallet/safe` + +Creates a Gnosis safe for given chain.
Request ```js { - "chain_type": ChainType, + "chain": Chain, } ``` @@ -223,23 +321,114 @@ Creates a gnosis safe for given chain type.
Response -```json +- If Gnosis safe creation is successful: + + ```json + { + "address": "0xFafd5cb31a611C5e5aa65ea8c6226EB4328175E7", + "safe_chains": [ + "gnosis" + ], + "ledger_type": 0, + "safes": { + "gnosis": "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23" + }, + "safe_nonce": 110558881674480320952254000342160989674913430251257716940579305238321962891821 + } + ``` + +- If Gnosis safe creation is not successful: + + ```json + { + "error": "Error message", + "traceback": "Traceback message" + } + ``` + +
+ +--- + +### `PUT /api/wallet/safe` + +Upadtes a Gnosis safe for given chain. If no `backup_owner` is provided, it will assume a null value, that is, it will remove the backup owner from the safe. + +
+ Request + +```js { - "address": "0xaaFd5cb31A611C5e5aa65ea8c6226EB4328175E3", - "safe_chains": [ - 2 - ], - "ledger_type": 0, - "safe": "0xe56fb574ce2C66008d5c4C09980c4f36Ab81ff22", - "safe_nonce": 110558881674480320952254000342160989674913430251157716140571305138121962898821 + "chain": Chain, + "backup_owner": "0x650e83Bc808B8f405A9aF7CF68644cc817e084A6" // Optional. } ``` + +
+ +
+ Response + +- If Gnosis safe update is successful: + + ```json + { + "backup_owner_updated": true, + "chain": "gnosis", + "message": "Backup owner updated.", + "wallet": { + "address": "0xFafd5cb31a611C5e5aa65ea8c6226EB4328175E7", + "safe_chains": [ + "gnosis" + ], + "ledger_type": 0, + "safes": { + "gnosis": "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23" + }, + "safe_nonce": 110558881674480320952254000342160989674913430251257716940579305238321962891821 + } + } + ``` + +- If Gnosis safe update is successful, but no changes required in the safe: + + ```json + { + "backup_owner_updated": false, + "chain": "gnosis", + "message": "No changes on backup owner. The backup owner provided matches the current one.", + "wallet": { + "address": "0xFafd5cb31a611C5e5aa65ea8c6226EB4328175E7", + "safe_chains": [ + "gnosis" + ], + "ledger_type": 0, + "safes": { + "gnosis": "0xd56fb274ce2C66008D5c4C09980c4f36Ab81ff23" + }, + "safe_nonce": 110558881674480320952254000342160989674913430251257716940579305238321962891821 + } + } + ``` + +- If Gnosis safe creation is not successful: + + ```json + { + "error": "Error message", + "traceback": "Traceback message" + } + ``` +
--- -#### `GET /api/services` -Returns the list of services +## Services + +### `GET /api/v2/services` + +Returns the list of existing service configurations.
Response @@ -247,253 +436,309 @@ Returns the list of services ```json [ { - "hash": "bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq", - "keys": [ - { - "ledger": 0, - "address": "0x6Db941e0e82feA3c02Ba83B20e3fB5Ea6ee539cf", - "private_key": "0x34f58dcc11acec007644e49921fd81b9c8a959f651d6d66a42242a1b2dbaf4be" - } - ], - "ledger_config": { - "rpc": "http://localhost:8545", - "type": 0, - "chain": 2 - }, - "chain_data": { - "instances": [ - "0x6Db941e0e82feA3c02Ba83B20e3fB5Ea6ee539cf" - ], - "token": 380, - "multisig": "0x7F3e460Cf596E783ca490791643C0055Fa2034AC", - "staked": false, - "on_chain_state": 6, - "user_params": { - "nft": "bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq", - "agent_id": 14, - "threshold": 1, - "use_staking": false, - "cost_of_bond": 10000000000000000, - "olas_cost_of_bond": 10000000000000000000, - "olas_required_to_stake": 10000000000000000000, - "fund_requirements": { - "agent": 0.1, - "safe": 0.5 - } - } - }, - "path": "/Users/virajpatel/valory/olas-operate-app/.operate/services/bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq", - "service_path": "/Users/virajpatel/valory/olas-operate-app/.operate/services/bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq/trader_omen_gnosis", - "name": "valory/trader_omen_gnosis" - } + "chain_configs": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "hash_history": {"1731487112": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u"}, + "home_chain": "gnosis", + "keys": [...], + "name": "valory/trader_omen_gnosis", + "service_config_id": "sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39", + "service_path": "/home/user/.operate/services/sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39/trader_omen_gnosis", + "version": 4 + }, + ... ] ```
--- -#### `POST /api/services` -Create a service using the service template +#### `POST /api/v2/services` + +Create a service configuration using a template.
Request ```json -{ - "name": "Trader Agent", - "description": "Trader agent for omen prediction markets", - "hash": "bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq", - "image": "https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75", - "configuration": { - "nft": "bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq", - "rpc": "http://localhost:8545", - "agent_id": 14, - "threshold": 1, - "use_staking": false, - "cost_of_bond": 10000000000000000, - "olas_cost_of_bond": 10000000000000000000, - "olas_required_to_stake": 10000000000000000000, - "fund_requirements": { - "agent": 0.1, - "safe": 0.5 - } + { + "configurations": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "image": "https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75", + "home_chain": "gnosis", + "name": "valory/trader_omen_gnosis", + "service_version": "v0.18.4" } -} ```
-Optionally you can add `deploy` parameter and set it to `true` for a full deployment in a single request. -
Response ```json { - "hash": "bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq", - "keys": [ - { - "ledger": 0, - "address": "0x10EB940024913dfCAE95D21E04Ba662cdfB79fF0", - "private_key": "0x00000000000000000000000000000000000000000000000000000000000000000" - } - ], - "ledger_config": { - "rpc": "http: //localhost:8545", - "type": 0, - "chain": 2 - }, - "chain_data": { - "instances": [ - "0x10EB940024913dfCAE95D21E04Ba662cdfB79fF0" - ], - "token": 382, - "multisig": "0xf21d8A424e83BBa2588306D1C574FE695AD410b5", - "staked": false, - "on_chain_state": 4, - "user_params": { - "nft": "bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq", - "agent_id": 14, - "threshold": 1, - "use_staking": false, - "cost_of_bond": 10000000000000000, - "olas_cost_of_bond": 10000000000000000000, - "olas_required_to_stake": 10000000000000000000, - "fund_requirements": { - "agent": 0.1, - "safe": 0.5 - } - } - }, - "path": "~/.operate/services/bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq", - "service_path": "~/.operate/services/bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq/trader_omen_gnosis", - "name": "valory/trader_omen_gnosis" + "chain_configs": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "hash_history": {"1731487112": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u"}, + "home_chain": "gnosis", + "keys": [...], + "name": "valory/trader_omen_gnosis", + "service_config_id": "sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39", + "service_path": "/home/user/.operate/services/sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39/trader_omen_gnosis", + "version": 4 } ```
--- -#### `PUT /api/services` -Update a service +### `PUT /api/v2/services` + +Update all the service configurations whose Service Public ID match the Service Public ID in the provided hash.
Request ```json -{ - "old_service_hash": "bafybeiha6dxygx2ntgjxhs6zzymgqk3s5biy3ozeqw6zuhr6yxgjlebfmq", - "new_service_hash": "bafybeicxdpkuk5z5zfbkso7v5pywf4v7chxvluyht7dtgalg6dnhl7ejoe", -} + { + "configurations": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeibpseosblmaw6sk6zsnic2kfxfsijrnfluuhkwboyqhx7ma7zw2me", + "image": "https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75", + "home_chain": "gnosis", + "name": "valory/trader_omen_gnosis", + "service_version": "v0.19.0" + } ```
-Optionally you can add `deploy` parameter and set it to `true` for a full deployment in a single request. -
Response +The response contains an array of the services which have been updated (an empty array if no service matches the Service Public ID in the provided hash). + ```json -{ - "hash": "bafybeicxdpkuk5z5zfbkso7v5pywf4v7chxvluyht7dtgalg6dnhl7ejoe", - "keys": [ - { - "ledger": 0, - "address": "0x10EB940024913dfCAE95D21E04Ba662cdfB79fF0", - "private_key": "0x00000000000000000000000000000000000000000000000000000000000000000" - } - ], - "ledger_config": { - "rpc": "http: //localhost:8545", - "type": 0, - "chain": 2 - }, - "chain_data": { - "instances": [ - "0x10EB940024913dfCAE95D21E04Ba662cdfB79fF0" - ], - "token": 382, - "multisig": "0xf21d8A424e83BBa2588306D1C574FE695AD410b5", - "staked": false, - "on_chain_state": 4, - "user_params": { - "nft": "bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq", - "agent_id": 14, - "threshold": 1, - "use_staking": false, - "cost_of_bond": 10000000000000000, - "olas_cost_of_bond": 10000000000000000000, - "olas_required_to_stake": 10000000000000000000, - "fund_requirements": { - "agent": 0.1, - "safe": 0.5 - } - } +[ + { + "chain_configs": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "hash_history": {"1731487112": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", "1731490000": "bafybeibpseosblmaw6sk6zsnic2kfxfsijrnfluuhkwboyqhx7ma7zw2me"}, + "home_chain": "gnosis", + "keys": [...], + "name": "valory/trader_omen_gnosis", + "service_config_id": "sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39", + "service_path": "/home/user/.operate/services/sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39/trader_omen_gnosis", + "version": 4 }, - "path": "~/.operate/services/bafybeicxdpkuk5z5zfbkso7v5pywf4v7chxvluyht7dtgalg6dnhl7ejoe", - "service_path": "~/.operate/services/bafybeicxdpkuk5z5zfbkso7v5pywf4v7chxvluyht7dtgalg6dnhl7ejoe/trader_omen_gnosis", - "name": "valory/trader_omen_gnosis" -} + ... +] ```
--- -#### `GET /api/services/{service}` + +#### `POST /api/v2/services/stop` (alias `GET /stop_all_services`) + +Stop all running deployments. + +
+ Response + +- If the operation was successful: + + ```json + { + "message": "Services stopped." + } + ``` + +- If the operation was not successful: + + ```json + { + "error": "Error message", + "traceback": "Traceback message" + } + ``` + +
+ +--- + +## Service + +### `GET /api/v2/service/{service_config_id}` + +Returns the service configuration `service_config_id`. + +
+ Response + +- If service configuration `service_config_id` exists: + + ```json + { + "chain_configs": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "hash_history": {"1731487112": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u"}, + "home_chain": "gnosis", + "keys": [...], + "name": "valory/trader_omen_gnosis", + "service_config_id": "sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39", + "service_path": "/home/user/.operate/services/sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39/trader_omen_gnosis", + "version": 4 + } + + ``` + +- If service configuration `service_config_id` does not exist: + + ```json + { + "error": "Service foo not found" + } + ``` + +
+ +--- + +### `POST /api/v2/service/{service_config_id}` + +Deploy service with service configuration `service_config_id` on-chain and run local deployment. This endpoint executes the following tasks: + +1. Stops any running service. +2. Ensures that the service is deployed on-chain on all the configured chains. +3. Ensures that the the service is staked on all the configured chains. +4. Runs the service locally. +5. Starts funding job. +6. Starts healthcheck job. + +
Response +The response contains the updated service configuration following the on-chain operations, including service Gnosis safe, on-chain token, etc. + ```json { - "hash": "{service}", - "keys": [ - { - "ledger": 0, - "address": "0x10EB940024913dfCAE95D21E04Ba662cdfB79fF0", - "private_key": "0x00000000000000000000000000000000000000000000000000000000000000000" - } - ], - "ledger_config": { - "rpc": "http: //localhost:8545", - "type": 0, - "chain": 2 - }, - "chain_data": { - "instances": [ - "0x10EB940024913dfCAE95D21E04Ba662cdfB79fF0" - ], - "token": 382, - "multisig": "0xf21d8A424e83BBa2588306D1C574FE695AD410b5", - "staked": false, - "on_chain_state": 4, - "user_params": { - "nft": "bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq", - "agent_id": 14, - "threshold": 1, - "use_staking": false, - "cost_of_bond": 10000000000000000, - "olas_cost_of_bond": 10000000000000000000, - "olas_required_to_stake": 10000000000000000000, - "fund_requirements": { - "agent": 0.1, - "safe": 0.5 - } - } - }, - "path": "~/.operate/services/{service}", - "service_path": "~/.operate/services/{service}/trader_omen_gnosis", - "name": "valory/trader_omen_gnosis" + "chain_configs": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "hash_history": {"1731487112": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u"}, + "home_chain": "gnosis", + "keys": [...], + "name": "valory/trader_omen_gnosis", + "service_config_id": "sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39", + "service_path": "/home/user/.operate/services/sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39/trader_omen_gnosis" } + ```
--- -#### `POST /api/services/{service}/onchain/deploy` + +### `PUT /api/v2/service/{service_config_id}` + +Update service configuration `service_config_id` with the provided template. + +
+ Request + +```json + { + "configurations": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeibpseosblmaw6sk6zsnic2kfxfsijrnfluuhkwboyqhx7ma7zw2me", + "image": "https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75", + "home_chain": "gnosis", + "name": "valory/trader_omen_gnosis", + "service_version": "v0.19.0" + } +``` + +
+ +
+ Response + +- If the update is successful, the response contains the updated service configuration: + + ```json + { + "chain_configs": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "hash_history": {"1731487112": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", "1731490000": "bafybeibpseosblmaw6sk6zsnic2kfxfsijrnfluuhkwboyqhx7ma7zw2me"}, + "home_chain": "gnosis", + "keys": [...], + "name": "valory/trader_omen_gnosis", + "service_config_id": "sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39", + "service_path": "/home/user/.operate/services/sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39/trader_omen_gnosis" + } + + ``` + +- If the update is not successful: + + ```json + { + "error": "Error message", + "traceback": "Traceback message" + } + ``` + +
+ +--- + +### `POST /api/service/{service_config_id}/stop` + +Stop service with service configuration `service_configuration_id`. + +
+ Response + +```json + { + "nodes": { + "agent": [], + "tendermint": [] + }, + "status": 1 + } +``` + +
+ +--- + +## Unused endpoints + +### `POST /api/services/{service}/onchain/deploy` + +**:warning: Deprecated** Deploy service on-chain @@ -514,7 +759,10 @@ Deploy service on-chain
--- -#### `POST /api/services/{service}/onchain/stop` + +### `POST /api/services/{service}/onchain/stop` + +**:warning: Deprecated** Stop service on-chain @@ -535,7 +783,10 @@ Stop service on-chain
--- -#### `GET /api/services/{service}/deployment` + +### `GET /api/services/{service}/deployment` + +**:warning: Deprecated**
Response @@ -557,7 +808,10 @@ Stop service on-chain
--- -#### `POST /api/services/{service}/deployment/build` + +### `POST /api/services/{service}/deployment/build` + +**:warning: Deprecated** Build service locally @@ -578,7 +832,10 @@ Build service locally --- -#### `POST /api/services/{service}/deployment/start` + +### `POST /api/services/{service}/deployment/start` + +**:warning: Deprecated** Start agent @@ -599,7 +856,10 @@ Start agent --- -#### `POST /api/services/{service}/deployment/stop` + +### `POST /api/services/{service}/deployment/stop` + +**:warning: Deprecated** Stop agent @@ -607,7 +867,10 @@ Stop agent ``` --- -#### `POST /api/services/{service}/deployment/delete` + +### `POST /api/services/{service}/deployment/delete` + +**:warning: Deprecated** Delete local deployment @@ -645,5 +908,3 @@ Delete local deployment --> - - diff --git a/build-win-tenderly.js b/build-win-tenderly.js index b5b733511..e98e3e5aa 100644 --- a/build-win-tenderly.js +++ b/build-win-tenderly.js @@ -13,9 +13,9 @@ const main = async () => { await build({ publish: 'onTag', config: { - appId: 'xyz.valory.olas-pearl-optimus', + appId: 'xyz.valory.olas-operate-app', artifactName: '${productName}-${version}-${platform}-${arch}-tenderly.${ext}', - productName: 'Pearl (Optimus)', + productName: 'Pearl', files: ['electron/**/*', 'package.json'], directories: { output: 'dist', @@ -35,4 +35,8 @@ const main = async () => { }); }; -main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); +main().then(() => { + console.log('Build & Notarize complete'); +}).catch(() => { + throw new Error('Failed to build and notarize.'); +}); \ No newline at end of file diff --git a/build-win.js b/build-win.js index bc430f8a5..627ef1d28 100644 --- a/build-win.js +++ b/build-win.js @@ -20,9 +20,9 @@ const main = async () => { await build({ publish: 'onTag', config: { - appId: 'xyz.valory.olas-pearl-optimus', + appId: 'xyz.valory.olas-operate-app', artifactName: artifactName(), - productName: 'Pearl (Optimus)', + productName: 'Pearl', files: ['electron/**/*', 'package.json'], directories: { output: 'dist', @@ -40,10 +40,18 @@ const main = async () => { to: 'bins', filter: ['**/*'], }, + { + from: '.env', + to: '.env' + }, ], }, }); }; -main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); +main().then(() => { + console.log('Build & Notarize complete'); +}).catch(() => { + throw new Error('Failed to build and notarize.'); +}); diff --git a/build.js b/build.js index 9f29e2f21..baccf0819 100644 --- a/build.js +++ b/build.js @@ -20,12 +20,12 @@ const main = async () => { console.log('Building...'); /** @type import {CliOptions} from "electron-builder" */ - await build({ + return build({ publish: 'onTag', config: { - appId: 'xyz.valory.olas-pearl-optimus', + appId: 'xyz.valory.olas-operate-app', artifactName: artifactName(), - productName: 'Pearl (Optimus)', + productName: 'Pearl', files: ['electron/**/*', 'package.json'], directories: { output: 'dist', @@ -57,12 +57,16 @@ const main = async () => { gatekeeperAssess: false, entitlements: 'electron/entitlements.mac.plist', entitlementsInherit: 'electron/entitlements.mac.plist', - notarize: { - teamId: process.env.APPLETEAMID, - }, }, }, }); }; -main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); +main().then((res) => { + console.log(JSON.stringify(res)) + console.log('Build & Notarize complete'); + +}).catch((e) => { + console.error(JSON.stringify(e)) + throw new Error('Failed to build and notarize.'); +}); diff --git a/build.tester.js b/build.tester.js index f87d15167..b4163427e 100644 --- a/build.tester.js +++ b/build.tester.js @@ -16,9 +16,9 @@ const main = async () => { await build({ publish: 'onTag', config: { - appId: 'xyz.valory.olas-pearl-optimus', + appId: 'xyz.valory.olas-operate-app', artifactName: '${productName}-${version}-${platform}-${arch}.${ext}', - productName: 'Pearl (Optimus)', + productName: 'Pearl', files: ['electron/**/*', 'package.json'], directories: { output: 'dist', @@ -49,4 +49,8 @@ const main = async () => { }); }; -main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); +main().then(() => { + console.log('Build & Notarize complete'); +}).catch(() => { + throw new Error('Failed to build and notarize.'); +}); diff --git a/download_binaries.sh b/download_binaries.sh index 40a9572e6..0904caa13 100755 --- a/download_binaries.sh +++ b/download_binaries.sh @@ -4,8 +4,10 @@ BIN_DIR="electron/bins/" mkdir -p $BIN_DIR trader_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/trader.yaml')); print(config['service_version'])") -optimus_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/optimus.yaml')); print(config['service_version'])") +# optimus_version=$(poetry run python -c "import yaml; config = yaml.safe_load(open('templates/optimus.yaml')); print(config['service_version'])") +# curl -L -o "${BIN_DIR}aea_bin_x64" "https://github.com/valory-xyz/optimus/releases/download/${optimus_version}/optimus_bin_x64" +# curl -L -o "${BIN_DIR}aea_bin_arm64" "https://github.com/valory-xyz/optimus/releases/download/${optimus_version}/optimus_bin_arm64" -curl -L -o "${BIN_DIR}aea_bin_x64" "https://github.com/valory-xyz/optimus/releases/download/${optimus_version}/optimus_bin_x64" -curl -L -o "${BIN_DIR}aea_bin_arm64" "https://github.com/valory-xyz/optimus/releases/download/${optimus_version}/optimus_bin_arm64" +curl -L -o "${BIN_DIR}aea_bin_x64" "https://github.com/valory-xyz/trader/releases/download/${trader_version}/trader_bin_x64" +curl -L -o "${BIN_DIR}aea_bin_arm64" "https://github.com/valory-xyz/trader/releases/download/${trader_version}/trader_bin_arm64" \ No newline at end of file diff --git a/electron/components/PearlTray.js b/electron/components/PearlTray.js index c28a571ae..506bea300 100644 --- a/electron/components/PearlTray.js +++ b/electron/components/PearlTray.js @@ -67,7 +67,7 @@ class PearlTray extends Electron.Tray { this.activeWindowCallback = activeWindowCallback; this.setContextMenu(new PearlTrayContextMenu(activeWindowCallback)); - this.setToolTip('Pearl (Optimus)'); + this.setToolTip('Pearl'); this.#bindClickEvents(); this.#bindIpcListener(); diff --git a/electron/install.js b/electron/install.js index 3aa2bb8f7..6bf21073e 100644 --- a/electron/install.js +++ b/electron/install.js @@ -17,7 +17,7 @@ const { app } = require('electron'); require('dotenv').config({ path: app.isPackaged ? path.join(process.resourcesPath, '.env') - : path.resolve(process.cwd(), '.env'), + : path.resolve(process.cwd(), '../.env'), }); const Env = { @@ -25,11 +25,11 @@ const Env = { PATH: `${process.env.PATH}:/opt/homebrew/bin:/usr/local/bin`, HOMEBREW_NO_AUTO_UPDATE: '1', PYTHONUTF8: '1', - PYTHONIOENCODING: 'utf8' + PYTHONIOENCODING: 'utf-8', }; const SudoOptions = { - name: 'Pearl (Optimus)', + name: 'Pearl', env: Env, }; @@ -123,9 +123,9 @@ function isTendermintInstalledUnix() { } function isTendermintInstalledWindows() { + // tendermint is bundled during release return true; - //always installed cause bundled in - return execSyncExitCode('tendermint --help') === 0; + // return execSyncExitCode('tendermint --help') === 0; } async function downloadFile(url, dest) { @@ -148,37 +148,38 @@ async function downloadFile(url, dest) { } async function installTendermintWindows() { + // windows tendermint is bundled during release return; - // bundled in - logger.electron(`Installing tendermint for ${os.platform()}-${process.arch}`); - const cwd = process.cwd(); - process.chdir(paths.tempDir); - const url = TendermintUrls[os.platform()][process.arch]; + // logger.electron(`Installing tendermint for ${os.platform()}-${process.arch}`); + // const cwd = process.cwd(); + // process.chdir(paths.tempDir); - logger.electron( - `Downloading ${url} to ${paths.tempDir}. This might take a while...`, - ); - await downloadFile(url, `${paths.tempDir}/tendermint.tar.gz`); + // const url = TendermintUrls[os.platform()][process.arch]; - logger.electron(`Installing tendermint binary`); - try { - execSync('tar -xvf tendermint.tar.gz'); - } catch (error) { - logger.electron(error.status); // Might be 127 in your example. - logger.electron(error.message); // Holds the message you typically want. - logger.electron(error.stderr.toString()); // Holds the stderr output. Use `.toString()`. - logger.electron(error.stdout.toString()); // Holds the stdout output. Use `.toString()`. - } + // logger.electron( + // `Downloading ${url} to ${paths.tempDir}. This might take a while...`, + // ); + // await downloadFile(url, `${paths.tempDir}/tendermint.tar.gz`); - const bin_dir = homedir + '//AppData//Local//Microsoft//WindowsApps//'; - if (!Env.CI) { - if (!fs.existsSync(bin_dir)) { - fs.mkdirSync(bin_dir, { recursive: true }); - } - fs.copyFileSync('tendermint.exe', bin_dir + 'tendermint.exe'); - } - process.chdir(cwd); + // logger.electron(`Installing tendermint binary`); + // try { + // execSync('tar -xvf tendermint.tar.gz'); + // } catch (error) { + // logger.electron(error.status); // Might be 127 in your example. + // logger.electron(error.message); // Holds the message you typically want. + // logger.electron(error.stderr.toString()); // Holds the stderr output. Use `.toString()`. + // logger.electron(error.stdout.toString()); // Holds the stdout output. Use `.toString()`. + // } + + // const bin_dir = homedir + '//AppData//Local//Microsoft//WindowsApps//'; + // if (!Env.CI) { + // if (!fs.existsSync(bin_dir)) { + // fs.mkdirSync(bin_dir, { recursive: true }); + // } + // fs.copyFileSync('tendermint.exe', bin_dir + 'tendermint.exe'); + // } + // process.chdir(cwd); } async function installTendermintUnix() { @@ -231,7 +232,7 @@ async function setupDarwin(ipcChannel) { logger.electron('Checking tendermint installation'); if (!isTendermintInstalledUnix()) { - ipcChannel.send('response', 'Installing Pearl (Optimus) Daemon'); + ipcChannel.send('response', 'Installing Pearl Daemon'); logger.electron('Installing tendermint'); await installTendermintUnix(); } @@ -245,7 +246,7 @@ async function setupUbuntu(ipcChannel) { logger.electron('Checking tendermint installation'); if (!isTendermintInstalledUnix()) { - ipcChannel.send('response', 'Installing Pearl (Optimus) Daemon'); + ipcChannel.send('response', 'Installing Pearl Daemon'); logger.electron('Installing tendermint'); await installTendermintUnix(); } diff --git a/electron/main.js b/electron/main.js index 29dc94155..4157b081d 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1,3 +1,4 @@ +require('dotenv').config(); const { app, BrowserWindow, @@ -13,6 +14,7 @@ const os = require('os'); const next = require('next/dist/server/next'); const http = require('http'); const AdmZip = require('adm-zip'); +const { validateEnv } = require('./utils/env-validation'); const { setupDarwin, setupUbuntu, setupWindows, Env } = require('./install'); @@ -25,6 +27,12 @@ const { logger } = require('./logger'); const { isDev } = require('./constants'); const { PearlTray } = require('./components/PearlTray'); +// Validates environment variables required for Pearl +// kills the app/process if required environment variables are unavailable +// mostly RPC URLs and NODE_ENV +// TODO: only reintroduce once refactor completed +// validateEnv(); + // Attempt to acquire the single instance lock const singleInstanceLock = app.requestSingleInstanceLock(); if (!singleInstanceLock) { @@ -70,11 +78,20 @@ let splashWindow = null; /** @type {Electron.Tray | null} */ let tray = null; -let operateDaemon, operateDaemonPid, nextAppProcess, nextAppProcessPid; +// Used in production and development +let operateDaemon; +let operateDaemonPid; + +// Child processes for running next app are only used in development +// required for hot reloads and other dev features +let devNextApp; +let devNextAppPid; +// Next.js app instance for production +// requires http server wrap to work; assign port, receive requests, deliver responses // @ts-ignore - Workaround for the missing type definitions const nextApp = next({ - dev: false, // this instance is only used for production + dev: false, // DO NOT SET TO TRUE dir: path.join(__dirname), }); @@ -85,28 +102,73 @@ function showNotification(title, body) { } async function beforeQuit() { - if (operateDaemonPid) { + // destroy all ui components for immediate feedback + tray?.destroy(); + splashWindow?.destroy(); + mainWindow?.destroy(); + + if (operateDaemon || operateDaemonPid) { + // gracefully stop running services try { await fetch( `http://localhost:${appConfig.ports.prod.operate}/stop_all_services`, ); - await killProcesses(operateDaemonPid); } catch (e) { - logger.electron(e); + logger.electron("Couldn't stop_all_services gracefully:"); + logger.electron(JSON.stringify(e, null, 2)); + } + + // clean-up via pid first* + // may have dangling subprocesses + try { + operateDaemonPid && (await killProcesses(operateDaemonPid)); + } catch (e) { + logger.electron("Couldn't kill daemon processes via pid:"); + logger.electron(JSON.stringify(e, null, 2)); + } + + // attempt to kill the daemon process via kill + // if the pid-based cleanup fails + try { + const dead = operateDaemon?.kill(); + if (!dead) { + logger.electron('Daemon process still alive after kill'); + } + } catch (e) { + logger.electron("Couldn't kill operate daemon process via kill:"); + logger.electron(JSON.stringify(e, null, 2)); } } - if (nextAppProcessPid) { + if (devNextApp || devNextAppPid) { + // attempt graceful kill first with next app + try { + const dead = devNextApp?.kill(); + if (!dead) { + logger.electron('Dev NextApp process still alive after kill'); + } + } catch (e) { + logger.electron("Couldn't kill devNextApp process via kill:"); + logger.electron(JSON.stringify(e, null, 2)); + } + + // attempt to kill the dev next app process via pid try { - await killProcesses(nextAppProcessPid); + devNextAppPid && (await killProcesses(devNextAppPid)); } catch (e) { - logger.electron(e); + logger.electron("Couldn't kill devNextApp processes via pid:"); + logger.electron(JSON.stringify(e, null, 2)); } } - tray?.destroy(); - splashWindow?.destroy(); - mainWindow?.destroy(); + if (nextApp) { + // attempt graceful close of prod next app + await nextApp.close().catch((e) => { + logger.electron("Couldn't close NextApp gracefully:"); + logger.electron(JSON.stringify(e, null, 2)); + }); + // electron will kill next service on exit + } } const APP_WIDTH = 460; @@ -121,7 +183,7 @@ const createSplashWindow = () => { height: APP_WIDTH, resizable: false, show: true, - title: 'Pearl (Optimus)', + title: 'Pearl', frame: false, webPreferences: { nodeIntegration: true, @@ -142,7 +204,7 @@ const HEIGHT = 700; const createMainWindow = async () => { const width = isDev ? 840 : APP_WIDTH; mainWindow = new BrowserWindow({ - title: 'Pearl (Optimus)', + title: 'Pearl', resizable: false, draggable: true, frame: false, @@ -340,7 +402,7 @@ async function launchNextApp() { async function launchNextAppDev() { await new Promise(function (resolve, _reject) { process.env.NEXT_PUBLIC_BACKEND_PORT = appConfig.ports.dev.operate; // must set next env var to connect to backend - nextAppProcess = spawn( + devNextApp = spawn( 'yarn', ['dev:frontend', '--port', appConfig.ports.dev.next], { @@ -352,8 +414,8 @@ async function launchNextAppDev() { }, }, ); - nextAppProcessPid = nextAppProcess.pid; - nextAppProcess.stdout.on('data', (data) => { + devNextAppPid = devNextApp.pid; + devNextApp.stdout.on('data', (data) => { logger.next(data.toString().trim()); resolve(); }); @@ -397,7 +459,7 @@ ipcMain.on('check', async function (event, _argument) { if (isDev) { event.sender.send( 'response', - 'Starting Pearl (Optimus) Daemon In Development Mode', + 'Starting Pearl Daemon In Development Mode', ); const daemonDevPortAvailable = await isPortAvailable( diff --git a/electron/processes.js b/electron/processes.js index faaa9266f..5a1e8ba0f 100644 --- a/electron/processes.js +++ b/electron/processes.js @@ -16,15 +16,16 @@ function killProcesses(pid) { // Array of PIDs to kill, starting with the children const pidsToKill = children.map((p) => p.PID); - logger.info("Pids to kill " + JSON.stringify(pidsToKill)); + logger.electron('Pids to kill ' + JSON.stringify(pidsToKill)); const killCommand = isWindows ? windowsKillCommand : unixKillCommand; let errors = []; - for (const ppid of pidsToKill) { - logger.info("kill: " + ppid); - exec(`${killCommand} ${ppid}`, (err) => { - logger.error("Pids to kill error:" + err); + for (const pid of pidsToKill) { + logger.electron('killing: ' + pid); + exec(`${killCommand} ${pid}`, (err) => { + err && logger.electron(`error killing pid ${pid}`); + err && logger.electron(JSON.stringify(err, null, 2)); if ( err?.message?.includes(isWindows ? 'not found' : 'No such process') ) { @@ -36,9 +37,7 @@ function killProcesses(pid) { if (errors.length === 0) { reject(errors); - - - } else resolve(); + } else resolve(); }); }); } diff --git a/electron/utils/env-validation.js b/electron/utils/env-validation.js new file mode 100644 index 000000000..b64d84e87 --- /dev/null +++ b/electron/utils/env-validation.js @@ -0,0 +1,49 @@ +/** + * Validates environment variables + */ + +require('dotenv').config(); +const { z, ZodError } = require('zod'); +const { app } = require('electron'); + +const nodeEnvRegex = new RegExp(/^(development|production)$/); + +// Update z.object keys if env variable names change +const envSchema = z.object({ + NODE_ENV: z + .string() + .regex( + nodeEnvRegex, + 'Invalid NODE_ENV, must be `development` or `production`', + ), + BASE_RPC: z.string().url('Invalid BASE_RPC must be a valid URL'), + ETHEREUM_RPC: z + .string() + .url('Invalid ETHEREUM_RPC_URL must be a valid URL'), + GNOSIS_RPC: z.string().url('Invalid GNOSIS_RPC must be a valid URL'), + OPTIMISM_RPC: z + .string() + .url('Invalid OPTIMISM_RPC must be a valid URL'), +}); + +const validateEnv = () => { + const { env } = process; + try { + envSchema.parse(env); + } catch (error) { + console.error(`Invalid environment variables in .env file`); + console.log(JSON.stringify(error, null, 2)); + + if (error instanceof ZodError) { + for (const issue of error.errors) { + console.error(issue.message); + } + } else { + console.error('An unexpected error occurred:', error); + } + + app.quit(); + } +}; + +module.exports = { validateEnv }; diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 46cd97cea..cf4afb727 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -18,23 +18,43 @@ "import" ], "rules": { + "@next/next/no-html-link-for-pages": "off", // stop Next.js from complaining about pages not being in root + "object-shorthand": [ + "error", + "always" + ], // don't do things like {service: service}, instead just {service} "import/first": "error", "import/newline-after-import": "error", "import/no-duplicates": "error", "simple-import-sort/imports": "error", "simple-import-sort/exports": "error", "unused-imports/no-unused-imports": "error", - "no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], - "no-console": ["error", { "allow": ["error"] }], - "prettier/prettier": ["error", { - "endOfLine": "auto", - "semi": true, - "singleQuote": true - }], + "no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_" + } + ], + "no-console": [ + "error", + { + "allow": [ + "error" + ] + } + ], + "prettier/prettier": [ + "error", + { + "endOfLine": "auto", + "semi": true, + "singleQuote": true + } + ], "react/jsx-props-no-spreading": "off", "react/no-array-index-key": "off", - "react/react-in-jsx-scope": "off", - "react-hooks/rules-of-hooks": "error", + "react/react-in-jsx-scope": "off", + "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn" } } \ No newline at end of file diff --git a/frontend/abis/agentMech.ts b/frontend/abis/agentMech.ts index 9f4e71e2f..bc3e1302e 100644 --- a/frontend/abis/agentMech.ts +++ b/frontend/abis/agentMech.ts @@ -1,4 +1,6 @@ -export const AGENT_MECH_ABI = [ +import { Abi } from '@/types/Abi'; + +export const AGENT_MECH_ABI: Abi = [ { inputs: [ { internalType: 'address', name: '_token', type: 'address' }, diff --git a/frontend/abis/erc20.ts b/frontend/abis/erc20.ts index e581ffc4f..7d91234f9 100644 --- a/frontend/abis/erc20.ts +++ b/frontend/abis/erc20.ts @@ -1,3 +1,23 @@ -export const ERC20_BALANCEOF_FRAGMENT = [ - 'function balanceOf(address owner) view returns (uint256)', +import { Abi } from '@/types/Abi'; + +export const ERC20_BALANCE_OF_STRING_FRAGMENT: Abi = [ + { + constant: true, + inputs: [ + { + name: '_owner', + type: 'address', + }, + ], + name: 'balanceOf', + outputs: [ + { + name: 'balance', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, ]; diff --git a/frontend/abis/gnosisSafe.ts b/frontend/abis/gnosisSafe.ts index cd4d7a454..b72267abb 100644 --- a/frontend/abis/gnosisSafe.ts +++ b/frontend/abis/gnosisSafe.ts @@ -1,4 +1,6 @@ -export const GNOSIS_SAFE_ABI = [ +import { Abi } from '@/types/Abi'; + +export const GNOSIS_SAFE_ABI: Abi = [ { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, { anonymous: false, diff --git a/frontend/abis/mechActivityChecker.ts b/frontend/abis/mechActivityChecker.ts index 125ee5ed6..79ee71ad5 100644 --- a/frontend/abis/mechActivityChecker.ts +++ b/frontend/abis/mechActivityChecker.ts @@ -1,4 +1,6 @@ -export const MECH_ACTIVITY_CHECKER_ABI = [ +import { Abi } from '@/types/Abi'; + +export const MECH_ACTIVITY_CHECKER_ABI: Abi = [ { inputs: [ { internalType: 'address', name: '_agentMech', type: 'address' }, diff --git a/frontend/abis/serviceRegistryL2.ts b/frontend/abis/serviceRegistryL2.ts index b9465e7fe..d55a724e3 100644 --- a/frontend/abis/serviceRegistryL2.ts +++ b/frontend/abis/serviceRegistryL2.ts @@ -1,4 +1,6 @@ -export const SERVICE_REGISTRY_L2_ABI = [ +import { Abi } from '@/types/Abi'; + +export const SERVICE_REGISTRY_L2_ABI: Abi = [ { inputs: [ { internalType: 'string', name: '_name', type: 'string' }, diff --git a/frontend/abis/serviceStakingTokenMechUsage.ts b/frontend/abis/stakingTokenProxy.ts similarity index 99% rename from frontend/abis/serviceStakingTokenMechUsage.ts rename to frontend/abis/stakingTokenProxy.ts index 0f1a270da..506a8a694 100644 --- a/frontend/abis/serviceStakingTokenMechUsage.ts +++ b/frontend/abis/stakingTokenProxy.ts @@ -1,4 +1,6 @@ -export const SERVICE_STAKING_TOKEN_MECH_USAGE_ABI = [ +import { JsonFragment } from '@ethersproject/abi'; + +export const STAKING_TOKEN_PROXY_ABI: JsonFragment[] = [ { inputs: [], name: 'AlreadyInitialized', diff --git a/frontend/client/enums.ts b/frontend/client/enums.ts index f880c942d..22e716848 100644 --- a/frontend/client/enums.ts +++ b/frontend/client/enums.ts @@ -1,4 +1,4 @@ -export enum Action { +export enum MiddlewareAction { STATUS = 0, BUILD = 1, DEPLOY = 2, @@ -6,21 +6,21 @@ export enum Action { } export enum MiddlewareChain { - ETHEREUM = 0, - GOERLI = 1, - GNOSIS = 2, - SOLANA = 3, - OPTIMISM = 4, - BASE = 5, - MODE = 6, + ETHEREUM = 'ethereum', + GOERLI = 'goerli', + GNOSIS = 'gnosis', + SOLANA = 'solana', + OPTIMISM = 'optimism', + BASE = 'base', + MODE = 'mode', } -export enum Ledger { +export enum MiddlewareLedger { ETHEREUM = 0, SOLANA = 1, } -export enum DeploymentStatus { +export enum MiddlewareDeploymentStatus { CREATED = 0, BUILT = 1, DEPLOYING = 2, @@ -30,9 +30,33 @@ export enum DeploymentStatus { DELETED = 6, } -export enum AccountIsSetup { +/** @note statuses where middleware deployment is moving from stopped to deployed, or vice versa, used for loading fallbacks */ +export const MiddlewareTransitioningStatuses = [ + MiddlewareDeploymentStatus.DEPLOYING, + MiddlewareDeploymentStatus.STOPPING, +]; + +/** @note statuses where middleware deployment is running */ +export const MiddlewareRunningStatuses = [ + MiddlewareDeploymentStatus.DEPLOYED, + ...MiddlewareTransitioningStatuses, +]; + +/** @note statuses where middleware is in the process of building/creating a new deployment */ +export const MiddlewareBuildingStatuses = [ + MiddlewareDeploymentStatus.BUILT, + MiddlewareDeploymentStatus.CREATED, +]; + +export enum MiddlewareAccountIsSetup { True, False, Loading, Error, } + +export enum EnvProvisionType { + FIXED = 'fixed', + USER = 'user', + COMPUTED = 'computed', +} diff --git a/frontend/client/types.ts b/frontend/client/types.ts index 805909cbd..208584595 100644 --- a/frontend/client/types.ts +++ b/frontend/client/types.ts @@ -1,15 +1,16 @@ +import { AgentType } from '@/enums/Agent'; import { StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; -import { DeploymentStatus, Ledger, MiddlewareChain } from './enums'; +import { + EnvProvisionType, + MiddlewareChain, + MiddlewareDeploymentStatus, + MiddlewareLedger, +} from './enums'; export type ServiceHash = string; - -export type LedgerConfig = { - rpc: string; - type: Ledger; - chain: MiddlewareChain; -}; +export type ServiceConfigId = string; export type ServiceKeys = { address: Address; @@ -17,6 +18,11 @@ export type ServiceKeys = { ledger: MiddlewareChain; }; +export type LedgerConfig = { + rpc: string; + chain: MiddlewareChain; +}; + export type ChainData = { instances?: Address[]; token?: number; @@ -24,6 +30,7 @@ export type ChainData = { on_chain_state: number; staked: boolean; user_params: { + agent_id: number; cost_of_bond: number; fund_requirements: { agent: number; @@ -32,38 +39,54 @@ export type ChainData = { nft: string; staking_program_id: StakingProgramId; threshold: number; + use_mech_marketplace: true; use_staking: true; }; }; -export type Service = { +export type MiddlewareServiceResponse = { + service_config_id: string; // TODO: update with uuid once middleware integrated name: string; hash: string; + hash_history: { + [block: string]: string; + }; + home_chain: MiddlewareChain; keys: ServiceKeys[]; - readme?: string; + service_path?: string; + version: string; chain_configs: { - [chainId: number]: { + [middlewareChain: string]: { ledger_config: LedgerConfig; chain_data: ChainData; }; }; }; +export type EnvVariableAttributes = { + name: string; + description: string; + value: string; + provision_type: EnvProvisionType; +}; + export type ServiceTemplate = { + agentType: AgentType; name: string; hash: string; - image: string; description: string; + image: string; service_version: string; - home_chain_id: string; + home_chain: string; configurations: { [key: string]: ConfigurationTemplate }; + env_variables: { [key: string]: EnvVariableAttributes }; deploy?: boolean; }; export type ConfigurationTemplate = { - rpc?: string; // added on deployment staking_program_id?: StakingProgramId; // added on deployment nft: string; + rpc?: string; // added on deployment agent_id: number; threshold: number; use_staking: boolean; @@ -84,59 +107,22 @@ export type DeployedNodes = { }; export type Deployment = { - status: DeploymentStatus; + status: MiddlewareDeploymentStatus; nodes: DeployedNodes; }; -export type EmptyPayload = Record; - -export type EmptyResponse = Record; - -export type HttpResponse = { - error?: string; - data?: string; -}; - -export type ClientResponse = { - error?: string; - data?: ResponseType; -}; - -export type StopDeployment = { - delete: boolean /* Delete deployment*/; -}; - -export type UpdateServicePayload = { - old: ServiceHash; - new: ServiceTemplate; -}; - -export type DeleteServicesPayload = { - hashes: ServiceHash[]; -}; - -export type DeleteServicesResponse = { - hashes: ServiceHash[]; -}; - export type AppInfo = { account?: { key: Address; }; }; -export type WalletResponse = { +export type MiddlewareWalletResponse = { address: Address; safe_chains: MiddlewareChain[]; - ledger_type: Ledger; + ledger_type: MiddlewareLedger; safes: { [middlewareChainId in (typeof MiddlewareChain)[keyof typeof MiddlewareChain]]: Address; }; safe_nonce: number; }; - -export type Wallet = WalletResponse & { - ethBalance?: number; - olasBalance?: number; - usdcBalance?: number; -}; diff --git a/frontend/components/AddressLink.tsx b/frontend/components/AddressLink.tsx index 2f7398b4b..d26fa0235 100644 --- a/frontend/components/AddressLink.tsx +++ b/frontend/components/AddressLink.tsx @@ -1,6 +1,6 @@ import { MiddlewareChain } from '@/client'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { EXPLORER_URL } from '@/constants/urls'; +import { EXPLORER_URL_BY_MIDDLEWARE_CHAIN } from '@/constants/urls'; import { Address } from '@/types/Address'; import { truncateAddress } from '@/utils/truncate'; @@ -15,7 +15,7 @@ export const AddressLink = ({ return ( {truncateAddress(address)} diff --git a/frontend/components/Layout/TopBar.tsx b/frontend/components/Layout/TopBar.tsx index d552d243e..9428fc7f8 100644 --- a/frontend/components/Layout/TopBar.tsx +++ b/frontend/components/Layout/TopBar.tsx @@ -62,9 +62,7 @@ export const TopBar = () => { - - {`Pearl (Optimus) (alpha) ${envName ? `(${envName})` : ''}`.trim()} - + {`Pearl (alpha) ${envName ? `(${envName})` : ''}`.trim()} ); }; diff --git a/frontend/components/Layout/index.tsx b/frontend/components/Layout/index.tsx index 42610c1bf..22f3c7bb0 100644 --- a/frontend/components/Layout/index.tsx +++ b/frontend/components/Layout/index.tsx @@ -5,6 +5,7 @@ import styled, { css } from 'styled-components'; import { COLOR } from '@/constants/colors'; import { OnlineStatusContext } from '@/context/OnlineStatusProvider'; +import { useNotifyOnNewEpoch } from '@/hooks/useNotifyOnNewEpoch'; import { TopBar } from './TopBar'; @@ -39,11 +40,18 @@ const Body = styled.div` overflow-y: auto; `; +const useSystemLevelNotifications = () => { + useNotifyOnNewEpoch(); +}; + export const Layout = ({ children, }: PropsWithChildren & { vertical?: boolean }) => { const { isOnline } = useContext(OnlineStatusContext); + // all the app level notifications + useSystemLevelNotifications(); + useEffect(() => { let messageKey; if (!isOnline) { diff --git a/frontend/components/MainPage/MainHeader/FirstRunModal.tsx b/frontend/components/MainPage/MainHeader/FirstRunModal.tsx index ce75f568b..f52543f53 100644 --- a/frontend/components/MainPage/MainHeader/FirstRunModal.tsx +++ b/frontend/components/MainPage/MainHeader/FirstRunModal.tsx @@ -3,19 +3,16 @@ import Image from 'next/image'; import { FC } from 'react'; import { MODAL_WIDTH } from '@/constants/width'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; -import { getMinimumStakedAmountRequired } from '@/utils/service'; +import { TokenSymbol } from '@/enums/Token'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; type FirstRunModalProps = { open: boolean; onClose: () => void }; export const FirstRunModal: FC = ({ open, onClose }) => { - const { getServiceTemplates } = useServiceTemplates(); + const { activeStakingProgramMeta } = useStakingProgram(); - if (!open) return null; - - const minimumStakedAmountRequired = getMinimumStakedAmountRequired( - getServiceTemplates()[0], - ); + const minimumStakedAmountRequired = + activeStakingProgramMeta?.stakingRequirements?.[TokenSymbol.OLAS]; return ( ( - - Your agent earned rewards for this epoch, so decided to stop working - until the next epoch. - - } - > - - -); - -const AgentStartingButton = () => ( - - - - - {LOADING_MESSAGE} - - } - > - - -); - -const AgentStoppingButton = () => ( - -); - -const AgentRunningButton = () => { - const { showNotification } = useElectronApi(); - const { isEligibleForRewards } = useReward(); - const { service, setIsServicePollingPaused, setServiceStatus } = - useServices(); - - const handlePause = useCallback(async () => { - if (!service) return; - // Paused to stop overlapping service poll while waiting for response - setIsServicePollingPaused(true); - - // Optimistically update service status - setServiceStatus(DeploymentStatus.STOPPING); - try { - await ServicesService.stopDeployment(service.hash); - } catch (error) { - console.error(error); - showNotification?.('Error while stopping agent'); - } finally { - // Resume polling, will update to correct status regardless of success - setIsServicePollingPaused(false); - } - }, [service, setIsServicePollingPaused, setServiceStatus, showNotification]); - - return ( - - - - - {isEligibleForRewards ? ( - - Agent is idle  - - - ) : ( - - Agent is working - - )} - - - - ); -}; - -/** Button used to start / deploy the agent */ -const AgentNotRunningButton = () => { - const { wallets, masterSafeAddress } = useWallet(); - const { - service, - serviceStatus, - setServiceStatus, - setIsServicePollingPaused, - updateServicesState, - } = useServices(); - const { serviceTemplate } = useServiceTemplates(); - const { showNotification } = useElectronApi(); - const { - setIsPaused: setIsBalancePollingPaused, - masterSafeBalance: safeBalance, - isLowBalance, - totalOlasStakedBalance, - totalEthBalance, - updateBalances, - } = useBalance(); - const { storeState } = useStore(); - const { - isEligibleForStaking, - isAgentEvicted, - setIsPaused: setIsStakingContractInfoPollingPaused, - updateActiveStakingContractInfo, - } = useStakingContractInfo(); - const { activeStakingProgramId } = useStakingProgram(); - - // const minStakingDeposit = - // stakingContractInfoRecord?.[activeStakingProgram ?? defaultStakingProgram] - // ?.minStakingDeposit; - - const requiredOlas = getMinimumStakedAmountRequired( - serviceTemplate, - activeStakingProgramId ?? DEFAULT_STAKING_PROGRAM_ID, - ); - - const safeOlasBalance = safeBalance?.OLAS; - const safeOlasBalanceWithStaked = - safeOlasBalance === undefined || totalOlasStakedBalance === undefined - ? undefined - : safeOlasBalance + totalOlasStakedBalance; - - const handleStart = useCallback(async () => { - // Must have a wallet to start the agent - if (!wallets?.[0]) return; - - // Paused to stop overlapping service poll while wallet is created or service is built - setIsServicePollingPaused(true); - - // Paused to stop confusing balance transitions while starting the agent - setIsBalancePollingPaused(true); - - // Paused to stop overlapping staking contract info poll while starting the agent - setIsStakingContractInfoPollingPaused(true); - - // Mock "DEPLOYING" status (service polling will update this once resumed) - setServiceStatus(DeploymentStatus.DEPLOYING); - - // Get the active staking program id; default id if there's no agent yet - const stakingProgramId: StakingProgramId = - activeStakingProgramId ?? DEFAULT_STAKING_PROGRAM_ID; - - // Create master safe if it doesn't exist - try { - if (!masterSafeAddress) { - await WalletService.createSafe(MiddlewareChain.OPTIMISM); - } - } catch (error) { - console.error(error); - setServiceStatus(undefined); - showNotification?.('Error while creating safe'); - setIsStakingContractInfoPollingPaused(false); - setIsServicePollingPaused(false); - setIsBalancePollingPaused(false); - return; - } - - // Then create / deploy the service - try { - await ServicesService.createService({ - stakingProgramId, - serviceTemplate, - deploy: true, - useMechMarketplace: false, - // stakingProgramId === StakingProgramId.BetaMechMarketplace, - }); - } catch (error) { - console.error(error); - setServiceStatus(undefined); - showNotification?.('Error while deploying service'); - setIsServicePollingPaused(false); - setIsBalancePollingPaused(false); - setIsStakingContractInfoPollingPaused(false); - return; - } - - // Show success notification based on whether there was a service prior to starting - try { - showNotification?.(`Your agent is running!`); - } catch (error) { - console.error(error); - showNotification?.('Error while showing "running" notification'); - } - - // Can assume successful deployment - setServiceStatus(DeploymentStatus.DEPLOYED); - - // TODO: remove this workaround, middleware should respond when agent is staked & confirmed running after `createService` call - await delayInSeconds(5); - - // update provider states sequentially - // service id is required before activeStakingContractInfo & balances can be updated - try { - await updateServicesState(); // reload the available services - await updateActiveStakingContractInfo(); // reload active staking contract with new service - await updateBalances(); // reload the balances - } catch (error) { - console.error(error); - } finally { - // resume polling - setIsServicePollingPaused(false); - setIsStakingContractInfoPollingPaused(false); - setIsBalancePollingPaused(false); - } - }, [ - wallets, - setIsServicePollingPaused, - setIsBalancePollingPaused, - setIsStakingContractInfoPollingPaused, - setServiceStatus, - masterSafeAddress, - showNotification, - activeStakingProgramId, - serviceTemplate, - updateServicesState, - updateActiveStakingContractInfo, - updateBalances, - ]); - - const isDeployable = useMemo(() => { - // if the agent is NOT running and the balance is too low, - // user should not be able to start the agent - const isServiceInactive = - serviceStatus === DeploymentStatus.BUILT || - serviceStatus === DeploymentStatus.STOPPED; - if (isServiceInactive && isLowBalance) { - return false; - } - - if (serviceStatus === DeploymentStatus.DEPLOYED) return false; - if (serviceStatus === DeploymentStatus.DEPLOYING) return false; - if (serviceStatus === DeploymentStatus.STOPPING) return false; - - if (!requiredOlas) return false; - - // case where service exists & user has initial funded - if (service && storeState?.isInitialFunded) { - if (!safeOlasBalanceWithStaked) return false; - // at present agent will always require staked/bonded OLAS (or the ability to stake/bond) - return safeOlasBalanceWithStaked >= requiredOlas; - } - - // case if agent is evicted and user has met the staking criteria - if (isEligibleForStaking && isAgentEvicted) return true; - - const hasEnoughOlas = (safeOlasBalanceWithStaked ?? 0) >= requiredOlas; - const hasEnoughEth = (totalEthBalance ?? 0) > requiredGas; - - return hasEnoughOlas && hasEnoughEth; - }, [ - serviceStatus, - service, - storeState?.isInitialFunded, - isEligibleForStaking, - isAgentEvicted, - safeOlasBalanceWithStaked, - requiredOlas, - totalEthBalance, - isLowBalance, - ]); - - const buttonProps: ButtonProps = { - type: 'primary', - size: 'large', - disabled: !isDeployable, - onClick: isDeployable ? handleStart : undefined, - }; - - const buttonText = `Start agent ${service ? '' : '& stake'}`; - - return ; -}; - -export const AgentButton = () => { - const { service, serviceStatus, hasInitialLoaded } = useServices(); - const { isEligibleForStaking, isAgentEvicted } = useStakingContractInfo(); - - return useMemo(() => { - if (!hasInitialLoaded) { - return + ); + } + + const selectedServiceStatus = + selectedServiceStatusOverride ?? selectedService?.deploymentStatus; + + if (selectedServiceStatus === MiddlewareDeploymentStatus.STOPPING) { + return ; + } + + if (selectedServiceStatus === MiddlewareDeploymentStatus.DEPLOYING) { + return ; + } + + if (selectedServiceStatus === MiddlewareDeploymentStatus.DEPLOYED) { + return ; + } + + if (!isEligibleForStaking && isAgentEvicted) + return ; + + if ( + !selectedService || + selectedServiceStatus === MiddlewareDeploymentStatus.STOPPED || + selectedServiceStatus === MiddlewareDeploymentStatus.CREATED || + selectedServiceStatus === MiddlewareDeploymentStatus.BUILT || + selectedServiceStatus === MiddlewareDeploymentStatus.DELETED + ) { + return ; + } + + return ; + }, [ + isServicesLoaded, + isSelectedStakingContractDetailsLoaded, + selectedServiceStatusOverride, + selectedService, + isEligibleForStaking, + isAgentEvicted, + ]); + + return ( + {button} + ); +}; diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx new file mode 100644 index 000000000..c21469ff2 --- /dev/null +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -0,0 +1,306 @@ +import { Button, ButtonProps } from 'antd'; +import { isNil, sum } from 'lodash'; +import { useCallback, useMemo } from 'react'; + +import { MiddlewareDeploymentStatus } from '@/client'; +import { MechType } from '@/config/mechs'; +import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; +import { SERVICE_TEMPLATES } from '@/constants/serviceTemplates'; +import { LOW_MASTER_SAFE_BALANCE } from '@/constants/thresholds'; +import { TokenSymbol } from '@/enums/Token'; +import { + useBalanceContext, + useMasterBalances, + useServiceBalances, +} from '@/hooks/useBalanceContext'; +import { useElectronApi } from '@/hooks/useElectronApi'; +import { useService } from '@/hooks/useService'; +import { useServices } from '@/hooks/useServices'; +import { + useActiveStakingContractInfo, + useStakingContractContext, +} from '@/hooks/useStakingContractDetails'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; +import { useStore } from '@/hooks/useStore'; +import { useMasterWalletContext } from '@/hooks/useWallet'; +import { ServicesService } from '@/service/Services'; +import { WalletService } from '@/service/Wallet'; +import { delayInSeconds } from '@/utils/delay'; + +/** Button used to start / deploy the agent */ +export const AgentNotRunningButton = () => { + const { storeState } = useStore(); + const { showNotification } = useElectronApi(); + + const { masterWallets, masterSafes } = useMasterWalletContext(); + const { + selectedService, + setPaused: setIsServicePollingPaused, + refetch: updateServicesState, + isLoading: isServicesLoading, + selectedAgentConfig, + selectedAgentType, + overrideSelectedServiceStatus, + } = useServices(); + + const { service, isServiceRunning } = useService( + selectedService?.service_config_id, + ); + + const { + setIsPaused: setIsBalancePollingPaused, + totalStakedOlasBalance, + updateBalances, + } = useBalanceContext(); + + const { serviceStakedBalances } = useServiceBalances( + selectedService?.service_config_id, + ); + + const serviceStakedOlasBalanceOnHomeChain = serviceStakedBalances?.find( + (stakedBalance) => + stakedBalance.evmChainId === selectedAgentConfig.evmHomeChainId, + ); + + const serviceTotalStakedOlas = sum([ + serviceStakedOlasBalanceOnHomeChain?.olasBondBalance, + serviceStakedOlasBalanceOnHomeChain?.olasDepositBalance, + ]); + + const { masterSafeBalances } = useMasterBalances(); + + const masterSafeNativeGasBalance = masterSafeBalances?.find( + (walletBalanceResult) => + walletBalanceResult.isNative && + walletBalanceResult.evmChainId === selectedAgentConfig.evmHomeChainId, + )?.balance; + + const { + isAllStakingContractDetailsRecordLoaded, + setIsPaused: setIsStakingContractInfoPollingPaused, + refetchSelectedStakingContractDetails: refetchActiveStakingContractDetails, + } = useStakingContractContext(); + + const { selectedStakingProgramId } = useStakingProgram(); + + const { isEligibleForStaking, isAgentEvicted, isServiceStaked } = + useActiveStakingContractInfo(); + + const { hasEnoughServiceSlots } = useActiveStakingContractInfo(); + + const requiredStakedOlas = + selectedStakingProgramId && + STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][ + selectedStakingProgramId + ]?.stakingRequirements[TokenSymbol.OLAS]; + + const serviceSafeOlasWithStaked = sum([totalStakedOlasBalance]); + + const isDeployable = useMemo(() => { + if (isServicesLoading) return false; + if (isServiceRunning) return false; + + if (!isAllStakingContractDetailsRecordLoaded) return false; + + if (isNil(requiredStakedOlas)) return false; + + if ( + !isNil(hasEnoughServiceSlots) && + !hasEnoughServiceSlots && + !isServiceStaked + ) + return false; + + const masterSafeOlasBalance = masterSafeBalances?.find( + (walletBalanceResult) => + walletBalanceResult.symbol === TokenSymbol.OLAS && + walletBalanceResult.evmChainId === selectedAgentConfig.evmHomeChainId, + )?.balance; + + if (service && storeState?.isInitialFunded && isServiceStaked) { + return (serviceTotalStakedOlas ?? 0) >= requiredStakedOlas; + } + + if (isEligibleForStaking && isAgentEvicted) return true; + + if (isServiceStaked) { + const hasEnoughOlas = + (serviceSafeOlasWithStaked ?? 0) >= requiredStakedOlas; + const hasEnoughNativeGas = + (masterSafeNativeGasBalance ?? 0) > LOW_MASTER_SAFE_BALANCE; + return hasEnoughOlas && hasEnoughNativeGas; + } + + const hasEnoughForInitialDeployment = + (masterSafeOlasBalance ?? 0) >= requiredStakedOlas && + (masterSafeNativeGasBalance ?? 0) >= LOW_MASTER_SAFE_BALANCE; + + return hasEnoughForInitialDeployment; + }, [ + isServicesLoading, + isServiceRunning, + isAllStakingContractDetailsRecordLoaded, + requiredStakedOlas, + hasEnoughServiceSlots, + isServiceStaked, + masterSafeBalances, + service, + storeState?.isInitialFunded, + isEligibleForStaking, + isAgentEvicted, + masterSafeNativeGasBalance, + selectedAgentConfig.evmHomeChainId, + serviceTotalStakedOlas, + serviceSafeOlasWithStaked, + ]); + + const pauseAllPolling = useCallback(() => { + setIsServicePollingPaused(true); + setIsBalancePollingPaused(true); + setIsStakingContractInfoPollingPaused(true); + }, [ + setIsServicePollingPaused, + setIsBalancePollingPaused, + setIsStakingContractInfoPollingPaused, + ]); + + const resumeAllPolling = useCallback(() => { + setIsServicePollingPaused(false); + setIsBalancePollingPaused(false); + setIsStakingContractInfoPollingPaused(false); + }, [ + setIsServicePollingPaused, + setIsBalancePollingPaused, + setIsStakingContractInfoPollingPaused, + ]); + + const createSafeIfNeeded = useCallback(async () => { + if ( + !masterSafes?.find( + (masterSafe) => + masterSafe.evmChainId === selectedAgentConfig.evmHomeChainId, + ) + ) { + await WalletService.createSafe(selectedAgentConfig.middlewareHomeChainId); + } + }, [ + masterSafes, + selectedAgentConfig.evmHomeChainId, + selectedAgentConfig.middlewareHomeChainId, + ]); + + /** + * @note only create a service if `service` does not exist + */ + const deployAndStartService = useCallback(async () => { + if (!selectedStakingProgramId) return; + + const serviceTemplate = SERVICE_TEMPLATES.find( + (template) => template.agentType === selectedAgentType, + ); + + if (!serviceTemplate) { + throw new Error(`Service template not found for ${selectedAgentType}`); + } + + // Create a new service if it does not exist + let middlewareServiceResponse; + if (!service) { + try { + middlewareServiceResponse = await ServicesService.createService({ + stakingProgramId: selectedStakingProgramId, + serviceTemplate, + deploy: true, + useMechMarketplace: + STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][ // TODO: support multi-agent, during optimus week + selectedStakingProgramId + ].mechType === MechType.Marketplace, + }); + } catch (error) { + console.error('Error while creating the service:', error); + showNotification?.('Failed to create service.'); + throw new Error('Failed to create service'); + } + } + + if (isNil(service) && isNil(middlewareServiceResponse)) + throw new Error('Service not found'); + + // Start the service + try { + const serviceToStart = service ?? middlewareServiceResponse; + await ServicesService.startService(serviceToStart!.service_config_id); + } catch (error) { + console.error('Error while starting the service:', error); + showNotification?.('Failed to start service.'); + throw error; + } + }, [ + selectedAgentConfig.evmHomeChainId, + selectedAgentType, + selectedStakingProgramId, + service, + showNotification, + ]); + + const updateStatesSequentially = useCallback(async () => { + await updateServicesState?.(); + await refetchActiveStakingContractDetails(); + await updateBalances(); + }, [ + updateServicesState, + refetchActiveStakingContractDetails, + updateBalances, + ]); + + const handleStart = useCallback(async () => { + if (!masterWallets?.[0]) return; + + pauseAllPolling(); + overrideSelectedServiceStatus(MiddlewareDeploymentStatus.DEPLOYING); + + try { + await createSafeIfNeeded(); + await deployAndStartService(); + } catch (error) { + console.error('Error while starting the agent:', error); + showNotification?.('An error occurred. Please try again.'); + overrideSelectedServiceStatus(null); // wipe status + throw error; + } + + try { + await updateStatesSequentially(); + } catch (error) { + console.error('Error while updating states sequentially:', error); + showNotification?.('Failed to update app state.'); + } + + overrideSelectedServiceStatus(MiddlewareDeploymentStatus.DEPLOYED); + + resumeAllPolling(); + await delayInSeconds(5); + + overrideSelectedServiceStatus(null); + }, [ + masterWallets, + pauseAllPolling, + resumeAllPolling, + overrideSelectedServiceStatus, + createSafeIfNeeded, + deployAndStartService, + showNotification, + updateStatesSequentially, + ]); + + const buttonProps: ButtonProps = { + type: 'primary', + size: 'large', + disabled: !isDeployable, + onClick: isDeployable ? handleStart : undefined, + }; + + const buttonText = `Start agent ${service ? '' : '& stake'}`; + + return ; +}; diff --git a/frontend/components/MainPage/header/AgentButton/AgentRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentRunningButton.tsx new file mode 100644 index 000000000..31e11823e --- /dev/null +++ b/frontend/components/MainPage/header/AgentButton/AgentRunningButton.tsx @@ -0,0 +1,89 @@ +import { InfoCircleOutlined } from '@ant-design/icons'; +import { Button, Flex, Tooltip, Typography } from 'antd'; +import { useCallback } from 'react'; + +import { MiddlewareDeploymentStatus } from '@/client'; +import { useElectronApi } from '@/hooks/useElectronApi'; +import { useReward } from '@/hooks/useReward'; +import { useService } from '@/hooks/useService'; +import { useServices } from '@/hooks/useServices'; +import { ServicesService } from '@/service/Services'; + +import { LastTransaction } from '../LastTransaction'; + +const { Paragraph, Text } = Typography; + +const IdleTooltip = () => ( + + Your agent earned rewards for this epoch, so decided to stop working + until the next epoch. + + } + > + + +); + +export const AgentRunningButton = () => { + const { showNotification } = useElectronApi(); + const { isEligibleForRewards } = useReward(); + + const { + selectedService, + isFetched: isLoaded, + setPaused, + overrideSelectedServiceStatus, + } = useServices(); + + const serviceConfigId = + isLoaded && selectedService?.service_config_id + ? selectedService.service_config_id + : ''; + const { service } = useService(serviceConfigId); + + const handlePause = useCallback(async () => { + if (!service) return; + // Paused to stop overlapping service poll while waiting for response + // setPaused(true); + + // Optimistically update service status + overrideSelectedServiceStatus(MiddlewareDeploymentStatus.STOPPING); + try { + await ServicesService.stopDeployment(service.service_config_id); + } catch (error) { + console.error(error); + showNotification?.('Error while stopping agent'); + } finally { + // Resume polling, will update to correct status regardless of success + setPaused(false); + overrideSelectedServiceStatus(null); // remove override + } + }, [overrideSelectedServiceStatus, service, setPaused, showNotification]); + + return ( + + + + + {isEligibleForRewards ? ( + + Agent is idle  + + + ) : ( + + Agent is working + + )} + + + + + ); +}; diff --git a/frontend/components/MainPage/header/AgentButton/AgentStartingButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentStartingButton.tsx new file mode 100644 index 000000000..6503f6cf6 --- /dev/null +++ b/frontend/components/MainPage/header/AgentButton/AgentStartingButton.tsx @@ -0,0 +1,27 @@ +import { InfoCircleOutlined } from '@ant-design/icons'; +import { Button, Flex, Popover, Typography } from 'antd'; + +import { COLOR } from '@/constants/colors'; + +const LOADING_MESSAGE = + "Starting the agent may take a while, so feel free to minimize the app. We'll notify you once it's running. Please, don't quit the app."; + +export const AgentStartingButton = () => ( + + + + + {LOADING_MESSAGE} + + } + > + + +); diff --git a/frontend/components/MainPage/header/AgentButton/AgentStoppingButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentStoppingButton.tsx new file mode 100644 index 000000000..8fdea7f36 --- /dev/null +++ b/frontend/components/MainPage/header/AgentButton/AgentStoppingButton.tsx @@ -0,0 +1,7 @@ +import { Button } from 'antd'; + +export const AgentStoppingButton = () => ( + +); diff --git a/frontend/components/MainPage/header/AgentHead.tsx b/frontend/components/MainPage/header/AgentHead.tsx index 94133f4f7..bccfc4817 100644 --- a/frontend/components/MainPage/header/AgentHead.tsx +++ b/frontend/components/MainPage/header/AgentHead.tsx @@ -1,7 +1,7 @@ import { Badge } from 'antd'; import Image from 'next/image'; -import { DeploymentStatus } from '@/client'; +import { MiddlewareDeploymentStatus } from '@/client'; import { useReward } from '@/hooks/useReward'; import { useServices } from '@/hooks/useServices'; @@ -32,17 +32,18 @@ const IdleAgentHead = () => ( ); export const AgentHead = () => { - const { serviceStatus } = useServices(); + const { selectedService } = useServices(); const { isEligibleForRewards } = useReward(); + const status = selectedService?.deploymentStatus; if ( - serviceStatus === DeploymentStatus.DEPLOYING || - serviceStatus === DeploymentStatus.STOPPING + status === MiddlewareDeploymentStatus.DEPLOYING || + status === MiddlewareDeploymentStatus.STOPPING ) { return ; } - if (serviceStatus === DeploymentStatus.DEPLOYED) { + if (status === MiddlewareDeploymentStatus.DEPLOYED) { // If the agent is eligible for rewards, agent is idle return isEligibleForRewards ? : ; } diff --git a/frontend/components/MainPage/header/CannotStartAgentPopover.tsx b/frontend/components/MainPage/header/CannotStartAgentPopover.tsx index db882f9c9..a4ecfe49b 100644 --- a/frontend/components/MainPage/header/CannotStartAgentPopover.tsx +++ b/frontend/components/MainPage/header/CannotStartAgentPopover.tsx @@ -4,7 +4,12 @@ import { Flex, Popover, PopoverProps, Typography } from 'antd'; import { COLOR } from '@/constants/colors'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { SUPPORT_URL } from '@/constants/urls'; -import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; +import { + useActiveStakingContractInfo, + useStakingContractContext, + useStakingContractDetails, +} from '@/hooks/useStakingContractDetails'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; import { formatToShortDateTime } from '@/utils/time'; const { Paragraph, Text } = Typography; @@ -45,7 +50,12 @@ export const CannotStartAgentDueToUnexpectedError = () => ( const evictedDescription = "You didn't run your agent enough and it missed its targets multiple times. You can run the agent again when the eviction period ends."; const AgentEvictedPopover = () => { - const { evictionExpiresAt } = useStakingContractInfo(); + const { isAllStakingContractDetailsRecordLoaded } = + useStakingContractContext(); + + const { evictionExpiresAt } = useActiveStakingContractInfo(); + + if (!isAllStakingContractDetailsRecordLoaded) return null; return ( ( ); export const CannotStartAgentPopover = () => { - const { - isEligibleForStaking, - hasEnoughServiceSlots, - isRewardsAvailable, - isAgentEvicted, - } = useStakingContractInfo(); + const { isAllStakingContractDetailsRecordLoaded } = + useStakingContractContext(); + + const { activeStakingProgramId } = useStakingProgram(); + + const { isAgentEvicted, isEligibleForStaking } = + useActiveStakingContractInfo(); + + const { hasEnoughServiceSlots, isRewardsAvailable } = + useStakingContractDetails(activeStakingProgramId); + if (!isAllStakingContractDetailsRecordLoaded) return null; if (isEligibleForStaking) return null; if (!hasEnoughServiceSlots) return ; if (!isRewardsAvailable) return ; diff --git a/frontend/components/MainPage/header/LastTransaction.tsx b/frontend/components/MainPage/header/LastTransaction.tsx index 9a8a526c2..bafe15bb5 100644 --- a/frontend/components/MainPage/header/LastTransaction.tsx +++ b/frontend/components/MainPage/header/LastTransaction.tsx @@ -4,11 +4,14 @@ import styled from 'styled-components'; import { useInterval } from 'usehooks-ts'; import { MiddlewareChain } from '@/client'; -import { EXPLORER_URL } from '@/constants/urls'; -import { useAddress } from '@/hooks/useAddress'; +import { ONE_MINUTE_INTERVAL } from '@/constants/intervals'; +import { EXPLORER_URL_BY_MIDDLEWARE_CHAIN } from '@/constants/urls'; import { usePageState } from '@/hooks/usePageState'; +import { useService } from '@/hooks/useService'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; import { getLatestTransaction } from '@/service/Ethers'; import { TransactionInfo } from '@/types/TransactionInfo'; +import { Optional } from '@/types/Util'; import { getTimeAgo } from '@/utils/time'; const { Text } = Typography; @@ -22,32 +25,38 @@ const Loader = styled(Skeleton.Input)` } `; -const POLLING_INTERVAL = 60 * 1000; // 1 minute +type LastTransactionProps = { serviceConfigId: Optional }; /** * Displays the last transaction time and link to the transaction on explorer * by agent safe. */ -export const LastTransaction = () => { +export const LastTransaction = ({ serviceConfigId }: LastTransactionProps) => { const { isPageLoadedAndOneMinutePassed } = usePageState(); - const { multisigAddress } = useAddress(); + const { activeStakingProgramMeta } = useStakingProgram(); + const { serviceSafes } = useService(serviceConfigId); + + const serviceSafe = serviceSafes?.[0]; + + const chainId = activeStakingProgramMeta?.chainId; const [isFetching, setIsFetching] = useState(true); const [transaction, setTransaction] = useState(null); const fetchTransaction = useCallback(async () => { - if (!multisigAddress) return; + if (!serviceSafe?.address) return; + if (!chainId) return; - getLatestTransaction(multisigAddress) + getLatestTransaction(serviceSafe.address, chainId) .then((tx) => setTransaction(tx)) .catch((error) => console.error('Failed to get latest transaction', error), ) .finally(() => setIsFetching(false)); - }, [multisigAddress]); + }, [serviceSafe, chainId]); // Poll for the latest transaction - useInterval(() => fetchTransaction(), POLLING_INTERVAL); + useInterval(() => fetchTransaction(), ONE_MINUTE_INTERVAL); // Fetch the latest transaction on mount useEffect(() => { @@ -77,7 +86,7 @@ export const LastTransaction = () => { className="text-xs pointer hover-underline" onClick={() => window.open( - `${EXPLORER_URL[MiddlewareChain.OPTIMISM]}/tx/${transaction.hash}`, + `${EXPLORER_URL_BY_MIDDLEWARE_CHAIN[MiddlewareChain.GNOSIS]}/tx/${transaction.hash}`, ) } > diff --git a/frontend/components/MainPage/header/constants.ts b/frontend/components/MainPage/header/constants.ts deleted file mode 100644 index af0649631..000000000 --- a/frontend/components/MainPage/header/constants.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { formatUnits } from 'ethers/lib/utils'; - -import { CHAINS } from '@/constants/chains'; -import { SERVICE_TEMPLATES } from '@/constants/serviceTemplates'; - -export const requiredGas = Number( - formatUnits( - `${SERVICE_TEMPLATES[0].configurations[CHAINS.OPTIMISM.chainId].monthly_gas_estimate}`, - 18, - ), -); diff --git a/frontend/components/MainPage/header/index.tsx b/frontend/components/MainPage/header/index.tsx index d09f681e7..9ce1e696d 100644 --- a/frontend/components/MainPage/header/index.tsx +++ b/frontend/components/MainPage/header/index.tsx @@ -1,31 +1,33 @@ import { Flex } from 'antd'; import { useCallback, useEffect, useState } from 'react'; -import { DeploymentStatus } from '@/client'; -import { useBalance } from '@/hooks/useBalance'; +import { MiddlewareDeploymentStatus } from '@/client'; +import { useBalanceContext } from '@/hooks/useBalanceContext'; import { useElectronApi } from '@/hooks/useElectronApi'; +import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; import { FirstRunModal } from '../modals/FirstRunModal'; -import { AgentButton } from './AgentButton'; +import { AgentButton } from './AgentButton/AgentButton'; import { AgentHead } from './AgentHead'; const useSetupTrayIcon = () => { - const { isLowBalance } = useBalance(); - const { serviceStatus } = useServices(); + const { isLowBalance } = useBalanceContext(); + const { selectedService } = useServices(); + const { deploymentStatus } = useService(selectedService?.service_config_id); const { setTrayIcon } = useElectronApi(); useEffect(() => { if (isLowBalance) { setTrayIcon?.('low-gas'); - } else if (serviceStatus === DeploymentStatus.DEPLOYED) { + } else if (deploymentStatus === MiddlewareDeploymentStatus.DEPLOYED) { setTrayIcon?.('running'); - } else if (serviceStatus === DeploymentStatus.STOPPED) { + } else if (deploymentStatus === MiddlewareDeploymentStatus.STOPPED) { setTrayIcon?.('paused'); - } else if (serviceStatus === DeploymentStatus.BUILT) { + } else if (deploymentStatus === MiddlewareDeploymentStatus.BUILT) { setTrayIcon?.('logged-out'); } - }, [isLowBalance, serviceStatus, setTrayIcon]); + }, [isLowBalance, deploymentStatus, setTrayIcon]); return null; }; @@ -35,6 +37,7 @@ export const MainHeader = () => { const handleModalClose = useCallback(() => setIsFirstRunModalOpen(false), []); useSetupTrayIcon(); + // TODO: support loading state return ( diff --git a/frontend/components/MainPage/index.tsx b/frontend/components/MainPage/index.tsx index b4d84a5f8..a0917bc50 100644 --- a/frontend/components/MainPage/index.tsx +++ b/frontend/components/MainPage/index.tsx @@ -1,43 +1,68 @@ import { QuestionCircleOutlined, SettingOutlined } from '@ant-design/icons'; import { Button, Card, Flex } from 'antd'; -import { useEffect } from 'react'; -import { Pages } from '@/enums/PageState'; +import { Pages } from '@/enums/Pages'; +import { StakingProgramId } from '@/enums/StakingProgram'; // import { StakingProgramId } from '@/enums/StakingProgram'; -import { useBalance } from '@/hooks/useBalance'; // import { useMasterSafe } from '@/hooks/useMasterSafe'; import { usePageState } from '@/hooks/usePageState'; -import { useServices } from '@/hooks/useServices'; +import { + useStakingContractContext, + useStakingContractDetails, +} from '@/hooks/useStakingContractDetails'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; -// import { useStakingProgram } from '@/hooks/useStakingProgram'; +// import { useMasterWalletContext } from '@/hooks/useWallet'; import { MainHeader } from './header'; import { AddFundsSection } from './sections/AddFundsSection'; -// import { MainNeedsFunds } from './sections/NeedsFundsSection'; +import { AlertSections } from './sections/AlertSections'; +import { GasBalanceSection } from './sections/GasBalanceSection'; +import { KeepAgentRunningSection } from './sections/KeepAgentRunningSection'; +import { MainNeedsFunds } from './sections/NeedsFundsSection'; import { MainOlasBalance } from './sections/OlasBalanceSection'; -// import { AlertSections } from './sections/AlertSections'; -// import { GasBalanceSection } from './sections/GasBalanceSection'; -// import { KeepAgentRunningSection } from './sections/KeepAgentRunningSection'; import { RewardsSection } from './sections/RewardsSection'; -// import { StakingContractUpdate } from './sections/StakingContractUpdate'; +import { StakingContractSection } from './sections/StakingContractUpdate'; export const Main = () => { const { goto } = usePageState(); - // const { backupSafeAddress } = useMasterSafe(); - const { updateServicesState } = useServices(); - const { updateBalances, isLoaded, setIsLoaded } = useBalance(); - // const { activeStakingProgramId: currentStakingProgram } = useStakingProgram(); + // const { backupSafeAddress } = useMasterWalletContext(); + // const { refetch: updateServicesState } = useServices(); + // const { + // updateBalances, + // isLoaded: isBalanceLoaded, + // setIsLoaded: setIsBalanceLoaded, + // } = useBalanceContext(); + const { activeStakingProgramId } = useStakingProgram(); - useEffect(() => { - if (!isLoaded) { - setIsLoaded(true); - updateServicesState().then(() => updateBalances()); - } - }, [isLoaded, setIsLoaded, updateBalances, updateServicesState]); + // TODO: reintroduce later, non critical + const { isAllStakingContractDetailsRecordLoaded } = + useStakingContractContext(); - // const hideMainOlasBalanceTopBorder = [ - // !backupSafeAddress, - // currentStakingProgram === StakingProgramId.Alpha, - // ].some((condition) => !!condition); + const { hasEnoughServiceSlots } = useStakingContractDetails( + activeStakingProgramId, + ); + + // TODO: reintroduce later, non critical + + // useEffect(() => { + // if (!isBalanceLoaded) { + // updateServicesState?.().then(() => updateBalances()); + // setIsBalanceLoaded(true); + // } + // }, [ + // isBalanceLoaded, + // setIsBalanceLoaded, + // updateBalances, + // updateServicesState, + // ]); + + // TODO: reintroduce later, non critical + + const hideMainOlasBalanceTopBorder = [ + // !backupSafeAddress, // TODO: update this condition to check backup safe relative to selectedService + activeStakingProgramId === StakingProgramId.PearlAlpha, + isAllStakingContractDetailsRecordLoaded && !hasEnoughServiceSlots, + ].some((condition) => !!condition); return ( { style={{ borderTopColor: 'transparent' }} > - {/* */} - - {/* */} + + - {/* */} - {/* */} - {/* */} - {/* */} + + + + diff --git a/frontend/components/MainPage/modals/FirstRunModal.tsx b/frontend/components/MainPage/modals/FirstRunModal.tsx index 0c57b3b03..611ecdb14 100644 --- a/frontend/components/MainPage/modals/FirstRunModal.tsx +++ b/frontend/components/MainPage/modals/FirstRunModal.tsx @@ -2,22 +2,28 @@ import { Button, Flex, Modal, Typography } from 'antd'; import Image from 'next/image'; import { FC } from 'react'; +import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; import { MODAL_WIDTH } from '@/constants/width'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; -import { getMinimumStakedAmountRequired } from '@/utils/service'; +import { TokenSymbol } from '@/enums/Token'; +import { useServices } from '@/hooks/useServices'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; const { Title, Paragraph } = Typography; type FirstRunModalProps = { open: boolean; onClose: () => void }; export const FirstRunModal: FC = ({ open, onClose }) => { - const { getServiceTemplates } = useServiceTemplates(); + const { selectedAgentConfig } = useServices(); + const { evmHomeChainId: homeChainId } = selectedAgentConfig; + const { activeStakingProgramId } = useStakingProgram(); if (!open) return null; + if (!activeStakingProgramId) return null; - const minimumStakedAmountRequired = getMinimumStakedAmountRequired( - getServiceTemplates()[0], - ); + const requiredStakedOlas = + STAKING_PROGRAMS[homeChainId][activeStakingProgramId]?.stakingRequirements[ + TokenSymbol.OLAS + ]; return ( = ({ open, onClose }) => { /> - {`Your agent is running and you've staked ${minimumStakedAmountRequired} OLAS!`} + {`Your agent is running and you've staked ${requiredStakedOlas} OLAS!`} Your agent is working towards earning rewards. diff --git a/frontend/components/MainPage/modals/MigrationModal.tsx b/frontend/components/MainPage/modals/MigrationModal.tsx index ce614e9fb..adda5f200 100644 --- a/frontend/components/MainPage/modals/MigrationModal.tsx +++ b/frontend/components/MainPage/modals/MigrationModal.tsx @@ -1,28 +1,25 @@ import { Button, Flex, Modal, Typography } from 'antd'; import Image from 'next/image'; -import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { MODAL_WIDTH } from '@/constants/width'; import { useStakingProgram } from '@/hooks/useStakingProgram'; +const { Title, Text, Link } = Typography; + +type MigrationModalProps = { open: boolean; onClose: () => void }; export const MigrationSuccessModal = ({ open, onClose, -}: { - open: boolean; - onClose: () => void; -}) => { - const { activeStakingProgramId } = useStakingProgram(); +}: MigrationModalProps) => { + const { activeStakingProgramMeta } = useStakingProgram(); // Close modal if no active staking program, migration doesn't apply to non-stakers - if (!activeStakingProgramId) { + if (!activeStakingProgramMeta) { onClose(); return null; } - const activeStakingProgramMeta = STAKING_PROGRAM_META[activeStakingProgramId]; - return ( - - You switched staking contract succesfully! - - + You switched staking contract successfully! + Your agent is now staked on {activeStakingProgramMeta.name}. - + {/* TODO: Add relevant block explorer domain */} - + View full contract details {UNICODE_SYMBOLS.EXTERNAL_LINK} - + ); diff --git a/frontend/components/MainPage/sections/AddFundsSection.tsx b/frontend/components/MainPage/sections/AddFundsSection.tsx index b8e3f29fc..eab85c722 100644 --- a/frontend/components/MainPage/sections/AddFundsSection.tsx +++ b/frontend/components/MainPage/sections/AddFundsSection.tsx @@ -11,23 +11,16 @@ import { Tooltip, Typography, } from 'antd'; -import { BigNumber, Contract, ethers } from 'ethers'; import Link from 'next/link'; import { forwardRef, useCallback, useMemo, useRef, useState } from 'react'; import styled from 'styled-components'; -import { useInterval } from 'usehooks-ts'; -import { ERC20_BALANCEOF_FRAGMENT } from '@/abis/erc20'; -import { CHAINS } from '@/constants/chains'; -import { - baseProvider, - ethereumProvider, - optimismProvider, -} from '@/constants/providers'; -import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { TOKENS } from '@/constants/tokens'; -import { COW_SWAP_GNOSIS_XDAI_OLAS_URL } from '@/constants/urls'; -import { useWallet } from '@/hooks/useWallet'; +import { CustomAlert } from '@/components/Alert'; +import { CHAIN_CONFIG } from '@/config/chains'; +import { NA, UNICODE_SYMBOLS } from '@/constants/symbols'; +import { SWAP_URL_BY_EVM_CHAIN } from '@/constants/urls'; +import { useServices } from '@/hooks/useServices'; +import { useMasterWalletContext } from '@/hooks/useWallet'; import { copyToClipboard } from '@/utils/copyToClipboard'; import { delayInSeconds } from '@/utils/delay'; import { truncateAddress } from '@/utils/truncate'; @@ -42,16 +35,30 @@ const CustomizedCardSection = styled(CardSection)<{ border?: boolean }>` } `; +const AddFundsGetTokensSection = () => { + const { selectedAgentConfig } = useServices(); + const { evmHomeChainId: homeChainId } = selectedAgentConfig; + + return ( + + + Get OLAS + {CHAIN_CONFIG[homeChainId].nativeToken.symbol} on{' '} + {CHAIN_CONFIG[homeChainId].name} {UNICODE_SYMBOLS.EXTERNAL_LINK} + + + ); +}; + export const AddFundsSection = () => { const fundSectionRef = useRef(null); const [isAddFundsVisible, setIsAddFundsVisible] = useState(false); const addFunds = useCallback(async () => { setIsAddFundsVisible(true); - await delayInSeconds(0.1); fundSectionRef?.current?.scrollIntoView({ behavior: 'smooth' }); }, []); + const closeAddFunds = useCallback(() => setIsAddFundsVisible(false), []); return ( @@ -82,21 +89,20 @@ export const AddFundsSection = () => { }; export const OpenAddFundsSection = forwardRef((_, ref) => { - const { masterSafeAddress } = useWallet(); + const { selectedAgentConfig } = useServices(); + const { evmHomeChainId: homeChainId } = selectedAgentConfig; + const { masterSafes } = useMasterWalletContext(); + const masterSafeAddress = useMemo( + () => + masterSafes?.find((wallet) => wallet.evmChainId === homeChainId)?.address, + [homeChainId, masterSafes], + ); const truncatedFundingAddress: string | undefined = useMemo( () => masterSafeAddress && truncateAddress(masterSafeAddress, 4), [masterSafeAddress], ); - const [ethEth, setethEth] = useState(0); - const [ethUsdc, setethUsdc] = useState(0); - - const [opEth, setopEth] = useState(0); - const [opOlas, setopOlas] = useState(0); - - const [baseEth, setbaseEth] = useState(0); - const handleCopyAddress = useCallback( () => masterSafeAddress && @@ -106,95 +112,43 @@ export const OpenAddFundsSection = forwardRef((_, ref) => { [masterSafeAddress], ); - useInterval(async () => { - if (!masterSafeAddress) return; - await Promise.allSettled([ - ethereumProvider - .getBalance(masterSafeAddress) - .then(ethers.utils.formatEther) - .then(Number) - .then(setethEth), - //USDC balance - new Contract( - TOKENS[CHAINS.ETHEREUM.chainId]['USDC'].address, - ERC20_BALANCEOF_FRAGMENT, - ethereumProvider, - ) - .balanceOf(masterSafeAddress) - .then((wei: BigNumber) => ethers.utils.formatUnits(wei, 6)) - .then(Number) - .then(setethUsdc), - optimismProvider - .getBalance(masterSafeAddress) - .then(ethers.utils.formatEther) - .then(Number) - .then(setopEth), - new Contract( - TOKENS[CHAINS.OPTIMISM.chainId]['OLAS'].address, - ERC20_BALANCEOF_FRAGMENT, - optimismProvider, - ) - .balanceOf(masterSafeAddress) - .then(ethers.utils.formatEther) - .then(Number) - .then(setopOlas), - baseProvider - .getBalance(masterSafeAddress) - .then(ethers.utils.formatEther) - .then(Number) - .then(setbaseEth), - ]); - }, 2000); - return ( - {/* */} - + -
-        {`
--- Master Safe Balances --
-Ethereum
-ETH ${ethEth}
-USDC ${ethUsdc}
-
-Optimism 
-ETH ${opEth} 
-OLAS ${opOlas}
-
-Base
-ETH ${baseEth}
-`}
-      
); }); OpenAddFundsSection.displayName = 'OpenAddFundsSection'; -// const AddFundsWarningAlertSection = () => ( -// -// -// -// Only send funds on {CHAINS.OPTIMISM.name}! -// -// -// You will lose any assets you send on other chains. -// -// -// } -// /> -// -// ); +const AddFundsWarningAlertSection = () => { + const { selectedAgentConfig } = useServices(); + const { evmHomeChainId: homeChainId } = selectedAgentConfig; + return ( + + + + Only send funds on {CHAIN_CONFIG[homeChainId].name} Chain! + + + You will lose any assets you send on other chains. + + + } + /> + + ); +}; const AddFundsAddressSection = ({ fundingAddress, @@ -213,7 +167,7 @@ const AddFundsAddressSection = ({ } > - {truncatedFundingAddress ?? '--'} + {truncatedFundingAddress ?? NA}
); }, [ - goto, isActiveStakingProgramLoaded, - stakingContractName, - canUpdateStakingContract, + isAllStakingContractDetailsRecordLoaded, + isServiceTransitioning, + selectedStakingProgramMeta?.name, + goto, ]); return ( @@ -62,19 +60,7 @@ export const StakingContractUpdate = () => { style={{ width: '100%' }} > Staking contract - - {canUpdateStakingContract ? ( - stakingButton - ) : ( - Fund your agent to manage staking contracts} - > - {stakingButton} - - )} + {gotoManageStakingButton} ); diff --git a/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx b/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx index adfa9c0fe..e45283ac3 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx @@ -1,12 +1,23 @@ import { Flex, Typography } from 'antd'; -import { isNil } from 'lodash'; +import { isEmpty, isNil } from 'lodash'; +import { useMemo } from 'react'; import { CustomAlert } from '@/components/Alert'; +import { getNativeTokenSymbol } from '@/config/tokens'; +import { LOW_MASTER_SAFE_BALANCE } from '@/constants/thresholds'; import { StakingProgramId } from '@/enums/StakingProgram'; -import { useBalance } from '@/hooks/useBalance'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; -import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; -import { getMinimumStakedAmountRequired } from '@/utils/service'; +import { TokenSymbol } from '@/enums/Token'; +import { + useBalanceContext, + useMasterBalances, +} from '@/hooks/useBalanceContext'; +import { useNeedsFunds } from '@/hooks/useNeedsFunds'; +import { useServices } from '@/hooks/useServices'; +import { + useActiveStakingContractInfo, + useStakingContractContext, +} from '@/hooks/useStakingContractDetails'; +import { balanceFormat } from '@/utils/numberFormatters'; import { CantMigrateReason } from './useMigrate'; @@ -15,25 +26,55 @@ const { Text } = Typography; type CantMigrateAlertProps = { stakingProgramId: StakingProgramId }; const AlertInsufficientMigrationFunds = ({ - stakingProgramId, + stakingProgramId: stakingProgramIdToMigrateTo, }: CantMigrateAlertProps) => { - const { serviceTemplate } = useServiceTemplates(); - const { isServiceStaked } = useStakingContractInfo(); - const { masterSafeBalance: safeBalance, totalOlasStakedBalance } = - useBalance(); - - const totalOlasRequiredForStaking = getMinimumStakedAmountRequired( - serviceTemplate, - stakingProgramId, + const { selectedAgentConfig } = useServices(); + const { isAllStakingContractDetailsRecordLoaded } = + useStakingContractContext(); + const { isServiceStaked } = useActiveStakingContractInfo(); + const { isLoaded: isBalanceLoaded, totalStakedOlasBalance } = + useBalanceContext(); + const { masterSafeBalances } = useMasterBalances(); + const { serviceFundRequirements, isInitialFunded } = useNeedsFunds( + stakingProgramIdToMigrateTo, ); - if (isNil(totalOlasRequiredForStaking)) return null; - if (isNil(safeBalance?.OLAS)) return null; - if (isNil(totalOlasStakedBalance)) return null; + const requiredStakedOlas = + serviceFundRequirements[selectedAgentConfig.evmHomeChainId][ + TokenSymbol.OLAS + ]; + + const safeBalance = useMemo(() => { + if (!isBalanceLoaded) return; + if (isNil(masterSafeBalances) || isEmpty(masterSafeBalances)) return; + return masterSafeBalances.reduce( + (acc, { evmChainId: chainId, symbol, balance }) => { + if (chainId === selectedAgentConfig.evmHomeChainId) { + acc[symbol] = balance; + } + return acc; + }, + {} as Record, + ); + }, [isBalanceLoaded, masterSafeBalances, selectedAgentConfig.evmHomeChainId]); + + if (!isAllStakingContractDetailsRecordLoaded) return null; + if (isNil(requiredStakedOlas)) return null; + if (isNil(safeBalance?.[TokenSymbol.OLAS])) return null; + + if (isNil(totalStakedOlasBalance)) return null; const requiredOlasDeposit = isServiceStaked - ? totalOlasRequiredForStaking - (totalOlasStakedBalance + safeBalance.OLAS) // when staked - : totalOlasRequiredForStaking - safeBalance.OLAS; // when not staked + ? requiredStakedOlas - + (totalStakedOlasBalance + safeBalance[TokenSymbol.OLAS]) // when staked + : requiredStakedOlas - safeBalance[TokenSymbol.OLAS]; // when not staked + + const homeChainId = selectedAgentConfig.evmHomeChainId; + const nativeTokenSymbol = getNativeTokenSymbol(homeChainId); + const requiredNativeTokenDeposit = isInitialFunded + ? LOW_MASTER_SAFE_BALANCE - (safeBalance[nativeTokenSymbol] || 0) // is already funded allow minimal maintenance + : (serviceFundRequirements[homeChainId]?.[nativeTokenSymbol] || 0) - + (safeBalance[nativeTokenSymbol] || 0); // otherwise require full initial funding requirements return ( - - An additional {requiredOlasDeposit} OLAS is required to switch - + Additional funds required - Add {requiredOlasDeposit} OLAS to your account to - meet the contract requirements and switch. +
    + {requiredOlasDeposit > 0 && ( +
  • + {`${balanceFormat(requiredOlasDeposit, 2)} ${TokenSymbol.OLAS}`} +
  • + )} + {requiredNativeTokenDeposit > 0 && ( +
  • + {`${balanceFormat(requiredNativeTokenDeposit, 2)} ${nativeTokenSymbol}`} +
  • + )} +
+ Add the required funds to your account to meet the staking + requirements.
} @@ -102,7 +153,10 @@ export const CantMigrateAlert = ({ return ; } - if (cantMigrateReason === CantMigrateReason.InsufficientOlasToMigrate) { + if ( + cantMigrateReason === CantMigrateReason.InsufficientOlasToMigrate || + cantMigrateReason === CantMigrateReason.InsufficientGasToMigrate + ) { return ( ); diff --git a/frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx b/frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx index d8f71c07a..79672fe53 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx @@ -3,25 +3,37 @@ import { isNil } from 'lodash'; import { useState } from 'react'; import { useInterval } from 'usehooks-ts'; -import { StakingContractInfo } from '@/types/Autonolas'; +import { POPOVER_WIDTH_LARGE } from '@/constants/width'; +import { + ServiceStakingDetails, + StakingContractDetails, +} from '@/types/Autonolas'; const { Text } = Typography; export const CountdownUntilMigration = ({ - activeStakingContractInfo, + currentStakingContractInfo, }: { - activeStakingContractInfo: Partial; + currentStakingContractInfo: + | Partial + | Partial; }) => { const [secondsUntilReady, setSecondsUntilMigration] = useState(); useInterval(() => { - if (!activeStakingContractInfo) return; + if (!currentStakingContractInfo) return; + + if ( + !('serviceStakingStartTime' in currentStakingContractInfo) || + !('minimumStakingDuration' in currentStakingContractInfo) + ) { + return; + } const { serviceStakingStartTime, minimumStakingDuration } = - activeStakingContractInfo; + currentStakingContractInfo; - if (isNil(minimumStakingDuration)) return; - if (isNil(serviceStakingStartTime)) return; + if (isNil(minimumStakingDuration) || isNil(serviceStakingStartTime)) return; const now = Math.round(Date.now() / 1000); const timeSinceLastStaked = now - serviceStakingStartTime; @@ -41,7 +53,7 @@ export const CountdownUntilMigration = ({ : countdownDisplayFormat(secondsUntilReady); return ( - + Can't switch because you unstaked too recently. This may be because your agent was suspended. Keep running your agent and you'll be able to switch in diff --git a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx index 9966f3d55..5242f2bfe 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx @@ -2,15 +2,22 @@ import { Button, Popover } from 'antd'; import { isNil } from 'lodash'; import { useMemo } from 'react'; -import { DeploymentStatus } from '@/client'; -import { Pages } from '@/enums/PageState'; +import { MiddlewareDeploymentStatus, ServiceTemplate } from '@/client'; +import { + getServiceTemplate, + SERVICE_TEMPLATES, +} from '@/constants/serviceTemplates'; +import { Pages } from '@/enums/Pages'; import { StakingProgramId } from '@/enums/StakingProgram'; -import { useBalance } from '@/hooks/useBalance'; +import { useBalanceContext } from '@/hooks/useBalanceContext'; import { useModals } from '@/hooks/useModals'; import { usePageState } from '@/hooks/usePageState'; +import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; -import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; +import { + useActiveStakingContractInfo, + useStakingContractDetails, +} from '@/hooks/useStakingContractDetails'; import { useStakingProgram } from '@/hooks/useStakingProgram'; import { ServicesService } from '@/service/Services'; @@ -20,32 +27,68 @@ import { CantMigrateReason, useMigrate } from './useMigrate'; type MigrateButtonProps = { stakingProgramId: StakingProgramId; }; -export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { +export const MigrateButton = ({ + stakingProgramId: stakingProgramIdToMigrateTo, +}: MigrateButtonProps) => { const { goto } = usePageState(); - const { serviceTemplate } = useServiceTemplates(); const { - setIsServicePollingPaused, - setServiceStatus, - updateServiceStatus, - hasInitialLoaded: isServicesLoaded, - service, + setPaused: setIsServicePollingPaused, + isFetched: isServicesLoaded, + selectedService, + selectedAgentConfig, + selectedAgentType, + overrideSelectedServiceStatus, } = useServices(); - const { setIsPaused: setIsBalancePollingPaused } = useBalance(); - const { updateActiveStakingProgramId: updateStakingProgram } = + const { evmHomeChainId: homeChainId } = selectedAgentConfig; + const serviceConfigId = + isServicesLoaded && selectedService + ? selectedService.service_config_id + : ''; + const { service } = useService(serviceConfigId); + const serviceTemplate = useMemo( + () => + service + ? getServiceTemplate(service.hash) + : SERVICE_TEMPLATES.find( + (template) => template.agentType === selectedAgentType, + ), + [selectedAgentType, service], + ); + + const { setIsPaused: setIsBalancePollingPaused } = useBalanceContext(); + + const { defaultStakingProgramId, setDefaultStakingProgramId } = useStakingProgram(); - const { activeStakingContractInfo } = useStakingContractInfo(); + const { + selectedStakingContractDetails, + isSelectedStakingContractDetailsLoaded, + } = useActiveStakingContractInfo(); + const { stakingContractInfo: defaultStakingContractInfo } = + useStakingContractDetails(defaultStakingProgramId); + + const currentStakingContractInfo = useMemo(() => { + if (!isSelectedStakingContractDetailsLoaded) return; + if (selectedStakingContractDetails) return selectedStakingContractDetails; + return defaultStakingContractInfo; + }, [ + selectedStakingContractDetails, + defaultStakingContractInfo, + isSelectedStakingContractDetailsLoaded, + ]); + const { setMigrationModalOpen } = useModals(); - const { migrateValidation, firstDeployValidation } = - useMigrate(stakingProgramId); + const { migrateValidation, firstDeployValidation } = useMigrate( + stakingProgramIdToMigrateTo, + ); // if false, user is migrating, not running for first time const isFirstDeploy = useMemo(() => { if (!isServicesLoaded) return false; - if (service) return false; + if (selectedService) return false; return true; - }, [isServicesLoaded, service]); + }, [isServicesLoaded, selectedService]); const validation = isFirstDeploy ? firstDeployValidation : migrateValidation; @@ -54,17 +97,17 @@ export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { if ( validation.reason === CantMigrateReason.NotStakedForMinimumDuration && - !isNil(activeStakingContractInfo) + !isNil(currentStakingContractInfo) ) { return ( ); } return validation.reason; - }, [activeStakingContractInfo, validation]); + }, [currentStakingContractInfo, validation]); return ( @@ -73,22 +116,43 @@ export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { size="large" disabled={!validation.canMigrate} onClick={async () => { + if (!serviceTemplate) return; + setIsServicePollingPaused(true); setIsBalancePollingPaused(true); + setDefaultStakingProgramId(stakingProgramIdToMigrateTo); + + // TODO: we should not get the default staking program id + // from the context, we should get it from the service + // setDefaultStakingProgramId(stakingProgramId); try { - setServiceStatus(DeploymentStatus.DEPLOYING); + overrideSelectedServiceStatus(MiddlewareDeploymentStatus.DEPLOYING); goto(Pages.Main); - await ServicesService.createService({ - stakingProgramId, + const serviceConfigParams = { + stakingProgramId: stakingProgramIdToMigrateTo, serviceTemplate, deploy: true, - useMechMarketplace: false, - // stakingProgramId === StakingProgramId.BetaMechMarketplace, - }); + useMechMarketplace: + stakingProgramIdToMigrateTo === + StakingProgramId.PearlBetaMechMarketplace, + chainId: homeChainId, + }; + + if (selectedService) { + // update service + await ServicesService.updateService({ + ...serviceConfigParams, + serviceConfigId, + }); + } else { + // create service if it doesn't exist + await ServicesService.createService(serviceConfigParams); + } - await updateStakingProgram(); + // start service after updating or creating + await ServicesService.startService(serviceConfigId); setMigrationModalOpen(true); } catch (error) { @@ -96,7 +160,6 @@ export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { } finally { setIsServicePollingPaused(false); setIsBalancePollingPaused(false); - updateServiceStatus(); } }} > diff --git a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx index 05020e203..17506754e 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx @@ -3,22 +3,31 @@ import { useMemo } from 'react'; import { InfoBreakdownList } from '@/components/InfoBreakdown'; import { StakingProgramId } from '@/enums/StakingProgram'; -import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; +import { useStakingContractContext } from '@/hooks/useStakingContractDetails'; export const StakingContractDetails = ({ stakingProgramId, }: { stakingProgramId: StakingProgramId; }) => { - const { stakingContractInfoRecord } = useStakingContractInfo(); + const { + allStakingContractDetailsRecord, + isAllStakingContractDetailsRecordLoaded, + } = useStakingContractContext(); - const balances = useMemo(() => { - if (!stakingContractInfoRecord) return null; - if (!stakingProgramId) return null; - if (!stakingContractInfoRecord?.[stakingProgramId]) return null; + const list = useMemo(() => { + if (!isAllStakingContractDetailsRecordLoaded) return; + if (!allStakingContractDetailsRecord) return; + if (!stakingProgramId) return; + if (!allStakingContractDetailsRecord?.[stakingProgramId]) return; + + const details = allStakingContractDetailsRecord[stakingProgramId]; - const details = stakingContractInfoRecord[stakingProgramId]; return [ + { + left: 'Available slots', + right: `${details.maxNumServices! - details.serviceIds!.length} / ${details.maxNumServices}`, + }, { left: 'Rewards per epoch', right: `~ ${details.rewardsPerWorkPeriod?.toFixed(2)} OLAS`, @@ -26,19 +35,24 @@ export const StakingContractDetails = ({ { left: 'Estimated Annual Percentage Yield (APY)', right: `${details.apy}%`, + leftClassName: 'max-width-200', }, { left: 'Required OLAS for staking', right: `${details.olasStakeRequired} OLAS`, }, ]; - }, [stakingContractInfoRecord, stakingProgramId]); + }, [ + isAllStakingContractDetailsRecordLoaded, + allStakingContractDetailsRecord, + stakingProgramId, + ]); - if (!stakingContractInfoRecord) { + if (!isAllStakingContractDetailsRecordLoaded) { return ; } - if (!balances) { + if (!allStakingContractDetailsRecord) { return ( + ); }; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractTag.tsx b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractTag.tsx deleted file mode 100644 index cd9e525df..000000000 --- a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractTag.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Tag } from 'antd'; - -import { StakingProgramStatus } from '@/enums/StakingProgramStatus'; - -export const StakingContractTag = ({ - status, -}: { - status: StakingProgramStatus | null; -}) => { - if (status === StakingProgramStatus.Selected) { - return Active; - } - return null; -}; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/index.tsx b/frontend/components/ManageStakingPage/StakingContractSection/index.tsx index afaf16ee4..eaabc8a2f 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/index.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/index.tsx @@ -1,115 +1,142 @@ -import { Flex, theme, Typography } from 'antd'; +import { Flex, Tag, theme, Typography } from 'antd'; import { useMemo } from 'react'; -import { MiddlewareChain } from '@/client'; import { CardSection } from '@/components/styled/CardSection'; -import { SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES } from '@/constants/contractAddresses'; -import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; +import { GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES } from '@/config/stakingPrograms/gnosis'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { EXPLORER_URL } from '@/constants/urls'; -import { DEFAULT_STAKING_PROGRAM_ID } from '@/context/StakingProgramProvider'; +import { EXPLORER_URL_BY_EVM_CHAIN_ID } from '@/constants/urls'; import { StakingProgramId } from '@/enums/StakingProgram'; import { StakingProgramStatus } from '@/enums/StakingProgramStatus'; +import { useServices } from '@/hooks/useServices'; import { useStakingProgram } from '@/hooks/useStakingProgram'; import { CantMigrateAlert } from './CantMigrateAlert'; import { MigrateButton } from './MigrateButton'; import { StakingContractDetails } from './StakingContractDetails'; import { StakingContractFundingButton } from './StakingContractFundingButton'; -import { StakingContractTag } from './StakingContractTag'; import { CantMigrateReason, useMigrate } from './useMigrate'; const { Title } = Typography; const { useToken } = theme; +type StakingContractTagProps = { status: StakingProgramStatus | null }; +export const StakingContractTag = ({ status }: StakingContractTagProps) => { + if (status === StakingProgramStatus.Active) { + return Active; + } + if (status === StakingProgramStatus.Default) { + return Default; + } + return null; +}; + type StakingContractSectionProps = { stakingProgramId: StakingProgramId }; export const StakingContractSection = ({ stakingProgramId, }: StakingContractSectionProps) => { - const { activeStakingProgramId } = useStakingProgram(); - const { token } = useToken(); - const { migrateValidation } = useMigrate(stakingProgramId); - - const stakingContractAddress = - SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[ - MiddlewareChain.OPTIMISM - ][stakingProgramId]; - - const stakingProgramMeta = STAKING_PROGRAM_META[stakingProgramId]; - - /** - * Returns `true` if this stakingProgram is active, - * or user is unstaked and this is the default - */ - const isActiveStakingProgram = useMemo(() => { - if (activeStakingProgramId === null) - return DEFAULT_STAKING_PROGRAM_ID === stakingProgramId; - return activeStakingProgramId === stakingProgramId; - }, [activeStakingProgramId, stakingProgramId]); + const { + defaultStakingProgramId, + activeStakingProgramId, + selectedStakingProgramId, + allStakingProgramsMeta, + isActiveStakingProgramLoaded, + } = useStakingProgram(); + const { selectedAgentConfig } = useServices(); + + // /** + // * Returns `true` if this stakingProgram is active, + // * or user is unstaked and this is the default + // */ + // const isActiveStakingProgram = useMemo(() => { + // if (activeStakingProgramId === null) + // return defaultStakingProgramId === stakingProgramId; + // return activeStakingProgramId === stakingProgramId; + // }, [activeStakingProgramId, defaultStakingProgramId, stakingProgramId]); const contractTagStatus = useMemo(() => { - if (activeStakingProgramId === stakingProgramId) - return StakingProgramStatus.Selected; + if (!isActiveStakingProgramLoaded) return null; + + if (activeStakingProgramId === stakingProgramId) { + return StakingProgramStatus.Active; + } // Pearl is not staked, set as Selected if default if ( !activeStakingProgramId && - stakingProgramId === DEFAULT_STAKING_PROGRAM_ID - ) - return StakingProgramStatus.Selected; + stakingProgramId === defaultStakingProgramId + ) { + return StakingProgramStatus.Default; + } // Otherwise, no tag return null; - }, [activeStakingProgramId, stakingProgramId]); + }, [ + activeStakingProgramId, + defaultStakingProgramId, + isActiveStakingProgramLoaded, + stakingProgramId, + ]); + + const showMigrateButton = + isActiveStakingProgramLoaded && + stakingProgramId !== selectedStakingProgramId; - const showMigrateButton = !isActiveStakingProgram; const showFundingButton = useMemo(() => { + if (!isActiveStakingProgramLoaded) return false; if (migrateValidation.canMigrate) return false; return ( - migrateValidation.reason === CantMigrateReason.InsufficientOlasToMigrate + migrateValidation.reason === + CantMigrateReason.InsufficientOlasToMigrate || + migrateValidation.reason === CantMigrateReason.InsufficientGasToMigrate ); - }, [migrateValidation]); + }, [isActiveStakingProgramLoaded, migrateValidation]); + + const evmChainId = selectedAgentConfig.evmHomeChainId; return ( - <> - - - - {`${stakingProgramMeta?.name} contract`} - - - - - + + + + {allStakingProgramsMeta[stakingProgramId]?.name || 'Unknown'} + + + + + + + {evmChainId && (
View contract details {UNICODE_SYMBOLS.EXTERNAL_LINK} - - {!migrateValidation.canMigrate && ( - - )} - - {showMigrateButton && ( - - )} - {showFundingButton && } - - + )} + + {!migrateValidation.canMigrate && ( + + )} + + {showMigrateButton && ( + + )} + {showFundingButton && } + ); }; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx b/frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx index 624b9288c..65fbb5d92 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx @@ -1,20 +1,30 @@ -import { isNil } from 'lodash'; +import { isEmpty, isNil } from 'lodash'; import { useMemo } from 'react'; -import { DeploymentStatus } from '@/client'; +import { MiddlewareDeploymentStatus } from '@/client'; +import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; import { StakingProgramId } from '@/enums/StakingProgram'; -import { useBalance } from '@/hooks/useBalance'; +import { TokenSymbol } from '@/enums/Token'; +import { + useBalanceContext, + useMasterBalances, +} from '@/hooks/useBalanceContext'; +import { useNeedsFunds } from '@/hooks/useNeedsFunds'; +import { useService } from '@/hooks/useService'; import { useServices } from '@/hooks/useServices'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; -import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; +import { + useActiveStakingContractInfo, + useStakingContractContext, + useStakingContractDetails, +} from '@/hooks/useStakingContractDetails'; import { useStakingProgram } from '@/hooks/useStakingProgram'; -import { getMinimumStakedAmountRequired } from '@/utils/service'; export enum CantMigrateReason { ContractAlreadySelected = 'This staking program is already selected', LoadingBalance = 'Loading balance...', LoadingStakingContractInfo = 'Loading staking contract information...', InsufficientOlasToMigrate = 'Insufficient OLAS to switch', + InsufficientGasToMigrate = 'Insufficient XDAI to switch', // TODO: make chain agnostic MigrationNotSupported = 'Switching to this program is not currently supported', NoAvailableRewards = 'This program has no rewards available', NoAvailableStakingSlots = 'The program has no more available slots', @@ -33,68 +43,105 @@ type MigrateValidation = reason: CantMigrateReason; }; -export const useMigrate = (stakingProgramId: StakingProgramId) => { - const { serviceStatus } = useServices(); - const { serviceTemplate } = useServiceTemplates(); +export const useMigrate = (migrateToStakingProgramId: StakingProgramId) => { const { - isBalanceLoaded, - masterSafeBalance: safeBalance, - totalOlasStakedBalance, - } = useBalance(); - const { activeStakingProgramId, activeStakingProgramMeta } = - useStakingProgram(); + isFetched: isServicesLoaded, + selectedAgentConfig, + selectedService, + selectedAgentType, + } = useServices(); + const { evmHomeChainId: homeChainId } = selectedAgentConfig; + const serviceConfigId = selectedService?.service_config_id; + const { deploymentStatus: serviceStatus } = useService(serviceConfigId); const { - activeStakingContractInfo, - isServiceStaked, - isServiceStakedForMinimumDuration, - isStakingContractInfoLoaded, - stakingContractInfoRecord, - } = useStakingContractInfo(); - - const stakingContractInfo = stakingContractInfoRecord?.[stakingProgramId]; + isLoaded: isBalanceLoaded, + totalStakedOlasBalance, + isLowBalance, + } = useBalanceContext(); + const { masterSafeBalances } = useMasterBalances(); + const { needsInitialFunding, hasEnoughEthForInitialFunding } = useNeedsFunds( + migrateToStakingProgramId, + ); - const { hasInitialLoaded: isServicesLoaded } = useServices(); + const { activeStakingProgramId } = useStakingProgram(); + const { + allStakingContractDetailsRecord, + isAllStakingContractDetailsRecordLoaded, + } = useStakingContractContext(); + const { isServiceStaked, isServiceStakedForMinimumDuration } = + useActiveStakingContractInfo(); + const { stakingContractInfo, hasEnoughServiceSlots } = + useStakingContractDetails(migrateToStakingProgramId); + + const safeOlasBalance = useMemo(() => { + if (!isBalanceLoaded) return 0; + if (isNil(masterSafeBalances) || isEmpty(masterSafeBalances)) return 0; + return masterSafeBalances.reduce( + (acc, { evmChainId: chainId, symbol, balance }) => { + if (chainId === homeChainId && symbol === TokenSymbol.OLAS) + return acc + balance; + return acc; + }, + 0, + ); + }, [homeChainId, isBalanceLoaded, masterSafeBalances]); const minimumOlasRequiredToMigrate = useMemo( - () => getMinimumStakedAmountRequired(serviceTemplate, stakingProgramId), - [serviceTemplate, stakingProgramId], + () => + STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][ + migrateToStakingProgramId + ]?.stakingRequirements[TokenSymbol.OLAS], + [selectedAgentConfig.evmHomeChainId, migrateToStakingProgramId], ); const hasEnoughOlasToMigrate = useMemo(() => { if (!isBalanceLoaded) return false; - if (isNil(safeBalance?.OLAS)) return false; - if (isNil(totalOlasStakedBalance)) return false; + if (isNil(safeOlasBalance)) return false; + if (isNil(totalStakedOlasBalance)) return false; if (isNil(minimumOlasRequiredToMigrate)) return false; - const balanceForMigration = safeBalance.OLAS + totalOlasStakedBalance; - + const balanceForMigration = safeOlasBalance + totalStakedOlasBalance; return balanceForMigration >= minimumOlasRequiredToMigrate; }, [ isBalanceLoaded, minimumOlasRequiredToMigrate, - safeBalance, - totalOlasStakedBalance, + safeOlasBalance, + totalStakedOlasBalance, ]); const hasEnoughOlasForFirstRun = useMemo(() => { if (!isBalanceLoaded) return false; - if (isNil(safeBalance?.OLAS)) return false; + if (isNil(safeOlasBalance)) return false; if (isNil(minimumOlasRequiredToMigrate)) return false; - return safeBalance.OLAS >= minimumOlasRequiredToMigrate; - }, [isBalanceLoaded, minimumOlasRequiredToMigrate, safeBalance]); + return safeOlasBalance >= minimumOlasRequiredToMigrate; + }, [isBalanceLoaded, minimumOlasRequiredToMigrate, safeOlasBalance]); const migrateValidation = useMemo(() => { if (!isServicesLoaded) { return { canMigrate: false, reason: CantMigrateReason.LoadingServices }; } + // Services must be not be running or in a transitional state + if ( + [ + MiddlewareDeploymentStatus.DEPLOYED, + MiddlewareDeploymentStatus.DEPLOYING, + MiddlewareDeploymentStatus.STOPPING, + ].some((status) => status === serviceStatus) + ) { + return { + canMigrate: false, + reason: CantMigrateReason.PearlCurrentlyRunning, + }; + } + if (!isBalanceLoaded) { return { canMigrate: false, reason: CantMigrateReason.LoadingBalance }; } - if (isServicesLoaded && !isStakingContractInfoLoaded) { + if (!isAllStakingContractDetailsRecordLoaded) { return { canMigrate: false, reason: CantMigrateReason.LoadingStakingContractInfo, @@ -109,13 +156,23 @@ export const useMigrate = (stakingProgramId: StakingProgramId) => { } // general requirements - if (activeStakingProgramId === stakingProgramId) { + if (activeStakingProgramId === migrateToStakingProgramId) { return { canMigrate: false, reason: CantMigrateReason.ContractAlreadySelected, }; } + if ( + (stakingContractInfo.serviceIds ?? [])?.length >= + (stakingContractInfo.maxNumServices ?? 0) + ) { + return { + canMigrate: false, + reason: CantMigrateReason.NoAvailableStakingSlots, + }; + } + if ((stakingContractInfo.availableRewards ?? 0) <= 0) { return { canMigrate: false, @@ -140,34 +197,23 @@ export const useMigrate = (stakingProgramId: StakingProgramId) => { }; } - // Services must be not be running or in a transitional state - if ( - [ - DeploymentStatus.DEPLOYED, - DeploymentStatus.DEPLOYING, - DeploymentStatus.STOPPING, - ].some((status) => status === serviceStatus) - ) { - return { - canMigrate: false, - reason: CantMigrateReason.PearlCurrentlyRunning, - }; - } - if (activeStakingProgramId === null && !isServiceStaked) { return { canMigrate: true }; } - // user must be staked from hereon + // user is staked from hereon + + const { deprecated: isDeprecated, agentsSupported } = + STAKING_PROGRAMS[homeChainId][migrateToStakingProgramId]; - if (!activeStakingProgramMeta?.canMigrateTo.includes(stakingProgramId)) { + if (isDeprecated || !agentsSupported.includes(selectedAgentType)) { return { canMigrate: false, reason: CantMigrateReason.MigrationNotSupported, }; } - if (activeStakingContractInfo && !isServiceStakedForMinimumDuration) { + if (!isServiceStakedForMinimumDuration) { return { canMigrate: false, reason: CantMigrateReason.NotStakedForMinimumDuration, @@ -178,35 +224,73 @@ export const useMigrate = (stakingProgramId: StakingProgramId) => { }, [ isServicesLoaded, isBalanceLoaded, - isStakingContractInfoLoaded, + isAllStakingContractDetailsRecordLoaded, stakingContractInfo, activeStakingProgramId, - stakingProgramId, + migrateToStakingProgramId, hasEnoughOlasToMigrate, isServiceStaked, - activeStakingProgramMeta?.canMigrateTo, - activeStakingContractInfo, + homeChainId, + selectedAgentType, isServiceStakedForMinimumDuration, serviceStatus, ]); const firstDeployValidation = useMemo(() => { + /** + * @todo fix temporary check for xDai balance on first deploy (same as initial funding requirement) + */ + if (!isServicesLoaded) { return { canMigrate: false, reason: CantMigrateReason.LoadingServices }; } + // Services must be not be running or in a transitional state + if ( + [ + MiddlewareDeploymentStatus.DEPLOYED, + MiddlewareDeploymentStatus.DEPLOYING, + MiddlewareDeploymentStatus.STOPPING, + ].some((status) => status === serviceStatus) + ) { + return { + canMigrate: false, + reason: CantMigrateReason.PearlCurrentlyRunning, + }; + } + if (!isBalanceLoaded) { return { canMigrate: false, reason: CantMigrateReason.LoadingBalance }; } - if (!hasEnoughOlasForFirstRun) { + // staking contract requirements + + if (!isAllStakingContractDetailsRecordLoaded) { return { canMigrate: false, - reason: CantMigrateReason.InsufficientOlasToMigrate, + reason: CantMigrateReason.LoadingStakingContractInfo, + }; + } + + const stakingContractInfo = + allStakingContractDetailsRecord?.[migrateToStakingProgramId]; + + if (!stakingContractInfo) { + return { + canMigrate: false, + reason: CantMigrateReason.CannotFindStakingContractInfo, }; } - const stakingContractInfo = stakingContractInfoRecord?.[stakingProgramId]; + if ( + (stakingContractInfo.serviceIds ?? [])?.length >= + (stakingContractInfo.maxNumServices ?? 0) + ) { + return { + canMigrate: false, + reason: CantMigrateReason.NoAvailableStakingSlots, + }; + } if ((stakingContractInfo?.availableRewards ?? 0) <= 0) { return { @@ -222,17 +306,48 @@ export const useMigrate = (stakingProgramId: StakingProgramId) => { }; } + if (!hasEnoughOlasForFirstRun) { + return { + canMigrate: false, + reason: CantMigrateReason.InsufficientOlasToMigrate, + }; + } + + if (!hasEnoughEthForInitialFunding) { + return { + canMigrate: false, + reason: CantMigrateReason.InsufficientGasToMigrate, + }; + } + return { canMigrate: true }; }, [ isServicesLoaded, isBalanceLoaded, + hasEnoughEthForInitialFunding, + isAllStakingContractDetailsRecordLoaded, + allStakingContractDetailsRecord, + migrateToStakingProgramId, hasEnoughOlasForFirstRun, - stakingContractInfoRecord, - stakingProgramId, + serviceStatus, + ]); + + const canUpdateStakingContract = useMemo(() => { + if (!isBalanceLoaded) return false; + if (isLowBalance) return false; + if (needsInitialFunding) return false; + if (!hasEnoughServiceSlots) return false; + return true; + }, [ + isBalanceLoaded, + isLowBalance, + needsInitialFunding, + hasEnoughServiceSlots, ]); return { migrateValidation, firstDeployValidation, + canUpdateStakingContract, }; }; diff --git a/frontend/components/ManageStakingPage/index.tsx b/frontend/components/ManageStakingPage/index.tsx index 320c81a06..b20da37fc 100644 --- a/frontend/components/ManageStakingPage/index.tsx +++ b/frontend/components/ManageStakingPage/index.tsx @@ -1,11 +1,12 @@ import { CloseOutlined } from '@ant-design/icons'; import { Button, Card } from 'antd'; +import { useMemo } from 'react'; -import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; -import { DEFAULT_STAKING_PROGRAM_ID } from '@/context/StakingProgramProvider'; -import { Pages } from '@/enums/PageState'; +import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; +import { Pages } from '@/enums/Pages'; import { StakingProgramId } from '@/enums/StakingProgram'; import { usePageState } from '@/hooks/usePageState'; +import { useServices } from '@/hooks/useServices'; import { useStakingProgram } from '@/hooks/useStakingProgram'; import { CardTitle } from '../Card/CardTitle'; @@ -15,37 +16,63 @@ import { WhatAreStakingContractsSection } from './WhatAreStakingContracts'; export const ManageStakingPage = () => { const { goto } = usePageState(); - const { activeStakingProgramId } = useStakingProgram(); - - const orderedStakingProgramIds: StakingProgramId[] = Object.values( - StakingProgramId, - ).reduce((acc: StakingProgramId[], stakingProgramId: StakingProgramId) => { - // put the active staking program at the top - if (stakingProgramId === activeStakingProgramId) { - return [stakingProgramId, ...acc]; - } - - // put default at the top if no activeStakingProgram - if ( - activeStakingProgramId === null && - stakingProgramId === DEFAULT_STAKING_PROGRAM_ID - ) - return [stakingProgramId, ...acc]; - - // if the program is deprecated, ignore it - if (STAKING_PROGRAM_META[stakingProgramId]?.deprecated) { - return acc; - } - - // otherwise, append to the end - return [...acc, stakingProgramId]; - }, []); + const { selectedAgentConfig } = useServices(); + const { + activeStakingProgramId, + isActiveStakingProgramLoaded, + defaultStakingProgramId, + } = useStakingProgram(); + + const currentStakingProgramId = isActiveStakingProgramLoaded + ? activeStakingProgramId || defaultStakingProgramId + : null; + + const stakingProgramIdsAvailable = Object.keys( + STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId], + ).map((stakingProgramIdKey) => stakingProgramIdKey as StakingProgramId); + + const orderedStakingProgramIds = useMemo( + () => + stakingProgramIdsAvailable.reduce( + (acc: StakingProgramId[], stakingProgramId: StakingProgramId) => { + if (!isActiveStakingProgramLoaded) return acc; + + // put the active staking program at the top + if (stakingProgramId === currentStakingProgramId) { + return [stakingProgramId, ...acc]; + } + + // if the program is deprecated, ignore it + if ( + STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][ + stakingProgramId + ].deprecated + ) { + return acc; + } + + // otherwise, append to the end + return [...acc, stakingProgramId]; + }, + [], + ), + [ + isActiveStakingProgramLoaded, + selectedAgentConfig.evmHomeChainId, + currentStakingProgramId, + stakingProgramIdsAvailable, + ], + ); const otherStakingProgramIds = orderedStakingProgramIds.filter( (stakingProgramId) => { - const info = STAKING_PROGRAM_META[stakingProgramId]; + if (!isActiveStakingProgramLoaded) return false; + + const info = + STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][stakingProgramId]; + if (!info) return false; - if (activeStakingProgramId === stakingProgramId) return false; + if (currentStakingProgramId === stakingProgramId) return false; if (info.deprecated) return false; return true; }, @@ -71,11 +98,12 @@ export const ManageStakingPage = () => { > - {activeStakingProgramId && ( - - )} + {isActiveStakingProgramLoaded && + (activeStakingProgramId || defaultStakingProgramId) && ( + + )} { {`Browse ${otherStakingProgramIds.length} staking contract${otherStakingProgramIds.length > 1 ? 's' : ''}.`} - {otherStakingProgramIds.map((stakingProgramId) => ( - + {otherStakingProgramIds.map((otherId) => ( + ))} ); diff --git a/frontend/components/Pages/AddBackupWalletViaSafePage/index.tsx b/frontend/components/Pages/AddBackupWalletViaSafePage/index.tsx index fa7235dab..d8459d4e1 100644 --- a/frontend/components/Pages/AddBackupWalletViaSafePage/index.tsx +++ b/frontend/components/Pages/AddBackupWalletViaSafePage/index.tsx @@ -1,16 +1,39 @@ -import { Card, Flex, Typography } from 'antd'; +import { Card, Flex, Skeleton, Typography } from 'antd'; import { CardTitle } from '@/components/Card/CardTitle'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { DISCORD_TICKET_URL } from '@/constants/urls'; -import { useWallet } from '@/hooks/useWallet'; +import { EvmChainId } from '@/enums/Chain'; +import { useServices } from '@/hooks/useServices'; +import { useMasterWalletContext } from '@/hooks/useWallet'; import { GoToMainPageButton } from '../GoToMainPageButton'; const { Text } = Typography; +/** + * update as needed; check https://app.safe.global/new-safe/create for prefixes + */ +const safeChainPrefix = { + [EvmChainId.Ethereum]: 'eth', + [EvmChainId.Base]: 'base', + [EvmChainId.Optimism]: 'oeth', + [EvmChainId.Gnosis]: 'gno', +}; + export const AddBackupWalletViaSafePage = () => { - const { masterSafeAddress } = useWallet(); + const { + selectedAgentConfig: { evmHomeChainId }, + } = useServices(); + + const { masterSafes } = useMasterWalletContext(); + + const masterSafe = masterSafes?.find( + ({ evmChainId: chainId }) => evmHomeChainId === chainId, + ); + + const safePrefix = + masterSafe?.evmChainId && safeChainPrefix[masterSafe?.evmChainId]; return ( { Manually add backup wallet via Safe interface: - - Add backup wallet {UNICODE_SYMBOLS.EXTERNAL_LINK} - + {!masterSafe?.address && } + {masterSafe?.address && ( + + Open Safe interface {UNICODE_SYMBOLS.EXTERNAL_LINK} + + )} diff --git a/frontend/components/Pages/GoToMainPageButton.tsx b/frontend/components/Pages/GoToMainPageButton.tsx index e70d5fd9f..d63303480 100644 --- a/frontend/components/Pages/GoToMainPageButton.tsx +++ b/frontend/components/Pages/GoToMainPageButton.tsx @@ -1,7 +1,7 @@ import { CloseOutlined } from '@ant-design/icons'; import { Button } from 'antd'; -import { Pages } from '@/enums/PageState'; +import { Pages } from '@/enums/Pages'; import { usePageState } from '@/hooks/usePageState'; export const GoToMainPageButton = () => { diff --git a/frontend/components/Pages/HelpAndSupportPage/index.tsx b/frontend/components/Pages/HelpAndSupportPage/index.tsx index 5c31731a5..4e721e047 100644 --- a/frontend/components/Pages/HelpAndSupportPage/index.tsx +++ b/frontend/components/Pages/HelpAndSupportPage/index.tsx @@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from 'react'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { FAQ_URL, SUPPORT_URL } from '@/constants/urls'; -import { Pages } from '@/enums/PageState'; +import { Pages } from '@/enums/Pages'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useLogs } from '@/hooks/useLogs'; import { usePageState } from '@/hooks/usePageState'; diff --git a/frontend/components/RewardsHistory/RewardsHistory.tsx b/frontend/components/RewardsHistory/RewardsHistory.tsx index 689d4ea61..210fc45da 100644 --- a/frontend/components/RewardsHistory/RewardsHistory.tsx +++ b/frontend/components/RewardsHistory/RewardsHistory.tsx @@ -22,21 +22,23 @@ import styled from 'styled-components'; import { MiddlewareChain } from '@/client'; import { CardTitle } from '@/components/Card/CardTitle'; import { CardFlex } from '@/components/styled/CardFlex'; +import { + STAKING_PROGRAM_ADDRESS, + STAKING_PROGRAMS, +} from '@/config/stakingPrograms'; import { COLOR } from '@/constants/colors'; -import { SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES } from '@/constants/contractAddresses'; -import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { EXPLORER_URL } from '@/constants/urls'; -import { Pages } from '@/enums/PageState'; +import { EXPLORER_URL_BY_MIDDLEWARE_CHAIN } from '@/constants/urls'; +import { Pages } from '@/enums/Pages'; import { StakingProgramId } from '@/enums/StakingProgram'; import { usePageState } from '@/hooks/usePageState'; +import { useService } from '@/hooks/useService'; +import { useServices } from '@/hooks/useServices'; +import { AgentConfig } from '@/types/Agent'; import { balanceFormat } from '@/utils/numberFormatters'; import { formatToMonthDay, formatToShortDateTime } from '@/utils/time'; -import { - TransformedCheckpoint, - useRewardsHistory, -} from '../../hooks/useRewardsHistory'; +import { Checkpoint, useRewardsHistory } from '../../hooks/useRewardsHistory'; import { EpochDetails } from './types'; const { Text, Title } = Typography; @@ -131,7 +133,7 @@ const EpochTime = ({ epoch }: { epoch: EpochDetails }) => { {timePeriod} End of epoch transaction {UNICODE_SYMBOLS.EXTERNAL_LINK} @@ -145,59 +147,92 @@ const EpochTime = ({ epoch }: { epoch: EpochDetails }) => { ); }; +type ContractRewardsProps = { + stakingProgramId: StakingProgramId; + checkpoints: Checkpoint[]; + selectedAgentConfig: AgentConfig; +}; + const ContractRewards = ({ - stakingProgramId, checkpoints, -}: { - stakingProgramId: StakingProgramId; - checkpoints: TransformedCheckpoint[]; -}) => ( - - - {STAKING_PROGRAM_META[stakingProgramId].name} - - - {checkpoints.map((checkpoint) => { - const currentEpochReward = checkpoint.reward - ? `~${balanceFormat(checkpoint.reward ?? 0, 2)} OLAS` - : '0 OLAS'; - - return ( - - - - - - {currentEpochReward} - - - {checkpoint.earned ? : } - - - ); - })} - -); + stakingProgramId, + selectedAgentConfig, +}: ContractRewardsProps) => { + const stakingProgramMeta = + STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][stakingProgramId]; + + return ( + + + {stakingProgramMeta.name} + + + {checkpoints.map((checkpoint) => { + const currentEpochReward = checkpoint.reward + ? `~${balanceFormat(checkpoint.reward ?? 0, 2)} OLAS` + : '0 OLAS'; + + return ( + + + + + + {currentEpochReward} + + + {checkpoint.earned ? : } + + + ); + })} + + ); +}; +/** + * TODO: Refactor, only supports a single service for now + * */ export const RewardsHistory = () => { - const { contractCheckpoints, isError, isLoading, isFetching, refetch } = + const { contractCheckpoints, isError, isFetched, refetch } = useRewardsHistory(); const { goto } = usePageState(); + const { selectedService, selectedAgentConfig } = useServices(); + const { serviceNftTokenId } = useService(selectedService?.service_config_id); const history = useMemo(() => { - if (isLoading || isFetching) return ; - if (isError) return ; + if (!isFetched || !selectedService?.service_config_id) return ; + if (isError) return ; // TODO: don't do this if (!contractCheckpoints) return ; - if (Object.keys(contractCheckpoints).length === 0) + if (Object.keys(contractCheckpoints).length === 0) { return ; + } + + // find the recent contract address where the service has participated in + const recentContractAddress = Object.values(contractCheckpoints) + .flat() + .sort((a, b) => b.epochEndTimeStamp - a.epochEndTimeStamp) + .find((checkpoint) => + checkpoint.serviceIds.includes(`${serviceNftTokenId}`), + )?.contractAddress; + + // most recent transaction staking contract at the top of the list + const latestContractAddresses = Object.keys(contractCheckpoints).sort( + (a, b) => { + if (a === recentContractAddress) return -1; + if (b === recentContractAddress) return 1; + return 0; + }, + ); + + if (!selectedAgentConfig.evmHomeChainId) return null; + return ( - {Object.keys(contractCheckpoints).map((contractAddress: string) => { + {latestContractAddresses.map((contractAddress: string) => { const checkpoints = contractCheckpoints[contractAddress]; const [stakingProgramId] = Object.entries( - SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[ - MiddlewareChain.OPTIMISM - ], + STAKING_PROGRAM_ADDRESS[selectedAgentConfig.evmHomeChainId], ).find((entry) => { const [, stakingProxyAddress] = entry; return ( @@ -213,12 +248,21 @@ export const RewardsHistory = () => { key={contractAddress} stakingProgramId={stakingProgramId as StakingProgramId} checkpoints={checkpoints} + selectedAgentConfig={selectedAgentConfig} /> ); })} ); - }, [isLoading, isFetching, isError, refetch, contractCheckpoints]); + }, [ + isFetched, + selectedService?.service_config_id, + isError, + refetch, + contractCheckpoints, + selectedAgentConfig, + serviceNftTokenId, + ]); return ( diff --git a/frontend/components/SettingsPage/AddBackupWalletPage.tsx b/frontend/components/SettingsPage/AddBackupWalletPage.tsx index 6bcea847f..e81644757 100644 --- a/frontend/components/SettingsPage/AddBackupWalletPage.tsx +++ b/frontend/components/SettingsPage/AddBackupWalletPage.tsx @@ -1,29 +1,40 @@ import { CloseOutlined } from '@ant-design/icons'; import { Button, Form, Input, Typography } from 'antd'; +import { isEmpty, isNil } from 'lodash'; import { useMemo } from 'react'; -import { MiddlewareChain } from '@/client'; import { MIN_ETH_BALANCE_THRESHOLDS } from '@/constants/thresholds'; import { SettingsScreen } from '@/enums/SettingsScreen'; -import { useBalance } from '@/hooks/useBalance'; +import { useMasterBalances } from '@/hooks/useBalanceContext'; +import { useServices } from '@/hooks/useServices'; import { useSettings } from '@/hooks/useSettings'; import { CardTitle } from '../Card/CardTitle'; import { CardFlex } from '../styled/CardFlex'; export const AddBackupWalletPage = () => { - const { masterEoaBalance: eoaBalance } = useBalance(); + const { + selectedAgentConfig: { evmHomeChainId: homeChainId }, + } = useServices(); + const { masterEoaBalances } = useMasterBalances(); const { goto } = useSettings(); - const [form] = Form.useForm(); - const isFunded = useMemo(() => { - if (!eoaBalance) return false; - return ( - eoaBalance.ETH >= - MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.OPTIMISM].safeAddSigner - ); - }, [eoaBalance]); + const isMasterEoaFunded = useMemo(() => { + if (isNil(masterEoaBalances) || isEmpty(masterEoaBalances)) return false; + + const masterEoaNativeBalance = masterEoaBalances.find( + ({ isNative, evmChainId: chainId }) => + isNative && chainId === homeChainId, + )?.balance; + + if (isNil(masterEoaNativeBalance)) return false; + + const nativeBalanceRequiredToAddSigner = + MIN_ETH_BALANCE_THRESHOLDS[homeChainId].safeAddSigner; + + return masterEoaNativeBalance >= nativeBalanceRequiredToAddSigner; + }, [homeChainId, masterEoaBalances]); return ( { > - diff --git a/frontend/components/SettingsPage/DebugInfoSection.tsx b/frontend/components/SettingsPage/DebugInfoSection.tsx index e3a6ccb5d..231997ffe 100644 --- a/frontend/components/SettingsPage/DebugInfoSection.tsx +++ b/frontend/components/SettingsPage/DebugInfoSection.tsx @@ -9,19 +9,25 @@ import { Tooltip, Typography, } from 'antd'; -import { useCallback, useMemo, useState } from 'react'; +import { isEmpty, isNil } from 'lodash'; +import { Fragment, useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; -import { MiddlewareChain } from '@/client'; import { COLOR } from '@/constants/colors'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { EXPLORER_URL } from '@/constants/urls'; +import { EXPLORER_URL_BY_EVM_CHAIN_ID } from '@/constants/urls'; import { MODAL_WIDTH } from '@/constants/width'; -import { Token } from '@/enums/Token'; -import { useAddress } from '@/hooks/useAddress'; -import { useBalance } from '@/hooks/useBalance'; -import { useWallet } from '@/hooks/useWallet'; -import { WalletAddressNumberRecord } from '@/types/Records'; +import { WalletBalanceResult } from '@/context/BalanceProvider'; +import { EvmChainId, EvmChainName } from '@/enums/Chain'; +import { TokenSymbol } from '@/enums/Token'; +import { WalletType } from '@/enums/Wallet'; +import { + useBalanceContext, + useMasterBalances, +} from '@/hooks/useBalanceContext'; +import { useServices } from '@/hooks/useServices'; +import { useMasterWalletContext } from '@/hooks/useWallet'; +import { Address } from '@/types/Address'; import { copyToClipboard } from '@/utils/copyToClipboard'; import { balanceFormat } from '@/utils/numberFormatters'; import { truncateAddress } from '@/utils/truncate'; @@ -38,29 +44,31 @@ const Card = styled.div` const ICON_STYLE = { color: '#606F85' }; -const getItemData = ( - walletBalances: WalletAddressNumberRecord, - address: `0x${string}`, -) => ({ - balance: { - OLAS: balanceFormat(walletBalances[address]?.OLAS, 2), - ETH: balanceFormat(walletBalances[address]?.ETH, 2), - }, - address: address, - truncatedAddress: address ? truncateAddress(address) : '', -}); +const getBalanceData = (walletBalances: WalletBalanceResult[]) => { + const result: { [chainId: number]: { [tokenSymbol: string]: number } } = {}; + + for (const walletBalanceResult of walletBalances) { + const { evmChainId: chainId, symbol } = walletBalanceResult; + if (!result[chainId]) result[chainId] = {}; + if (!result[chainId][symbol]) result[chainId][symbol] = 0; + result[chainId][symbol] += walletBalanceResult.balance; + } + + return { balance: result }; +}; const DebugItem = ({ item, }: { item: { title: string; - balance: Record; - address: `0x${string}`; - truncatedAddress: string; + balance: Record>; + address: Address; link?: { title: string; href: string }; }; }) => { + const truncatedAddress = truncateAddress(item.address); + const onCopyToClipboard = useCallback( () => copyToClipboard(item.address).then(() => @@ -69,42 +77,68 @@ const DebugItem = ({ [item.address], ); + const balances = Object.entries(item.balance); + return ( {item.title} - - - - - Balance - - {item.balance.OLAS} OLAS - {item.balance.ETH} ETH - {/* {item.balance.USDC} USDC */} - - - - - - - Address - - - - {item.truncatedAddress} - - - - - - - - + {balances.map(([chainId, balance]) => { + const evmChainId = +chainId as keyof typeof EvmChainName; + return ( + + {balances.length > 1 && ( + + + {EvmChainName[evmChainId]}: + + + )} + 1 ? 'mb-16' : undefined}> + + + + Balance{' '} + + + {Object.entries(balance).map(([tokenSymbol, balance]) => { + return ( + + {balanceFormat(balance, 2)} + {tokenSymbol} + + ); + })} + + + + + + + + Address + + + + {truncatedAddress} + + + + + + + + + + ); + })} {item.link ? ( @@ -117,55 +151,86 @@ const DebugItem = ({ }; export const DebugInfoSection = () => { - const { wallets, masterEoaAddress, masterSafeAddress } = useWallet(); - const { instanceAddress, multisigAddress } = useAddress(); - const { walletBalances } = useBalance(); + const { masterEoa, masterSafes } = useMasterWalletContext(); + const { serviceWallets: serviceAddresses } = useServices(); + const { walletBalances } = useBalanceContext(); + const { masterEoaBalances, masterSafeBalances } = useMasterBalances(); const [isModalOpen, setIsModalOpen] = useState(false); const showModal = useCallback(() => setIsModalOpen(true), []); const handleCancel = useCallback(() => setIsModalOpen(false), []); const data = useMemo(() => { - if (!wallets?.length) return null; + if (isNil(masterEoa)) return null; + if (isNil(masterSafes) || isEmpty(masterSafes)) return null; + if (isNil(walletBalances) || isEmpty(walletBalances)) return null; - const result = []; + const result: { + title: string; + balance: Record< + number | EvmChainId, + Record + >; + address: Address; + link?: { title: string; href: string }; + }[] = []; - if (masterEoaAddress) { + if (!isNil(masterEoaBalances)) { result.push({ title: 'Master EOA', - ...getItemData(walletBalances, masterEoaAddress), + ...getBalanceData(masterEoaBalances), + address: masterEoa.address, }); } - if (masterSafeAddress) { - result.push({ - title: 'Master Safe', - ...getItemData(walletBalances, masterSafeAddress), + if (!isNil(masterSafeBalances)) { + masterSafes.forEach((wallet) => { + result.push({ + title: 'Master Safe', + ...getBalanceData(masterSafeBalances), + address: wallet.address, + }); }); } - if (instanceAddress) { - result.push({ - title: 'Agent Instance EOA', - ...getItemData(walletBalances, instanceAddress!), - }); - } + if (!isNil(serviceAddresses)) { + serviceAddresses?.forEach((serviceWallet) => { + if (serviceWallet.type === WalletType.EOA) { + result.push({ + title: 'Agent Instance EOA', + ...getBalanceData( + walletBalances.filter( + (balance) => balance.walletAddress === serviceWallet.address, + ), + ), + address: serviceWallet.address, + }); + } - if (multisigAddress) { - result.push({ - title: 'Agent Safe', - ...getItemData(walletBalances, multisigAddress), + if (serviceWallet.type === WalletType.Safe) { + result.push({ + title: 'Agent Safe', + ...getBalanceData( + walletBalances.filter( + (walletBalance) => + walletBalance.walletAddress === serviceWallet.address && + walletBalance.evmChainId === serviceWallet.evmChainId, + ), + ), + address: serviceWallet.address, + }); + } }); } return result; }, [ - masterEoaAddress, - masterSafeAddress, - instanceAddress, - multisigAddress, + masterEoa, + masterEoaBalances, + masterSafeBalances, + masterSafes, + serviceAddresses, walletBalances, - wallets?.length, ]); return ( diff --git a/frontend/components/SettingsPage/index.tsx b/frontend/components/SettingsPage/index.tsx index 3b212f4c0..e1123d10d 100644 --- a/frontend/components/SettingsPage/index.tsx +++ b/frontend/components/SettingsPage/index.tsx @@ -1,16 +1,20 @@ import { CloseOutlined, SettingOutlined } from '@ant-design/icons'; -import { Button, Card, Flex, Typography } from 'antd'; +import { Button, Card, Flex, Skeleton, Typography } from 'antd'; +import { isEmpty, isNil } from 'lodash'; import Link from 'next/link'; import { useMemo } from 'react'; import { MiddlewareChain } from '@/client'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { EXPLORER_URL } from '@/constants/urls'; -import { Pages } from '@/enums/PageState'; +import { EXPLORER_URL_BY_MIDDLEWARE_CHAIN } from '@/constants/urls'; +import { Pages } from '@/enums/Pages'; import { SettingsScreen } from '@/enums/SettingsScreen'; -import { useMasterSafe } from '@/hooks/useMasterSafe'; +import { useMultisig } from '@/hooks/useMultisig'; import { usePageState } from '@/hooks/usePageState'; import { useSettings } from '@/hooks/useSettings'; +import { useMasterWalletContext } from '@/hooks/useWallet'; +import { Address } from '@/types/Address'; +import { Optional } from '@/types/Util'; import { truncateAddress } from '@/utils/truncate'; import { CustomAlert } from '../Alert'; @@ -82,14 +86,36 @@ export const Settings = () => { }; const SettingsMain = () => { - const { backupSafeAddress } = useMasterSafe(); + const { masterEoa, masterSafes } = useMasterWalletContext(); + + const { owners, ownersIsFetched } = useMultisig( + masterSafes?.[0], // TODO: all master safes should have the same address, but dirty implementation + ); + const { goto } = usePageState(); - const truncatedBackupSafeAddress: string | undefined = useMemo(() => { - if (backupSafeAddress) { - return truncateAddress(backupSafeAddress); + const masterSafeBackupAddresses = useMemo>(() => { + if (!ownersIsFetched) return; + if (!masterEoa) return; + if (isNil(owners) || isEmpty(owners)) return []; + + // TODO: handle edge cases where there are multiple owners due to middleware failure, or user interaction via safe.global + return owners.filter( + (owner) => owner.toLowerCase() !== masterEoa.address.toLowerCase(), + ); + }, [ownersIsFetched, owners, masterEoa]); + + const masterSafeBackupAddress = useMemo>(() => { + if (isNil(masterSafeBackupAddresses)) return; + + return masterSafeBackupAddresses[0]; + }, [masterSafeBackupAddresses]); + + const truncatedBackupSafeAddress: Optional = useMemo(() => { + if (masterSafeBackupAddress && masterSafeBackupAddress?.length) { + return truncateAddress(masterSafeBackupAddress); } - }, [backupSafeAddress]); + }, [masterSafeBackupAddress]); return ( { {/* Wallet backup */} Backup wallet - {backupSafeAddress ? ( + + {!ownersIsFetched ? ( + + ) : masterSafeBackupAddress ? ( {truncatedBackupSafeAddress} {UNICODE_SYMBOLS.EXTERNAL_LINK} diff --git a/frontend/components/SetupPage/Create/SetupBackupSigner.tsx b/frontend/components/SetupPage/Create/SetupBackupSigner.tsx index 60d2e4d18..8fab9334c 100644 --- a/frontend/components/SetupPage/Create/SetupBackupSigner.tsx +++ b/frontend/components/SetupPage/Create/SetupBackupSigner.tsx @@ -17,10 +17,11 @@ export const SetupBackupSigner = () => { const [form] = Form.useForm(); const handleFinish = (values: { 'backup-signer': string }) => { + // important to lowercase the address before check summing, invalid checksums will cause ethers to throw + // returns null if invalid, ethers type is incorrect... const checksummedAddress = getAddress( - // important to lowercase the address before checksumming, invalid checksums will cause ethers to throw values['backup-signer'].toLowerCase(), - ) as Address | null; // returns null if invalid, ethers type is incorrect... + ) as Address | null; // If the address is invalid, show an error message if (!checksummedAddress) { diff --git a/frontend/components/SetupPage/Create/SetupCreateSafe.tsx b/frontend/components/SetupPage/Create/SetupCreateSafe.tsx index d222c868f..7dd921bc8 100644 --- a/frontend/components/SetupPage/Create/SetupCreateSafe.tsx +++ b/frontend/components/SetupPage/Create/SetupCreateSafe.tsx @@ -6,96 +6,133 @@ import { MiddlewareChain } from '@/client'; import { CardSection } from '@/components/styled/CardSection'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { SUPPORT_URL } from '@/constants/urls'; -import { Pages } from '@/enums/PageState'; -import { useMasterSafe } from '@/hooks/useMasterSafe'; +import { Pages } from '@/enums/Pages'; import { usePageState } from '@/hooks/usePageState'; import { useSetup } from '@/hooks/useSetup'; -import { useWallet } from '@/hooks/useWallet'; +import { useMasterWalletContext } from '@/hooks/useWallet'; import { WalletService } from '@/service/Wallet'; import { delayInSeconds } from '@/utils/delay'; const { Text } = Typography; -const capitalizedMiddlewareChainNames = { - [+MiddlewareChain.ETHEREUM]: 'Ethereum', - [+MiddlewareChain.BASE]: 'Base', - [+MiddlewareChain.OPTIMISM]: 'Optimism', +const capitalizedMiddlewareChainNames: { [key in MiddlewareChain]: string } = { + [MiddlewareChain.ETHEREUM]: 'Ethereum', + [MiddlewareChain.BASE]: 'Base', + [MiddlewareChain.OPTIMISM]: 'Optimism', + [MiddlewareChain.GOERLI]: 'Goerli', + [MiddlewareChain.GNOSIS]: 'Gnosis', + [MiddlewareChain.SOLANA]: 'Solana', + [MiddlewareChain.MODE]: 'Mode', }; +const YouWillBeRedirected = ({ text }: { text: string }) => ( + <> + logo + + {text} + + + You will be redirected once the account is created. + + +); + +const CreationError = () => ( + <> + logo + + Error, please restart the app and try again. + + + If the issue persists,{' '} + + contact Olas community support {UNICODE_SYMBOLS.EXTERNAL_LINK} + + . + + +); + export const SetupCreateSafe = () => { const { goto } = usePageState(); - const { - updateWallets, - masterSafeAddressKeyExistsForChain, - masterSafeAddress, - } = useWallet(); - const { updateMasterSafeOwners } = useMasterSafe(); + const { masterSafes, refetch: updateWallets } = useMasterWalletContext(); + // const { updateMasterSafeOwners } = useMultisig(); const { backupSigner } = useSetup(); + const masterSafeAddress = useMemo(() => { + if (!masterSafes) return; + return masterSafes[0]?.address; + }, [masterSafes]); + const [isCreatingSafe, setIsCreatingSafe] = useState(false); - const [optimismFailed, setOptimismFailed] = useState(false); - const [ethereumFailed, setEthereumFailed] = useState(false); - const [baseFailed, setBaseFailed] = useState(false); + const [gnosisFailed, setGnosisFailed] = useState(false); + // const [optimismFailed, setOptimismFailed] = useState(false); + // const [ethereumFailed, setEthereumFailed] = useState(false); + // const [baseFailed, setBaseFailed] = useState(false); - const [isOptimismSuccess, setIsOptimismSuccess] = useState(false); - const [isEthereumSuccess, setIsEthereumSuccess] = useState(false); - const [isBaseSuccess, setIsBaseSuccess] = useState(false); + const [isGnosisSuccess, setIsGnosisSuccess] = useState(false); + // const [isOptimismSuccess, setIsOptimismSuccess] = useState(false); + // const [isEthereumSuccess, setIsEthereumSuccess] = useState(false); + // const [isBaseSuccess, setIsBaseSuccess] = useState(false); const createSafeWithRetries = useCallback( async (middlewareChain: MiddlewareChain, retries: number) => { setIsCreatingSafe(true); - // If we have retried too many times, set failed - if (retries <= 0) { - if (middlewareChain === MiddlewareChain.OPTIMISM) { - setOptimismFailed(true); - setIsOptimismSuccess(false); - throw new Error('Failed to create safe on Ethereum'); - } - if (middlewareChain === MiddlewareChain.ETHEREUM) { - setEthereumFailed(true); - setIsEthereumSuccess(false); - throw new Error('Failed to create safe on Ethereum'); - } - if (middlewareChain === MiddlewareChain.BASE) { - setBaseFailed(true); - setIsBaseSuccess(false); - throw new Error('Failed to create safe on Base'); - } - throw new Error('Failed to create safe as chain is not supported'); - } - - // Try to create the safe - WalletService.createSafe(middlewareChain, backupSigner) - .then(async () => { - // Attempt wallet and master safe updates before proceeding - try { - await updateWallets(); - await updateMasterSafeOwners(); - } catch (e) { - console.error(e); - } + for (let attempt = retries; attempt > 0; attempt--) { + try { + // Attempt to create the safe + await WalletService.createSafe(middlewareChain, backupSigner); - // Set states for successful creation + // Update wallets and handle successful creation + await updateWallets?.(); setIsCreatingSafe(false); - setOptimismFailed(false); - }) - .catch(async (e) => { + setGnosisFailed(false); + break; // Exit the loop once successful + } catch (e) { console.error(e); - // Wait for 5 seconds before retrying - await delayInSeconds(5); - // Retry - const newRetries = retries - 1; - if (newRetries <= 0) { - message.error('Failed to create account'); + if (attempt === 1) { + // Final failure case after all retries + // If we have retried too many times, set failed + // if (middlewareChain === MiddlewareChain.OPTIMISM) { + // setOptimismFailed(true); + // setIsOptimismSuccess(false); + // throw new Error('Failed to create safe on Optimism'); + // } + // if (middlewareChain === MiddlewareChain.ETHEREUM) { + // setEthereumFailed(true); + // setIsEthereumSuccess(false); + // throw new Error('Failed to create safe on Ethereum'); + // } + // if (middlewareChain === MiddlewareChain.BASE) { + // setBaseFailed(true); + // setIsBaseSuccess(false); + // throw new Error('Failed to create safe on Base'); + // } + + if (middlewareChain === MiddlewareChain.GNOSIS) { + setGnosisFailed(true); + setIsGnosisSuccess(false); + throw new Error('Failed to create safe on Gnosis'); + } + + throw new Error('Failed to create safe as chain is not supported'); } else { - message.error('Failed to create account, retrying in 5 seconds'); + // Retry delay + message.error( + `Failed to create account, retrying in 5 seconds... (${attempt - 1} retries left)`, + ); + await delayInSeconds(5); } - createSafeWithRetries(middlewareChain, newRetries); - }); + } + } }, - [backupSigner, updateMasterSafeOwners, updateWallets], + [backupSigner, updateWallets], ); const creationStatusText = useMemo(() => { @@ -109,37 +146,47 @@ export const SetupCreateSafe = () => { /** * Avoid creating safes if any of the following conditions are met: */ - [optimismFailed, baseFailed, ethereumFailed].some((x) => x) || // any of the chains failed + [ + // optimismFailed, baseFailed, ethereumFailed + gnosisFailed, + ].some((x) => x) || // any of the chains failed isCreatingSafe //|| // already creating a safe // [isBaseSuccess, isEthereumSuccess, isOptimismSuccess].some((x) => !x) // any of the chains are not successful ) return; const chainsToCreateSafesFor = { - [MiddlewareChain.OPTIMISM]: masterSafeAddressKeyExistsForChain( - MiddlewareChain.OPTIMISM, - ), - [MiddlewareChain.ETHEREUM]: masterSafeAddressKeyExistsForChain( - MiddlewareChain.ETHEREUM, - ), - [MiddlewareChain.BASE]: masterSafeAddressKeyExistsForChain( - MiddlewareChain.BASE, - ), + // [MiddlewareChain.OPTIMISM]: masterSafeAddressKeyExistsForChain( + // MiddlewareChain.OPTIMISM, + // ), + // [MiddlewareChain.ETHEREUM]: masterSafeAddressKeyExistsForChain( + // MiddlewareChain.ETHEREUM, + // ), + // [MiddlewareChain.BASE]: masterSafeAddressKeyExistsForChain( + // MiddlewareChain.BASE, + // ), + [MiddlewareChain.GNOSIS]: !!masterSafeAddress, }; const safeCreationsRequired = Object.entries(chainsToCreateSafesFor).reduce( (acc, [chain, safeAddressAlreadyExists]) => { - const middlewareChain = +chain as MiddlewareChain; + const middlewareChain = chain as MiddlewareChain; if (safeAddressAlreadyExists) { + // switch (middlewareChain) { + // case MiddlewareChain.OPTIMISM: + // setIsOptimismSuccess(true); + // break; + // case MiddlewareChain.ETHEREUM: + // setIsEthereumSuccess(true); + // break; + // case MiddlewareChain.BASE: + // setIsBaseSuccess(true); + // break; + // } + switch (middlewareChain) { - case MiddlewareChain.OPTIMISM: - setIsOptimismSuccess(true); - break; - case MiddlewareChain.ETHEREUM: - setIsEthereumSuccess(true); - break; - case MiddlewareChain.BASE: - setIsBaseSuccess(true); + case MiddlewareChain.GNOSIS: + setIsGnosisSuccess(true); break; } return acc; @@ -169,14 +216,16 @@ export const SetupCreateSafe = () => { }, [ backupSigner, createSafeWithRetries, - optimismFailed, + masterSafeAddress, isCreatingSafe, - isBaseSuccess, - isEthereumSuccess, - isOptimismSuccess, - baseFailed, - ethereumFailed, - masterSafeAddressKeyExistsForChain, + // optimismFailed, + // isBaseSuccess, + // isEthereumSuccess, + // isOptimismSuccess, + // baseFailed, + // ethereumFailed, + isGnosisSuccess, + gnosisFailed, ]); useEffect(() => { @@ -193,39 +242,10 @@ export const SetupCreateSafe = () => { padding="80px 24px" gap={12} > - {optimismFailed ? ( - <> - logo - - Error, please restart the app and try again. - - - If the issue persists,{' '} - - contact Olas community support {UNICODE_SYMBOLS.EXTERNAL_LINK} - - . - - + {gnosisFailed ? ( + ) : ( - <> - logo - - {creationStatusText} - - - You will be redirected once the account is created. - - + )} diff --git a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx index da81b7ddd..5f8d6492b 100644 --- a/frontend/components/SetupPage/Create/SetupEoaFunding.tsx +++ b/frontend/components/SetupPage/Create/SetupEoaFunding.tsx @@ -1,7 +1,7 @@ import { CopyOutlined } from '@ant-design/icons'; import { Flex, message, Tooltip, Typography } from 'antd'; import { BigNumber, ethers } from 'ethers'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; import { useInterval } from 'usehooks-ts'; @@ -9,16 +9,15 @@ import { MiddlewareChain } from '@/client'; import { CustomAlert } from '@/components/Alert'; import { CardFlex } from '@/components/styled/CardFlex'; import { CardSection } from '@/components/styled/CardSection'; -import { CHAINS } from '@/constants/chains'; -import { - baseProvider, - ethereumProvider, - optimismProvider, -} from '@/constants/providers'; +import { CHAIN_CONFIG } from '@/config/chains'; +import { PROVIDERS } from '@/constants/providers'; +import { NA } from '@/constants/symbols'; import { MIN_ETH_BALANCE_THRESHOLDS } from '@/constants/thresholds'; +import { EvmChainId } from '@/enums/Chain'; import { SetupScreen } from '@/enums/SetupScreen'; +import { useMasterBalances } from '@/hooks/useBalanceContext'; import { useSetup } from '@/hooks/useSetup'; -import { useWallet } from '@/hooks/useWallet'; +import { useMasterWalletContext } from '@/hooks/useWallet'; import { Address } from '@/types/Address'; import { copyToClipboard } from '@/utils/copyToClipboard'; import { delayInSeconds } from '@/utils/delay'; @@ -40,9 +39,18 @@ const AccountCreationCard = styled.div` const ICON_STYLE = { color: '#606F85' }; +const statusMessage = (isFunded?: boolean) => { + if (isFunded) { + return 'Funds have been received!'; + } else { + return 'Waiting for transaction'; + } +}; + type SetupEoaFundingWaitingProps = { chainName: string }; const SetupEoaFundingWaiting = ({ chainName }: SetupEoaFundingWaitingProps) => { - const { masterEoaAddress } = useWallet(); + const { masterEoa } = useMasterWalletContext(); + const masterEoaAddress = masterEoa?.address; return ( <> @@ -80,7 +88,7 @@ const SetupEoaFundingWaiting = ({ chainName }: SetupEoaFundingWaitingProps) => { - {`ETH: ${masterEoaAddress}`} + {`XDAI: ${masterEoaAddress || NA}`} {/* { const { goto } = useSetup(); - const statusMessage = useMemo(() => { - if (isFunded) { - return 'Funds have been received!'; - } else { - return 'Waiting for transaction'; - } - }, [isFunded]); - useEffect(() => { message.success(`${chainName} funds have been received!`); @@ -141,7 +141,7 @@ export const SetupEoaFundingForChain = ({ borderbottom={isFunded ? 'true' : 'false'} > - Status: {statusMessage} + Status: {statusMessage(isFunded)} {!isFunded && } @@ -149,35 +149,43 @@ export const SetupEoaFundingForChain = ({ ); }; +// TODO: chain independent const eoaFundingMap = { - [MiddlewareChain.OPTIMISM]: { - provider: optimismProvider, - chainConfig: CHAINS.OPTIMISM, - requiredEth: - MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.OPTIMISM].safeCreation, - }, - [MiddlewareChain.ETHEREUM]: { - provider: ethereumProvider, - chainConfig: CHAINS.ETHEREUM, - requiredEth: - MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.ETHEREUM].safeCreation, - }, - [MiddlewareChain.BASE]: { - provider: baseProvider, - chainConfig: CHAINS.BASE, - requiredEth: MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.BASE].safeCreation, + // [MiddlewareChain.OPTIMISM]: { + // provider: OPTIMISM_PROVIDER, + // chainConfig: CHAIN_CONFIG.OPTIMISM, + // requiredEth: + // MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.OPTIMISM].safeCreation, + // }, + // [MiddlewareChain.ETHEREUM]: { + // provider: ETHEREUM_PROVIDER, + // chainConfig: CHAIN_CONFIG.ETHEREUM, + // requiredEth: + // MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.ETHEREUM].safeCreation, + // }, + // [MiddlewareChain.BASE]: { + // provider: BASE_PROVIDER, + // chainConfig: CHAIN_CONFIG.BASE, + // requiredEth: MIN_ETH_BALANCE_THRESHOLDS[MiddlewareChain.BASE].safeCreation, + // }, + [MiddlewareChain.GNOSIS]: { + provider: PROVIDERS[EvmChainId.Gnosis].provider, + chainConfig: CHAIN_CONFIG[EvmChainId.Gnosis], + requiredEth: MIN_ETH_BALANCE_THRESHOLDS[EvmChainId.Gnosis].safeCreation, }, }; export const SetupEoaFunding = () => { const { goto } = useSetup(); - const { masterEoaAddress } = useWallet(); + const { masterEoa } = useMasterWalletContext(); + const { masterWalletBalances } = useMasterBalances(); + const masterEoaAddress = masterEoa?.address; + const [currentChain, setCurrentChain] = useState( - +Object.keys(eoaFundingMap)[0] as MiddlewareChain, + MiddlewareChain.GNOSIS, ); - const currentFundingMapObject = - eoaFundingMap[+currentChain as keyof typeof eoaFundingMap]; + const currentFundingMapObject = eoaFundingMap[MiddlewareChain.GNOSIS]; const getIsCurrentChainFunded = useCallback( async ( @@ -218,32 +226,40 @@ export const SetupEoaFunding = () => { if (nextChainExists) { // goto next chain setCurrentChain( - +Object.keys(eoaFundingMap)[indexOfCurrentChain + 1] as MiddlewareChain, + Object.keys(eoaFundingMap)[indexOfCurrentChain + 1] as MiddlewareChain, ); return; } goto(SetupScreen.SetupCreateSafe); }, 5000); + const eoaBalance = masterWalletBalances?.find( + (balance) => balance.walletAddress === masterEoaAddress, + ); + const isFunded = + eoaBalance?.evmChainId === EvmChainId.Gnosis && + eoaBalance.balance >= + MIN_ETH_BALANCE_THRESHOLDS[EvmChainId.Gnosis].safeCreation; + return ( - {`Deposit ${currentFundingMapObject.requiredEth} ${currentFundingMapObject.chainConfig.currency} on ${currentFundingMapObject.chainConfig.name}`} + {`Deposit ${currentFundingMapObject.requiredEth} ${currentFundingMapObject.chainConfig.nativeToken.symbol} on ${currentFundingMapObject.chainConfig.name}`} The app needs these funds to create your account on-chain. - {/* - Status: {statusMessage} + Status: {statusMessage(isFunded)} - */} + { const [form] = Form.useForm<{ password: string; terms: boolean }>(); const [isLoading, setIsLoading] = useState(false); - const isTermsAccepted = Form.useWatch('terms', form); const handleCreateEoa = async ({ password }: { password: string }) => { @@ -26,7 +24,7 @@ export const SetupPassword = () => { setIsLoading(true); AccountService.createAccount(password) .then(() => AccountService.loginAccount(password)) - .then(() => WalletService.createEoa(MiddlewareChain.OPTIMISM)) + .then(() => WalletService.createEoa()) .then(({ mnemonic }: { mnemonic: string[] }) => { setMnemonic(mnemonic); goto(SetupScreen.SetupSeedPhrase); diff --git a/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx b/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx index 46a8d1bca..dd8811f61 100644 --- a/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx +++ b/frontend/components/SetupPage/Create/SetupSeedPhrase.tsx @@ -18,6 +18,7 @@ export const SetupSeedPhrase = () => { Back up seed phrase + Seed phrase is needed to regain access to your account if you forget @@ -33,6 +34,7 @@ export const SetupSeedPhrase = () => { ))} + + If you don’t have the seed phrase but added a backup wallet to your @@ -134,6 +136,7 @@ export const SetupRestoreViaSeed = () => { export const SetupRestoreSetPassword = () => { const { goto } = useSetup(); const [password, setPassword] = useState(''); + return ( { const electronApi = useElectronApi(); - const [isSetup, setIsSetup] = useState(null); + const [isSetup, setIsSetup] = useState(null); useEffect(() => { if (isSetup !== null) return; - setIsSetup(AccountIsSetup.Loading); + setIsSetup(MiddlewareAccountIsSetup.Loading); AccountService.getAccount() .then((res) => { switch (res.is_setup) { case true: - setIsSetup(AccountIsSetup.True); + setIsSetup(MiddlewareAccountIsSetup.True); break; case false: { // Reset persistent state // if creating new account electronApi.store?.clear?.(); - setIsSetup(AccountIsSetup.False); + setIsSetup(MiddlewareAccountIsSetup.False); break; } default: - setIsSetup(AccountIsSetup.Error); + setIsSetup(MiddlewareAccountIsSetup.Error); break; } }) .catch((e) => { console.error(e); - setIsSetup(AccountIsSetup.Error); + setIsSetup(MiddlewareAccountIsSetup.Error); }); }, [electronApi.store, isSetup]); const welcomeScreen = useMemo(() => { switch (isSetup) { - case AccountIsSetup.True: + case MiddlewareAccountIsSetup.True: return ; - case AccountIsSetup.False: + case MiddlewareAccountIsSetup.False: return ; - case AccountIsSetup.Loading: + case MiddlewareAccountIsSetup.Loading: return ( { ); - case AccountIsSetup.Error: + case MiddlewareAccountIsSetup.Error: return ( { const { goto } = useSetup(); const { goto: gotoPage } = usePageState(); - const { masterSafeAddress, wallets } = useWallet(); - const { isBalanceLoaded, masterEoaBalance: eoaBalance } = useBalance(); + const { selectedService } = useServices(); + const { + masterSafes, + masterWallets: wallets, + masterEoa, + } = useMasterWalletContext(); + const { isLoaded: isBalanceLoaded, updateBalances } = useBalanceContext(); + const { masterWalletBalances } = useMasterBalances(); + + const masterSafe = + masterSafes?.find( + (safe) => + selectedService?.home_chain && + safe.evmChainId === asEvmChainId(selectedService?.home_chain), + ) ?? null; + + const eoaBalanceEth = masterWalletBalances?.find( + (balance) => balance.walletAddress === masterEoa?.address, + ); const [isLoggingIn, setIsLoggingIn] = useState(false); const [canNavigate, setCanNavigate] = useState(false); @@ -141,7 +163,8 @@ export const SetupWelcomeLogin = () => { async ({ password }: { password: string }) => { setIsLoggingIn(true); AccountService.loginAccount(password) - .then(() => { + .then(async () => { + await updateBalances(); setCanNavigate(true); }) .catch((e) => { @@ -150,17 +173,20 @@ export const SetupWelcomeLogin = () => { message.error('Invalid password'); }); }, - [], + [updateBalances], ); useEffect(() => { // Navigate only when wallets and balances are loaded // To check if some setup steps were missed - if (canNavigate && wallets?.length && isBalanceLoaded) { + // if (canNavigate && wallets?.length && isBalanceLoaded) { + + // TODO: fix wallet and balance loads + if (canNavigate) { setIsLoggingIn(false); - if (!eoaBalance?.ETH) { + if (!eoaBalanceEth) { goto(SetupScreen.SetupEoaFundingIncomplete); - } else if (!masterSafeAddress) { + } else if (!masterSafe?.address) { goto(SetupScreen.SetupCreateSafe); } else { gotoPage(Pages.Main); @@ -168,11 +194,11 @@ export const SetupWelcomeLogin = () => { } }, [ canNavigate, - eoaBalance?.ETH, + eoaBalanceEth, goto, gotoPage, isBalanceLoaded, - masterSafeAddress, + masterSafe?.address, wallets?.length, ]); diff --git a/frontend/components/SetupPage/index.tsx b/frontend/components/SetupPage/index.tsx index 412f4bc83..935ac2810 100644 --- a/frontend/components/SetupPage/index.tsx +++ b/frontend/components/SetupPage/index.tsx @@ -16,6 +16,10 @@ import { } from './SetupRestore'; import { SetupWelcome } from './SetupWelcome'; +const UnexpectedError = () => ( +
Something went wrong!
+); + export const Setup = () => { const { setupObject } = useContext(SetupContext); const setupScreen = useMemo(() => { @@ -45,7 +49,7 @@ export const Setup = () => { case SetupScreen.RestoreViaBackup: return ; default: - return <>Error; + return ; } }, [setupObject.state]); diff --git a/frontend/components/YourWalletPage/Titles.tsx b/frontend/components/YourWalletPage/Titles.tsx index 4b2c7645f..c5f46af9b 100644 --- a/frontend/components/YourWalletPage/Titles.tsx +++ b/frontend/components/YourWalletPage/Titles.tsx @@ -1,6 +1,7 @@ import { Flex, Typography } from 'antd'; import { InfoTooltip } from '@/components/InfoTooltip'; +import { TokenSymbol } from '@/enums/Token'; import { Address } from '@/types/Address'; import { AddressLink } from '../AddressLink'; @@ -17,8 +18,8 @@ export const SignerTitle = ({ Signer  - Your wallet and agent’s wallet use Safe, a multi-signature wallet. The - app is designed to trigger transactions on these Safe wallets via + Your wallet and agent's wallet use Safe, a multi-signature wallet. + The app is designed to trigger transactions on these Safe wallets via Signers. @@ -43,23 +44,24 @@ export const OlasTitle = () => ( Agent rewards accumulate in the staking contract. The agent is designed - to claim rewards periodically. Withdrawal of claimed rewards isn’t + to claim rewards periodically. Withdrawal of claimed rewards isn't available yet.
); -export const XdaiTitle = () => ( +export const NativeTokenTitle = ({ symbol }: { symbol: TokenSymbol }) => ( - XDAI + {symbol}   + {/* TODO: address multi-agent tooltip, specfic to agent config */} - XDAI is used by the agent to engage in prediction markets. This amount - will fluctuate based on your agent’s performance. + {symbol} is used by the agent to engage in prediction markets. This + amount will fluctuate based on your agent's performance. @@ -75,20 +77,20 @@ export const OwnershipNftTitle = () => ( Agents are minted through the Olas Registry. Each agent has an NFT - that gives its owner control over the agent’s settings. + that gives its owner control over the agent's settings.
); -export const ServiceIdTitle = () => ( +export const ServiceNftIdTitle = () => ( ID  Each minted agent gets a unique ID. Technically, agents are referred to - as ‘services’. + as 'services'. diff --git a/frontend/components/YourWalletPage/YourAgent.tsx b/frontend/components/YourWalletPage/YourAgent.tsx index 8105e9d52..811565f54 100644 --- a/frontend/components/YourWalletPage/YourAgent.tsx +++ b/frontend/components/YourWalletPage/YourAgent.tsx @@ -1,15 +1,22 @@ import { Card, Flex, Skeleton, Tooltip, Typography } from 'antd'; +import { isArray, isEmpty, isNil } from 'lodash'; import Image from 'next/image'; import { useMemo } from 'react'; import styled from 'styled-components'; -import { MiddlewareChain } from '@/client'; -import { SERVICE_REGISTRY_L2_CONTRACT_ADDRESS } from '@/constants/contractAddresses'; +import { OLAS_CONTRACTS } from '@/config/olasContracts'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { useAddress } from '@/hooks/useAddress'; -import { useBalance } from '@/hooks/useBalance'; +import { EvmChainId } from '@/enums/Chain'; +import { ContractType } from '@/enums/Contract'; +import { TokenSymbol } from '@/enums/Token'; +import { AgentSafe, Safe } from '@/enums/Wallet'; +import { + useBalanceContext, + useServiceBalances, +} from '@/hooks/useBalanceContext'; import { useReward } from '@/hooks/useReward'; -import { useServices } from '@/hooks/useServices'; +import { useService } from '@/hooks/useService'; +import { Address } from '@/types/Address'; import { generateName } from '@/utils/agentName'; import { balanceFormat } from '@/utils/numberFormatters'; import { truncateAddress } from '@/utils/truncate'; @@ -17,13 +24,7 @@ import { truncateAddress } from '@/utils/truncate'; import { AddressLink } from '../AddressLink'; import { InfoBreakdownList } from '../InfoBreakdown'; import { Container, infoBreakdownParentStyle } from './styles'; -import { - OlasTitle, - OwnershipNftTitle, - ServiceIdTitle, - SignerTitle, - XdaiTitle, -} from './Titles'; +import { OlasTitle, OwnershipNftTitle, ServiceNftIdTitle } from './Titles'; const { Text, Paragraph } = Typography; @@ -36,8 +37,8 @@ const NftCard = styled(Card)` } `; -const SafeAddress = () => { - const { multisigAddress } = useAddress(); +const SafeAddress = ({ serviceSafe }: { serviceSafe: Safe }) => { + const multisigAddress = serviceSafe.address; return ( @@ -56,12 +57,10 @@ const SafeAddress = () => { ); }; -const AgentTitle = () => { - const { multisigAddress: agentSafeAddress } = useAddress(); - +const AgentTitle = ({ serviceSafe }: { serviceSafe: AgentSafe }) => { const agentName = useMemo( - () => (agentSafeAddress ? generateName(agentSafeAddress) : '--'), - [agentSafeAddress], + () => (serviceSafe ? generateName(serviceSafe.address) : '--'), + [serviceSafe], ); return ( @@ -83,22 +82,21 @@ const AgentTitle = () => { arrow={false} title={ - This is your agent’s unique name + This is your agent's unique name } placement="top" > {agentName} - {/* - ONLY APPLIES TO PREDICT AGENT + {/* TODO: address multi-agent at later point */} Agent profile {UNICODE_SYMBOLS.EXTERNAL_LINK} - */} + @@ -106,10 +104,13 @@ const AgentTitle = () => { ); }; -const ServiceAndNftDetails = () => { - const { serviceId } = useServices(); - const serviceAddress = - SERVICE_REGISTRY_L2_CONTRACT_ADDRESS[`${MiddlewareChain.OPTIMISM}`]; +const ServiceAndNftDetails = ({ + serviceNftTokenId, +}: { + serviceNftTokenId: number; +}) => { + const serviceRegistryL2ContractAddress = + OLAS_CONTRACTS[EvmChainId.Gnosis][ContractType.ServiceRegistryL2].address; return ( @@ -126,20 +127,21 @@ const ServiceAndNftDetails = () => { - {truncateAddress(serviceAddress)} {UNICODE_SYMBOLS.EXTERNAL_LINK} + {truncateAddress(serviceRegistryL2ContractAddress as Address)}{' '} + {UNICODE_SYMBOLS.EXTERNAL_LINK} - + - {serviceId} {UNICODE_SYMBOLS.EXTERNAL_LINK} + {serviceNftTokenId} {UNICODE_SYMBOLS.EXTERNAL_LINK} @@ -148,26 +150,42 @@ const ServiceAndNftDetails = () => { ); }; -export const YourAgentWallet = () => { - const { isBalanceLoaded, agentSafeBalance, agentEoaBalance } = useBalance(); +export const YourAgentWallet = ({ + serviceConfigId, +}: { + serviceConfigId: string; +}) => { + const { isLoaded } = useBalanceContext(); + const { serviceSafes, serviceNftTokenId, serviceEoa } = + useService(serviceConfigId); + const { serviceSafeBalances, serviceEoaBalances } = + useServiceBalances(serviceConfigId); + const { availableRewardsForEpochEth, isEligibleForRewards, accruedServiceStakingRewards, } = useReward(); - const { instanceAddress: agentEoaAddress } = useAddress(); const reward = useMemo(() => { - if (!isBalanceLoaded) return ; + if (!isLoaded) return ; if (!isEligibleForRewards) return 'Not yet earned'; return `~${balanceFormat(availableRewardsForEpochEth, 2)} OLAS`; - }, [isBalanceLoaded, isEligibleForRewards, availableRewardsForEpochEth]); + }, [isLoaded, isEligibleForRewards, availableRewardsForEpochEth]); - const olasBalances = useMemo(() => { - return [ + const serviceSafeOlasBalances = useMemo( + () => + serviceSafeBalances?.filter( + (walletBalance) => walletBalance.symbol === TokenSymbol.OLAS, + ), + [serviceSafeBalances], + ); + + const serviceSafeRewards = useMemo( + () => [ { title: 'Claimed rewards', - value: `${balanceFormat(agentSafeBalance?.OLAS, 2)} OLAS`, + value: `${balanceFormat(serviceSafeOlasBalances?.[0]?.balance ?? 0, 2)} OLAS`, }, { title: 'Unclaimed rewards', @@ -177,58 +195,78 @@ export const YourAgentWallet = () => { title: 'Current epoch rewards', value: reward, }, - ]; - }, [agentSafeBalance?.OLAS, accruedServiceStakingRewards, reward]); + ], + [accruedServiceStakingRewards, reward, serviceSafeOlasBalances], + ); + + const serviceSafeNativeBalances = useMemo( + () => serviceSafeBalances?.filter((balance) => balance.isNative), + [serviceSafeBalances], + ); + + const serviceEoaNativeBalances = useMemo( + () => serviceEoaBalances?.filter((balance) => balance.isNative), + [serviceEoaBalances], + ); + + const serviceSafe = useMemo(() => { + if (isNil(serviceSafes) || isEmpty(serviceSafes)) return null; + return serviceSafes[0]; + }, [serviceSafes]); + + if (isNil(serviceSafe)) return null; return ( - }> + }> - - - - - ({ - left: item.title, - leftClassName: 'text-light text-sm', - right: item.value, - }))} - parentStyle={infoBreakdownParentStyle} - /> - + - - , + {!isEmpty(serviceSafeRewards) && ( + + + ({ + left: item.title, leftClassName: 'text-light text-sm', - right: `${balanceFormat(agentSafeBalance?.ETH, 2)} XDAI`, - }, - ]} - parentStyle={infoBreakdownParentStyle} - /> - + right: item.value, + }))} + parentStyle={infoBreakdownParentStyle} + /> + + )} - - - ), - leftClassName: 'text-light text-sm', - right: `${balanceFormat(agentEoaBalance?.ETH, 2)} XDAI`, - }, - ]} - parentStyle={infoBreakdownParentStyle} - /> - + {(!isNil(serviceSafeNativeBalances) || + !isNil(serviceEoaNativeBalances)) && ( + + {isArray(serviceSafeNativeBalances) && ( + ({ + left: {balance.symbol}, + leftClassName: 'text-sm', + right: `${balanceFormat(balance.balance, 2)} ${balance.symbol}`, + }))} + parentStyle={infoBreakdownParentStyle} + /> + )} + {!isNil(serviceEoa) && ( + , + rightClassName: 'font-normal text-sm', + }, + ]} + parentStyle={infoBreakdownParentStyle} + /> + )} + + )} - + {!isNil(serviceNftTokenId) && ( + + )} ); diff --git a/frontend/components/YourWalletPage/index.tsx b/frontend/components/YourWalletPage/index.tsx index 1d09879db..163fdc388 100644 --- a/frontend/components/YourWalletPage/index.tsx +++ b/frontend/components/YourWalletPage/index.tsx @@ -1,16 +1,32 @@ import { CloseOutlined } from '@ant-design/icons'; -import { Button, ConfigProvider, Flex, ThemeConfig, Typography } from 'antd'; +import { + Button, + ConfigProvider, + Flex, + Skeleton, + ThemeConfig, + Typography, +} from 'antd'; +import { isEmpty, isNil } from 'lodash'; import { useMemo } from 'react'; import { AddressLink } from '@/components/AddressLink'; import { CardTitle } from '@/components/Card/CardTitle'; import { InfoBreakdownList } from '@/components/InfoBreakdown'; import { CardFlex } from '@/components/styled/CardFlex'; -import { Pages } from '@/enums/PageState'; -import { useBalance } from '@/hooks/useBalance'; +import { getNativeTokenSymbol } from '@/config/tokens'; +import { EvmChainId } from '@/enums/Chain'; +import { Pages } from '@/enums/Pages'; +import { TokenSymbol } from '@/enums/Token'; +import { + useBalanceContext, + useMasterBalances, +} from '@/hooks/useBalanceContext'; import { usePageState } from '@/hooks/usePageState'; import { useServices } from '@/hooks/useServices'; -import { useWallet } from '@/hooks/useWallet'; +import { useMasterWalletContext } from '@/hooks/useWallet'; +import { type Address } from '@/types/Address'; +import { Optional } from '@/types/Util'; import { balanceFormat } from '@/utils/numberFormatters'; import { Container, infoBreakdownParentStyle } from './styles'; @@ -25,10 +41,15 @@ const yourWalletTheme: ThemeConfig = { }, }; -const YourWalletTitle = () => ; +const YourWalletTitle = () => ; const Address = () => { - const { masterSafeAddress } = useWallet(); + const { masterSafes } = useMasterWalletContext(); + + if (!masterSafes) return ; + if (isEmpty(masterSafes)) return null; + + const masterSafeAddress = masterSafes[0].address; // TODO: handle multiple safes in future return ( @@ -48,29 +69,36 @@ const Address = () => { }; const OlasBalance = () => { - const { masterSafeBalance: safeBalance, totalOlasStakedBalance } = - useBalance(); + const { totalStakedOlasBalance } = useBalanceContext(); + const { masterWalletBalances } = useMasterBalances(); + + const masterSafeOlasBalance = masterWalletBalances + ?.filter((walletBalance) => walletBalance.symbol === TokenSymbol.OLAS) + .reduce((acc, balance) => acc + balance.balance, 0); + const olasBalances = useMemo(() => { return [ { title: 'Available', - value: balanceFormat(safeBalance?.OLAS ?? 0, 2), + value: balanceFormat(masterSafeOlasBalance ?? 0, 2), }, { title: 'Staked', - value: balanceFormat(totalOlasStakedBalance ?? 0, 2), + value: balanceFormat(totalStakedOlasBalance ?? 0, 2), }, ]; - }, [safeBalance?.OLAS, totalOlasStakedBalance]); + }, [masterSafeOlasBalance, totalStakedOlasBalance]); + + if (isNil(masterSafeOlasBalance)) return ; return ( - OLAS + {TokenSymbol.OLAS} ({ left: item.title, leftClassName: 'text-light', - right: `${item.value} OLAS`, + right: `${item.value} ${TokenSymbol.OLAS}`, }))} parentStyle={infoBreakdownParentStyle} /> @@ -78,17 +106,50 @@ const OlasBalance = () => { ); }; -const XdaiBalance = () => { - const { masterSafeBalance: safeBalance } = useBalance(); +const MasterSafeNativeBalance = () => { + const { selectedAgentConfig } = useServices(); + const { masterSafes } = useMasterWalletContext(); + const { masterSafeBalances } = useMasterBalances(); + + const selectedMasterSafe = useMemo(() => { + if (!masterSafes) return; + if (!selectedAgentConfig) return; + + return masterSafes.find( + (masterSafe) => + masterSafe.evmChainId === selectedAgentConfig.evmHomeChainId, + ); + }, [masterSafes, selectedAgentConfig]); + + const selectedMasterSafeNativeBalance: Optional = useMemo(() => { + if (isNil(selectedMasterSafe)) return; + if (isNil(masterSafeBalances)) return; + + return masterSafeBalances + .filter(({ walletAddress, evmChainId, isNative }) => { + return ( + evmChainId === selectedAgentConfig?.evmHomeChainId && // TODO: address multi chain, need to refactor as per product requirement + isNative && + walletAddress === selectedMasterSafe.address + ); + }) + .reduce((acc, { balance }) => acc + balance, 0); + }, [ + masterSafeBalances, + selectedAgentConfig?.evmHomeChainId, + selectedMasterSafe, + ]); + + const nativeTokenSymbol = getNativeTokenSymbol(EvmChainId.Gnosis); return ( XDAI, + left: {getNativeTokenSymbol(EvmChainId.Gnosis)}, leftClassName: 'text-light', - right: `${balanceFormat(safeBalance?.ETH, 2)} XDAI`, + right: `${balanceFormat(selectedMasterSafeNativeBalance, 2)} ${nativeTokenSymbol}`, }, ]} parentStyle={infoBreakdownParentStyle} @@ -97,9 +158,29 @@ const XdaiBalance = () => { ); }; -const Signer = () => { - const { masterEoaAddress } = useWallet(); - const { masterEoaBalance: eoaBalance } = useBalance(); +const MasterEoaSignerNativeBalance = () => { + const { masterEoa } = useMasterWalletContext(); + const { masterWalletBalances } = useMasterBalances(); + const { selectedAgentConfig } = useServices(); + + const masterEoaBalance: Optional = useMemo(() => { + if (isNil(masterEoa)) return; + if (isNil(masterWalletBalances)) return; + + return masterWalletBalances + .filter( + ({ walletAddress, isNative, evmChainId }) => + walletAddress === masterEoa.address && + isNative && + selectedAgentConfig?.evmHomeChainId === evmChainId, // TODO: address multi chain, need to refactor as per product requirement + ) + .reduce((acc, { balance }) => acc + balance, 0); + }, [masterEoa, masterWalletBalances, selectedAgentConfig?.evmHomeChainId]); + + const nativeTokenSymbol = useMemo( + () => getNativeTokenSymbol(EvmChainId.Gnosis), // TODO: support multi chain + [], + ); return ( @@ -109,11 +190,11 @@ const Signer = () => { left: ( ), leftClassName: 'text-light', - right: `${balanceFormat(eoaBalance?.ETH, 2)} XDAI`, + right: `${balanceFormat(masterEoaBalance, 2)} ${nativeTokenSymbol}`, }, ]} parentStyle={infoBreakdownParentStyle} @@ -124,7 +205,8 @@ const Signer = () => { export const YourWalletPage = () => { const { goto } = usePageState(); - const { service } = useServices(); + + const { services } = useServices(); return ( @@ -142,9 +224,15 @@ export const YourWalletPage = () => {
- - - {service && } + + + {services?.map(({ service_config_id }) => ( + // TODO: bit dirty, but should be fine for now + + ))} diff --git a/frontend/components/errors/ErrorComponent.tsx b/frontend/components/errors/ErrorComponent.tsx new file mode 100644 index 000000000..12765eb20 --- /dev/null +++ b/frontend/components/errors/ErrorComponent.tsx @@ -0,0 +1,3 @@ +export const ErrorComponent = () => { + return Error; +}; diff --git a/frontend/config/activityCheckers.ts b/frontend/config/activityCheckers.ts new file mode 100644 index 000000000..5207f61c6 --- /dev/null +++ b/frontend/config/activityCheckers.ts @@ -0,0 +1,39 @@ +import { Contract as MulticallContract } from 'ethers-multicall'; + +import { MECH_ACTIVITY_CHECKER_ABI } from '@/abis/mechActivityChecker'; +import { REQUESTER_ACTIVITY_CHECKER_ABI } from '@/abis/requesterActivityChecker'; +import { EvmChainId } from '@/enums/Chain'; + +import { MechType } from './mechs'; + +enum ActivityCheckerType { + MechActivityChecker = MechType.Agent, + RequesterActivityChecker = MechType.Marketplace, + Staking = 'StakingActivityChecker', +} + +type ActivityCheckers = { + [activityCheckerType: string]: MulticallContract; +}; + +export const GNOSIS_ACTIVITY_CHECKERS: ActivityCheckers = { + [ActivityCheckerType.MechActivityChecker]: new MulticallContract( + '0x155547857680A6D51bebC5603397488988DEb1c8', + MECH_ACTIVITY_CHECKER_ABI, + ), + [ActivityCheckerType.RequesterActivityChecker]: new MulticallContract( + '0x7Ec96996Cd146B91779f01419db42E67463817a0', + REQUESTER_ACTIVITY_CHECKER_ABI, + ), +}; + +export const OPTIMISM_ACTIVITY_CHECKERS: ActivityCheckers = {}; + +export const ACTIVITY_CHECKERS: { + [chainId: number]: { + [activityCheckerType: string]: MulticallContract; + }; +} = { + [EvmChainId.Gnosis]: GNOSIS_ACTIVITY_CHECKERS, + [EvmChainId.Optimism]: OPTIMISM_ACTIVITY_CHECKERS, +} as const; diff --git a/frontend/config/agents.ts b/frontend/config/agents.ts new file mode 100644 index 000000000..b3b446982 --- /dev/null +++ b/frontend/config/agents.ts @@ -0,0 +1,38 @@ +import { MiddlewareChain } from '@/client'; +import { AgentType } from '@/enums/Agent'; +import { EvmChainId } from '@/enums/Chain'; +import { PredictTraderService } from '@/service/agents/PredictTrader'; +// import { OptimusService } from '@/service/agents/Optimus'; +import { AgentConfig } from '@/types/Agent'; + +// TODO: complete this config +// TODO: add funding requirements + +export const AGENT_CONFIG: { + [key in AgentType]: AgentConfig; +} = { + [AgentType.PredictTrader]: { + name: 'Predict Trader', + evmHomeChainId: EvmChainId.Gnosis, + middlewareHomeChainId: MiddlewareChain.GNOSIS, + requiresAgentSafesOn: [EvmChainId.Gnosis], + agentSafeFundingRequirements: { + [EvmChainId.Gnosis]: 100000000000000000, + }, + requiresMasterSafesOn: [EvmChainId.Gnosis], + serviceApi: PredictTraderService, + }, + // TODO: check optimus config + // [AgentType.Optimus]: { + // name: 'Optimus', + // homeChainId: ChainId.Optimism, + // requiresAgentSafesOn: [ChainId.Optimism, ChainId.Ethereum, ChainId.Base], + // requiresMasterSafesOn: [ChainId.Optimism, ChainId.Ethereum, ChainId.Base], + // agentSafeFundingRequirements: { + // [ChainId.Optimism]: 100000000000000000, + // [ChainId.Ethereum]: 100000000000000000, + // [ChainId.Base]: 100000000000000000, + // }, + // serviceApi: OptimusService, + // }, +}; diff --git a/frontend/config/chains.ts b/frontend/config/chains.ts new file mode 100644 index 000000000..2968cfe1d --- /dev/null +++ b/frontend/config/chains.ts @@ -0,0 +1,60 @@ +/** + * Chain configurations + * - add new chains to the CHAIN_CONFIGS object + */ +import { MiddlewareChain as MiddlewareChainId } from '@/client'; +import { EvmChainId } from '@/enums/Chain'; +import { TokenSymbol } from '@/enums/Token'; + +import { TOKEN_CONFIG, TokenConfig } from './tokens'; + +type HttpUrl = `http${'s' | ''}://${string}`; + +type ChainConfig = { + name: string; + nativeToken: TokenConfig; + evmChainId: number; + middlewareChain: MiddlewareChainId; + rpc: HttpUrl; +}; + +export const GNOSIS_CHAIN_CONFIG: ChainConfig = { + evmChainId: EvmChainId.Gnosis, + name: 'Gnosis', + nativeToken: TOKEN_CONFIG[EvmChainId.Gnosis][TokenSymbol.XDAI], + middlewareChain: MiddlewareChainId.GNOSIS, + rpc: process.env.GNOSIS_RPC as HttpUrl, +}; + +export const OPTIMISM_CHAIN_CONFIG: ChainConfig = { + evmChainId: EvmChainId.Optimism, + name: 'Optimism', + nativeToken: TOKEN_CONFIG[EvmChainId.Optimism][TokenSymbol.ETH], + middlewareChain: MiddlewareChainId.OPTIMISM, + rpc: process.env.OPTIMISM_RPC as HttpUrl, +}; + +export const BASE_CHAIN_CONFIG: ChainConfig = { + evmChainId: EvmChainId.Base, + name: 'Base', + nativeToken: TOKEN_CONFIG[EvmChainId.Base][TokenSymbol.ETH], + middlewareChain: MiddlewareChainId.BASE, + rpc: process.env.BASE_RPC as HttpUrl, +}; + +export const ETHEREUM_CHAIN_CONFIG: ChainConfig = { + evmChainId: EvmChainId.Ethereum, + name: 'Ethereum', + nativeToken: TOKEN_CONFIG[EvmChainId.Ethereum][TokenSymbol.ETH], + middlewareChain: MiddlewareChainId.ETHEREUM, + rpc: process.env.GNOSIS_RPC as HttpUrl, +}; + +export const CHAIN_CONFIG: { + [evmChainId: number]: ChainConfig; +} = { + // [EvmChainId.Base]: BASE_CHAIN_CONFIG, + // [EvmChainId.Ethereum]: ETHEREUM_CHAIN_CONFIG, + [EvmChainId.Gnosis]: GNOSIS_CHAIN_CONFIG, + // [EvmChainId.Optimism]: OPTIMISM_CHAIN_CONFIG, +} as const; diff --git a/frontend/config/mechs.ts b/frontend/config/mechs.ts new file mode 100644 index 000000000..91c97d0a8 --- /dev/null +++ b/frontend/config/mechs.ts @@ -0,0 +1,42 @@ +import { JsonFragment } from '@ethersproject/abi'; +import { Contract as MulticallContract } from 'ethers-multicall'; + +import { AGENT_MECH_ABI } from '@/abis/agentMech'; +import { MECH_MARKETPLACE_ABI } from '@/abis/mechMarketplace'; +import { EvmChainId } from '@/enums/Chain'; +import { extractFunctionsFromAbi } from '@/utils/abi'; + +export enum MechType { + Agent = 'mech-agent', + Marketplace = 'mech-marketplace', +} + +type Mechs = { + [chainId: number]: { + [mechType: string]: { + name: string; + contract: MulticallContract; + }; + }; +}; + +export const MECHS: Mechs = { + [EvmChainId.Gnosis]: { + [MechType.Agent]: { + name: 'Agent Mech', + contract: new MulticallContract( + '0x77af31De935740567Cf4fF1986D04B2c964A786a', + extractFunctionsFromAbi(AGENT_MECH_ABI), + ), + }, + [MechType.Marketplace]: { + name: 'Mech Marketplace', + contract: new MulticallContract( + '0x4554fE75c1f5576c1d7F765B2A036c199Adae329', + MECH_MARKETPLACE_ABI.filter( + (abi) => (abi as JsonFragment).type === 'function', + ) as JsonFragment[], + ), + }, + }, +}; diff --git a/frontend/config/olasContracts.ts b/frontend/config/olasContracts.ts new file mode 100644 index 000000000..7586d202c --- /dev/null +++ b/frontend/config/olasContracts.ts @@ -0,0 +1,48 @@ +import { Contract as MulticallContract } from 'ethers-multicall'; + +import { SERVICE_REGISTRY_L2_ABI } from '@/abis/serviceRegistryL2'; +import { SERVICE_REGISTRY_TOKEN_UTILITY_ABI } from '@/abis/serviceRegistryTokenUtility'; +import { STAKING_TOKEN_PROXY_ABI } from '@/abis/stakingTokenProxy'; +import { EvmChainId } from '@/enums/Chain'; +import { ContractType } from '@/enums/Contract'; + +export type ContractsByType = { + [contractType: string]: MulticallContract; +}; + +export type ContractsByChain = { + [chainId: number]: ContractsByType; +}; + +export const OPTIMISM_OLAS_CONTRACTS: ContractsByType = { + [ContractType.ServiceRegistryL2]: new MulticallContract( + '0x3d77596beb0f130a4415df3D2D8232B3d3D31e44', + SERVICE_REGISTRY_L2_ABI, + ), + [ContractType.ServiceRegistryTokenUtility]: new MulticallContract( + '0xBb7e1D6Cb6F243D6bdE81CE92a9f2aFF7Fbe7eac', + SERVICE_REGISTRY_TOKEN_UTILITY_ABI, + ), + [ContractType.StakingActivity]: new MulticallContract( + '0x7Fd1F4b764fA41d19fe3f63C85d12bf64d2bbf68', + STAKING_TOKEN_PROXY_ABI, + ), +}; + +export const GNOSIS_OLAS_CONTRACTS: ContractsByType = { + [ContractType.ServiceRegistryL2]: new MulticallContract( + '0x9338b5153AE39BB89f50468E608eD9d764B755fD', + SERVICE_REGISTRY_L2_ABI, + ), + [ContractType.ServiceRegistryTokenUtility]: new MulticallContract( + '0xa45E64d13A30a51b91ae0eb182e88a40e9b18eD8', + SERVICE_REGISTRY_TOKEN_UTILITY_ABI, + ), +}; + +export const OLAS_CONTRACTS: { + [chainId: number]: ContractsByType; +} = { + [EvmChainId.Gnosis]: GNOSIS_OLAS_CONTRACTS, + [EvmChainId.Optimism]: OPTIMISM_OLAS_CONTRACTS, +}; diff --git a/frontend/config/stakingPrograms/gnosis.ts b/frontend/config/stakingPrograms/gnosis.ts new file mode 100644 index 000000000..5036cecab --- /dev/null +++ b/frontend/config/stakingPrograms/gnosis.ts @@ -0,0 +1,137 @@ +import { Contract as MulticallContract } from 'ethers-multicall'; + +import { STAKING_TOKEN_PROXY_ABI } from '@/abis/stakingTokenProxy'; +import { AgentType } from '@/enums/Agent'; +import { EvmChainId } from '@/enums/Chain'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { TokenSymbol } from '@/enums/Token'; +import { Address } from '@/types/Address'; + +import { ACTIVITY_CHECKERS } from '../activityCheckers'; +import { MECHS, MechType } from '../mechs'; +import { StakingProgramMap } from '.'; + +export const GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES: Record< + string, + Address +> = { + [StakingProgramId.PearlAlpha]: '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', + [StakingProgramId.PearlBeta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', + [StakingProgramId.PearlBeta2]: '0x1c2F82413666d2a3fD8bC337b0268e62dDF67434', + [StakingProgramId.PearlBeta3]: '0xBd59Ff0522aA773cB6074ce83cD1e4a05A457bc1', + [StakingProgramId.PearlBeta4]: '0x3052451e1eAee78e62E169AfdF6288F8791F2918', + [StakingProgramId.PearlBeta5]: '0x4Abe376Fda28c2F43b84884E5f822eA775DeA9F4', + [StakingProgramId.PearlBetaMechMarketplace]: + '0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA', +}; + +export const GNOSIS_STAKING_PROGRAMS: StakingProgramMap = { + [StakingProgramId.PearlAlpha]: { + deprecated: true, + name: 'Pearl Alpha', + chainId: EvmChainId.Gnosis, + agentsSupported: [AgentType.PredictTrader], + stakingRequirements: { + [TokenSymbol.OLAS]: 20, + }, + mechType: MechType.Agent, + mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, + activityChecker: ACTIVITY_CHECKERS[EvmChainId.Gnosis][MechType.Agent], + contract: new MulticallContract( + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlAlpha], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [StakingProgramId.PearlBeta]: { + chainId: EvmChainId.Gnosis, + name: 'Pearl Beta', + agentsSupported: [AgentType.PredictTrader], + stakingRequirements: { + [TokenSymbol.OLAS]: 40, + }, + mechType: MechType.Agent, + mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, + activityChecker: ACTIVITY_CHECKERS[EvmChainId.Gnosis][MechType.Agent], + contract: new MulticallContract( + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [StakingProgramId.PearlBeta2]: { + chainId: EvmChainId.Gnosis, + name: 'Pearl Beta 2', + agentsSupported: [AgentType.PredictTrader], + stakingRequirements: { + [TokenSymbol.OLAS]: 100, + }, + mechType: MechType.Agent, + mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, + activityChecker: ACTIVITY_CHECKERS[EvmChainId.Gnosis][MechType.Agent], + contract: new MulticallContract( + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta2], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [StakingProgramId.PearlBeta3]: { + chainId: EvmChainId.Gnosis, + name: 'Pearl Beta 3', + agentsSupported: [AgentType.PredictTrader], + stakingRequirements: { + [TokenSymbol.OLAS]: 100, + }, + mechType: MechType.Agent, + mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, + activityChecker: ACTIVITY_CHECKERS[EvmChainId.Gnosis][MechType.Agent], + contract: new MulticallContract( + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta3], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [StakingProgramId.PearlBeta4]: { + chainId: EvmChainId.Gnosis, + name: 'Pearl Beta 4', + agentsSupported: [AgentType.PredictTrader], + stakingRequirements: { + [TokenSymbol.OLAS]: 100, + }, + mechType: MechType.Agent, + mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, + activityChecker: ACTIVITY_CHECKERS[EvmChainId.Gnosis][MechType.Agent], + contract: new MulticallContract( + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta4], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [StakingProgramId.PearlBeta5]: { + chainId: EvmChainId.Gnosis, + name: 'Pearl Beta 5', + agentsSupported: [AgentType.PredictTrader], + stakingRequirements: { + [TokenSymbol.OLAS]: 10, + }, + mechType: MechType.Agent, + mech: MECHS[EvmChainId.Gnosis][MechType.Agent].contract, + activityChecker: ACTIVITY_CHECKERS[EvmChainId.Gnosis][MechType.Agent], + contract: new MulticallContract( + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[StakingProgramId.PearlBeta5], + STAKING_TOKEN_PROXY_ABI, + ), + }, + [StakingProgramId.PearlBetaMechMarketplace]: { + chainId: EvmChainId.Gnosis, + name: 'Pearl Beta Mech Marketplace', + agentsSupported: [AgentType.PredictTrader], + stakingRequirements: { + [TokenSymbol.OLAS]: 40, + }, + mechType: MechType.Marketplace, + mech: MECHS[EvmChainId.Gnosis][MechType.Marketplace].contract, + activityChecker: ACTIVITY_CHECKERS[EvmChainId.Gnosis][MechType.Marketplace], + contract: new MulticallContract( + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ + StakingProgramId.PearlBetaMechMarketplace + ], + STAKING_TOKEN_PROXY_ABI, + ), + }, +}; diff --git a/frontend/config/stakingPrograms/index.ts b/frontend/config/stakingPrograms/index.ts new file mode 100644 index 000000000..c19b6f682 --- /dev/null +++ b/frontend/config/stakingPrograms/index.ts @@ -0,0 +1,58 @@ +import { Contract as MulticallContract } from 'ethers-multicall'; + +import { AgentType } from '@/enums/Agent'; +import { EvmChainId } from '@/enums/Chain'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { Address } from '@/types/Address'; + +import { MechType } from '../mechs'; +import { + GNOSIS_STAKING_PROGRAMS, + GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES, +} from './gnosis'; +// import { +// OPTIMISM_STAKING_PROGRAMS, +// OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, +// } from './optimism'; + +/** + * Single non-chain specific staking program configuration + */ +export type StakingProgramConfig = { + chainId: EvmChainId; + deprecated?: boolean; // hides program from UI unless user is already staked in this program + name: string; + agentsSupported: AgentType[]; + stakingRequirements: { + [tokenSymbol: string]: number; + }; + contract: MulticallContract; + mechType?: MechType; + mech?: MulticallContract; + activityChecker: MulticallContract; +}; + +export type StakingProgramMap = { + [stakingProgramId: string]: StakingProgramConfig; +}; + +export const STAKING_PROGRAMS: { + [chainId: number | EvmChainId]: StakingProgramMap; +} = { + [EvmChainId.Gnosis]: GNOSIS_STAKING_PROGRAMS, + // [ChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS, +}; + +export const STAKING_PROGRAM_ADDRESS: { + [chainId: number | EvmChainId]: Record; +} = { + [EvmChainId.Gnosis]: GNOSIS_STAKING_PROGRAMS_CONTRACT_ADDRESSES, + // [ChainId.Optimism]: OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES, +}; + +export const DEFAULT_STAKING_PROGRAM_IDS: { + [chainId: number | EvmChainId]: StakingProgramId; +} = { + [EvmChainId.Gnosis]: StakingProgramId.PearlBeta, + // [ChainId.Optimism]: StakingProgramId.OptimusAlpha, +}; diff --git a/frontend/config/stakingPrograms/optimism.ts b/frontend/config/stakingPrograms/optimism.ts new file mode 100644 index 000000000..1ade198f6 --- /dev/null +++ b/frontend/config/stakingPrograms/optimism.ts @@ -0,0 +1,34 @@ +/** + * Staking program configurations by staking program id + * @note Add new staking programs here + * @note Used to type chain specific staking program configs + */ + +import { StakingProgramId } from '@/enums/StakingProgram'; +import { Address } from '@/types/Address'; + +export const OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES: Record< + string, + Address +> = { + [StakingProgramId.OptimusAlpha]: '0x88996bbdE7f982D93214881756840cE2c77C4992', +}; + +// export const OPTIMISM_STAKING_PROGRAMS: StakingProgramMap = { +// [StakingProgramId.OptimusAlpha]: { +// name: 'Optimus Alpha', +// agentsSupported: [AgentType.Optimus], +// stakingRequirements: { +// [TokenSymbol.OLAS]: 40, +// }, +// mech: MECHS[EvmChainId.Optimism][MechType.Agent].contract, +// activityChecker: ACTIVITY_CHECKERS[EvmChainId.Optimism][MechType.Agent], +// chainId: EvmChainId.Optimism, +// contract: new MulticallContract( +// OPTIMISM_STAKING_PROGRAMS_CONTRACT_ADDRESSES[ +// StakingProgramId.OptimusAlpha +// ], +// STAKING_TOKEN_PROXY_ABI, +// ), +// }, +// }; diff --git a/frontend/config/tokens.ts b/frontend/config/tokens.ts new file mode 100644 index 000000000..7cabcf7d8 --- /dev/null +++ b/frontend/config/tokens.ts @@ -0,0 +1,148 @@ +import { EvmChainId } from '@/enums/Chain'; +import { TokenSymbol } from '@/enums/Token'; +import { Address } from '@/types/Address'; + +export enum TokenType { + NativeGas = 'native', + Erc20 = 'erc20', + Erc721 = 'erc721', + // Erc1155 = 'erc1155', + // UniswapV2Lp = 'v2lp', + // UniswapV3Lp = 'v3lp', +} + +export type Erc20TokenConfig = { + address: Address; + tokenType: TokenType.Erc20; + decimals: number; + symbol: TokenSymbol; +}; + +export type NativeTokenConfig = { + address?: undefined; + tokenType: TokenType.NativeGas; + decimals: number; + symbol: TokenSymbol; +}; + +export type TokenConfig = Erc20TokenConfig | NativeTokenConfig; + +export type ChainTokenConfig = { + [tokenSymbol: string]: TokenConfig; +}; + +export const GNOSIS_TOKEN_CONFIG: ChainTokenConfig = { + [TokenSymbol.XDAI]: { + decimals: 18, + tokenType: TokenType.NativeGas, + symbol: TokenSymbol.XDAI, + }, + [TokenSymbol.OLAS]: { + address: '0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f', + decimals: 18, + tokenType: TokenType.Erc20, + symbol: TokenSymbol.OLAS, + }, +}; + +export const OPTIMISM_TOKEN_CONFIG: ChainTokenConfig = { + [TokenSymbol.ETH]: { + tokenType: TokenType.NativeGas, + decimals: 18, + symbol: TokenSymbol.ETH, + }, + [TokenSymbol.OLAS]: { + address: '0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527', + decimals: 18, + tokenType: TokenType.Erc20, + symbol: TokenSymbol.OLAS, + }, +}; + +export const ETHEREUM_TOKEN_CONFIG: ChainTokenConfig = { + [TokenSymbol.ETH]: { + tokenType: TokenType.NativeGas, + decimals: 18, + symbol: TokenSymbol.ETH, + }, + [TokenSymbol.OLAS]: { + address: '0x0001A500A6B18995B03f44bb040A5fFc28E45CB0', + decimals: 18, + tokenType: TokenType.Erc20, + symbol: TokenSymbol.OLAS, + }, + /** + * @warning USDC is a special case, it has 6 decimals, not 18. + * https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#readProxyContract#F11 + * @note When parsing or formatting units, use `decimals` (6) instead of the standard `ether` sizing (10^18). + */ + [TokenSymbol.USDC]: { + address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + decimals: 6, + tokenType: TokenType.Erc20, + symbol: TokenSymbol.USDC, + }, +}; + +export const BASE_TOKEN_CONFIG: ChainTokenConfig = { + [TokenSymbol.ETH]: { + tokenType: TokenType.NativeGas, + decimals: 18, + symbol: TokenSymbol.ETH, + }, + [TokenSymbol.OLAS]: { + address: '0x4B1a99467a284CC690e3237bc69105956816F762', + decimals: 18, + tokenType: TokenType.Erc20, + symbol: TokenSymbol.OLAS, + }, +}; + +export const TOKEN_CONFIG = { + [EvmChainId.Gnosis]: GNOSIS_TOKEN_CONFIG, + [EvmChainId.Optimism]: OPTIMISM_TOKEN_CONFIG, + [EvmChainId.Ethereum]: ETHEREUM_TOKEN_CONFIG, + [EvmChainId.Base]: BASE_TOKEN_CONFIG, +} as const; + +/** + * @note This is a mapping of all ERC20 tokens on each chain. + */ +export const ERC20_TOKEN_CONFIG = Object.fromEntries( + Object.entries(TOKEN_CONFIG).map(([chainId, chainTokenConfig]) => [ + +chainId as EvmChainId, + Object.fromEntries( + Object.entries(chainTokenConfig).filter( + ([, tokenConfig]) => tokenConfig.tokenType === TokenType.Erc20, + ), + ), + ]), +) as { + [chainId: number]: { + [tokenSymbol: string]: Erc20TokenConfig; + }; +}; + +/** + * @note This is a mapping of all native tokens on each chain. + */ +export const NATIVE_TOKEN_CONFIG = Object.fromEntries( + Object.entries(TOKEN_CONFIG).map(([chainId, chainTokenConfig]) => [ + +chainId as EvmChainId, + Object.fromEntries( + Object.entries(chainTokenConfig).filter( + ([, tokenConfig]) => tokenConfig.tokenType === TokenType.NativeGas, + ), + ), + ]), +) as { + [chainId: number]: { + [tokenSymbol: string]: NativeTokenConfig; + }; +}; + +export const getNativeTokenSymbol = (chainId: EvmChainId): TokenSymbol => + Object.keys(NATIVE_TOKEN_CONFIG[chainId])[0] as TokenSymbol; + +export const getErc20s = (chainId: EvmChainId): Erc20TokenConfig[] => + Object.values(ERC20_TOKEN_CONFIG[chainId]); diff --git a/frontend/constants/chains.ts b/frontend/constants/chains.ts deleted file mode 100644 index 92baf3c6a..000000000 --- a/frontend/constants/chains.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { MiddlewareChain } from '@/client'; - -export const CHAINS: { - [chain: string]: { - name: string; - currency: string; - chainId: number; - middlewareChain: MiddlewareChain; - }; -} = { - GNOSIS: { - name: 'Gnosis', - currency: 'XDAI', - chainId: 100, - middlewareChain: MiddlewareChain.GNOSIS, - }, - OPTIMISM: { - name: 'Optimism', - currency: 'ETH', - chainId: 10, - middlewareChain: MiddlewareChain.OPTIMISM, - }, - BASE: { - name: 'Base', - currency: 'ETH', - chainId: 8453, - middlewareChain: MiddlewareChain.BASE, - }, - ETHEREUM: { - name: 'Ethereum', - currency: 'ETH', - chainId: 1, - middlewareChain: MiddlewareChain.ETHEREUM, - }, -}; diff --git a/frontend/constants/colors.ts b/frontend/constants/colors.ts index 2df0154fa..7b11ae7da 100644 --- a/frontend/constants/colors.ts +++ b/frontend/constants/colors.ts @@ -11,4 +11,5 @@ export const COLOR = { BROWN: '#873800', TEXT: '#1f2229', TEXT_LIGHT: '#606F85', + GRAY_1: '#f2f4f9', }; diff --git a/frontend/constants/contractAddresses.ts b/frontend/constants/contractAddresses.ts deleted file mode 100644 index b5fa380be..000000000 --- a/frontend/constants/contractAddresses.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { setMulticallAddress } from 'ethers-multicall'; - -import { MiddlewareChain } from '@/client'; -import { StakingProgramId } from '@/enums/StakingProgram'; -import { Address } from '@/types/Address'; - -import { CHAINS } from './chains'; - -export const MULTICALL_CONTRACT_ADDRESS: Address = - '0xcA11bde05977b3631167028862bE2a173976CA11'; // https://github.com/mds1/multicall, https://www.multicall3.com/ - -/** - * Sets the multicall contract address for each chain - * @warning Do not remove this, it is required for the multicall provider to work as package is not updated - * @see https://github.com/cavanmflynn/ethers-multicall/blob/fb84bcc3763fe54834a35a44c34d610bafc87ce5/src/provider.ts#L35C1-L53C1 - * @note will use different multicall package in future - */ -Object.entries(CHAINS).forEach(([, { chainId }]) => { - setMulticallAddress(chainId, MULTICALL_CONTRACT_ADDRESS); -}); - -export const SERVICE_REGISTRY_L2_CONTRACT_ADDRESS: Record = { - // [MiddlewareChain.GNOSIS]: '0x9338b5153AE39BB89f50468E608eD9d764B755fD', - [MiddlewareChain.OPTIMISM]: '0x3d77596beb0f130a4415df3D2D8232B3d3D31e44', -}; - -export const SERVICE_REGISTRY_TOKEN_UTILITY_CONTRACT_ADDRESS: Record< - number, - Address -> = { - // [MiddlewareChain.GNOSIS]: '0xa45E64d13A30a51b91ae0eb182e88a40e9b18eD8', - [MiddlewareChain.OPTIMISM]: '0xBb7e1D6Cb6F243D6bdE81CE92a9f2aFF7Fbe7eac', -}; - -export const SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES: Record< - number, - Record -> = { - // [Chain.GNOSIS]: { - // [StakingProgramId.Beta2]: '0x1c2F82413666d2a3fD8bC337b0268e62dDF67434', - // [StakingProgramId.Beta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', - // [StakingProgramId.Alpha]: '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', - // [StakingProgramId.BetaMechMarketplace]: - // '0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA', - // }, - [MiddlewareChain.OPTIMISM]: { - [StakingProgramId.OptimusAlpha]: - '0x88996bbdE7f982D93214881756840cE2c77C4992', - }, -}; - -// /** -// * Standard mech contract addresses -// */ -// export const AGENT_MECH_CONTRACT_ADDRESS: Record = { -// [Chain.GNOSIS]: '0x77af31De935740567Cf4fF1986D04B2c964A786a', -// }; - -// /** -// * Standard mech activity checker contract addresses -// */ -// export const MECH_ACTIVITY_CHECKER_CONTRACT_ADDRESS: Record = { -// [Chain.GNOSIS]: '0x155547857680A6D51bebC5603397488988DEb1c8', -// }; - -// /** -// * Mech marketplace contract addresses -// */ -// export const MECH_MARKETPLACE_CONTRACT_ADDRESS: Record = { -// [Chain.GNOSIS]: '0x4554fE75c1f5576c1d7F765B2A036c199Adae329', -// }; - -// /** -// * Mech marketplace activity checker contract addresses -// */ -// export const REQUESTER_ACTIVITY_CHECKER_CONTRACT_ADDRESS: Record< -// number, -// Address -// > = { -// [Chain.GNOSIS]: '0x7Ec96996Cd146B91779f01419db42E67463817a0', -// }; - -export const STAKING_ACTIVITY_CHECKER_CONTRACT_ADDRESS: Record< - number, - Address -> = { - [MiddlewareChain.OPTIMISM]: '0x7Fd1F4b764fA41d19fe3f63C85d12bf64d2bbf68', -}; diff --git a/frontend/constants/intervals.ts b/frontend/constants/intervals.ts index 50afd39d0..0983cbf5d 100644 --- a/frontend/constants/intervals.ts +++ b/frontend/constants/intervals.ts @@ -1 +1,3 @@ +export const ONE_MINUTE_INTERVAL = 60 * 1000; // 1 minute + export const FIVE_SECONDS_INTERVAL = 5000; diff --git a/frontend/constants/providers.ts b/frontend/constants/providers.ts index 3b6eaa21a..028adc630 100644 --- a/frontend/constants/providers.ts +++ b/frontend/constants/providers.ts @@ -1,56 +1,33 @@ import { ethers } from 'ethers'; import { Provider as MulticallProvider } from 'ethers-multicall'; -import { CHAINS } from './chains'; - -export const gnosisProvider = new ethers.providers.JsonRpcProvider( - process.env.RPC, - { - chainId: CHAINS.GNOSIS.chainId, - name: CHAINS.GNOSIS.name, - }, -); - -export const gnosisMulticallProvider = new MulticallProvider( - gnosisProvider, - CHAINS.GNOSIS.chainId, -); - -export const optimismProvider = new ethers.providers.JsonRpcProvider( - process.env.OPTIMISM_RPC, - { - chainId: CHAINS.OPTIMISM.chainId, - name: CHAINS.OPTIMISM.name, - }, -); - -export const optimismMulticallProvider = new MulticallProvider( - optimismProvider, - CHAINS.OPTIMISM.chainId, -); - -export const ethereumProvider = new ethers.providers.JsonRpcProvider( - process.env.ETHEREUM_RPC, - { - chainId: CHAINS.ETHEREUM.chainId, - name: CHAINS.ETHEREUM.name, +import { EvmChainId } from '@/enums/Chain'; + +import { CHAIN_CONFIG } from '../config/chains'; + +type Providers = { + [evmChainId in EvmChainId]: { + provider: ethers.providers.JsonRpcProvider; + multicallProvider: MulticallProvider; + }; +}; + +export const PROVIDERS: Providers = Object.entries(CHAIN_CONFIG).reduce( + (acc, [, { rpc, name, evmChainId }]) => { + const provider = new ethers.providers.StaticJsonRpcProvider(rpc, { + name, + chainId: evmChainId, + }); + + const multicallProvider = new MulticallProvider(provider, evmChainId); + + return { + ...acc, + [evmChainId]: { + provider, + multicallProvider, + }, + }; }, -); - -export const ethereumMulticallProvider = new MulticallProvider( - ethereumProvider, - CHAINS.ETHEREUM.chainId, -); - -export const baseProvider = new ethers.providers.JsonRpcProvider( - process.env.BASE_RPC, - { - chainId: CHAINS.BASE.chainId, - name: CHAINS.BASE.name, - }, -); - -export const baseMulticallProvider = new MulticallProvider( - baseProvider, - CHAINS.BASE.chainId, + {} as Providers, ); diff --git a/frontend/constants/react-query-keys.ts b/frontend/constants/react-query-keys.ts new file mode 100644 index 000000000..07219498f --- /dev/null +++ b/frontend/constants/react-query-keys.ts @@ -0,0 +1,75 @@ +import { Safe } from '@/enums/Wallet'; +import { Maybe } from '@/types/Util'; + +export const REACT_QUERY_KEYS = { + // services + SERVICES_KEY: ['services'] as const, + SERVICE_DEPLOYMENT_STATUS_KEY: (serviceConfigId: Maybe) => + ['serviceStatus', serviceConfigId ?? ''] as const, + + // staking programs + STAKING_CONTRACT_DETAILS_BY_STAKING_PROGRAM_KEY: ( + chainId: number, + serviceConfigId: number, + activeStakingProgramId: string, + ) => + [ + 'stakingContractDetailsByStakingProgramId', + chainId, + serviceConfigId, + activeStakingProgramId, + ] as const, + ALL_STAKING_CONTRACT_DETAILS: (chainId: number, stakingProgramId: string) => + ['allStakingContractDetails', chainId, stakingProgramId] as const, + STAKING_PROGRAM_KEY: (chainId: number, serviceConfigId: number = 0) => + ['stakingProgram', chainId, serviceConfigId] as const, + + // wallets + WALLETS_KEY: ['wallets'] as const, + + // epoch + LATEST_EPOCH_TIME_KEY: (chainId: number, stakingProgramId: string) => + ['latestEpochTime', chainId, stakingProgramId] as const, + + // rewards + REWARDS_KEY: ( + chainId: number, + serviceConfigId: string, + stakingProgramId: string, + multisig: string, + token: number, + ) => + [ + 'rewards', + chainId, + serviceConfigId, + stakingProgramId, + multisig, + token, + ] as const, + AVAILABLE_REWARDS_FOR_EPOCH_KEY: ( + currentChainId: number, + serviceConfigId: string, + stakingProgramId: string, + chainId: number, + ) => + [ + 'availableRewardsForEpoch', + currentChainId, + serviceConfigId, + stakingProgramId, + chainId, + ] as const, + REWARDS_HISTORY_KEY: (chainId: number, serviceId: number) => + ['rewardsHistory', chainId, serviceId] as const, + + // multisigs + MULTISIG_GET_OWNERS_KEY: (multisig: Safe) => + ['multisig', 'getOwners', multisig.evmChainId, multisig.address] as const, + MULTISIGS_GET_OWNERS_KEY: (multisigs: Safe[]) => + [ + 'multisigs', + 'getOwners', + multisigs.map((multisig) => multisig.address), + ] as const, +} as const; diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index d96eb2327..41fc45e99 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -1,89 +1,165 @@ -import { ServiceTemplate } from '@/client'; +import { EnvProvisionType, MiddlewareChain, ServiceTemplate } from '@/client'; +import { AgentType } from '@/enums/Agent'; import { StakingProgramId } from '@/enums/StakingProgram'; -import { CHAINS } from './chains'; - export const SERVICE_TEMPLATES: ServiceTemplate[] = [ - // { - // name: 'Trader Agent', - // hash: 'bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u', - // description: 'Trader agent for omen prediction markets', - // image: - // 'https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75', - // service_version: 'v0.18.4', - // home_chain_id: '100', - // configurations: { - // 100: { - // staking_program_id: StakingProgramId.OptimusAlpha, // default, may be overwritten - // nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', - // rpc: 'http://localhost:8545', - // agent_id: 14, - // threshold: 1, - // use_staking: true, - // use_mech_marketplace: true, - // cost_of_bond: 10000000000000000, - // monthly_gas_estimate: 10000000000000000000, - // fund_requirements: { - // agent: 100000000000000000, - // safe: 5000000000000000000, - // }, - // }, - // }, - // }, { - name: 'Optimus', - hash: 'bafybeibzujtdlgsft3hnjmboa5yfni7vqc2iocjlyti5nadc55jxj3kxbu', - description: 'Optimus', + agentType: AgentType.PredictTrader, // TODO: remove if causes errors on middleware + name: 'Trader Agent', + hash: 'bafybeicts6zhavxzz2rxahz3wzs2pzamoq64n64wp4q4cdanfuz7id6c2q', + description: 'Trader agent for omen prediction markets', image: 'https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75', - service_version: 'v0.2.9', - home_chain_id: `${CHAINS.OPTIMISM.chainId}`, + service_version: 'v0.18.4', + home_chain: MiddlewareChain.GNOSIS, configurations: { - [CHAINS.OPTIMISM.chainId]: { - staking_program_id: StakingProgramId.OptimusAlpha, // default, may be overwritten + [MiddlewareChain.GNOSIS]: { + staking_program_id: StakingProgramId.PearlBeta, // default, may be overwritten nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', - // rpc: 'http://localhost:8545', - agent_id: 40, + rpc: 'http://localhost:8545', // overwritten + agent_id: 14, threshold: 1, use_staking: true, use_mech_marketplace: false, - cost_of_bond: 1000, - monthly_gas_estimate: 1000, + // TODO: pull fund requirements from staking program config + cost_of_bond: 10000000000000000, + monthly_gas_estimate: 10000000000000000000, fund_requirements: { - agent: 1000, - safe: 1000, + agent: 100000000000000000, + safe: 5000000000000000000, }, }, - [CHAINS.ETHEREUM.chainId]: { - staking_program_id: StakingProgramId.OptimusAlpha, // default, may be overwritten - nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', - // rpc: 'http://localhost:8545', - agent_id: 40, - threshold: 1, - use_staking: false, - use_mech_marketplace: false, - cost_of_bond: 1, - monthly_gas_estimate: 1000, - fund_requirements: { - agent: 1000, - safe: 1000, - }, + }, + env_variables: { + GNOSIS_LEDGER_RPC: { + name: 'Gnosis ledger RPC', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, }, - [CHAINS.BASE.chainId]: { - staking_program_id: StakingProgramId.OptimusAlpha, // default, may be overwritten - nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', - // rpc: 'http://localhost:8545', - agent_id: 40, - threshold: 1, - use_staking: false, - use_mech_marketplace: false, - cost_of_bond: 1, - monthly_gas_estimate: 1000, - fund_requirements: { - agent: 1000, - safe: 1000, - }, + // ETHEREUM_LEDGER_RPC: { + // name: "Ethereum ledger RPC", + // description: "", + // value: "", + // provision_type: EnvProvisionType.COMPUTED + // }, + // BASE_LEDGER_RPC: { + // name: "Base ledger RPC", + // description: "", + // value: "", + // provision_type: EnvProvisionType.COMPUTED + // }, + // OPTIMISM_LEDGER_RPC: { + // name: "Optimism ledger RPC", + // description: "", + // value: "", + // provision_type: EnvProvisionType.COMPUTED + // }, + STAKING_CONTRACT_ADDRESS: { + name: 'Staking contract address', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + MECH_ACTIVITY_CHECKER_CONTRACT: { + name: 'Mech activity checker contract', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + MECH_CONTRACT_ADDRESS: { + name: 'Mech contract address', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + MECH_REQUEST_PRICE: { + name: 'Mech request price', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + USE_MECH_MARKETPLACE: { + name: 'Use Mech marketplace', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + REQUESTER_STAKING_INSTANCE_ADDRESS: { + name: 'Requester staking instance address', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, + }, + PRIORITY_MECH_ADDRESS: { + name: 'Priority Mech address', + description: '', + value: '', + provision_type: EnvProvisionType.COMPUTED, }, }, }, + // { + // name: 'Optimus Test', + // hash: 'bafybeibzujtdlgsft3hnjmboa5yfni7vqc2iocjlyti5nadc55jxj3kxbu', + // description: 'Optimus', + // image: + // 'https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75', + // service_version: 'v0.2.9', + // home_chain: `${CHAINS.OPTIMISM}`, + // configurations: { + // [CHAINS.OPTIMISM.middlewareChain]: { + // staking_program_id: StakingProgramId.OptimusAlpha, // default, may be overwritten + // nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', + // // rpc: 'http://localhost:8545', + // agent_id: 40, + // threshold: 1, + // use_staking: true, + // use_mech_marketplace: false, + // cost_of_bond: 1000, + // monthly_gas_estimate: 1000, + // fund_requirements: { + // agent: 1000, + // safe: 1000, + // }, + // }, + // [CHAINS.ETHEREUM.middlewareChain]: { + // staking_program_id: StakingProgramId.OptimusAlpha, // default, may be overwritten + // nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', + // // rpc: 'http://localhost:8545', + // agent_id: 40, + // threshold: 1, + // use_staking: false, + // use_mech_marketplace: false, + // cost_of_bond: 1, + // monthly_gas_estimate: 1000, + // fund_requirements: { + // agent: 1000, + // safe: 1000, + // }, + // }, + // [CHAINS.BASE.middlewareChain]: { + // staking_program_id: StakingProgramId.OptimusAlpha, // default, may be overwritten + // nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', + // // rpc: 'http://localhost:8545', + // agent_id: 40, + // threshold: 1, + // use_staking: false, + // use_mech_marketplace: false, + // cost_of_bond: 1, + // monthly_gas_estimate: 1000, + // fund_requirements: { + // agent: 1000, + // safe: 1000, + // }, + // }, + // }, + // }, ]; + +export const getServiceTemplates = (): ServiceTemplate[] => SERVICE_TEMPLATES; + +export const getServiceTemplate = ( + templateHash: string, +): ServiceTemplate | undefined => + SERVICE_TEMPLATES.find((template) => template.hash === templateHash); diff --git a/frontend/constants/stakingProgramMeta.ts b/frontend/constants/stakingProgramMeta.ts deleted file mode 100644 index fd2b887ca..000000000 --- a/frontend/constants/stakingProgramMeta.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { StakingProgramId } from '@/enums/StakingProgram'; - -export type StakingProgramMeta = { - name: string; - canMigrateTo: StakingProgramId[]; - deprecated: boolean; -}; - -const allStakingProgramIds = Object.values(StakingProgramId); -const deprecatedStakingProgramIds = [] as StakingProgramId[]; -const activeStakingProgramIds = allStakingProgramIds.filter( - (id) => !deprecatedStakingProgramIds.includes(id), -); - -const activeStakingProgramsWithout = (stakingProgramId: StakingProgramId) => - activeStakingProgramIds.filter((id) => id !== stakingProgramId); - -export const STAKING_PROGRAM_META: Record< - StakingProgramId, - StakingProgramMeta -> = { - // [StakingProgramId.Alpha]: { - // name: 'Pearl Alpha', - // canMigrateTo: activeStakingProgramsWithout(StakingProgramId.Alpha), - // deprecated: true, - // }, - // [StakingProgramId.Beta]: { - // name: 'Pearl Beta', - // canMigrateTo: activeStakingProgramsWithout(StakingProgramId.Beta), - // deprecated: false, - // }, - // [StakingProgramId.Beta2]: { - // name: 'Pearl Beta 2', - // canMigrateTo: activeStakingProgramsWithout(StakingProgramId.Beta2), - // deprecated: false, - // }, - // [StakingProgramId.Beta3]: { - // name: 'Pearl Beta 3', - // canMigrateTo: activeStakingProgramsWithout(StakingProgramId.Beta3), - // deprecated: false, - // }, - // [StakingProgramId.Beta4]: { - // name: 'Pearl Beta 4', - // canMigrateTo: activeStakingProgramsWithout(StakingProgramId.Beta4), - // deprecated: false, - // }, - // [StakingProgramId.Beta5]: { - // name: 'Pearl Beta 5', - // canMigrateTo: activeStakingProgramsWithout(StakingProgramId.Beta5), - // deprecated: false, - // }, - // [StakingProgramId.BetaMechMarketplace]: { - // name: 'Pearl Beta Mech Marketplace', - // canMigrateTo: activeStakingProgramsWithout( - // StakingProgramId.BetaMechMarketplace, - // ), - // deprecated: false, - // }, - [StakingProgramId.OptimusAlpha]: { - name: 'Optimus Alpha', - canMigrateTo: activeStakingProgramsWithout(StakingProgramId.OptimusAlpha), - deprecated: false, - }, -}; diff --git a/frontend/constants/symbols.ts b/frontend/constants/symbols.ts index 14c16e9f2..5deb80160 100644 --- a/frontend/constants/symbols.ts +++ b/frontend/constants/symbols.ts @@ -1,3 +1,5 @@ +export const NA = 'n/a'; + export const UNICODE_SYMBOLS = { OLAS: '☴', EXTERNAL_LINK: '↗', diff --git a/frontend/constants/thresholds.ts b/frontend/constants/thresholds.ts index 8a3546420..57e8977ed 100644 --- a/frontend/constants/thresholds.ts +++ b/frontend/constants/thresholds.ts @@ -1,26 +1,31 @@ -import { MiddlewareChain } from '@/client'; +import { EvmChainId } from '@/enums/Chain'; -/** - * @warning must be updated to be dynamic - */ -export const MIN_ETH_BALANCE_THRESHOLDS = { - // [Chain.GNOSIS]: { - // safeCreation: 1.5, - // safeAddSigner: 0.1, - // }, - [MiddlewareChain.OPTIMISM]: { +// TODO: confirm eth requirements, very flaky, eth requirements will fluctuate +export const MIN_ETH_BALANCE_THRESHOLDS: Record< + EvmChainId, + { + safeCreation: number; + safeAddSigner: number; + } +> = { + [EvmChainId.Gnosis]: { + safeCreation: 1.5, + safeAddSigner: 0.1, + }, + [EvmChainId.Optimism]: { safeCreation: 0.005, safeAddSigner: 0.005, }, - [MiddlewareChain.ETHEREUM]: { + [EvmChainId.Ethereum]: { safeCreation: 0.02, safeAddSigner: 0.02, }, - [MiddlewareChain.BASE]: { + [EvmChainId.Base]: { safeCreation: 0.005, safeAddSigner: 0.005, }, }; +// TODO: update to support multi-chain, very poor implementation export const LOW_AGENT_SAFE_BALANCE = 0.5; export const LOW_MASTER_SAFE_BALANCE = 2; diff --git a/frontend/constants/tokens.ts b/frontend/constants/tokens.ts deleted file mode 100644 index 125c52c78..000000000 --- a/frontend/constants/tokens.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Token } from '@/enums/Token'; -import { Address } from '@/types/Address'; - -import { CHAINS } from './chains'; - -export type TokenConfig = { - [symbol: string]: { - address: Address; - decimals: number; - }; -}; - -export const TOKENS: { - [chain: number]: TokenConfig; -} = { - [CHAINS.GNOSIS.chainId]: { - [Token.OLAS]: { - address: '0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f', - decimals: 18, - }, - }, - [CHAINS.OPTIMISM.chainId]: { - [Token.OLAS]: { - address: '0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527', - decimals: 18, - }, - }, - [CHAINS.ETHEREUM.chainId]: { - [Token.OLAS]: { - address: '0x0001A500A6B18995B03f44bb040A5fFc28E45CB0', - decimals: 18, - }, - /** - * @warning USDC is a special case, it has 6 decimals, not 18. - * https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#readProxyContract#F11 - * @note When parsing or formatting units, use `decimals` (6) instead of the standard `ether` sizing (10^18). - */ - [Token.USDC]: { - address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - decimals: 6, - }, - }, - [CHAINS.BASE.chainId]: { - [Token.OLAS]: { - address: '0x4B1a99467a284CC690e3237bc69105956816F762', - decimals: 18, - }, - }, -}; diff --git a/frontend/constants/urls.ts b/frontend/constants/urls.ts index 97afa4d61..b0814159a 100644 --- a/frontend/constants/urls.ts +++ b/frontend/constants/urls.ts @@ -1,33 +1,55 @@ import { MiddlewareChain } from '@/client'; +import { EvmChainId } from '@/enums/Chain'; +import { asEvmChainId } from '@/utils/middlewareHelpers'; -export const BACKEND_URL: string = `http://localhost:${process.env.NODE_ENV === 'production' ? 8765 : 8000}/api`; +type Url = `http${'s' | ''}://${string}`; -export const COW_SWAP_GNOSIS_XDAI_OLAS_URL: string = +export const BACKEND_URL: Url = `http://localhost:${process.env.NODE_ENV === 'production' ? 8765 : 8000}/api`; + +export const BACKEND_URL_V2: Url = `http://localhost:${process.env.NODE_ENV === 'production' ? 8765 : 8000}/api/v2`; + +// cowswap +export const COW_SWAP_GNOSIS_XDAI_OLAS_URL: Url = 'https://swap.cow.fi/#/100/swap/WXDAI/OLAS'; // olas.network -export const FAQ_URL = 'https://olas.network/operate#faq'; -export const DOWNLOAD_URL = 'https://olas.network/operate#download'; +export const FAQ_URL: Url = 'https://olas.network/operate#faq'; +export const DOWNLOAD_URL: Url = 'https://olas.network/operate#download'; // thegraph -export const GNOSIS_REWARDS_HISTORY_SUBGRAPH_URL = +export const GNOSIS_REWARDS_HISTORY_SUBGRAPH_URL: Url = 'https://api.studio.thegraph.com/query/81371/gnosis-pearl-rewards-history/version/latest'; // discord -export const SUPPORT_URL = +export const SUPPORT_URL: Url = 'https://discord.com/channels/899649805582737479/1244588374736502847'; -export const DISCORD_TICKET_URL = +export const DISCORD_TICKET_URL: Url = 'https://discord.com/channels/899649805582737479/1245674435160178712/1263815577240076308'; // github -export const GITHUB_API_LATEST_RELEASE = +export const GITHUB_API_LATEST_RELEASE: Url = 'https://api.github.com/repos/valory-xyz/olas-operate-app/releases/latest'; // explorers @note DO NOT END WITH `/` -export const OPTIMISM_EXPLORER_URL = 'https://optimistic.etherscan.io'; -export const GNOSIS_EXPLORER_URL = 'https://gnosisscan.io'; - -export const EXPLORER_URL = { - [MiddlewareChain.OPTIMISM]: OPTIMISM_EXPLORER_URL, +// export const OPTIMISM_EXPLORER_URL: Url = 'https://optimistic.etherscan.io'; +export const GNOSIS_EXPLORER_URL: Url = 'https://gnosisscan.io'; + +export const EXPLORER_URL_BY_MIDDLEWARE_CHAIN: Record< + string | MiddlewareChain, + Url +> = { + // [MiddlewareChain.OPTIMISM]: OPTIMISM_EXPLORER_URL, [MiddlewareChain.GNOSIS]: GNOSIS_EXPLORER_URL, }; + +export const SWAP_URL_BY_EVM_CHAIN: Record = { + // [EvmChainId.OPTIMISM]: COW_SWAP_GNOSIS_XDAI_OLAS_URL, + [EvmChainId.Gnosis]: COW_SWAP_GNOSIS_XDAI_OLAS_URL, +}; + +export const EXPLORER_URL_BY_EVM_CHAIN_ID: Record = + Object.fromEntries( + Object.entries(EXPLORER_URL_BY_MIDDLEWARE_CHAIN).map( + ([middlewareChain, url]) => [asEvmChainId(middlewareChain), url], + ), + ); diff --git a/frontend/constants/width.ts b/frontend/constants/width.ts index 65295b698..2bb0e5eb2 100644 --- a/frontend/constants/width.ts +++ b/frontend/constants/width.ts @@ -1,3 +1,5 @@ export const MODAL_WIDTH = 412; export const POPOVER_WIDTH_MEDIUM = 260; + +export const POPOVER_WIDTH_LARGE = 340; diff --git a/frontend/context/BalanceProvider.tsx b/frontend/context/BalanceProvider.tsx index 122ae7c58..858549634 100644 --- a/frontend/context/BalanceProvider.tsx +++ b/frontend/context/BalanceProvider.tsx @@ -1,7 +1,7 @@ -import { message } from 'antd'; -import { isAddress } from 'ethers/lib/utils'; -import { isNumber } from 'lodash'; -import { ValueOf } from 'next/dist/shared/lib/constants'; +import { BigNumberish } from 'ethers'; +import { getAddress, isAddress } from 'ethers/lib/utils'; +import { Contract as MulticallContract } from 'ethers-multicall'; +import { isEmpty, isNil, sum } from 'lodash'; import { createContext, Dispatch, @@ -9,301 +9,186 @@ import { SetStateAction, useCallback, useContext, + useEffect, useMemo, useState, } from 'react'; import { useInterval } from 'usehooks-ts'; -import { Wallet } from '@/client'; -import { CHAINS } from '@/constants/chains'; +import { ERC20_BALANCE_OF_STRING_FRAGMENT } from '@/abis/erc20'; +import { MiddlewareChain, MiddlewareServiceResponse } from '@/client'; +import { TOKEN_CONFIG, TokenType } from '@/config/tokens'; import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; -import { - LOW_AGENT_SAFE_BALANCE, - LOW_MASTER_SAFE_BALANCE, -} from '@/constants/thresholds'; -import { TOKENS } from '@/constants/tokens'; +import { PROVIDERS } from '@/constants/providers'; +import { EvmChainId } from '@/enums/Chain'; import { ServiceRegistryL2ServiceState } from '@/enums/ServiceRegistryL2ServiceState'; -import { Token } from '@/enums/Token'; -import { AutonolasService } from '@/service/Autonolas'; -import { EthersService } from '@/service/Ethers'; -import MulticallService from '@/service/Multicall'; +import { TokenSymbol } from '@/enums/Token'; +import { Wallets, WalletType } from '@/enums/Wallet'; +import { StakedAgentService } from '@/service/agents/StakedAgentService'; import { Address } from '@/types/Address'; -import { - AddressNumberRecord, - WalletAddressNumberRecord, -} from '@/types/Records'; +import { Maybe } from '@/types/Util'; +import { asEvmChainId } from '@/utils/middlewareHelpers'; +import { formatEther } from '@/utils/numberFormatters'; +import { MasterWalletContext } from './MasterWalletProvider'; import { OnlineStatusContext } from './OnlineStatusProvider'; -import { RewardContext } from './RewardProvider'; import { ServicesContext } from './ServicesProvider'; -import { WalletContext } from './WalletProvider'; + +type CrossChainStakedBalances = Array<{ + serviceId: string; + evmChainId: number; + olasBondBalance: number; + olasDepositBalance: number; + walletAddress: Address; +}>; export const BalanceContext = createContext<{ isLoaded: boolean; setIsLoaded: Dispatch>; - isBalanceLoaded: boolean; - olasBondBalance?: number; - olasDepositBalance?: number; - masterEoaBalance?: ValueOf; - masterSafeBalance?: ValueOf; - totalEthBalance?: number; - totalOlasBalance?: number; - isLowBalance: boolean; - wallets?: Wallet[]; - walletBalances: WalletAddressNumberRecord; - agentSafeBalance?: ValueOf; - agentEoaBalance?: ValueOf; updateBalances: () => Promise; setIsPaused: Dispatch>; - totalOlasStakedBalance?: number; - baseBalance?: number; - ethereumBalance?: number; - optimismBalance?: number; + walletBalances?: WalletBalanceResult[]; + stakedBalances?: CrossChainStakedBalances; + totalOlasBalance?: number; + totalEthBalance?: number; + totalStakedOlasBalance?: number; + lowBalances?: { + serviceConfigId: string; + chainId: EvmChainId; + walletAddress: Address; + balance: number; + expectedBalance: number; + }[]; + isLowBalance?: boolean; + isPaused: boolean; }>({ isLoaded: false, setIsLoaded: () => {}, - isBalanceLoaded: false, - olasBondBalance: undefined, - olasDepositBalance: undefined, - masterEoaBalance: undefined, - masterSafeBalance: undefined, - totalEthBalance: undefined, - totalOlasBalance: undefined, - isLowBalance: false, - wallets: undefined, - walletBalances: {}, - agentSafeBalance: undefined, - agentEoaBalance: undefined, updateBalances: async () => {}, + isPaused: false, setIsPaused: () => {}, - totalOlasStakedBalance: undefined, - baseBalance: undefined, - ethereumBalance: undefined, - optimismBalance: undefined, }); export const BalanceProvider = ({ children }: PropsWithChildren) => { const { isOnline } = useContext(OnlineStatusContext); - const { wallets, masterEoaAddress, masterSafeAddress } = - useContext(WalletContext); - const { services, serviceAddresses } = useContext(ServicesContext); - const { optimisticRewardsEarnedForEpoch, accruedServiceStakingRewards } = - useContext(RewardContext); + const { masterWallets } = useContext(MasterWalletContext); + const { services, serviceWallets, selectedAgentConfig } = + useContext(ServicesContext); const [isLoaded, setIsLoaded] = useState(false); const [isPaused, setIsPaused] = useState(false); - const [olasDepositBalance, setOlasDepositBalance] = useState(); - const [olasBondBalance, setOlasBondBalance] = useState(); - const [isBalanceLoaded, setIsBalanceLoaded] = useState(false); - const [walletBalances, setWalletBalances] = - useState({}); - const [baseBalance, setBaseBalance] = useState(); - const [ethereumBalance, setEthereumBalance] = useState(); - const [optimismBalance, setOptimismBalance] = useState(); - - const totalEthBalance: number | undefined = useMemo(() => { - if (!isLoaded) return; - return Object.values(walletBalances).reduce( - (acc: number, walletBalance) => acc + walletBalance.ETH, - 0, - ); - }, [isLoaded, walletBalances]); - - const totalOlasBalance: number | undefined = useMemo(() => { - if (!isLoaded) return; - - const sumWalletBalances = Object.values(walletBalances).reduce( - (acc: number, walletBalance) => acc + walletBalance.OLAS, - 0, - ); - - const total = - sumWalletBalances + - (olasDepositBalance ?? 0) + - (olasBondBalance ?? 0) + - (optimisticRewardsEarnedForEpoch ?? 0) + - (accruedServiceStakingRewards ?? 0); + const [isUpdatingBalances, setIsUpdatingBalances] = useState(false); - return total; - }, [ - accruedServiceStakingRewards, - isLoaded, - olasBondBalance, - olasDepositBalance, - optimisticRewardsEarnedForEpoch, - walletBalances, - ]); - - const totalOlasStakedBalance: number | undefined = useMemo(() => { - if (!isLoaded) return; - return (olasBondBalance ?? 0) + (olasDepositBalance ?? 0); - }, [isLoaded, olasBondBalance, olasDepositBalance]); - - const updateBalances = useCallback(async (): Promise => { - if (!masterEoaAddress) return; - - const walletAddresses: Address[] = []; - if (isAddress(masterEoaAddress)) walletAddresses.push(masterEoaAddress); - if (isAddress(`${masterSafeAddress}`)) { - walletAddresses.push(masterSafeAddress as Address); - } - if (serviceAddresses) { - walletAddresses.push(...serviceAddresses.filter(isAddress)); - } - - // fetch balances for other chains - try { - const baseBalanceTemp = - EthersService.getBaseBalance(masterEoaAddress).then(setBaseBalance); + const [walletBalances, setWalletBalances] = useState( + [], + ); + const [stakedBalances, setStakedBalances] = + useState([]); + + const totalEthBalance = useMemo(() => { + if (!isLoaded) return 0; + return walletBalances.reduce((acc, walletBalance) => { + if (walletBalance.isNative) { + return acc + walletBalance.balance; + } + return acc; + }, 0); + }, [isLoaded, walletBalances]); - const ethereumBalanceTemp = - EthersService.getEthereumBalance(masterEoaAddress).then( - setEthereumBalance, - ); + const totalOlasBalance = useMemo(() => { + if (!isLoaded) return 0; + return walletBalances.reduce((acc, walletBalance) => { + if (walletBalance.symbol === TokenSymbol.OLAS) { + return acc + walletBalance.balance; + } + return acc; + }, 0); + }, [isLoaded, walletBalances]); - const optimismBalanceTemp = - EthersService.getOptimismBalance(masterEoaAddress).then( - setOptimismBalance, + const totalStakedOlasBalance = useMemo(() => { + return stakedBalances + .filter( + (walletBalance) => + walletBalance.evmChainId === selectedAgentConfig.evmHomeChainId, + ) + .reduce((acc, balance) => { + return sum([acc, balance.olasBondBalance, balance.olasDepositBalance]); + }, 0); + }, [selectedAgentConfig.evmHomeChainId, stakedBalances]); + + const updateBalances = useCallback(async () => { + if (!isNil(masterWallets) && !isEmpty(masterWallets) && !isNil(services)) { + setIsUpdatingBalances(true); + + try { + const masterSafe = masterWallets.find( + (masterWallet) => + masterWallet.type === WalletType.Safe && + masterWallet.evmChainId === selectedAgentConfig.evmHomeChainId, ); - await Promise.allSettled([ - baseBalanceTemp, - ethereumBalanceTemp, - optimismBalanceTemp, - ]); - } catch (error) { - console.error(error); - } - - try { - const walletBalances = await getWalletBalances(walletAddresses); - if (!walletBalances) return; - - setWalletBalances(walletBalances); - - const serviceId = - services?.[0]?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data.token; - - if (!isNumber(serviceId)) { + const [walletBalancesResult, stakedBalancesResult] = + await Promise.allSettled([ + getCrossChainWalletBalances([ + ...masterWallets, + ...(serviceWallets || []), + ]), + getCrossChainStakedBalances(services, masterSafe?.address), + ]); + + // parse the results + const walletBalances = + walletBalancesResult.status === 'fulfilled' + ? walletBalancesResult.value + : []; + + const stakedBalances = + stakedBalancesResult.status === 'fulfilled' + ? stakedBalancesResult.value + : []; + + setWalletBalances(walletBalances || []); + setStakedBalances(stakedBalances || []); setIsLoaded(true); - setIsBalanceLoaded(true); - return; + } catch (error) { + console.error('Error updating balances:', error); + } finally { + setIsUpdatingBalances(false); } - - if (isAddress(`${masterSafeAddress}`) && serviceId > 0) { - const { depositValue, bondValue, serviceState } = - await AutonolasService.getServiceRegistryInfo( - masterSafeAddress as Address, - serviceId, - ); - - switch (serviceState) { - case ServiceRegistryL2ServiceState.NonExistent: - setOlasBondBalance(0); - setOlasDepositBalance(0); - break; - case ServiceRegistryL2ServiceState.PreRegistration: - setOlasBondBalance(0); - setOlasDepositBalance(0); - break; - case ServiceRegistryL2ServiceState.ActiveRegistration: - setOlasBondBalance(0); - setOlasDepositBalance(depositValue); - break; - case ServiceRegistryL2ServiceState.FinishedRegistration: - setOlasBondBalance(bondValue); - setOlasDepositBalance(depositValue); - break; - case ServiceRegistryL2ServiceState.Deployed: - setOlasBondBalance(bondValue); - setOlasDepositBalance(depositValue); - break; - case ServiceRegistryL2ServiceState.TerminatedBonded: - setOlasBondBalance(bondValue); - setOlasDepositBalance(0); - break; - } - } - - // update balance loaded state - setIsLoaded(true); - setIsBalanceLoaded(true); - } catch (error) { - console.error(error); - message.error('Unable to retrieve wallet balances'); - setIsBalanceLoaded(true); } - }, [masterEoaAddress, masterSafeAddress, serviceAddresses, services]); + }, [ + masterWallets, + services, + serviceWallets, + selectedAgentConfig.evmHomeChainId, + ]); - const agentEoaAddress = useMemo( - () => - services?.[0]?.chain_configs?.[CHAINS.OPTIMISM.chainId]?.chain_data - ?.instances?.[0], - [services], - ); - const masterEoaBalance = useMemo( - () => masterEoaAddress && walletBalances[masterEoaAddress], - [masterEoaAddress, walletBalances], - ); - const masterSafeBalance = useMemo( - () => masterSafeAddress && walletBalances[masterSafeAddress], - [masterSafeAddress, walletBalances], - ); - const agentSafeBalance = useMemo( - () => - services?.[0]?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data - ?.multisig && - walletBalances[ - services[0].chain_configs[CHAINS.OPTIMISM.chainId].chain_data.multisig! - ], - [services, walletBalances], - ); - const agentEoaBalance = useMemo( - () => agentEoaAddress && walletBalances[agentEoaAddress], - [agentEoaAddress, walletBalances], - ); + useEffect(() => { + // Update balances once on load, then use interval + if (!isOnline || isUpdatingBalances || isLoaded) return; - const isLowBalance = useMemo(() => { - if (!masterSafeBalance || !agentSafeBalance) return false; - if ( - masterSafeBalance.ETH < LOW_MASTER_SAFE_BALANCE && - // Need to check agentSafe balance as well, because it's auto-funded from safeBalance - agentSafeBalance.ETH < LOW_AGENT_SAFE_BALANCE - ) - return true; - return false; - }, [masterSafeBalance, agentSafeBalance]); - - useInterval( - () => { + updateBalances(); + }, [isOnline, isUpdatingBalances, isLoaded, updateBalances]); + + useInterval(() => { + if (!isPaused && isOnline && !isUpdatingBalances) { updateBalances(); - }, - isPaused || !isOnline ? null : FIVE_SECONDS_INTERVAL, - ); + } + }, FIVE_SECONDS_INTERVAL); return ( {children} @@ -311,84 +196,220 @@ export const BalanceProvider = ({ children }: PropsWithChildren) => { ); }; -export const getEthBalances = async ( - walletAddresses: Address[], -): Promise => { - const rpcIsValid = await EthersService.checkRpc( - `${process.env.OPTIMISM_RPC}`, - ); - if (!rpcIsValid) return; - - const ethBalances = await MulticallService.getEthBalances( - walletAddresses, - ).catch((e) => { - console.error(e); - return walletAddresses.reduce((acc, address) => { - acc[address] = 0; - return acc; - }, {} as AddressNumberRecord); - }); - - return ethBalances; +export type WalletBalanceResult = { + walletAddress: Address; + evmChainId: EvmChainId; + symbol: TokenSymbol; + isNative: boolean; + balance: number; }; -export const getOlasBalances = async ( - walletAddresses: Address[], -): Promise => { - const rpcIsValid = await EthersService.checkRpc( - `${process.env.OPTIMISM_RPC}`, - ); - if (!rpcIsValid) return; +const getCrossChainWalletBalances = async ( + wallets: Wallets, +): Promise => { + const balanceResults: WalletBalanceResult[] = []; - const olasBalances = await MulticallService.getErc20Balances( - walletAddresses, - TOKENS[CHAINS.OPTIMISM.chainId].OLAS.address, - ); + const providerEntries = Object.entries(PROVIDERS); - return olasBalances; -}; + for (const [ + evmChainIdKey, + { multicallProvider, provider }, + ] of providerEntries) { + try { + const providerEvmChainId = +evmChainIdKey as EvmChainId; + + const tokensOnChain = TOKEN_CONFIG[providerEvmChainId]; + // if (!tokensOnChain) continue; + + const relevantWallets = wallets.filter((wallet) => { + const isEoa = wallet.type === WalletType.EOA; + const isSafe = wallet.type === WalletType.Safe; + const isOnProviderChain = + isEoa || (isSafe && wallet.evmChainId === providerEvmChainId); + + return isOnProviderChain; + }); + + for (const { + tokenType, + symbol: tokenSymbol, + address: tokenAddress, + } of Object.values(tokensOnChain)) { + const isNative = tokenType === TokenType.NativeGas; + const isErc20 = tokenType === TokenType.Erc20; + + if (isNative) { + // get native balances for all relevant wallets + const nativeBalancePromises = + relevantWallets.map | null>( + ({ address: walletAddress }) => + isAddress(walletAddress) + ? provider.getBalance(getAddress(walletAddress)) + : null, + ); + + const nativeBalances = await Promise.all(nativeBalancePromises).catch( + (e) => { + console.error('Error fetching native balances:', e); + return []; + }, + ); -export const getWalletAddresses = ( - wallets: Wallet[], - serviceAddresses: Address[], -): Address[] => { - const walletsToCheck: Address[] = []; + // add the results to the balance results + nativeBalances.forEach( + (balance, index) => + !isNil(balance) && + balanceResults.push({ + walletAddress: relevantWallets[index].address, + evmChainId: providerEvmChainId, + symbol: tokenSymbol, + isNative: true, + balance: Number(formatEther(balance)), + }), + ); + } - for (const wallet of wallets) { - const { address } = wallet; + if (isErc20) { + if (!tokenAddress) continue; - if (address && isAddress(address)) { - walletsToCheck.push(address); - } - } + const erc20Contract = new MulticallContract( + tokenAddress, + ERC20_BALANCE_OF_STRING_FRAGMENT, + ); - for (const serviceAddress of serviceAddresses) { - if (serviceAddress && isAddress(`${serviceAddress}`)) { - walletsToCheck.push(serviceAddress); + const erc20Calls = relevantWallets.map((wallet) => + erc20Contract.balanceOf(wallet.address), + ); + + const erc20Balances = await multicallProvider.all(erc20Calls); + + const erc20Results = relevantWallets.map( + ({ address: walletAddress }, index) => ({ + walletAddress, + evmChainId: providerEvmChainId, + symbol: tokenSymbol, + isNative: false, + balance: Number(formatEther(erc20Balances[index])), + }), + ) as WalletBalanceResult[]; + + balanceResults.push(...erc20Results); + } + } + } catch (error) { + console.error('Error fetching balances for chain:', evmChainIdKey, error); } } - return walletsToCheck; + return balanceResults; }; -export const getWalletBalances = async ( - walletAddresses: Address[], -): Promise => { - const [ethBalances, olasBalances] = await Promise.all([ - getEthBalances(walletAddresses), - getOlasBalances(walletAddresses), - ]); +const getCrossChainStakedBalances = async ( + services: MiddlewareServiceResponse[], + masterSafeAddress: Maybe
, +): Promise => { + const result: CrossChainStakedBalances = []; + + const registryInfoPromises = services.map(async (service) => { + const serviceConfigId = service.service_config_id; + const middlewareChain: MiddlewareChain = service.home_chain; + const chainConfig = service.chain_configs[middlewareChain]; + const { token: serviceNftTokenId } = chainConfig.chain_data; + if ( + isNil(serviceNftTokenId) || + serviceNftTokenId <= 0 || + isNil(masterSafeAddress) || + !isAddress(masterSafeAddress) + ) { + return null; + } - if (!ethBalances) return; - if (!olasBalances) return; + const registryInfo = await StakedAgentService.getServiceRegistryInfo( + masterSafeAddress, + serviceNftTokenId, + asEvmChainId(middlewareChain), + ); - const tempWalletBalances: WalletAddressNumberRecord = {}; - for (const [address, balance] of Object.entries(ethBalances)) { - tempWalletBalances[address as Address] = { - [Token.ETH]: balance, - [Token.OLAS]: olasBalances[address as Address], + return { + serviceId: serviceConfigId, + chainId: middlewareChain, + ...registryInfo, }; - } + }); - return tempWalletBalances; + const registryInfos = await Promise.allSettled(registryInfoPromises); + + registryInfos.forEach((res, idx) => { + if (res.status === 'fulfilled' && res.value) { + const { serviceId, chainId, depositValue, bondValue, serviceState } = + res.value; + + result.push({ + serviceId, + evmChainId: asEvmChainId(chainId), + ...correctBondDepositByServiceState({ + olasBondBalance: bondValue, + olasDepositBalance: depositValue, + serviceState, + }), + walletAddress: + services[idx].chain_configs[chainId].chain_data.multisig!, // multisig must exist if registry info is fetched + }); + } else { + console.error( + 'Error fetching registry info for', + services[idx].service_config_id, + ); + } + }); + + return result; +}; + +/** + * Corrects the bond and deposit balances based on the service state + * @note the service state is used to determine the correct bond and deposit balances + */ +const correctBondDepositByServiceState = ({ + olasBondBalance, + olasDepositBalance, + serviceState, +}: { + olasBondBalance: number; + olasDepositBalance: number; + serviceState: ServiceRegistryL2ServiceState; +}): { + olasBondBalance: number; + olasDepositBalance: number; +} => { + switch (serviceState) { + case ServiceRegistryL2ServiceState.NonExistent: + case ServiceRegistryL2ServiceState.PreRegistration: + return { + olasBondBalance: 0, + olasDepositBalance: 0, + }; + case ServiceRegistryL2ServiceState.ActiveRegistration: + return { + olasBondBalance: 0, + olasDepositBalance, + }; + case ServiceRegistryL2ServiceState.FinishedRegistration: + case ServiceRegistryL2ServiceState.Deployed: + return { + olasBondBalance, + olasDepositBalance, + }; + case ServiceRegistryL2ServiceState.TerminatedBonded: + return { + olasBondBalance, + olasDepositBalance: 0, + }; + default: + console.error('Invalid service state'); + return { + olasBondBalance, + olasDepositBalance, + }; + } }; diff --git a/frontend/context/MasterSafeProvider.tsx b/frontend/context/MasterSafeProvider.tsx deleted file mode 100644 index 0ff84e89d..000000000 --- a/frontend/context/MasterSafeProvider.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { - createContext, - PropsWithChildren, - useContext, - useMemo, - useState, -} from 'react'; -import { useInterval } from 'usehooks-ts'; - -import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; -import { GnosisSafeService } from '@/service/GnosisSafe'; -import { Address } from '@/types/Address'; - -import { OnlineStatusContext } from './OnlineStatusProvider'; -import { WalletContext } from './WalletProvider'; - -export const MasterSafeContext = createContext<{ - backupSafeAddress?: Address; - masterSafeAddress?: Address; - masterEoaAddress?: Address; - masterSafeOwners?: Address[]; - updateMasterSafeOwners: () => Promise; -}>({ - backupSafeAddress: undefined, - masterSafeAddress: undefined, - masterEoaAddress: undefined, - masterSafeOwners: undefined, - updateMasterSafeOwners: async () => {}, -}); - -export const MasterSafeProvider = ({ children }: PropsWithChildren) => { - const { isOnline } = useContext(OnlineStatusContext); - const { masterSafeAddress, masterEoaAddress } = useContext(WalletContext); - - const [masterSafeOwners, setMasterSafeOwners] = useState(); - - const backupSafeAddress = useMemo
(() => { - if (!masterEoaAddress) return; - if (!masterSafeOwners) return; - if (!masterSafeOwners.length) return; - if ( - !masterSafeOwners.find( - (address) => address.toLowerCase() === masterEoaAddress.toLowerCase(), - ) - ) { - console.error('Safe not owned by master EOA'); - return; - } - - const currentBackupAddress = masterSafeOwners.find( - (address) => address !== masterEoaAddress, - ); - - return currentBackupAddress; - }, [masterEoaAddress, masterSafeOwners]); - - const updateMasterSafeOwners = async () => { - if (!masterSafeAddress) return; - try { - const safeSigners = await GnosisSafeService.getOwners({ - address: masterSafeAddress, - }); - if (!safeSigners) return; - setMasterSafeOwners(safeSigners); - } catch (error) { - console.error('Error fetching safe owners', error); - } - }; - - useInterval( - updateMasterSafeOwners, - (masterSafeOwners && masterSafeOwners.length >= 2) || !isOnline - ? null - : FIVE_SECONDS_INTERVAL, - ); - - return ( - - {children} - - ); -}; diff --git a/frontend/context/MasterWalletProvider.tsx b/frontend/context/MasterWalletProvider.tsx new file mode 100644 index 000000000..c981cc372 --- /dev/null +++ b/frontend/context/MasterWalletProvider.tsx @@ -0,0 +1,106 @@ +import { QueryObserverBaseResult, useQuery } from '@tanstack/react-query'; +import { getAddress } from 'ethers/lib/utils'; +import { createContext, PropsWithChildren, useContext, useState } from 'react'; + +import { MiddlewareWalletResponse } from '@/client'; +import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; +import { REACT_QUERY_KEYS } from '@/constants/react-query-keys'; +import { + MasterEoa, + MasterSafe, + MasterWallets, + WalletOwnerType, + WalletType, +} from '@/enums/Wallet'; +import { UsePause } from '@/hooks/usePause'; +import { WalletService } from '@/service/Wallet'; +import { asEvmChainId } from '@/utils/middlewareHelpers'; + +import { OnlineStatusContext } from './OnlineStatusProvider'; + +type MasterWalletContext = { + masterEoa?: MasterEoa; + masterSafes?: MasterSafe[]; + masterWallets?: (MasterEoa | MasterSafe)[]; +} & Partial> & + UsePause; + +export const MasterWalletContext = createContext({ + paused: false, + setPaused: () => {}, + togglePaused: () => {}, +}); + +const transformMiddlewareWalletResponse = ( + data: MiddlewareWalletResponse[], +): MasterWallets => { + const result: MasterWallets = []; + + data.forEach((response) => { + if (getAddress(response.address)) { + result.push({ + address: response.address, + owner: WalletOwnerType.Master, + type: WalletType.EOA, + }); + } + + Object.entries(response.safes).forEach(([middlewareChain, safeAddress]) => { + if (getAddress(safeAddress)) { + result.push({ + address: safeAddress, + evmChainId: asEvmChainId(middlewareChain), + owner: WalletOwnerType.Master, + type: WalletType.Safe, + }); + } + }); + }, []); + + return result; +}; + +export const MasterWalletProvider = ({ children }: PropsWithChildren) => { + const { isOnline } = useContext(OnlineStatusContext); + + const [paused, setPaused] = useState(false); + + const { + data: masterWallets, + refetch, + isFetched, + } = useQuery({ + queryKey: REACT_QUERY_KEYS.WALLETS_KEY, + queryFn: WalletService.getWallets, + refetchInterval: isOnline && !paused ? FIVE_SECONDS_INTERVAL : false, + select: (data) => transformMiddlewareWalletResponse(data), + }); + + const masterEoa = masterWallets?.find( + (wallet): wallet is MasterEoa => + wallet.type === WalletType.EOA && wallet.owner === WalletOwnerType.Master, + ); + + const masterSafes = masterWallets?.filter( + (wallet): wallet is MasterSafe => + wallet.type === WalletType.Safe && + wallet.owner === WalletOwnerType.Master, + ); + + return ( + setPaused((prev) => !prev), + refetch, + isFetched, + }} + > + {children} + + ); +}; diff --git a/frontend/context/PageStateProvider.tsx b/frontend/context/PageStateProvider.tsx index 76e44486b..9a1761f9d 100644 --- a/frontend/context/PageStateProvider.tsx +++ b/frontend/context/PageStateProvider.tsx @@ -7,7 +7,7 @@ import { } from 'react'; import { useTimeout } from 'usehooks-ts'; -import { Pages } from '@/enums/PageState'; +import { Pages } from '@/enums/Pages'; const LAST_TRANSACTION_SHOW_DELAY = 60 * 1000; diff --git a/frontend/context/RewardProvider.tsx b/frontend/context/RewardProvider.tsx index 99eda450e..2a109c586 100644 --- a/frontend/context/RewardProvider.tsx +++ b/frontend/context/RewardProvider.tsx @@ -1,4 +1,6 @@ -import { ethers } from 'ethers'; +import { useQuery } from '@tanstack/react-query'; +import { formatUnits } from 'ethers/lib/utils'; +import { isNil } from 'lodash'; import { createContext, PropsWithChildren, @@ -6,18 +8,19 @@ import { useContext, useEffect, useMemo, - useState, } from 'react'; -import { useInterval } from 'usehooks-ts'; -import { CHAINS } from '@/constants/chains'; +import { AGENT_CONFIG } from '@/config/agents'; +import { GNOSIS_CHAIN_CONFIG } from '@/config/chains'; import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; +import { REACT_QUERY_KEYS } from '@/constants/react-query-keys'; import { useElectronApi } from '@/hooks/useElectronApi'; +import { useServices } from '@/hooks/useServices'; import { useStore } from '@/hooks/useStore'; -import { AutonolasService } from '@/service/Autonolas'; +import { StakingRewardsInfoSchema } from '@/types/Autonolas'; +import { asMiddlewareChain } from '@/utils/middlewareHelpers'; import { OnlineStatusContext } from './OnlineStatusProvider'; -import { ServicesContext } from './ServicesProvider'; import { StakingProgramContext } from './StakingProgramProvider'; export const RewardContext = createContext<{ @@ -28,98 +31,156 @@ export const RewardContext = createContext<{ optimisticRewardsEarnedForEpoch?: number; minimumStakedAmountRequired?: number; updateRewards: () => Promise; + isStakingRewardsDetailsFetched?: boolean; }>({ - accruedServiceStakingRewards: undefined, - availableRewardsForEpoch: undefined, - availableRewardsForEpochEth: undefined, - isEligibleForRewards: undefined, - optimisticRewardsEarnedForEpoch: undefined, - minimumStakedAmountRequired: undefined, updateRewards: async () => {}, }); -export const RewardProvider = ({ children }: PropsWithChildren) => { +const currentAgent = AGENT_CONFIG.trader; // TODO: replace with dynamic agent selection +const currentChainId = GNOSIS_CHAIN_CONFIG.evmChainId; // TODO: replace with selectedAgentConfig.chainId + +/** + * hook to fetch staking rewards details + */ +const useStakingRewardsDetails = () => { + const { isOnline } = useContext(OnlineStatusContext); + const { selectedStakingProgramId } = useContext(StakingProgramContext); + + const { selectedService } = useServices(); + // const { service } = useService(selectedService?.service_config_id); + + const serviceConfigId = selectedService?.service_config_id; + + // fetch chain data from the selected service + const chainData = !isNil(selectedService?.chain_configs) + ? selectedService?.chain_configs?.[asMiddlewareChain(currentChainId)] + .chain_data + : null; + const multisig = chainData?.multisig; + const token = chainData?.token; + + return useQuery({ + queryKey: REACT_QUERY_KEYS.REWARDS_KEY( + currentChainId, + serviceConfigId!, + selectedStakingProgramId!, + multisig!, + token!, + ), + queryFn: async () => { + if (!multisig || !token || !selectedStakingProgramId) return; + const response = await currentAgent.serviceApi.getAgentStakingRewardsInfo( + { + agentMultisigAddress: multisig, + serviceId: token, + stakingProgramId: selectedStakingProgramId, + chainId: currentChainId, + }, + ); + + if (!response) return; + + try { + const parsed = StakingRewardsInfoSchema.parse(response); + return parsed; + } catch (e) { + console.error('Error parsing staking rewards info', e); + } + }, + enabled: + !!isOnline && + !!serviceConfigId && + !!selectedStakingProgramId && + !!multisig && + !!token, + refetchInterval: isOnline ? FIVE_SECONDS_INTERVAL : false, + refetchOnWindowFocus: false, + }); +}; + +/** + * hook to fetch available rewards for the current epoch + */ +const useAvailableRewardsForEpoch = () => { const { isOnline } = useContext(OnlineStatusContext); - const { services } = useContext(ServicesContext); - const service = useMemo(() => services?.[0], [services]); + const { selectedStakingProgramId } = useContext(StakingProgramContext); + + const { selectedService, isFetched: isServicesFetched } = useServices(); + const serviceConfigId = + isServicesFetched && selectedService + ? selectedService?.service_config_id + : ''; + + return useQuery({ + queryKey: REACT_QUERY_KEYS.AVAILABLE_REWARDS_FOR_EPOCH_KEY( + currentChainId, + serviceConfigId, + selectedStakingProgramId!, + currentChainId, + ), + queryFn: async () => { + return await currentAgent.serviceApi.getAvailableRewardsForEpoch( + selectedStakingProgramId!, + currentChainId, + ); + }, + enabled: !!isOnline && !!selectedStakingProgramId, + refetchInterval: isOnline ? FIVE_SECONDS_INTERVAL : false, + refetchOnWindowFocus: false, + }); +}; + +/** + * Provider to manage rewards context + */ +export const RewardProvider = ({ children }: PropsWithChildren) => { const { storeState } = useStore(); const electronApi = useElectronApi(); - const { activeStakingProgramId, defaultStakingProgramId } = useContext( - StakingProgramContext, - ); - const [accruedServiceStakingRewards, setAccruedServiceStakingRewards] = - useState(); - const [availableRewardsForEpoch, setAvailableRewardsForEpoch] = - useState(); - const [isEligibleForRewards, setIsEligibleForRewards] = useState(); + const { + data: stakingRewardsDetails, + refetch: refetchStakingRewardsDetails, + isFetched: isStakingRewardsDetailsFetched, + } = useStakingRewardsDetails(); - const availableRewardsForEpochEth = useMemo(() => { - if (!availableRewardsForEpoch) return; + const { + data: availableRewardsForEpoch, + refetch: refetchAvailableRewardsForEpoch, + } = useAvailableRewardsForEpoch(); - const formatRewardsEth = parseFloat( - ethers.utils.formatUnits(`${availableRewardsForEpoch}`, 18), - ); + const isEligibleForRewards = stakingRewardsDetails?.isEligibleForRewards; + const accruedServiceStakingRewards = + stakingRewardsDetails?.accruedServiceStakingRewards; - return formatRewardsEth; + // available rewards for the current epoch in ETH + const availableRewardsForEpochEth = useMemo(() => { + if (!availableRewardsForEpoch) return; + return parseFloat(formatUnits(`${availableRewardsForEpoch}`)); }, [availableRewardsForEpoch]); + // optimistic rewards earned for the current epoch in ETH const optimisticRewardsEarnedForEpoch = useMemo(() => { - if (isEligibleForRewards && availableRewardsForEpochEth) { - return availableRewardsForEpochEth; - } - return; + if (!isEligibleForRewards) return; + if (!availableRewardsForEpochEth) return; + return availableRewardsForEpochEth; }, [availableRewardsForEpochEth, isEligibleForRewards]); - const updateRewards = useCallback(async (): Promise => { - let stakingRewardsInfoPromise; - - // only check for rewards if there's a currentStakingProgram active - if ( - activeStakingProgramId && - service?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data?.multisig && - service?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data?.token - ) { - stakingRewardsInfoPromise = AutonolasService.getAgentStakingRewardsInfo({ - agentMultisigAddress: - service.chain_configs[CHAINS.OPTIMISM.chainId].chain_data.multisig!, - serviceId: - service.chain_configs[CHAINS.OPTIMISM.chainId].chain_data.token!, - stakingProgram: activeStakingProgramId, - }); - } - - // can fallback to default staking program if no current staking program is active - const epochRewardsPromise = AutonolasService.getAvailableRewardsForEpoch( - activeStakingProgramId ?? defaultStakingProgramId, - ); - - const [stakingRewardsInfo, rewards] = await Promise.all([ - stakingRewardsInfoPromise, - epochRewardsPromise, - ]); - - setIsEligibleForRewards(stakingRewardsInfo?.isEligibleForRewards); - setAccruedServiceStakingRewards( - stakingRewardsInfo?.accruedServiceStakingRewards, - ); - setAvailableRewardsForEpoch(rewards); - }, [activeStakingProgramId, defaultStakingProgramId, service]); - + // store the first staking reward achieved in the store for notification useEffect(() => { - if (isEligibleForRewards && !storeState?.firstStakingRewardAchieved) { - electronApi.store?.set?.('firstStakingRewardAchieved', true); - } + if (!isEligibleForRewards) return; + if (storeState?.firstStakingRewardAchieved) return; + electronApi.store?.set?.('firstStakingRewardAchieved', true); }, [ electronApi.store, isEligibleForRewards, storeState?.firstStakingRewardAchieved, ]); - useInterval( - async () => updateRewards(), - isOnline ? FIVE_SECONDS_INTERVAL : null, - ); + // refresh rewards data + const updateRewards = useCallback(async () => { + await refetchStakingRewardsDetails(); + await refetchAvailableRewardsForEpoch(); + }, [refetchStakingRewardsDetails, refetchAvailableRewardsForEpoch]); return ( { isEligibleForRewards, optimisticRewardsEarnedForEpoch, updateRewards, + isStakingRewardsDetailsFetched, }} > {children} diff --git a/frontend/context/ServicesProvider.tsx b/frontend/context/ServicesProvider.tsx index 73a16c84b..f535d87b8 100644 --- a/frontend/context/ServicesProvider.tsx +++ b/frontend/context/ServicesProvider.tsx @@ -1,123 +1,244 @@ -import { message } from 'antd'; +import { QueryObserverBaseResult, useQuery } from '@tanstack/react-query'; +import { isEmpty, noop } from 'lodash'; import { createContext, - Dispatch, PropsWithChildren, - SetStateAction, useCallback, useContext, + useEffect, useMemo, useState, } from 'react'; -import { useInterval } from 'usehooks-ts'; -import { DeploymentStatus, Service } from '@/client'; -import { CHAINS } from '@/constants/chains'; +import { + MiddlewareChain, + MiddlewareDeploymentStatus, + MiddlewareServiceResponse, +} from '@/client'; +import { AGENT_CONFIG } from '@/config/agents'; import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; +import { REACT_QUERY_KEYS } from '@/constants/react-query-keys'; +import { AgentType } from '@/enums/Agent'; +import { + AgentEoa, + AgentSafe, + AgentWallets, + WalletOwnerType, + WalletType, +} from '@/enums/Wallet'; +import { UsePause, usePause } from '@/hooks/usePause'; import { ServicesService } from '@/service/Services'; -import { Address } from '@/types/Address'; +import { AgentConfig } from '@/types/Agent'; +import { Service } from '@/types/Service'; +import { Maybe, Optional } from '@/types/Util'; +import { asEvmChainId } from '@/utils/middlewareHelpers'; import { OnlineStatusContext } from './OnlineStatusProvider'; -type ServicesContextProps = { - services?: Service[]; - serviceAddresses?: Address[]; - setServices: Dispatch>; - serviceStatus: DeploymentStatus | undefined; - setServiceStatus: Dispatch>; - updateServicesState: () => Promise; - updateServiceStatus: () => Promise; - hasInitialLoaded: boolean; - setHasInitialLoaded: Dispatch>; - setIsPaused: Dispatch>; -}; +type ServicesContextType = { + services?: MiddlewareServiceResponse[]; + serviceWallets?: AgentWallets; + selectService: (serviceConfigId: string) => void; + selectedService?: Service; + selectedServiceStatusOverride?: Maybe; + isSelectedServiceStatusFetched: boolean; + refetchSelectedServiceStatus: () => void; + selectedAgentConfig: AgentConfig; + selectedAgentType: AgentType; + updateAgentType: (agentType: AgentType) => void; + overrideSelectedServiceStatus: ( + status?: Maybe, + ) => void; +} & Partial> & + UsePause; -export const ServicesContext = createContext({ - services: undefined, - serviceAddresses: undefined, - setServices: () => {}, - serviceStatus: undefined, - setServiceStatus: () => {}, - updateServicesState: async () => {}, - updateServiceStatus: async () => {}, - hasInitialLoaded: false, - setHasInitialLoaded: () => {}, - setIsPaused: () => {}, +export const ServicesContext = createContext({ + paused: false, + setPaused: noop, + togglePaused: noop, + selectService: noop, + isSelectedServiceStatusFetched: false, + refetchSelectedServiceStatus: noop, + selectedAgentConfig: AGENT_CONFIG[AgentType.PredictTrader], + selectedAgentType: AgentType.PredictTrader, + updateAgentType: noop, + overrideSelectedServiceStatus: noop, }); +/** + * Polls for available services via the middleware API globally + */ export const ServicesProvider = ({ children }: PropsWithChildren) => { const { isOnline } = useContext(OnlineStatusContext); + const { paused, setPaused, togglePaused } = usePause(); - const [services, setServices] = useState(); - - const [serviceStatus, setServiceStatus] = useState< - DeploymentStatus | undefined - >(); - const [hasInitialLoaded, setHasInitialLoaded] = useState(false); - const [isPaused, setIsPaused] = useState(false); - - const serviceAddresses = useMemo( - () => - services?.reduce((acc, service: Service) => { - const instances = - service.chain_configs[CHAINS.OPTIMISM.chainId].chain_data.instances; - if (instances) { - acc.push(...instances); - } - - const multisig = - service.chain_configs[CHAINS.OPTIMISM.chainId].chain_data.multisig; - if (multisig) { - acc.push(multisig); - } - return acc; - }, []), - [services], + // selected agent type + const [selectedAgentType, setAgentType] = useState( + AgentType.PredictTrader, ); - const updateServicesState = useCallback( - async (): Promise => - ServicesService.getServices() - .then((data: Service[]) => { - if (!Array.isArray(data)) return; - setServices(data); - setHasInitialLoaded(true); - }) - .catch((e) => { - console.error(e); - // message.error(e.message); Commented out to avoid showing error message; need to handle "isAuthenticated" in a better way - }), - [], - ); + // user selected service identifier + const [selectedServiceConfigId, setSelectedServiceConfigId] = + useState>(); - const updateServiceStatus = useCallback(async () => { - if (!services?.[0]) return; - const serviceStatus = await ServicesService.getDeployment(services[0].hash); - setServiceStatus(serviceStatus.status); - }, [services]); - - // Update service state - useInterval( - () => - updateServicesState() - .then(() => updateServiceStatus()) - .catch((e) => message.error(e.message)), - isOnline && !isPaused ? FIVE_SECONDS_INTERVAL : null, - ); + const { + data: services, + isError, + isFetched: isServicesFetched, + isLoading, + isFetching, + refetch, + } = useQuery({ + queryKey: REACT_QUERY_KEYS.SERVICES_KEY, + queryFn: ServicesService.getServices, + enabled: isOnline && !paused, + refetchInterval: FIVE_SECONDS_INTERVAL, + }); + + const { + data: selectedServiceStatus, + isFetched: isSelectedServiceStatusFetched, + refetch: refetchSelectedServiceStatus, + } = useQuery({ + queryKey: REACT_QUERY_KEYS.SERVICE_DEPLOYMENT_STATUS_KEY( + selectedServiceConfigId, + ), + queryFn: () => + ServicesService.getDeployment(selectedServiceConfigId as string), + enabled: !!selectedServiceConfigId, + refetchInterval: FIVE_SECONDS_INTERVAL, + }); + + const [selectedServiceStatusOverride, setSelectedServiceStatusOverride] = + useState>(); + + const selectedService = useMemo(() => { + if (!services) return; + + return services.find( + (service) => service.service_config_id === selectedServiceConfigId, + ); + }, [selectedServiceConfigId, services]); + + const selectedServiceWithStatus = useMemo(() => { + if (!selectedService) return; + return { + ...selectedService, + deploymentStatus: + selectedServiceStatusOverride ?? selectedServiceStatus?.status, + }; + }, [ + selectedService, + selectedServiceStatus?.status, + selectedServiceStatusOverride, + ]); + + const selectService = useCallback((serviceConfigId: string) => { + setSelectedServiceConfigId(serviceConfigId); + }, []); + + const updateAgentType = useCallback((agentType: AgentType) => { + setAgentType(agentType); + }, []); + + const selectedAgentConfig = useMemo(() => { + const config: Maybe = AGENT_CONFIG[selectedAgentType]; + + if (!config) { + throw new Error(`Agent config not found for ${selectedAgentType}`); + } + return config; + }, [selectedAgentType]); + + const serviceWallets: Optional = useMemo(() => { + if (!isServicesFetched) return; + if (isEmpty(services)) return []; + + return services?.reduce( + (acc, service: MiddlewareServiceResponse) => { + return [ + ...acc, + ...Object.keys(service.chain_configs).reduce( + (acc: AgentWallets, middlewareChain: string) => { + const chainConfig = + service.chain_configs[middlewareChain as MiddlewareChain]; + + if (!chainConfig) return acc; + + const instances = chainConfig.chain_data.instances; + const multisig = chainConfig.chain_data.multisig; + + if (instances) { + acc.push( + ...instances.map( + (instance: string) => + ({ + address: instance, + type: WalletType.EOA, + owner: WalletOwnerType.Agent, + }) as AgentEoa, + ), + ); + } + + if (multisig) { + acc.push({ + address: multisig, + type: WalletType.Safe, + owner: WalletOwnerType.Agent, + evmChainId: asEvmChainId(middlewareChain), + } as AgentSafe); + } + + return acc; + }, + [], + ), + ]; + }, + [], + ); + }, [isServicesFetched, services]); + + /** + * Select the first service by default + */ + useEffect(() => { + if (!isServicesFetched) return; + + if (isEmpty(services)) setSelectedServiceConfigId(null); + + if (!selectedServiceConfigId && services && services.length > 0) { + setSelectedServiceConfigId(services[0].service_config_id); + } + }, [isServicesFetched, selectedServiceConfigId, services]); return ( , + ) => { + setSelectedServiceStatusOverride(status); + }, }} > {children} diff --git a/frontend/context/StakingContractDetailsProvider.tsx b/frontend/context/StakingContractDetailsProvider.tsx new file mode 100644 index 000000000..776ff8adc --- /dev/null +++ b/frontend/context/StakingContractDetailsProvider.tsx @@ -0,0 +1,210 @@ +import { useQueries, useQuery } from '@tanstack/react-query'; +import { Maybe } from 'graphql/jsutils/Maybe'; +import { isNil } from 'lodash'; +import { + createContext, + Dispatch, + PropsWithChildren, + SetStateAction, + useCallback, + useContext, + useState, +} from 'react'; + +import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; +import { REACT_QUERY_KEYS } from '@/constants/react-query-keys'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { useServices } from '@/hooks/useServices'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; +import { + ServiceStakingDetails, + StakingContractDetails, +} from '@/types/Autonolas'; +import { asMiddlewareChain } from '@/utils/middlewareHelpers'; + +import { StakingProgramContext } from './StakingProgramProvider'; + +/** + * hook to get all staking contract details + */ +const useAllStakingContractDetails = () => { + const { allStakingProgramIds } = useStakingProgram(); + const { selectedAgentConfig } = useServices(); + const { serviceApi, evmHomeChainId: homeChainId } = selectedAgentConfig; + + const queryResults = useQueries({ + queries: allStakingProgramIds.map((programId) => ({ + queryKey: REACT_QUERY_KEYS.ALL_STAKING_CONTRACT_DETAILS( + homeChainId, + programId, + ), + queryFn: async () => + await serviceApi.getStakingContractDetails( + programId as StakingProgramId, + homeChainId, + ), + onError: (error: Error) => { + console.error( + `Error fetching staking details for ${programId}:`, + error, + ); + }, + })), + }); + + // Aggregate results into a record + const allStakingContractDetailsRecord = allStakingProgramIds.reduce( + (record, programId, index) => { + const query = queryResults[index]; + if (query.status === 'success') { + record[programId] = query.data; + } else if (query.status === 'error') { + console.error(query.error); + } + return record; + }, + {} as Record>, + ); + + const isAllStakingContractDetailsLoaded = queryResults.every( + (query) => query.isSuccess, + ); + + return { allStakingContractDetailsRecord, isAllStakingContractDetailsLoaded }; +}; + +/** + * hook to get staking contract details by staking program + */ +const useStakingContractDetailsByStakingProgram = ({ + serviceNftTokenId, + stakingProgramId, + isPaused, +}: { + serviceNftTokenId: Maybe; + stakingProgramId: Maybe; + isPaused?: boolean; +}) => { + const { selectedAgentConfig } = useServices(); + const { serviceApi, evmHomeChainId } = selectedAgentConfig; + return useQuery({ + queryKey: REACT_QUERY_KEYS.STAKING_CONTRACT_DETAILS_BY_STAKING_PROGRAM_KEY( + evmHomeChainId, + serviceNftTokenId!, + stakingProgramId!, + ), + queryFn: async () => { + /** + * Request staking contract details + * if service is present, request it's info and states on the staking contract + */ + const promises: Promise< + StakingContractDetails | ServiceStakingDetails + >[] = [ + serviceApi.getStakingContractDetails(stakingProgramId!, evmHomeChainId), + ]; + + if (!isNil(serviceNftTokenId)) { + promises.push( + serviceApi.getServiceStakingDetails( + serviceNftTokenId, + stakingProgramId!, + evmHomeChainId, + ), + ); + } + + return Promise.allSettled(promises).then((results) => { + const [stakingContractDetails, serviceStakingDetails] = results; + return { + ...(stakingContractDetails.status === 'fulfilled' + ? (stakingContractDetails.value as StakingContractDetails) + : {}), + ...(serviceStakingDetails.status === 'fulfilled' + ? (serviceStakingDetails.value as ServiceStakingDetails) + : {}), + }; + }); + }, + enabled: !isPaused && !!stakingProgramId, + refetchInterval: !isPaused ? FIVE_SECONDS_INTERVAL : false, + refetchOnWindowFocus: false, + }); +}; + +type StakingContractDetailsContextProps = { + selectedStakingContractDetails: Maybe< + Partial + >; + isSelectedStakingContractDetailsLoaded: boolean; + isPaused: boolean; + allStakingContractDetailsRecord?: Record< + StakingProgramId, + Partial + >; + isAllStakingContractDetailsRecordLoaded: boolean; + refetchSelectedStakingContractDetails: () => Promise; + setIsPaused: Dispatch>; +}; + +/** + * Context for staking contract details + */ +export const StakingContractDetailsContext = + createContext({ + selectedStakingContractDetails: null, + isPaused: false, + isAllStakingContractDetailsRecordLoaded: false, + isSelectedStakingContractDetailsLoaded: false, + refetchSelectedStakingContractDetails: async () => {}, + setIsPaused: () => {}, + }); + +/** + * Provider for staking contract details + */ +export const StakingContractDetailsProvider = ({ + children, +}: PropsWithChildren) => { + const [isPaused, setIsPaused] = useState(false); + const { selectedService, selectedAgentConfig } = useServices(); + + const { selectedStakingProgramId } = useContext(StakingProgramContext); + + const { + data: selectedStakingContractDetails, + isFetched, + refetch, + } = useStakingContractDetailsByStakingProgram({ + serviceNftTokenId: !isNil(selectedService?.service_config_id) + ? selectedService?.chain_configs?.[ + asMiddlewareChain(selectedAgentConfig.evmHomeChainId) + ].chain_data.token + : null, + stakingProgramId: selectedStakingProgramId, + }); + + const { allStakingContractDetailsRecord, isAllStakingContractDetailsLoaded } = + useAllStakingContractDetails(); + + const refetchSelectedStakingContractDetails = useCallback(async () => { + await refetch(); + }, [refetch]); + + return ( + + {children} + + ); +}; diff --git a/frontend/context/StakingContractInfoProvider.tsx b/frontend/context/StakingContractInfoProvider.tsx deleted file mode 100644 index 53f4ba469..000000000 --- a/frontend/context/StakingContractInfoProvider.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { - createContext, - Dispatch, - PropsWithChildren, - SetStateAction, - useCallback, - useContext, - useEffect, - useMemo, - useState, -} from 'react'; -import { useInterval } from 'usehooks-ts'; - -import { CHAINS } from '@/constants/chains'; -import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; -import { StakingProgramId } from '@/enums/StakingProgram'; -import { AutonolasService } from '@/service/Autonolas'; -import { StakingContractInfo } from '@/types/Autonolas'; - -import { ServicesContext } from './ServicesProvider'; -import { - DEFAULT_STAKING_PROGRAM_ID, - StakingProgramContext, -} from './StakingProgramProvider'; - -type StakingContractInfoContextProps = { - activeStakingContractInfo?: Partial; - isPaused: boolean; - isStakingContractInfoLoaded: boolean; - stakingContractInfoRecord?: Record< - StakingProgramId, - Partial - >; - updateActiveStakingContractInfo: () => Promise; - setIsPaused: Dispatch>; -}; - -export const StakingContractInfoContext = - createContext({ - activeStakingContractInfo: undefined, - isPaused: false, - isStakingContractInfoLoaded: false, - stakingContractInfoRecord: undefined, - updateActiveStakingContractInfo: async () => {}, - setIsPaused: () => {}, - }); - -export const StakingContractInfoProvider = ({ - children, -}: PropsWithChildren) => { - const { services } = useContext(ServicesContext); - const { activeStakingProgramId } = useContext(StakingProgramContext); - - const [isPaused, setIsPaused] = useState(false); - const [isStakingContractInfoLoaded, setIsStakingContractInfoLoaded] = - useState(false); - - const [activeStakingContractInfo, setActiveStakingContractInfo] = - useState>(); - - const [stakingContractInfoRecord, setStakingContractInfoRecord] = - useState>>(); - - const serviceId = useMemo( - () => - services?.[0]?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data?.token, - [services], - ); - - /** Updates staking contract info specific to the actively staked service owned by the user */ - const updateActiveStakingContractInfo = useCallback(async () => { - if (!serviceId) return; - if (!activeStakingProgramId) return; - - AutonolasService.getStakingContractInfoByServiceIdStakingProgram( - serviceId, - activeStakingProgramId, - ).then(setActiveStakingContractInfo); - }, [activeStakingProgramId, serviceId]); - - useInterval( - async () => { - await updateStakingContractInfoRecord().catch(console.error); - await updateActiveStakingContractInfo().catch(console.error); - }, - isPaused ? null : FIVE_SECONDS_INTERVAL, - ); - - /** Updates general staking contract information, not user or service specific */ - const updateStakingContractInfoRecord = async () => { - const stakingPrograms = Object.values([DEFAULT_STAKING_PROGRAM_ID]); - - try { - const stakingInfoPromises = stakingPrograms.map((programId) => - AutonolasService.getStakingContractInfoByStakingProgram(programId), - ); - - const stakingInfos = await Promise.allSettled(stakingInfoPromises); - - const stakingContractInfoRecord = stakingPrograms.reduce( - (record, programId, index) => { - if (stakingInfos[index].status === 'rejected') { - console.error(stakingInfos[index].reason); - return record; - } - record[programId] = stakingInfos[index].value; - return record; - }, - {} as Record>, - ); - - setStakingContractInfoRecord(stakingContractInfoRecord); - setIsStakingContractInfoLoaded(true); - } catch (e) { - console.error(e); - } - }; - - useEffect(() => { - // Load generic staking contract info record on mount - updateStakingContractInfoRecord(); - }, []); - - return ( - - {children} - - ); -}; diff --git a/frontend/context/StakingProgramProvider.tsx b/frontend/context/StakingProgramProvider.tsx index 9970d79b8..267efa3e5 100644 --- a/frontend/context/StakingProgramProvider.tsx +++ b/frontend/context/StakingProgramProvider.tsx @@ -1,58 +1,130 @@ -import { createContext, PropsWithChildren, useCallback, useState } from 'react'; -import { useInterval } from 'usehooks-ts'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { isNil } from 'lodash'; +import { + createContext, + PropsWithChildren, + useCallback, + useEffect, + useState, +} from 'react'; -import { CHAINS } from '@/constants/chains'; +import { DEFAULT_STAKING_PROGRAM_IDS } from '@/config/stakingPrograms'; +import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; +import { REACT_QUERY_KEYS } from '@/constants/react-query-keys'; import { StakingProgramId } from '@/enums/StakingProgram'; import { useServices } from '@/hooks/useServices'; -import { AutonolasService } from '@/service/Autonolas'; - -export const DEFAULT_STAKING_PROGRAM_ID = StakingProgramId.OptimusAlpha; +import { Maybe, Nullable } from '@/types/Util'; export const StakingProgramContext = createContext<{ - activeStakingProgramId?: StakingProgramId | null; - defaultStakingProgramId: StakingProgramId; - updateActiveStakingProgramId: () => Promise; + isActiveStakingProgramLoaded: boolean; + activeStakingProgramId?: Maybe; + defaultStakingProgramId?: Maybe; + selectedStakingProgramId: Nullable; + setDefaultStakingProgramId: (stakingProgramId: StakingProgramId) => void; }>({ - activeStakingProgramId: undefined, - defaultStakingProgramId: DEFAULT_STAKING_PROGRAM_ID, - updateActiveStakingProgramId: async () => {}, + isActiveStakingProgramLoaded: false, + selectedStakingProgramId: null, + setDefaultStakingProgramId: () => {}, }); -/** Determines the current active staking program, if any */ -export const StakingProgramProvider = ({ children }: PropsWithChildren) => { - const { service } = useServices(); - - const [activeStakingProgramId, setActiveStakingProgramId] = - useState(); - - const updateActiveStakingProgramId = useCallback(async () => { - // if no service nft, not staked - const serviceId = - service?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data?.token; - - if (!service?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data?.token) { - setActiveStakingProgramId(null); - return; - } - - if (serviceId) { - // if service exists, we need to check if it is staked - AutonolasService.getCurrentStakingProgramByServiceId(serviceId).then( - (stakingProgramId) => { - setActiveStakingProgramId(stakingProgramId); - }, +/** + * hook to get the active staking program id + */ +const useGetActiveStakingProgramId = (serviceNftTokenId: Maybe) => { + const queryClient = useQueryClient(); + const { selectedAgentConfig, isFetched: isServicesLoaded } = useServices(); + + const { serviceApi, evmHomeChainId } = selectedAgentConfig; + + const isQueryEnabled = + !isNil(evmHomeChainId) && isServicesLoaded && !!serviceNftTokenId; + + const response = useQuery({ + queryKey: REACT_QUERY_KEYS.STAKING_PROGRAM_KEY(evmHomeChainId), + queryFn: async () => { + if (!serviceNftTokenId) return null; + if (!Number(serviceNftTokenId)) return null; + + const currentStakingProgramId = + await serviceApi.getCurrentStakingProgramByServiceId( + serviceNftTokenId, + evmHomeChainId, + ); + + return ( + currentStakingProgramId || + DEFAULT_STAKING_PROGRAM_IDS[selectedAgentConfig.evmHomeChainId] + ); + }, + // enabled: isQueryEnabled, + refetchInterval: isQueryEnabled ? FIVE_SECONDS_INTERVAL : false, + }); + + const setActiveStakingProgramId = useCallback( + (stakingProgramId: Nullable) => { + if (!serviceNftTokenId) + throw new Error( + 'serviceNftTokenId is required to set the active staking program id', + ); + if (!stakingProgramId) + throw new Error( + 'stakingProgramId is required to set the active staking program id', + ); + + // update the active staking program id in the cache + queryClient.setQueryData( + REACT_QUERY_KEYS.STAKING_PROGRAM_KEY(evmHomeChainId, serviceNftTokenId), + stakingProgramId, ); - } - }, [service]); + }, + [queryClient, evmHomeChainId, serviceNftTokenId], + ); + + return { ...response, isEnabled: isQueryEnabled, setActiveStakingProgramId }; +}; + +/** + * context provider responsible for determining the current active staking program based on the service. + * It does so by checking if the current service is staked, and if so, which staking program it is staked in. + * It also provides a method to update the active staking program id in state. + * + * @note When the service is not yet deployed, a default staking program state is used to allow switching + * between staking programs before deployment is complete, ensuring the relevant staking program is displayed, + * even if deployment is still in progress + */ +export const StakingProgramProvider = ({ children }: PropsWithChildren) => { + const { selectedService, selectedAgentConfig } = useServices(); + + const [defaultStakingProgramId, setDefaultStakingProgramId] = useState( + DEFAULT_STAKING_PROGRAM_IDS[selectedAgentConfig.evmHomeChainId], + ); + + useEffect(() => { + setDefaultStakingProgramId( + DEFAULT_STAKING_PROGRAM_IDS[selectedAgentConfig.evmHomeChainId], + ); + }, [selectedAgentConfig]); + + const serviceNftTokenId = !isNil(selectedService?.chain_configs) + ? selectedService?.chain_configs?.[selectedService?.home_chain]?.chain_data + ?.token + : null; + + const { isLoading, data: activeStakingProgramId } = + useGetActiveStakingProgramId(serviceNftTokenId); - useInterval(updateActiveStakingProgramId, 5000); + const selectedStakingProgramId = isLoading + ? null + : activeStakingProgramId || defaultStakingProgramId; return ( {children} diff --git a/frontend/context/SystemNotificationTriggers.tsx b/frontend/context/SystemNotificationTriggers.tsx index 82678b056..94e8b42a6 100644 --- a/frontend/context/SystemNotificationTriggers.tsx +++ b/frontend/context/SystemNotificationTriggers.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren, useCallback, useEffect, useRef } from 'react'; -import { DeploymentStatus } from '@/client'; +import { MiddlewareDeploymentStatus } from '@/client'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useReward } from '@/hooks/useReward'; import { useServices } from '@/hooks/useServices'; @@ -12,7 +12,7 @@ const Notifications = { export const SystemNotificationTriggers = ({ children }: PropsWithChildren) => { const electronApi = useElectronApi(); - const { serviceStatus } = useServices(); + const { selectedService } = useServices(); const { isEligibleForRewards } = useReward(); const prevIsEligibleForRewards = useRef(); @@ -22,7 +22,10 @@ export const SystemNotificationTriggers = ({ children }: PropsWithChildren) => { if (!electronApi.showNotification) return; // ignore if agent is not running - if (serviceStatus !== DeploymentStatus.DEPLOYED) return; + if ( + selectedService?.deploymentStatus !== MiddlewareDeploymentStatus.DEPLOYED + ) + return; // ignore if eligibility is not yet defined if (isEligibleForRewards === undefined) return; // ignore if agent was previously eligible and is still eligible @@ -37,13 +40,13 @@ export const SystemNotificationTriggers = ({ children }: PropsWithChildren) => { } prevIsEligibleForRewards.current = isEligibleForRewards; - }, [electronApi, isEligibleForRewards, serviceStatus]); + }, [electronApi, isEligibleForRewards, selectedService?.deploymentStatus]); useEffect(() => { if (!electronApi.showNotification) return; // Show notification when agent earns rewards handleAgentEarned(); - }, [electronApi, handleAgentEarned, isEligibleForRewards, serviceStatus]); + }, [electronApi, handleAgentEarned, isEligibleForRewards]); return children; }; diff --git a/frontend/context/WalletProvider.tsx b/frontend/context/WalletProvider.tsx deleted file mode 100644 index e76c4b82e..000000000 --- a/frontend/context/WalletProvider.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { - createContext, - PropsWithChildren, - useCallback, - useContext, - useState, -} from 'react'; -import { useInterval } from 'usehooks-ts'; - -import { MiddlewareChain, Wallet } from '@/client'; -import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; -import { WalletService } from '@/service/Wallet'; -import { Address } from '@/types/Address'; - -import { OnlineStatusContext } from './OnlineStatusProvider'; - -export const WalletContext = createContext<{ - masterEoaAddress?: Address; - masterSafeAddress?: Address; - masterSafeAddresses?: Record; - wallets?: Wallet[]; - updateWallets: () => Promise; - masterSafeAddressKeyExistsForChain: ( - middlewareChain: MiddlewareChain, - ) => boolean; -}>({ - masterEoaAddress: undefined, - masterSafeAddress: undefined, - wallets: undefined, - updateWallets: async () => {}, - masterSafeAddressKeyExistsForChain: () => false, -}); - -export const WalletProvider = ({ children }: PropsWithChildren) => { - const { isOnline } = useContext(OnlineStatusContext); - - const [wallets, setWallets] = useState(); - - const masterEoaAddress: Address | undefined = wallets?.[0]?.address; - const masterSafeAddress: Address | undefined = - wallets?.[0]?.safes[MiddlewareChain.OPTIMISM]; - - const masterSafeAddresses = wallets?.[0]?.safes; - - const masterSafeAddressKeyExistsForChain = useCallback( - (middlewareChain: MiddlewareChain) => - !!wallets?.[0]?.safes[middlewareChain], - [wallets], - ); - - const updateWallets = async () => { - try { - const wallets = await WalletService.getWallets(); - setWallets(wallets); - } catch (e) { - console.error(e); - } - }; - - useInterval(updateWallets, isOnline ? FIVE_SECONDS_INTERVAL : null); - - return ( - - {children} - - ); -}; diff --git a/frontend/enums/Agent.ts b/frontend/enums/Agent.ts new file mode 100644 index 000000000..e709e3994 --- /dev/null +++ b/frontend/enums/Agent.ts @@ -0,0 +1,6 @@ +export const AgentType = { + PredictTrader: 'trader', + // Optimus: 'optimus', +} as const; + +export type AgentType = (typeof AgentType)[keyof typeof AgentType]; diff --git a/frontend/enums/Chain.ts b/frontend/enums/Chain.ts new file mode 100644 index 000000000..2e0e5d1f8 --- /dev/null +++ b/frontend/enums/Chain.ts @@ -0,0 +1,13 @@ +export enum EvmChainId { + Ethereum = 1, + Optimism = 10, + Gnosis = 100, + Base = 8453, +} + +export const EvmChainName = { + [EvmChainId.Ethereum]: 'Ethereum', + [EvmChainId.Optimism]: 'Optimism', + [EvmChainId.Gnosis]: 'Gnosis', + [EvmChainId.Base]: 'Base', +}; diff --git a/frontend/enums/Contract.ts b/frontend/enums/Contract.ts new file mode 100644 index 000000000..7b0a1018c --- /dev/null +++ b/frontend/enums/Contract.ts @@ -0,0 +1,16 @@ +export enum ContractType { + Multicall3 = 'multicall3', + ServiceRegistryL2 = 'serviceRegistryL2', + ServiceRegistryTokenUtility = 'serviceRegistryTokenUtility', + StakingTokenProxy = 'stakingTokenProxy', + AgentMech = 'agentMech', + MechMarketplace = 'mechMarketplace', + AgentMechActivity = 'agentMechActivity', + MechMarketplaceActivity = 'mechMarketplaceActivity', + StakingActivity = 'stakingActivity', + Erc20 = 'erc20', + Erc721 = 'erc721', + // Erc1155 = 'erc1155', + // UniswapV2Lp = 'uniswapV2Lp', + // UniswapV3Lp = 'uniswapV3Lp', +} diff --git a/frontend/enums/PageState.ts b/frontend/enums/Pages.ts similarity index 100% rename from frontend/enums/PageState.ts rename to frontend/enums/Pages.ts diff --git a/frontend/enums/StakingProgram.ts b/frontend/enums/StakingProgram.ts index c2b9e0637..07c36876c 100644 --- a/frontend/enums/StakingProgram.ts +++ b/frontend/enums/StakingProgram.ts @@ -1,7 +1,10 @@ export enum StakingProgramId { - // Alpha = 'pearl_alpha', - // Beta = 'pearl_beta', - // Beta2 = 'pearl_beta_2', - // BetaMechMarketplace = 'pearl_beta_mech_marketplace', + PearlAlpha = 'pearl_alpha', + PearlBeta = 'pearl_beta', + PearlBeta2 = 'pearl_beta_2', + PearlBeta3 = 'pearl_beta_3', + PearlBeta4 = 'pearl_beta_4', + PearlBeta5 = 'pearl_beta_5', + PearlBetaMechMarketplace = 'pearl_beta_mech_marketplace', OptimusAlpha = 'optimus_alpha', } diff --git a/frontend/enums/StakingProgramStatus.ts b/frontend/enums/StakingProgramStatus.ts index d161434b7..7e7364d09 100644 --- a/frontend/enums/StakingProgramStatus.ts +++ b/frontend/enums/StakingProgramStatus.ts @@ -1,3 +1,4 @@ export enum StakingProgramStatus { - Selected = 'current', + Active = 'current', + Default = 'default', } diff --git a/frontend/enums/Token.ts b/frontend/enums/Token.ts index 642072af1..dba01ea34 100644 --- a/frontend/enums/Token.ts +++ b/frontend/enums/Token.ts @@ -1,5 +1,6 @@ -export enum Token { +export enum TokenSymbol { ETH = 'ETH', OLAS = 'OLAS', USDC = 'USDC', + XDAI = 'XDAI', } diff --git a/frontend/enums/Wallet.ts b/frontend/enums/Wallet.ts new file mode 100644 index 000000000..ed52a5a6d --- /dev/null +++ b/frontend/enums/Wallet.ts @@ -0,0 +1,52 @@ +import { Address } from '@/types/Address'; + +import { EvmChainId } from './Chain'; + +export enum WalletType { + Safe = 'multisig', + EOA = 'eoa', +} +export enum WalletOwnerType { + Master = 'master', // user + Agent = 'agent', +} + +// types of wallet +export type Eoa = { + address: Address; + type: WalletType.EOA; +}; + +export type Safe = { + address: Address; + type: WalletType.Safe; + evmChainId: EvmChainId; +}; + +// owned eoas +export type MasterEoa = Eoa & { + owner: WalletOwnerType.Master; +}; + +export type AgentEoa = Eoa & { + owner: WalletOwnerType.Agent; +}; + +// owned safes +export type MasterSafe = Safe & { + owner: WalletOwnerType.Master; +}; + +export type AgentSafe = Safe & { + owner: WalletOwnerType.Agent; +}; + +// generic wallets +export type MasterWallet = MasterEoa | MasterSafe; +export type AgentWallet = AgentEoa | AgentSafe; +export type Wallet = MasterWallet | AgentWallet; + +// collections of wallets // TODO: probably not needed +export type MasterWallets = MasterWallet[]; +export type AgentWallets = AgentWallet[]; +export type Wallets = Wallet[]; diff --git a/frontend/graphql/queries.ts b/frontend/graphql/queries.ts new file mode 100644 index 000000000..c2c3e6806 --- /dev/null +++ b/frontend/graphql/queries.ts @@ -0,0 +1,35 @@ +import { gql, request } from 'graphql-request'; + +import { GNOSIS_REWARDS_HISTORY_SUBGRAPH_URL } from '@/constants/urls'; +import { + EpochDetailsResponse, + EpochDetailsResponseSchema, +} from '@/types/Epoch'; + +export const getLatestEpochTimeQuery = (contractAddress: string) => gql` + query { + checkpoints( + orderBy: epoch + orderDirection: desc + first: 1 + where: { + contractAddress: "${contractAddress}" + } + ) { + epoch + epochLength + blockTimestamp + } + } +`; + +export const getLatestEpochDetails = async (contractAddress: string) => { + const response = await request<{ + checkpoints: EpochDetailsResponse[]; + }>( + GNOSIS_REWARDS_HISTORY_SUBGRAPH_URL, + getLatestEpochTimeQuery(contractAddress), + ); + + return EpochDetailsResponseSchema.parse(response.checkpoints[0]); +}; diff --git a/frontend/hooks/useAddress.ts b/frontend/hooks/useAddress.ts deleted file mode 100644 index 9529c61a9..000000000 --- a/frontend/hooks/useAddress.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { CHAINS } from '@/constants/chains'; - -import { useServices } from './useServices'; - -export const useAddress = () => { - const { service } = useServices(); - - /** agent safe multisig address */ - const multisigAddress = - service?.chain_configs?.[CHAINS.OPTIMISM.chainId]?.chain_data?.multisig; - - /** agent instance EOA address */ - const instanceAddress = - service?.chain_configs?.[CHAINS.OPTIMISM.chainId]?.chain_data - ?.instances?.[0]; - - return { instanceAddress, multisigAddress }; -}; diff --git a/frontend/hooks/useBalance.ts b/frontend/hooks/useBalance.ts deleted file mode 100644 index c8d21df91..000000000 --- a/frontend/hooks/useBalance.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { useContext } from 'react'; - -import { BalanceContext } from '@/context/BalanceProvider'; - -export const useBalance = () => useContext(BalanceContext); diff --git a/frontend/hooks/useBalanceContext.ts b/frontend/hooks/useBalanceContext.ts new file mode 100644 index 000000000..410bad47c --- /dev/null +++ b/frontend/hooks/useBalanceContext.ts @@ -0,0 +1,160 @@ +import { useContext, useMemo } from 'react'; + +import { CHAIN_CONFIG } from '@/config/chains'; +import { BalanceContext, WalletBalanceResult } from '@/context/BalanceProvider'; +import { Optional } from '@/types/Util'; + +import { useService } from './useService'; +import { useServices } from './useServices'; +import { useMasterWalletContext } from './useWallet'; + +export const useBalanceContext = () => useContext(BalanceContext); + +/** + * Balances relevant to a specific service (agent) + * @param serviceConfigId + * @returns + */ +export const useServiceBalances = (serviceConfigId: string | undefined) => { + const { flatAddresses, serviceSafes, serviceEoa } = + useService(serviceConfigId); + const { walletBalances, stakedBalances } = useBalanceContext(); + + /** + * Staked balances, only relevant to safes + */ + const serviceStakedBalances = useMemo( + () => + stakedBalances?.filter((balance) => + flatAddresses.includes(balance.walletAddress), + ), + [flatAddresses, stakedBalances], + ); + + /** + * Cross-chain unstaked balances in service safes + */ + const serviceSafeBalances = useMemo>( + () => + walletBalances?.filter((balance) => + serviceSafes.find(({ address }) => balance.walletAddress === address), + ), + [serviceSafes, walletBalances], + ); + + /** + * Cross-chain unstaked balances in service eoa (signer) + */ + const serviceEoaBalances = useMemo>( + () => + walletBalances?.filter( + (balance) => balance.walletAddress === serviceEoa?.address, + ), + [serviceEoa?.address, walletBalances], + ); + + /** + * Balances i.e. native, erc20, etc + * Across all service wallets, including eoa + * @note NOT STAKED BALANCES + */ + const serviceWalletBalances = useMemo>(() => { + let result; + if (serviceSafeBalances || serviceEoaBalances) { + result = [...(serviceSafeBalances || []), ...(serviceEoaBalances || [])]; + } + return result; + }, [serviceEoaBalances, serviceSafeBalances]); + + return { + serviceWalletBalances, + serviceStakedBalances, + serviceSafeBalances, + serviceEoaBalances, + }; +}; + +/** + * Balances relevant to the master wallets, eoa, and safes + * @note master wallets are *shared* wallets across all services + * @note master safe addresses are deterministic, and should be the same + */ +export const useMasterBalances = () => { + const { selectedAgentConfig } = useServices(); + const { masterSafes, masterEoa } = useMasterWalletContext(); + const { walletBalances } = useBalanceContext(); + + // TODO: unused, check only services stake? + // const masterStakedBalances = useMemo( + // () => + // stakedBalances?.filter((balance) => + // masterSafes?.find((safe) => safe.address === balance.walletAddress), + // ), + // [masterSafes, stakedBalances], + // ); + + const masterSafeBalances = useMemo>( + () => + walletBalances?.filter(({ walletAddress }) => + masterSafes?.find( + ({ address: masterSafeAddress }) => + walletAddress === masterSafeAddress, + ), + ), + [masterSafes, walletBalances], + ); + + const masterEoaBalances = useMemo>( + () => + walletBalances?.filter( + ({ walletAddress }) => walletAddress === masterEoa?.address, + ), + [masterEoa?.address, walletBalances], + ); + + /** + * Unstaked balances across master safes and eoas + */ + const masterWalletBalances = useMemo>(() => { + let result; + if (masterSafeBalances || masterEoaBalances) { + result = [...(masterSafeBalances || []), ...(masterEoaBalances || [])]; + } + return result; + }, [masterEoaBalances, masterSafeBalances]); + + const isMasterSafeLowOnNativeGas = useMemo(() => { + if (!masterSafeBalances) return; + if (!selectedAgentConfig?.evmHomeChainId) return; + + const homeChainNativeToken = + CHAIN_CONFIG[selectedAgentConfig?.evmHomeChainId].nativeToken; + + const nativeGasBalance = masterSafeBalances.find( + (walletBalance) => + walletBalance.isNative && + walletBalance.evmChainId === selectedAgentConfig.evmHomeChainId && + walletBalance.symbol === homeChainNativeToken.symbol, + ); + + if (!nativeGasBalance) return; + + const agentNativeGasRequirement = + selectedAgentConfig.agentSafeFundingRequirements?.[ + homeChainNativeToken.symbol + ]; + + return nativeGasBalance.balance < agentNativeGasRequirement; + }, [ + masterSafeBalances, + selectedAgentConfig.agentSafeFundingRequirements, + selectedAgentConfig.evmHomeChainId, + ]); + + return { + masterWalletBalances, + masterSafeBalances, + masterEoaBalances, + isMasterSafeLowOnNativeGas, + }; +}; diff --git a/frontend/hooks/useLogs.ts b/frontend/hooks/useLogs.ts index b72e59c3b..be005320f 100644 --- a/frontend/hooks/useLogs.ts +++ b/frontend/hooks/useLogs.ts @@ -1,43 +1,76 @@ import { useMemo } from 'react'; -import { DeploymentStatus } from '@/client'; +import { EvmChainId } from '@/enums/Chain'; +import { Eoa, WalletType } from '@/enums/Wallet'; +import { Address } from '@/types/Address'; +import { Service } from '@/types/Service'; +import { Optional } from '@/types/Util'; -import { useBalance } from './useBalance'; -import { useMasterSafe } from './useMasterSafe'; +import { useBalanceContext } from './useBalanceContext'; +import { useMultisigs } from './useMultisig'; import { useServices } from './useServices'; import { useStore } from './useStore'; -import { useWallet } from './useWallet'; +import { useMasterWalletContext } from './useWallet'; const useAddressesLogs = () => { - const { wallets, masterEoaAddress, masterSafeAddress } = useWallet(); + const { + masterSafes, + masterEoa, + isFetched: masterWalletsIsFetched, + } = useMasterWalletContext(); + + const { masterSafesOwners, masterSafesOwnersIsFetched } = + useMultisigs(masterSafes); + + const backupEoas = useMemo>(() => { + if (!masterEoa) return; + if (!masterSafesOwners) return; - const { backupSafeAddress, masterSafeOwners } = useMasterSafe(); + const result = masterSafesOwners + .map((masterSafeOwners) => { + const { owners, safeAddress, evmChainId } = masterSafeOwners; + return owners + .filter((owner): owner is Address => owner !== masterEoa.address) + .map((address) => ({ + address, + type: WalletType.EOA, + safeAddress, + evmChainId, + })); + }) + .flat(); + + return result; + }, [masterSafesOwners, masterEoa]); return { - isLoaded: wallets?.length !== 0 && !!masterSafeOwners, + isLoaded: masterWalletsIsFetched && masterSafesOwnersIsFetched, data: [ - { backupSafeAddress: backupSafeAddress ?? 'undefined' }, - { masterSafeAddress: masterSafeAddress ?? 'undefined' }, - { masterEoaAddress: masterEoaAddress ?? 'undefined' }, - { masterSafeOwners: masterSafeOwners ?? 'undefined' }, + { masterEoa: masterEoa ?? 'undefined' }, + { + masterSafes: + masterSafes?.find((safe) => safe.evmChainId === EvmChainId.Gnosis) ?? + 'undefined', + }, + { masterSafeBackups: backupEoas ?? 'undefined' }, ], }; }; const useBalancesLogs = () => { + const { masterWallets } = useMasterWalletContext(); const { - isBalanceLoaded, + isLoaded: isBalanceLoaded, totalEthBalance, totalOlasBalance, - wallets, walletBalances, - totalOlasStakedBalance, - } = useBalance(); + totalStakedOlasBalance: totalOlasStakedBalance, + } = useBalanceContext(); return { isLoaded: isBalanceLoaded, data: [ - { wallets: wallets ?? 'undefined' }, + { masterWallets: masterWallets ?? 'undefined' }, { walletBalances: walletBalances ?? 'undefined' }, { totalOlasStakedBalance: totalOlasStakedBalance ?? 'undefined' }, { totalEthBalance: totalEthBalance ?? 'undefined' }, @@ -47,18 +80,20 @@ const useBalancesLogs = () => { }; const useServicesLogs = () => { - const { serviceStatus, services, hasInitialLoaded } = useServices(); + const { services, isFetched: isLoaded, selectedService } = useServices(); + // const { getQueryData } = useQueryClient(); return { - isLoaded: hasInitialLoaded, + isLoaded, data: { - serviceStatus: serviceStatus - ? DeploymentStatus[serviceStatus] - : 'undefined', services: - services?.map((item) => ({ + services?.map((item: Service) => ({ ...item, keys: item.keys.map((key) => key.address), + deploymentStatus: + selectedService?.service_config_id === item.service_config_id + ? selectedService.deploymentStatus + : item.deploymentStatus, })) ?? 'undefined', }, }; diff --git a/frontend/hooks/useMasterSafe.ts b/frontend/hooks/useMasterSafe.ts deleted file mode 100644 index ec5d52059..000000000 --- a/frontend/hooks/useMasterSafe.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useContext } from 'react'; - -import { MasterSafeContext } from '@/context/MasterSafeProvider'; - -export const useMasterSafe = () => { - return useContext(MasterSafeContext); -}; diff --git a/frontend/hooks/useMultisig.ts b/frontend/hooks/useMultisig.ts new file mode 100644 index 000000000..1abe0f843 --- /dev/null +++ b/frontend/hooks/useMultisig.ts @@ -0,0 +1,141 @@ +import { useQuery } from '@tanstack/react-query'; +import { Contract } from 'ethers'; +import { Contract as MulticallContract, ContractCall } from 'ethers-multicall'; +import { isEmpty, isNil } from 'lodash'; + +import { GNOSIS_SAFE_ABI } from '@/abis/gnosisSafe'; +import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; +import { PROVIDERS } from '@/constants/providers'; +import { REACT_QUERY_KEYS } from '@/constants/react-query-keys'; +import { EvmChainId } from '@/enums/Chain'; +import { Safe } from '@/enums/Wallet'; +import { Address } from '@/types/Address'; +import { extractFunctionsFromAbi } from '@/utils/abi'; + +import { useMasterWalletContext } from './useWallet'; + +/** + * Hook to fetch multisig owners + * @param safe + * @returns multisig owners + * @note extend with further multisig functions as needed + */ +export const useMultisig = (safe?: Safe) => { + const { masterEoa } = useMasterWalletContext(); + const { + data: owners, + isFetched: ownersIsFetched, + // isPending: ownersIsPending, + } = useQuery({ + enabled: !isNil(safe), + queryKey: safe ? REACT_QUERY_KEYS.MULTISIG_GET_OWNERS_KEY(safe) : [], + queryFn: async () => { + if (!safe) { + return []; + } + const contract = new Contract( + safe.address, + GNOSIS_SAFE_ABI, + PROVIDERS[safe.evmChainId].provider, + ); + return contract.getOwners() as Promise; + }, + refetchInterval: isNil(safe) ? 0 : FIVE_SECONDS_INTERVAL, + }); + + const backupOwners = owners?.filter( + (owner) => owner.toLowerCase() !== masterEoa?.address.toLowerCase(), + ); + + return { owners, ownersIsFetched, backupOwners }; +}; + +type MultisigOwners = { + safeAddress: Address; + evmChainId: EvmChainId; + owners: Address[]; +}; + +/** + * Hook to fetch from an array of multisigs + */ +export const useMultisigs = (safes?: Safe[]) => { + const { + data: masterSafesOwners, + isFetched: masterSafesOwnersIsFetched, + isPending: masterSafesOwnersIsPending, + } = useQuery({ + enabled: !isNil(safes) && !isEmpty(safes), + queryKey: safes ? REACT_QUERY_KEYS.MULTISIGS_GET_OWNERS_KEY(safes) : [], + queryFn: async (): Promise => { + if (!safes || isEmpty(safes)) return []; + + const contractCallsByChainId: { + [chainId: number]: { + safeAddress: string; + contractCall: ContractCall; + }[]; + } = {}; + + // Step 1: Group safes by chainId and prepare contract calls + for (const [evmChainIdKey] of Object.entries(PROVIDERS)) { + const safesOnChainId = safes.filter( + (safe) => safe.evmChainId === +evmChainIdKey, + ); + if (safesOnChainId.length === 0) { + continue; + } + + contractCallsByChainId[+evmChainIdKey] = safesOnChainId.map( + (safe) => ({ + safeAddress: safe.address, + contractCall: new MulticallContract( + safe.address, + extractFunctionsFromAbi(GNOSIS_SAFE_ABI), + ).getOwners(), + }), + ); + } + + // Step 2: Execute multicall and gather results + const output: MultisigOwners[] = []; + + for (const [evmChainIdKey, calls] of Object.entries( + contractCallsByChainId, + )) { + const evmChainId = +evmChainIdKey; + + const provider = PROVIDERS[evmChainId]?.multicallProvider; + + if (!provider) { + console.error(`No provider found for chainId ${evmChainId}`); + continue; + } + + // Execute the multicall + const ownersArray = await provider.all( + calls.map((call) => call.contractCall), + ); + + // Combine results into the output + ownersArray.forEach((owners, index) => { + const safeAddress =
calls[index].safeAddress; + output.push({ + safeAddress, + evmChainId, + owners, + }); + }); + } + + return output; + }, + refetchInterval: FIVE_SECONDS_INTERVAL, + }); + + return { + masterSafesOwners, + masterSafesOwnersIsFetched, + masterSafesOwnersIsPending, + }; +}; diff --git a/frontend/hooks/useNeedsFunds.ts b/frontend/hooks/useNeedsFunds.ts index 16e3a8323..8d0f0eb92 100644 --- a/frontend/hooks/useNeedsFunds.ts +++ b/frontend/hooks/useNeedsFunds.ts @@ -1,57 +1,129 @@ import { formatUnits } from 'ethers/lib/utils'; +import { isNil } from 'lodash'; import { useMemo } from 'react'; -import { CHAINS } from '@/constants/chains'; -import { getMinimumStakedAmountRequired } from '@/utils/service'; +import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; +import { getNativeTokenSymbol } from '@/config/tokens'; +import { SERVICE_TEMPLATES } from '@/constants/serviceTemplates'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { TokenSymbol } from '@/enums/Token'; +import { Maybe } from '@/types/Util'; +import { asEvmChainId } from '@/utils/middlewareHelpers'; -import { useBalance } from './useBalance'; -import { useServiceTemplates } from './useServiceTemplates'; +import { useBalanceContext, useMasterBalances } from './useBalanceContext'; +import { useServices } from './useServices'; +import { useStakingProgram } from './useStakingProgram'; import { useStore } from './useStore'; -export const useNeedsFunds = () => { - const { getServiceTemplates } = useServiceTemplates(); +export const useNeedsFunds = (stakingProgramId: Maybe) => { + const { storeState } = useStore(); - const serviceTemplate = useMemo( - () => getServiceTemplates()[0], - [getServiceTemplates], + const { selectedAgentType } = useServices(); + const serviceTemplate = SERVICE_TEMPLATES.find( + (template) => template.agentType === selectedAgentType, ); + const { selectedStakingProgramId } = useStakingProgram(); - const { storeState } = useStore(); - const { - isBalanceLoaded, - masterSafeBalance: safeBalance, - totalOlasStakedBalance, - } = useBalance(); - - const serviceFundRequirements = useMemo(() => { - const gasEstimate = - serviceTemplate.configurations[CHAINS.OPTIMISM.chainId] - .monthly_gas_estimate; - const monthlyGasEstimate = Number(formatUnits(`${gasEstimate}`, 18)); - const minimumStakedAmountRequired = - getMinimumStakedAmountRequired(serviceTemplate); - - return { eth: monthlyGasEstimate, olas: minimumStakedAmountRequired }; - }, [serviceTemplate]); - - const hasEnoughEthForInitialFunding = useMemo( - () => (safeBalance?.ETH || 0) >= (serviceFundRequirements?.eth || 0), - [serviceFundRequirements?.eth, safeBalance], - ); + const { isLoaded: isBalanceLoaded } = useBalanceContext(); + const { masterSafeBalances } = useMasterBalances(); + + const isInitialFunded = storeState?.isInitialFunded; + + const serviceFundRequirements = useMemo<{ + [chainId: number]: { + [tokenSymbol: string]: number; + }; + }>(() => { + if (isNil(serviceTemplate)) return {}; + + const results: { + [chainId: number]: { + [tokenSymbol: string]: number; + }; + } = {}; + + Object.entries(serviceTemplate.configurations).forEach( + ([middlewareChain, config]) => { + const evmChainId = asEvmChainId(middlewareChain); + + // if stakingProgramId not provided, use the selected one + const resolvedStakingProgramId = + stakingProgramId ?? selectedStakingProgramId; + + if (!resolvedStakingProgramId) return; + + const gasEstimate = config.monthly_gas_estimate; + const monthlyGasEstimate = Number(formatUnits(`${gasEstimate}`, 18)); + const minimumStakedAmountRequired = + STAKING_PROGRAMS[evmChainId]?.[resolvedStakingProgramId] + ?.stakingRequirements?.[TokenSymbol.OLAS] || 0; + + const nativeTokenSymbol = getNativeTokenSymbol(evmChainId); + + results[evmChainId] = { + [TokenSymbol.OLAS]: minimumStakedAmountRequired, + [nativeTokenSymbol]: monthlyGasEstimate, + // TODO: extend with any further erc20s.. + }; + }, + ); + + return results; + }, [selectedStakingProgramId, serviceTemplate, stakingProgramId]); + + const hasEnoughEthForInitialFunding = useMemo(() => { + if (isNil(serviceFundRequirements)) return; + if (isNil(masterSafeBalances)) return; + + const nativeBalancesByChain = masterSafeBalances.reduce<{ + [chainId: number]: number; + }>((acc, { symbol, balance, evmChainId }) => { + if (getNativeTokenSymbol(evmChainId) !== symbol) return acc; + + if (!acc[evmChainId]) acc[evmChainId] = 0; + acc[evmChainId] += balance; + + return acc; + }, {}); + + const chainIds = Object.keys(serviceFundRequirements).map(Number); + + return chainIds.every((chainId) => { + const nativeTokenSymbol = getNativeTokenSymbol(chainId); + const nativeTokenBalance = nativeBalancesByChain[chainId] || 0; + const nativeTokenRequired = + serviceFundRequirements[chainId]?.[nativeTokenSymbol] || 0; + + return nativeTokenBalance >= nativeTokenRequired; + }); + }, [serviceFundRequirements, masterSafeBalances]); const hasEnoughOlasForInitialFunding = useMemo(() => { - const olasInSafe = safeBalance?.OLAS || 0; - const olasStakedBySafe = totalOlasStakedBalance || 0; - const olasRequiredToFundService = serviceFundRequirements.olas || 0; - const olasInSafeAndStaked = olasInSafe + olasStakedBySafe; - return olasInSafeAndStaked >= olasRequiredToFundService; - }, [ - safeBalance?.OLAS, - totalOlasStakedBalance, - serviceFundRequirements?.olas, - ]); + if (!serviceFundRequirements) return; + if (!masterSafeBalances) return; + + const olasBalancesByChain = masterSafeBalances.reduce<{ + [chainId: number]: number; + }>((acc, { symbol, balance, evmChainId }) => { + if (TokenSymbol.OLAS !== symbol) return acc; + + if (!acc[evmChainId]) acc[evmChainId] = 0; + acc[evmChainId] += balance; + + return acc; + }, {}); + + const chainIds = Object.keys(serviceFundRequirements).map(Number); + + return chainIds.every((chainId) => { + const olasBalance = olasBalancesByChain[chainId] || 0; + const olasRequired = + serviceFundRequirements[chainId]?.[TokenSymbol.OLAS] || 0; + + return olasBalance >= olasRequired; + }); + }, [masterSafeBalances, serviceFundRequirements]); - const isInitialFunded = storeState?.isInitialFunded; const needsInitialFunding: boolean = useMemo(() => { if (isInitialFunded) return false; if (!isBalanceLoaded) return false; diff --git a/frontend/hooks/useNotifyOnNewEpoch.ts b/frontend/hooks/useNotifyOnNewEpoch.ts new file mode 100644 index 000000000..30b0a3d97 --- /dev/null +++ b/frontend/hooks/useNotifyOnNewEpoch.ts @@ -0,0 +1,67 @@ +import { useEffect, useState } from 'react'; + +import { useElectronApi } from '@/hooks/useElectronApi'; +import { useServices } from '@/hooks/useServices'; + +import { useService } from './useService'; +import { useActiveStakingContractInfo } from './useStakingContractDetails'; + +type EpochStatusNotification = { + lastEpoch: number; + isNotified: boolean; +}; + +/** + * Hook to notify the user when a new epoch is started + * and agent is not running. + */ +export const useNotifyOnNewEpoch = () => { + const { showNotification } = useElectronApi(); + const { selectedService } = useServices(); + const { isServiceRunning } = useService(selectedService?.service_config_id); + + const { + selectedStakingContractDetails: activeStakingContractDetails, + isSelectedStakingContractDetailsLoaded: + isActiveStakingContractDetailsLoaded, + } = useActiveStakingContractInfo(); + const epoch = activeStakingContractDetails?.epochCounter; + + const [epochStatusNotification, setEpochStatusNotification] = + useState(null); + + useEffect(() => { + // if active staking contract info is not loaded yet, return + if (!isActiveStakingContractDetailsLoaded) return; + + // if agent is running, no need to show notification + if (isServiceRunning) return; + + // latest epoch is not loaded yet + if (!epoch) return; + + // first time, just load the epoch status + if (!epochStatusNotification) { + setEpochStatusNotification({ lastEpoch: epoch, isNotified: false }); + return; + } + + // already notified for this epoch + if (epochStatusNotification.isNotified) return; + + // if latest epoch is not the last notified epoch + if (epochStatusNotification.lastEpoch !== epoch) { + showNotification?.( + 'Start your agent to avoid missing rewards and getting evicted.', + ); + + setEpochStatusNotification({ lastEpoch: epoch, isNotified: true }); + } + }, [ + epochStatusNotification, + epoch, + isActiveStakingContractDetailsLoaded, + showNotification, + isServiceRunning, + ]); +}; diff --git a/frontend/hooks/usePageState.ts b/frontend/hooks/usePageState.ts index da6797d94..3bac2dff9 100644 --- a/frontend/hooks/usePageState.ts +++ b/frontend/hooks/usePageState.ts @@ -1,7 +1,7 @@ import { useContext } from 'react'; import { PageStateContext } from '@/context/PageStateProvider'; -import { Pages } from '@/enums/PageState'; +import { Pages } from '@/enums/Pages'; export const usePageState = () => { const { pageState, setPageState, isPageLoadedAndOneMinutePassed } = diff --git a/frontend/hooks/usePause.tsx b/frontend/hooks/usePause.tsx new file mode 100644 index 000000000..cee68f925 --- /dev/null +++ b/frontend/hooks/usePause.tsx @@ -0,0 +1,28 @@ +import { useCallback, useState } from 'react'; + +export type UsePause = { + paused: boolean; + setPaused: (paused: boolean) => void; + togglePaused: () => void; +}; + +export const usePause = (): UsePause => { + const [paused, set] = useState(false); + + const setPaused = useCallback( + (value: boolean) => { + set(value); + }, + [set], + ); + + const togglePaused = useCallback(() => { + set((prev) => !prev); + }, [set]); + + return { + paused, + setPaused, + togglePaused, + }; +}; diff --git a/frontend/hooks/useReward.ts b/frontend/hooks/useReward.ts index c269a4430..692d5f2aa 100644 --- a/frontend/hooks/useReward.ts +++ b/frontend/hooks/useReward.ts @@ -8,6 +8,7 @@ export const useReward = () => { availableRewardsForEpochEth, isEligibleForRewards, accruedServiceStakingRewards, + isStakingRewardsDetailsFetched, } = useContext(RewardContext); return { @@ -15,5 +16,6 @@ export const useReward = () => { availableRewardsForEpochEth, isEligibleForRewards, accruedServiceStakingRewards, + isStakingRewardsDetailsFetched, }; }; diff --git a/frontend/hooks/useRewardsHistory.ts b/frontend/hooks/useRewardsHistory.ts index f9ca9975c..c2997a5ce 100644 --- a/frontend/hooks/useRewardsHistory.ts +++ b/frontend/hooks/useRewardsHistory.ts @@ -1,12 +1,20 @@ import { useQuery } from '@tanstack/react-query'; import { ethers } from 'ethers'; +import { Maybe } from 'graphql/jsutils/Maybe'; import { gql, request } from 'graphql-request'; -import { groupBy } from 'lodash'; -import { useEffect, useMemo } from 'react'; +import { groupBy, isEmpty, isNil } from 'lodash'; +import { useCallback, useEffect, useMemo } from 'react'; import { z } from 'zod'; +import { STAKING_PROGRAM_ADDRESS } from '@/config/stakingPrograms'; +import { REACT_QUERY_KEYS } from '@/constants/react-query-keys'; import { GNOSIS_REWARDS_HISTORY_SUBGRAPH_URL } from '@/constants/urls'; +import { EvmChainId } from '@/enums/Chain'; +import { Address } from '@/types/Address'; +import { Nullable } from '@/types/Util'; +import { asMiddlewareChain } from '@/utils/middlewareHelpers'; +import { useService } from './useService'; import { useServices } from './useServices'; const ONE_DAY_IN_S = 24 * 60 * 60; @@ -32,14 +40,28 @@ const CheckpointGraphResponseSchema = z.object({ message: 'Expected epochLength to be a string', }), contractAddress: z.string({ - message: 'Expected contractAddress to be a string', + message: 'Expected contractAddress to be a valid Ethereum address', }), }); -type CheckpointGraphResponse = z.infer; +const CheckpointsGraphResponseSchema = z.array(CheckpointGraphResponseSchema); +type CheckpointResponse = z.infer; -const fetchRewardsQuery = gql` +const fetchRewardsQuery = (chainId: number) => { + const supportedStakingContracts = Object.values( + STAKING_PROGRAM_ADDRESS[chainId], + ).map((address) => `"${address}"`); + + return gql` { - checkpoints(orderBy: epoch, orderDirection: desc) { + checkpoints( + orderBy: epoch + orderDirection: desc + first: 1000 + where: { + serviceIds_not: [] + contractAddress_in: [${supportedStakingContracts}] + } + ) { id availableRewards blockTimestamp @@ -52,8 +74,9 @@ const fetchRewardsQuery = gql` } } `; +}; -export type TransformedCheckpoint = { +export type Checkpoint = { epoch: string; rewards: string[]; serviceIds: string[]; @@ -61,144 +84,174 @@ export type TransformedCheckpoint = { transactionHash: string; epochLength: string; contractAddress: string; + contractName: Nullable; epochEndTimeStamp: number; epochStartTimeStamp: number; reward: number; earned: boolean; }; -const transformCheckpoints = ( - checkpoints: CheckpointGraphResponse[], - serviceId?: number, - timestampToIgnore?: null | number, -): TransformedCheckpoint[] => { - if (!checkpoints || checkpoints.length === 0) return []; - if (!serviceId) return []; - - const transformed = checkpoints - .map((checkpoint: CheckpointGraphResponse, index: number) => { - const serviceIdIndex = - checkpoint.serviceIds?.findIndex((id) => Number(id) === serviceId) ?? - -1; - - let reward = '0'; - - if (serviceIdIndex !== -1) { - const isRewardFinite = isFinite( - Number(checkpoint.rewards?.[serviceIdIndex]), - ); - reward = isRewardFinite - ? checkpoint.rewards?.[serviceIdIndex] ?? '0' - : '0'; - } +const useTransformCheckpoints = () => { + const { selectedAgentConfig } = useServices(); + const { serviceApi: agent, evmHomeChainId: chainId } = selectedAgentConfig; + + return useCallback( + ( + serviceId: number, + checkpoints: CheckpointResponse[], + timestampToIgnore?: null | number, + ) => { + if (!checkpoints || checkpoints.length === 0) return []; + if (!serviceId) return []; + + return checkpoints + .map((checkpoint: CheckpointResponse, index: number) => { + const serviceIdIndex = + checkpoint.serviceIds?.findIndex( + (id) => Number(id) === serviceId, + ) ?? -1; + + let reward = '0'; + + if (serviceIdIndex !== -1) { + const currentReward = checkpoint.rewards?.[serviceIdIndex]; + const isRewardFinite = isFinite(Number(currentReward)); + reward = isRewardFinite ? currentReward ?? '0' : '0'; + } + + // If the epoch is 0, it means it's the first epoch else, + // the start time of the epoch is the end time of the previous epoch + const epochStartTimeStamp = + checkpoint.epoch === '0' + ? Number(checkpoint.blockTimestamp) - + Number(checkpoint.epochLength) + : checkpoints[index + 1]?.blockTimestamp ?? 0; + + const stakingContractId = agent.getStakingProgramIdByAddress( + chainId, + checkpoint.contractAddress as Address, + ); - // If the epoch is 0, it means it's the first epoch else, - // the start time of the epoch is the end time of the previous epoch - const epochStartTimeStamp = - checkpoint.epoch === '0' - ? Number(checkpoint.blockTimestamp) - Number(checkpoint.epochLength) - : checkpoints[index + 1]?.blockTimestamp ?? 0; - - return { - ...checkpoint, - epochEndTimeStamp: Number(checkpoint.blockTimestamp ?? Date.now()), - epochStartTimeStamp: Number(epochStartTimeStamp), - reward: Number(ethers.utils.formatUnits(reward, 18)), - earned: serviceIdIndex !== -1, - }; - }) - .filter((epoch) => { - // If the contract has been switched to new contract, ignore the rewards from the old contract of the same epoch, - // as the rewards are already accounted in the new contract. - // example: If contract was switched on September 1st, 2024, ignore the rewards before that date - // in the old contract. - if (!timestampToIgnore) return true; - - if (!epoch) return false; - if (!epoch.epochEndTimeStamp) return false; - return epoch.epochEndTimeStamp < timestampToIgnore; - }); - - return transformed; + return { + ...checkpoint, + epochEndTimeStamp: Number(checkpoint.blockTimestamp ?? Date.now()), + epochStartTimeStamp: Number(epochStartTimeStamp), + reward: Number(ethers.utils.formatUnits(reward, 18)), + earned: serviceIdIndex !== -1, + contractName: stakingContractId, + }; + }) + .filter((checkpoint) => { + // If the contract has been switched to new contract, + // ignore the rewards from the old contract of the same epoch, + // as the rewards are already accounted in the new contract. + // Example: If contract was switched on September 1st, 2024, + // ignore the rewards before that date in the old contract. + if (!timestampToIgnore) return true; + + if (!checkpoint) return false; + if (!checkpoint.epochEndTimeStamp) return false; + + return checkpoint.epochEndTimeStamp < timestampToIgnore; + }); + }, + [agent, chainId], + ); }; -export const useRewardsHistory = () => { - const { serviceId } = useServices(); +type CheckpointsResponse = { checkpoints: CheckpointResponse[] }; + +/** + * hook to fetch rewards history for all contracts + */ +const useContractCheckpoints = ( + chainId: EvmChainId, + serviceId: Maybe, +) => { + const transformCheckpoints = useTransformCheckpoints(); + + return useQuery({ + queryKey: REACT_QUERY_KEYS.REWARDS_HISTORY_KEY(chainId, serviceId!), + queryFn: async () => { + const checkpointsResponse = await request( + GNOSIS_REWARDS_HISTORY_SUBGRAPH_URL, + fetchRewardsQuery(chainId), + ); - const { - data: contractCheckpoints, - isError, - isLoading, - isFetching, - refetch, - } = useQuery({ - queryKey: [], - async queryFn() { - if (!serviceId) return { checkpoints: [] }; - - const checkpointsResponse: { - checkpoints: CheckpointGraphResponse[]; - } = await request(GNOSIS_REWARDS_HISTORY_SUBGRAPH_URL, fetchRewardsQuery); - return checkpointsResponse; + const parsedCheckpoints = CheckpointsGraphResponseSchema.safeParse( + checkpointsResponse.checkpoints, + ); + + if (parsedCheckpoints.error) { + console.error(parsedCheckpoints.error); + return []; + } + + return parsedCheckpoints.data; }, - select: ({ - checkpoints, - }): { [contractAddress: string]: TransformedCheckpoint[] } => { + select: (checkpoints): { [contractAddress: string]: Checkpoint[] } => { if (!serviceId) return {}; - if (!checkpoints) return {}; + if (isNil(checkpoints) || isEmpty(checkpoints)) return {}; - // group checkpoints by contract address / staking program + // group checkpoints by contract address (staking program) const checkpointsByContractAddress = groupBy( checkpoints, 'contractAddress', ); - // only need relevant contract history that service has participated in + // only need relevant contract history that service has participated in, // ignore contract addresses with no activity from the service - const relevantTransformedCheckpoints = Object.keys( - checkpointsByContractAddress, - ).reduce( - ( - acc: { [stakingContractAddress: string]: TransformedCheckpoint[] }, - stakingContractAddress: string, - ) => { - const checkpoints = - checkpointsByContractAddress[stakingContractAddress]; - - // skip if there are no checkpoints for the contract address - if (!checkpoints) return acc; - if (checkpoints.length <= 0) return acc; - if ( - !checkpoints.some((checkpoint) => - checkpoint.serviceIds.includes(`${serviceId}`), - ) - ) - return acc; - - // transform the checkpoints .. - // includes epoch start and end time, rewards, etc - const transformedCheckpoints = transformCheckpoints( - checkpoints, - serviceId as number, - null, - ); + return Object.keys(checkpointsByContractAddress).reduce<{ + [stakingContractAddress: string]: Checkpoint[]; + }>((acc, stakingContractAddress: string) => { + const checkpoints = + checkpointsByContractAddress[stakingContractAddress]; + + // skip if there are no checkpoints for the contract address + if (!checkpoints) return acc; + if (checkpoints.length <= 0) return acc; + + // check if the service has participated in the staking contract + // if not, skip the contract + const isServiceParticipatedInContract = checkpoints.some((checkpoint) => + checkpoint.serviceIds.includes(`${serviceId}`), + ); + if (!isServiceParticipatedInContract) return acc; - return { - ...acc, - [stakingContractAddress]: transformedCheckpoints, - }; - }, - {}, - ); + // transform the checkpoints, includes epoch start and end time, rewards, etc + const transformedCheckpoints = transformCheckpoints( + serviceId, + checkpoints, + null, + ); - return relevantTransformedCheckpoints; + return { ...acc, [stakingContractAddress]: transformedCheckpoints }; + }, {}); }, - refetchOnWindowFocus: false, - refetchInterval: ONE_DAY_IN_MS, enabled: !!serviceId, + refetchInterval: ONE_DAY_IN_MS, + refetchOnWindowFocus: false, }); +}; + +export const useRewardsHistory = () => { + const { selectedService, selectedAgentConfig } = useServices(); + const { evmHomeChainId: homeChainId } = selectedAgentConfig; + const serviceConfigId = selectedService?.service_config_id; + const { service } = useService(serviceConfigId); - const allCheckpoints = useMemo( + const serviceNftTokenId = + service?.chain_configs?.[asMiddlewareChain(homeChainId)].chain_data?.token; + + const { + isError, + isLoading, + isFetched, + refetch, + data: contractCheckpoints, + } = useContractCheckpoints(homeChainId, serviceNftTokenId); + + const epochSortedCheckpoints = useMemo( () => Object.values(contractCheckpoints ?? {}) .flat() @@ -207,66 +260,62 @@ export const useRewardsHistory = () => { ); const latestRewardStreak = useMemo(() => { + if (isLoading || !isFetched) return 0; if (!contractCheckpoints) return 0; // remove all histories that are not earned - const earnedCheckpoints = allCheckpoints.filter( + const earnedCheckpoints = epochSortedCheckpoints.filter( (checkpoint) => checkpoint.earned, ); - // sort descending by epoch end time - const sorted = earnedCheckpoints.sort( - (a, b) => b.epochEndTimeStamp - a.epochEndTimeStamp, - ); + const timeNow = Math.trunc(Date.now() / 1000); - let streak = 0; - for (let i = 0; i < sorted.length; i++) { - const current = sorted[i]; + let isStreakBroken = false; // flag to break the streak + return earnedCheckpoints.reduce((streakCount, current, i) => { + if (isStreakBroken) return streakCount; // first iteration if (i === 0) { - const timeNow = Date.now() / 1000; - - // multiplied by 2 to give a buffer of 2 days - const initialEpochGap = timeNow - current.epochEndTimeStamp; + const initialEpochGap = Math.trunc(timeNow - current.epochEndTimeStamp); - // if the last epoch was more than 1 day ago, break - if (initialEpochGap > ONE_DAY_IN_S) break; + // If the epoch gap is greater than the epoch length + if (initialEpochGap > Number(current.epochLength)) { + isStreakBroken = true; + return streakCount; + } - // if the last epoch was less than 1 day ago, increment streak if (current.earned) { - streak++; - continue; + return streakCount + 1; } - break; + isStreakBroken = true; + return streakCount; } - // nth interations - const previous = sorted[i - 1]; + // other iterations + const previous = earnedCheckpoints[i - 1]; const epochGap = previous.epochStartTimeStamp - current.epochEndTimeStamp; - if (current.earned && epochGap <= ONE_DAY_IN_S) { - streak++; - continue; + if (current.earned && epochGap <= Number(current.epochLength)) { + return streakCount + 1; } - break; - } - return streak; - }, [allCheckpoints, contractCheckpoints]); + isStreakBroken = true; + return streakCount; + }, 0); + }, [isLoading, isFetched, contractCheckpoints, epochSortedCheckpoints]); useEffect(() => { - serviceId && refetch(); - }, [refetch, serviceId]); + serviceNftTokenId && refetch(); + }, [refetch, serviceNftTokenId]); return { isError, - isFetching, + isFetched, isLoading, latestRewardStreak, refetch, - allCheckpoints, + allCheckpoints: epochSortedCheckpoints, contractCheckpoints, }; }; diff --git a/frontend/hooks/useService.ts b/frontend/hooks/useService.ts new file mode 100644 index 000000000..e7af93cc0 --- /dev/null +++ b/frontend/hooks/useService.ts @@ -0,0 +1,192 @@ +import { useMemo } from 'react'; + +import { + MiddlewareBuildingStatuses, + MiddlewareChain, + MiddlewareDeploymentStatus, + MiddlewareRunningStatuses, + MiddlewareTransitioningStatuses, +} from '@/client'; +import { EvmChainId } from '@/enums/Chain'; +import { + AgentEoa, + AgentSafe, + AgentWallets, + WalletOwnerType, + WalletType, +} from '@/enums/Wallet'; +import { Address } from '@/types/Address'; +import { Service } from '@/types/Service'; +import { Optional } from '@/types/Util'; +import { asEvmChainId } from '@/utils/middlewareHelpers'; + +import { useServices } from './useServices'; + +type ServiceChainIdAddressRecord = { + [evmChainId: number]: { + agentSafe?: Address; + agentEoas?: Address[]; + }; +}; + +/** + * Hook for interacting with a single service. + */ +export const useService = (serviceConfigId?: string) => { + const { services, isFetched: isLoaded, selectedService } = useServices(); + // const queryClient = useQueryClient(); + // const { wallets } = useMasterWalletContext(); // TODO: implement + + const service = useMemo>(() => { + if (serviceConfigId === selectedService?.service_config_id) + return selectedService; + return services?.find( + (service) => service.service_config_id === serviceConfigId, + ); + }, [selectedService, serviceConfigId, services]); + + const deploymentStatus = useMemo>(() => { + if (!service) return undefined; + if (service.deploymentStatus) return service.deploymentStatus; + }, [service]); + + const serviceNftTokenId = useMemo>(() => { + return service?.chain_configs?.[service?.home_chain]?.chain_data.token; + }, [service?.chain_configs, service?.home_chain]); + + // TODO: quick hack to fix for refactor (only predict), will make it dynamic later + const serviceWallets: AgentWallets = useMemo(() => { + if (!service) return []; + if (!service.chain_configs?.[MiddlewareChain.GNOSIS]) return []; + + const chainConfig = service.chain_configs[MiddlewareChain.GNOSIS]; + if (!chainConfig) return []; + + return [ + ...(chainConfig.chain_data.instances ?? []).map( + (address) => + ({ + address, + owner: WalletOwnerType.Agent, + type: WalletType.EOA, + }) as AgentEoa, + ), + ...(chainConfig.chain_data.multisig + ? [ + { + address: chainConfig.chain_data.multisig, + owner: WalletOwnerType.Agent, + type: WalletType.Safe, + evmChainId: EvmChainId.Gnosis, + } as AgentSafe, + ] + : []), + ]; + }, [service]); + + const addresses: ServiceChainIdAddressRecord = useMemo(() => { + if (!service) return {}; + const chainData = service.chain_configs; + + // group multisigs by chainId + const addressesByChainId: ServiceChainIdAddressRecord = chainData + ? Object.keys(chainData).reduce((acc, middlewareChain) => { + const { multisig, instances } = + chainData[middlewareChain as keyof typeof chainData].chain_data; + + const evmChainId = asEvmChainId(middlewareChain); + + return { + ...acc, + [evmChainId]: { + agentSafe: multisig, + agentEoas: instances, + }, + }; + }, {}) + : {}; + + return addressesByChainId; + }, [service]); + + const flatAddresses = useMemo(() => { + return Object.values(addresses).reduce((acc, { agentSafe, agentEoas }) => { + if (agentSafe) acc.push(agentSafe); + if (agentEoas) acc.push(...agentEoas); + return acc; + }, [] as Address[]); + }, [addresses]); + + const serviceSafes = useMemo(() => { + return ( + serviceWallets?.filter( + (wallet): wallet is AgentSafe => + flatAddresses.includes(wallet.address) && + wallet.owner === WalletOwnerType.Agent && + wallet.type === WalletType.Safe, + ) ?? [] + ); + }, [flatAddresses, serviceWallets]); + + const serviceEoa = useMemo(() => { + return ( + serviceWallets?.find( + (wallet): wallet is AgentEoa => + flatAddresses.includes(wallet.address) && + wallet.owner === WalletOwnerType.Agent && + wallet.type === WalletType.EOA, + ) ?? null + ); + }, [flatAddresses, serviceWallets]); + + /** + * Overrides the deployment status of the service in the cache. + * @note Overwrite is only temporary if ServicesContext is polling + */ + // const setDeploymentStatus = ( + // deploymentStatus?: MiddlewareDeploymentStatus, + // ) => { + // // if (!serviceConfigId) throw new Error('Service config ID is required'); + // // if (!deploymentStatus) throw new Error('Deployment status is required'); + + // queryClient.setQueryData( + // REACT_QUERY_KEYS.SERVICE_DEPLOYMENT_STATUS_KEY(serviceConfigId), + // deploymentStatus, + // ); + // }; + + // const deploymentStatus = serviceConfigId + // ? queryClient.getQueryData( + // REACT_QUERY_KEYS.SERVICE_DEPLOYMENT_STATUS_KEY(serviceConfigId), + // ) + // : undefined; + + /** @note deployment is transitioning from stopped to deployed (and vice versa) */ + const isServiceTransitioning = deploymentStatus + ? MiddlewareTransitioningStatuses.includes(deploymentStatus) + : false; + + /** @note deployment is running, or transitioning, both assume the deployment is active */ + const isServiceRunning = deploymentStatus + ? MiddlewareRunningStatuses.includes(deploymentStatus) + : false; + + /** @note new deployment being created/built */ + const isServiceBuilding = deploymentStatus + ? MiddlewareBuildingStatuses.includes(deploymentStatus) + : false; + + return { + service, + serviceNftTokenId, + addresses, + flatAddresses, + isLoaded, + deploymentStatus, + serviceSafes, + serviceEoa, + isServiceTransitioning, + isServiceRunning, + isServiceBuilding, + }; +}; diff --git a/frontend/hooks/useServiceTemplates.ts b/frontend/hooks/useServiceTemplates.ts deleted file mode 100644 index 7e4e733b3..000000000 --- a/frontend/hooks/useServiceTemplates.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ServiceTemplate } from '@/client/types'; -import { SERVICE_TEMPLATES } from '@/constants/serviceTemplates'; - -export const useServiceTemplates = () => { - const getServiceTemplates = (): ServiceTemplate[] => SERVICE_TEMPLATES; - const getServiceTemplate = (hash: string): ServiceTemplate | undefined => - SERVICE_TEMPLATES.find((template) => template.hash === hash); - - return { - getServiceTemplate, - getServiceTemplates, - serviceTemplate: SERVICE_TEMPLATES[0], // Default to the first template - }; -}; diff --git a/frontend/hooks/useServices.ts b/frontend/hooks/useServices.ts index 36aed02a9..47aa0b977 100644 --- a/frontend/hooks/useServices.ts +++ b/frontend/hooks/useServices.ts @@ -1,109 +1,79 @@ import { useContext } from 'react'; -import { Service, ServiceHash, ServiceTemplate } from '@/client'; -import { CHAINS } from '@/constants/chains'; import { ServicesContext } from '@/context/ServicesProvider'; -import MulticallService from '@/service/Multicall'; -import { ServicesService } from '@/service/Services'; -import { Address } from '@/types/Address'; -import { AddressBooleanRecord } from '@/types/Records'; - -const checkServiceIsFunded = async ( - service: Service, - serviceTemplate: ServiceTemplate, -): Promise => { - const { - chain_configs: { - [CHAINS.OPTIMISM.chainId]: { - chain_data: { instances, multisig }, - }, - }, - } = service; - - if (!instances || !multisig) return false; - - const addresses = [...instances, multisig]; - - const balances = await MulticallService.getEthBalances(addresses); - - if (!balances) return false; - - const fundRequirements: AddressBooleanRecord = addresses.reduce( - (acc: AddressBooleanRecord, address: Address) => - Object.assign(acc, { - [address]: instances.includes(address) - ? balances[address] > - serviceTemplate.configurations[CHAINS.OPTIMISM.chainId] - .fund_requirements.agent - : balances[address] > - serviceTemplate.configurations[CHAINS.OPTIMISM.chainId] - .fund_requirements.safe, - }), - {}, - ); - - return Object.values(fundRequirements).every((f) => f); -}; - -export const useServices = () => { - const { - services, - updateServicesState, - hasInitialLoaded, - setServices, - serviceStatus, - setServiceStatus, - updateServiceStatus, - setIsPaused, - } = useContext(ServicesContext); - - const serviceId = - services?.[0]?.chain_configs[CHAINS.OPTIMISM.chainId].chain_data?.token; - - // STATE METHODS - const getServiceFromState = ( - serviceHash: ServiceHash, - ): Service | undefined => { - if (!hasInitialLoaded) return; - if (!services) return; - return services.find((service) => service.hash === serviceHash); - }; - - const getServicesFromState = (): Service[] | undefined => - hasInitialLoaded ? services : []; - - const updateServiceState = (serviceHash: ServiceHash) => { - ServicesService.getService(serviceHash).then((service: Service) => { - setServices((prev) => { - if (!prev) return [service]; - - const index = prev.findIndex((s) => s.hash === serviceHash); // findIndex returns -1 if not found - if (index === -1) return [...prev, service]; - - const newServices = [...prev]; - newServices[index] = service; - return newServices; - }); - }); - }; - - const deleteServiceState = (serviceHash: ServiceHash) => - setServices((prev) => prev?.filter((s) => s.hash !== serviceHash)); - - return { - service: services?.[0], - services, - serviceId, - serviceStatus, - setServiceStatus, - getServiceFromState, - getServicesFromState, - checkServiceIsFunded, - updateServicesState, - updateServiceState, - updateServiceStatus, - deleteServiceState, - hasInitialLoaded, - setIsServicePollingPaused: setIsPaused, - }; -}; + +export const useServices = () => useContext(ServicesContext); + +// const checkServiceIsFundedOnChain = async ({ +// service, +// chainId, +// }: { +// service: MiddlewareServiceResponse; +// chainId: ChainId; +// }) => { +// if (!service.chain_configs[chainId].chain_data.instances) return false; +// if (!service.chain_configs[chainId].chain_data.multisig) return false; + +// const instances: Address[] = +// service.chain_configs[chainId].chain_data.instances; + +// const multisig: Address = service.chain_configs[chainId].chain_data.multisig; + +// const addresses = [...instances, multisig]; + +// const balances = await MulticallService.getEthBalances(addresses, chainId); + +// if (!balances) return false; + +// const fundRequirements: AddressBooleanRecord = addresses.reduce( +// (acc: AddressBooleanRecord, address: Address) => +// Object.assign(acc, { +// [address]: instances.includes(address) +// ? balances[address] > stakingProgram +// : balances[address] > +// serviceTemplate.configurations[chainId].fund_requirements.safe, +// }), +// {}, +// ); + +// return Object.values(fundRequirements).every((f) => f); +// }; + +// const checkServiceIsFunded = async ( +// service: MiddlewareServiceResponse, +// stakingProgramFundingRequirements: +// ): Promise => { +// // get all the chainIds from the service +// const chainIds: ChainId[] = Object.keys(service.chain_configs).map( +// (chainId) => +chainId, +// ); + +// // loop over the chainIds and check if the service is funded +// const instanceAddresses = chainIds.map( +// (chainId) => service.chain_configs[chainId].chain_data.instances, +// ); + +// if (!instances || !multisig) return false; + +// const addresses = [...instances, multisig]; + +// const balances = await MulticallService.getEthBalances(addresses); + +// if (!balances) return false; + +// const fundRequirements: AddressBooleanRecord = addresses.reduce( +// (acc: AddressBooleanRecord, address: Address) => +// Object.assign(acc, { +// [address]: instances.includes(address) +// ? balances[address] > +// serviceTemplate.configurations[CHAIN_CONFIG.OPTIMISM.chainId] +// .fund_requirements.agent +// : balances[address] > +// serviceTemplate.configurations[CHAIN_CONFIG.OPTIMISM.chainId] +// .fund_requirements.safe, +// }), +// {}, +// ); + +// return Object.values(fundRequirements).every((f) => f); +// }; diff --git a/frontend/hooks/useStakingContractDetails.ts b/frontend/hooks/useStakingContractDetails.ts new file mode 100644 index 000000000..e23ab74f1 --- /dev/null +++ b/frontend/hooks/useStakingContractDetails.ts @@ -0,0 +1,130 @@ +import { isNil } from 'lodash'; +import { useContext } from 'react'; + +import { StakingContractDetailsContext } from '@/context/StakingContractDetailsProvider'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { StakingState } from '@/types/Autonolas'; +import { Maybe } from '@/types/Util'; + +export const useStakingContractContext = () => + useContext(StakingContractDetailsContext); + +/** + * Returns ACTIVE staking contract details + * Has staked service specific information that `useStakingContractDetails` does not have + + * @note requires serviceConfigId once multiple instances are supported + */ +export const useActiveStakingContractInfo = () => { + const { + selectedStakingContractDetails, + isSelectedStakingContractDetailsLoaded, + // allStakingContractDetailsRecord, + // refetchActiveStakingContractDetails, + // isPaused, + // setIsPaused, + } = useStakingContractContext(); + + // const { selectedService } = useServices(); + + // // TODO: find a better way to handle this, currently stops react lifecycle hooks being implemented below it + // if (!selectedService || !activeStakingContractDetails) { + // return { + // allStakingContractDetailsRecord, + // refetchActiveStakingContractDetails, + // isPaused, + // setIsPaused, + // isActiveStakingContractDetailsLoaded, + // }; + // } + + const { + serviceStakingState, + serviceStakingStartTime, + minimumStakingDuration, + availableRewards, + serviceIds, + maxNumServices, + } = selectedStakingContractDetails ?? {}; + + const isAgentEvicted = serviceStakingState === StakingState.Evicted; + + const isServiceStaked = + !!serviceStakingStartTime && serviceStakingState === StakingState.Staked; + + const isRewardsAvailable = availableRewards ?? 0 > 0; + + const hasEnoughServiceSlots = + isNil(serviceIds) || isNil(maxNumServices) + ? null + : serviceIds.length < maxNumServices; + + const hasEnoughRewardsAndSlots = isRewardsAvailable && hasEnoughServiceSlots; + + /** + * Important: Assumes service is staked. Returns false for unstaked. + * For example: minStakingDuration = 3 days + * + * - Service starts staking 1st June 00:01 + * - Service stops being active on 1st June 02:01 (after 2 hours) + * - Contract will evict the service at 3rd June 02:02 + * - Now, cannot unstake the service until 4th June 00:01, because it hasn’t met the minStakingDuration of 3 days. + * - IMPORTANT: Between 3rd June 02:02 and 4th June 00:01 the service is EVICTED and without the possibility of unstake and re-stake + * - That is, user should not be able to run/start your agent if this condition is met. + * + */ + const isServiceStakedForMinimumDuration = + !isNil(serviceStakingStartTime) && + !isNil(minimumStakingDuration) && + Math.round(Date.now() / 1000) - serviceStakingStartTime >= + minimumStakingDuration; + + // Eviction expire time in seconds + const evictionExpiresAt = + (serviceStakingStartTime ?? 0) + (minimumStakingDuration ?? 0); + + const isEligibleForStaking = + !isNil(hasEnoughRewardsAndSlots) && + (isAgentEvicted ? isServiceStakedForMinimumDuration : true); + + return { + isAgentEvicted, + isEligibleForStaking, + isServiceStakedForMinimumDuration, + isServiceStaked, + evictionExpiresAt, + isSelectedStakingContractDetailsLoaded, + selectedStakingContractDetails, + hasEnoughRewardsAndSlots, + hasEnoughServiceSlots, + isRewardsAvailable, + }; +}; + +export const useStakingContractDetails = ( + stakingProgramId: Maybe, +) => { + const { allStakingContractDetailsRecord } = useStakingContractContext(); + const stakingContractInfo = stakingProgramId + ? allStakingContractDetailsRecord?.[stakingProgramId] + : null; + + const { serviceIds, maxNumServices, availableRewards } = + stakingContractInfo ?? {}; + + const isRewardsAvailable = availableRewards ?? 0 > 0; + + const hasEnoughServiceSlots = + !isNil(serviceIds) && + !isNil(maxNumServices) && + serviceIds.length < maxNumServices; + + const hasEnoughRewardsAndSlots = isRewardsAvailable && hasEnoughServiceSlots; + + return { + hasEnoughServiceSlots, + isRewardsAvailable, + stakingContractInfo, + hasEnoughRewardsAndSlots, + }; +}; diff --git a/frontend/hooks/useStakingContractInfo.ts b/frontend/hooks/useStakingContractInfo.ts deleted file mode 100644 index 96860360d..000000000 --- a/frontend/hooks/useStakingContractInfo.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { isNil } from 'lodash'; -import { useContext } from 'react'; - -import { StakingContractInfoContext } from '@/context/StakingContractInfoProvider'; - -import { useServices } from './useServices'; - -export const useStakingContractInfo = () => { - const { - activeStakingContractInfo, - isPaused, - isStakingContractInfoLoaded, - stakingContractInfoRecord, - updateActiveStakingContractInfo, - setIsPaused, - } = useContext(StakingContractInfoContext); - - const { service } = useServices(); - - // TODO: find a better way to handle this, currently stops react lifecycle hooks being implemented below it - if (!service || !activeStakingContractInfo) - return { - stakingContractInfoRecord, - updateActiveStakingContractInfo, - setIsPaused, - isPaused, - }; - - const { - serviceStakingState, - serviceStakingStartTime, - serviceIds, - maxNumServices, - minimumStakingDuration, - availableRewards, - } = activeStakingContractInfo; - - const isRewardsAvailable = availableRewards ?? 0 > 0; - - const hasEnoughServiceSlots = - !isNil(serviceIds) && - !isNil(maxNumServices) && - serviceIds.length < maxNumServices; - - const hasEnoughRewardsAndSlots = isRewardsAvailable && hasEnoughServiceSlots; - const isAgentEvicted = serviceStakingState === 2; - const isServiceStaked = - !!serviceStakingStartTime && serviceStakingState === 1; - - /** - * Important: Assumes service is staked. Returns false for unstaked. - * For example: minStakingDuration = 3 days - * - * - Service starts staking 1st June 00:01 - * - Service stops being active on 1st June 02:01 (after 2 hours) - * - Contract will evict the service at 3rd June 02:02 - * - Now, cannot unstake the service until 4th June 00:01, because it hasn’t met the minStakingDuration of 3 days. - * - IMPORTANT: Between 3rd June 02:02 and 4th June 00:01 the service is EVICTED and without the possibility of unstake and re-stake - * - That is, user should not be able to run/start your agent if this condition is met. - * - */ - const isServiceStakedForMinimumDuration = - !isNil(serviceStakingStartTime) && - !isNil(minimumStakingDuration) && - Math.round(Date.now() / 1000) - serviceStakingStartTime >= - minimumStakingDuration; - - /** - * User can only stake if: - * - rewards are available - * - service has enough slots - * - agent is not evicted - * - if agent is evicted, then service should be staked for minimum duration - */ - const isEligibleForStaking = - !isNil(hasEnoughRewardsAndSlots) && - (isAgentEvicted ? isServiceStakedForMinimumDuration : true); - - // Eviction expire time in seconds - const evictionExpiresAt = - (serviceStakingStartTime ?? 0) + (minimumStakingDuration ?? 0); - - return { - activeStakingContractInfo, - hasEnoughServiceSlots, - isAgentEvicted, - evictionExpiresAt, - isEligibleForStaking, - isPaused, - isRewardsAvailable, - isServiceStakedForMinimumDuration, - isServiceStaked, - isStakingContractInfoLoaded, - stakingContractInfoRecord, - updateActiveStakingContractInfo, - setIsPaused, - }; -}; diff --git a/frontend/hooks/useStakingProgram.ts b/frontend/hooks/useStakingProgram.ts index e7a054b1b..b9d1dcd84 100644 --- a/frontend/hooks/useStakingProgram.ts +++ b/frontend/hooks/useStakingProgram.ts @@ -1,58 +1,85 @@ import { useContext, useMemo } from 'react'; -import { MiddlewareChain } from '@/client'; -import { SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES } from '@/constants/contractAddresses'; -import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; import { - DEFAULT_STAKING_PROGRAM_ID, - StakingProgramContext, -} from '@/context/StakingProgramProvider'; + STAKING_PROGRAM_ADDRESS, + STAKING_PROGRAMS, +} from '@/config/stakingPrograms'; +import { StakingProgramContext } from '@/context/StakingProgramProvider'; +import { Address } from '@/types/Address'; +import { Nullable } from '@/types/Util'; + +import { useServices } from './useServices'; /** - * Hook to get the active staking program and its metadata, and the default staking program. - * @returns {Object} The active staking program and its metadata. + * Hook to get the staking program and its metadata. */ export const useStakingProgram = () => { - const { activeStakingProgramId, updateActiveStakingProgramId } = useContext( - StakingProgramContext, - ); - - const isActiveStakingProgramLoaded = activeStakingProgramId !== undefined; - - /** - * TODO: implement enums - * returns `StakingProgramMeta` if defined - * returns `undefined` if not loaded - * returns `null` if not actively staked - */ + const { + isActiveStakingProgramLoaded, + activeStakingProgramId, + defaultStakingProgramId, + selectedStakingProgramId, + setDefaultStakingProgramId, + } = useContext(StakingProgramContext); + const { selectedAgentConfig } = useServices(); + + const allStakingProgramsMeta = useMemo(() => { + return STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId]; + }, [selectedAgentConfig.evmHomeChainId]); + + const allStakingProgramNameAddressPair = + STAKING_PROGRAM_ADDRESS[selectedAgentConfig.evmHomeChainId]; + const activeStakingProgramMeta = useMemo(() => { - if (activeStakingProgramId === undefined) return; - if (activeStakingProgramId === null) return null; - return STAKING_PROGRAM_META[activeStakingProgramId]; - }, [activeStakingProgramId]); - - const defaultStakingProgramMeta = - STAKING_PROGRAM_META[DEFAULT_STAKING_PROGRAM_ID]; - - const activeStakingProgramAddress = useMemo(() => { - if (!activeStakingProgramId) return; - return SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[MiddlewareChain.OPTIMISM][ - activeStakingProgramId + if (!isActiveStakingProgramLoaded) return null; + if (!activeStakingProgramId) return null; + if (!allStakingProgramsMeta) return null; + + return allStakingProgramsMeta[activeStakingProgramId]; + }, [ + isActiveStakingProgramLoaded, + allStakingProgramsMeta, + activeStakingProgramId, + ]); + + const activeStakingProgramAddress: Nullable
= useMemo(() => { + if (!activeStakingProgramId) return null; + return allStakingProgramNameAddressPair[activeStakingProgramId]; + }, [allStakingProgramNameAddressPair, activeStakingProgramId]); + + const defaultStakingProgramMeta = useMemo(() => { + if (!defaultStakingProgramId) return null; + return STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][ + defaultStakingProgramId ]; - }, [activeStakingProgramId]); + }, [defaultStakingProgramId, selectedAgentConfig.evmHomeChainId]); - const defaultStakingProgramAddress = - SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[MiddlewareChain.OPTIMISM][ - DEFAULT_STAKING_PROGRAM_ID + const selectedStakingProgramMeta = useMemo(() => { + if (!selectedStakingProgramId) return null; + return STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][ + selectedStakingProgramId ]; + }, [selectedAgentConfig.evmHomeChainId, selectedStakingProgramId]); return { - activeStakingProgramAddress, + // active staking program + isActiveStakingProgramLoaded, activeStakingProgramId, + activeStakingProgramAddress, activeStakingProgramMeta, - defaultStakingProgramAddress, + + // default staking program + defaultStakingProgramId, defaultStakingProgramMeta, - isActiveStakingProgramLoaded, - updateActiveStakingProgramId, + setDefaultStakingProgramId, + + // selected staking program id + selectedStakingProgramId, + selectedStakingProgramMeta, + + // all staking programs + allStakingProgramIds: Object.keys(allStakingProgramNameAddressPair), + allStakingProgramAddress: Object.values(allStakingProgramNameAddressPair), + allStakingProgramsMeta, }; }; diff --git a/frontend/hooks/useWallet.ts b/frontend/hooks/useWallet.ts index 3ac343b60..d3a944baa 100644 --- a/frontend/hooks/useWallet.ts +++ b/frontend/hooks/useWallet.ts @@ -1,5 +1,5 @@ import { useContext } from 'react'; -import { WalletContext } from '@/context/WalletProvider'; +import { MasterWalletContext } from '@/context/MasterWalletProvider'; -export const useWallet = () => useContext(WalletContext); +export const useMasterWalletContext = () => useContext(MasterWalletContext); diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 88a36de2c..e7f80a606 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -32,10 +32,10 @@ const nextConfig = { return config; }, env: { - GNOSIS_RPC: process.env.GNOSIS_DEV_RPC, - OPTIMISM_RPC: process.env.OPTIMISM_DEV_RPC, - BASE_RPC: process.env.BASE_DEV_RPC, - ETHEREUM_RPC: process.env.ETHEREUM_DEV_RPC, + GNOSIS_RPC: process.env.GNOSIS_RPC, + OPTIMISM_RPC: process.env.OPTIMISM_RPC, + BASE_RPC: process.env.BASE_RPC, + ETHEREUM_RPC: process.env.ETHEREUM_RPC, }, }; diff --git a/frontend/package.json b/frontend/package.json index d5b99af41..4986cf2d8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,6 +6,7 @@ "@fontsource/inter": "^5.0.17", "@tanstack/react-query": "^5.29.0", "antd": "^5.14.0", + "axios": "^1.7.7", "ethers": "5.7.2", "ethers-multicall": "^0.2.3", "graphql": "^16.8.1", @@ -29,8 +30,8 @@ "@types/node": "20.14.10", "@types/react": "18.3.3", "@types/react-dom": "^18", - "@typescript-eslint/eslint-plugin": "^7.0.1", - "@typescript-eslint/parser": "^7.0.1", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", "eslint": "^8.56.0", "eslint-config-next": "14.1.0", "eslint-config-prettier": "^9.1.0", @@ -44,13 +45,13 @@ "jest-environment-jsdom": "^29.7.0", "prettier": "^3.2.5", "ts-node": "^10.9.2", - "typescript": "5.5.3" + "typescript": "5.3.x" }, "name": "olas-operate-app", "private": true, "scripts": { "dev": "next dev", - "build": "bash -c \"DEV_RPC=$DEV_RPC FORK_URL=$FORK_URL NODE_ENV=production next build\"", + "build": "bash -c \"GNOSIS_RPC=$GNOSIS_RPC BASE_RPC=$BASE_RPC OPTIMISM_RPC=$OPTIMISM_RPC ETHEREUM_RPC=$ETHEREUM_RPC NODE_ENV=production next build\"", "lint": "next lint", "test": "jest", "start": "next start" diff --git a/frontend/pages/_app.tsx b/frontend/pages/_app.tsx index c20032656..63ecbdf74 100644 --- a/frontend/pages/_app.tsx +++ b/frontend/pages/_app.tsx @@ -8,7 +8,7 @@ import { useEffect, useState } from 'react'; import { Layout } from '@/components/Layout'; import { BalanceProvider } from '@/context/BalanceProvider'; import { ElectronApiProvider } from '@/context/ElectronApiProvider'; -import { MasterSafeProvider } from '@/context/MasterSafeProvider'; +import { MasterWalletProvider } from '@/context/MasterWalletProvider'; import { ModalProvider } from '@/context/ModalProvider'; import { OnlineStatusProvider } from '@/context/OnlineStatusProvider'; import { PageStateProvider } from '@/context/PageStateProvider'; @@ -16,12 +16,15 @@ import { RewardProvider } from '@/context/RewardProvider'; import { ServicesProvider } from '@/context/ServicesProvider'; import { SettingsProvider } from '@/context/SettingsProvider'; import { SetupProvider } from '@/context/SetupProvider'; -import { StakingContractInfoProvider } from '@/context/StakingContractInfoProvider'; +import { StakingContractDetailsProvider } from '@/context/StakingContractDetailsProvider'; import { StakingProgramProvider } from '@/context/StakingProgramProvider'; import { StoreProvider } from '@/context/StoreProvider'; import { SystemNotificationTriggers } from '@/context/SystemNotificationTriggers'; -import { WalletProvider } from '@/context/WalletProvider'; import { mainTheme } from '@/theme'; +import { setupMulticallAddresses } from '@/utils/setupMulticall'; + +// Setup multicall addresses +setupMulticallAddresses(); const queryClient = new QueryClient(); @@ -35,12 +38,12 @@ export default function App({ Component, pageProps }: AppProps) { - - - - + + + + - + @@ -48,13 +51,11 @@ export default function App({ Component, pageProps }: AppProps) { {isMounted ? ( - - - - - - - + + + + + ) : null} @@ -62,12 +63,12 @@ export default function App({ Component, pageProps }: AppProps) { - + - - - - + + + + diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index 63fbc8f43..a2096d367 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -8,7 +8,7 @@ import { RewardsHistory } from '@/components/RewardsHistory/RewardsHistory'; import { Settings } from '@/components/SettingsPage'; import { Setup } from '@/components/SetupPage'; import { YourWalletPage } from '@/components/YourWalletPage'; -import { Pages } from '@/enums/PageState'; +import { Pages } from '@/enums/Pages'; import { useElectronApi } from '@/hooks/useElectronApi'; import { usePageState } from '@/hooks/usePageState'; diff --git a/frontend/service/Autonolas.ts b/frontend/service/Autonolas.ts deleted file mode 100644 index 22b8ad8c7..000000000 --- a/frontend/service/Autonolas.ts +++ /dev/null @@ -1,428 +0,0 @@ -import { BigNumber, ethers } from 'ethers'; -import { formatEther } from 'ethers/lib/utils'; -import { Contract as MulticallContract } from 'ethers-multicall'; - -import { SERVICE_REGISTRY_L2_ABI } from '@/abis/serviceRegistryL2'; -import { SERVICE_REGISTRY_TOKEN_UTILITY_ABI } from '@/abis/serviceRegistryTokenUtility'; -import { SERVICE_STAKING_TOKEN_MECH_USAGE_ABI } from '@/abis/serviceStakingTokenMechUsage'; -import { STAKING_ACTIVITY_CHECKER_ABI } from '@/abis/stakingActivityChecker'; -import { MiddlewareChain } from '@/client'; -import { - SERVICE_REGISTRY_L2_CONTRACT_ADDRESS, - SERVICE_REGISTRY_TOKEN_UTILITY_CONTRACT_ADDRESS, - SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES, - STAKING_ACTIVITY_CHECKER_CONTRACT_ADDRESS, -} from '@/constants/contractAddresses'; -import { optimismMulticallProvider } from '@/constants/providers'; -import { ServiceRegistryL2ServiceState } from '@/enums/ServiceRegistryL2ServiceState'; -import { StakingProgramId } from '@/enums/StakingProgram'; -import { Address } from '@/types/Address'; -import { StakingContractInfo, StakingRewardsInfo } from '@/types/Autonolas'; - -const ONE_YEAR = 1 * 24 * 60 * 60 * 365; -const REQUIRED_MECH_REQUESTS_SAFETY_MARGIN = 1; - -const ServiceStakingTokenAbi = SERVICE_STAKING_TOKEN_MECH_USAGE_ABI.filter( - (abi) => abi.type === 'function', -); - -const serviceStakingTokenMechUsageContracts: Record< - StakingProgramId, - MulticallContract -> = Object.values(StakingProgramId).reduce( - (contracts, programId) => { - contracts[programId] = new MulticallContract( - SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[ - MiddlewareChain.OPTIMISM - ][programId], - ServiceStakingTokenAbi, - ); - return contracts; - }, - {} as Record, -); - -const serviceRegistryTokenUtilityContract = new MulticallContract( - SERVICE_REGISTRY_TOKEN_UTILITY_CONTRACT_ADDRESS[MiddlewareChain.OPTIMISM], - SERVICE_REGISTRY_TOKEN_UTILITY_ABI.filter((abi) => abi.type === 'function'), -); - -const serviceRegistryL2Contract = new MulticallContract( - SERVICE_REGISTRY_L2_CONTRACT_ADDRESS[MiddlewareChain.OPTIMISM], - SERVICE_REGISTRY_L2_ABI.filter((abi) => abi.type === 'function'), -); - -// const agentMechContract = new MulticallContract( -// AGENT_MECH_CONTRACT_ADDRESS[Chain.GNOSIS], -// AGENT_MECH_ABI.filter((abi) => abi.type === 'function'), -// ); - -// const agentMechActivityCheckerContract = new MulticallContract( -// AGENT_MECH_ACTIVITY_CHECKER_CONTRACT_ADDRESS[Chain.GNOSIS], -// MECH_ACTIVITY_CHECKER_ABI.filter((abi) => abi.type === 'function'), -// ); - -// const mechMarketplaceContract = new MulticallContract( -// MECH_MARKETPLACE_CONTRACT_ADDRESS[Chain.GNOSIS], -// MECH_MARKETPLACE_ABI.filter((abi) => abi.type === 'function'), -// ); - -// const mechMarketplaceActivityChecker = new MulticallContract( -// REQUESTER_ACTIVITY_CHECKER_CONTRACT_ADDRESS[Chain.GNOSIS], -// REQUESTER_ACTIVITY_CHECKER_ABI.filter((abi) => abi.type === 'function'), -// ); - -const stakingActivityCheckerContract = new MulticallContract( - STAKING_ACTIVITY_CHECKER_CONTRACT_ADDRESS[MiddlewareChain.OPTIMISM], - STAKING_ACTIVITY_CHECKER_ABI.filter((abi) => abi.type === 'function'), -); - -const getAgentStakingRewardsInfo = async ({ - agentMultisigAddress, - serviceId, - stakingProgram, -}: { - agentMultisigAddress: Address; - serviceId: number; - stakingProgram: StakingProgramId; -}): Promise => { - if (!agentMultisigAddress) return; - if (!serviceId) return; - if (stakingProgram === StakingProgramId.OptimusAlpha) return; - - // const mechContract = agentMechContract; - - // stakingProgram === StakingProgramId.BetaMechMarketplace - // ? mechMarketplaceContract - // : agentMechContract; - - const activityCheckerContract = stakingActivityCheckerContract; - // stakingProgram === StakingProgramId.BetaMechMarketplace - // ? mechMarketplaceActivityCheckerContract - // : agentMechActivityCheckerContract; - - const contractCalls = [ - // mechContract.getRequestsCount(agentMultisigAddress), - serviceStakingTokenMechUsageContracts[stakingProgram].getServiceInfo( - serviceId, - ), - serviceStakingTokenMechUsageContracts[stakingProgram].livenessPeriod(), - activityCheckerContract.livenessRatio(), - serviceStakingTokenMechUsageContracts[stakingProgram].rewardsPerSecond(), - serviceStakingTokenMechUsageContracts[ - stakingProgram - ].calculateStakingReward(serviceId), - serviceStakingTokenMechUsageContracts[stakingProgram].minStakingDeposit(), - serviceStakingTokenMechUsageContracts[stakingProgram].tsCheckpoint(), - ]; - - const multicallResponse = await optimismMulticallProvider.all(contractCalls); - - const [ - mechRequestCount, - serviceInfo, - livenessPeriod, - livenessRatio, - rewardsPerSecond, - accruedStakingReward, - minStakingDeposit, - tsCheckpoint, - ] = multicallResponse; - - /** - * struct ServiceInfo { - // Service multisig address - address multisig; - // Service owner - address owner; - // Service multisig nonces - uint256[] nonces; <-- (we use this in the rewards eligibility check) - // Staking start time - uint256 tsStart; - // Accumulated service staking reward - uint256 reward; - // Accumulated inactivity that might lead to the service eviction - uint256 inactivity;} - */ - - const nowInSeconds = Math.floor(Date.now() / 1000); - - const requiredMechRequests = - (Math.ceil(Math.max(livenessPeriod, nowInSeconds - tsCheckpoint)) * - livenessRatio) / - 1e18 + - REQUIRED_MECH_REQUESTS_SAFETY_MARGIN; - - const mechRequestCountOnLastCheckpoint = serviceInfo[2][1]; - const eligibleRequests = mechRequestCount - mechRequestCountOnLastCheckpoint; - - const isEligibleForRewards = eligibleRequests >= requiredMechRequests; - - const availableRewardsForEpoch = Math.max( - rewardsPerSecond * livenessPeriod, // expected rewards for the epoch - rewardsPerSecond * (nowInSeconds - tsCheckpoint), // incase of late checkpoint - ); - - // Minimum staked amount is double the minimum staking deposit - // (all the bonds must be the same as deposit) - const minimumStakedAmount = - parseFloat(ethers.utils.formatEther(`${minStakingDeposit}`)) * 2; - - return { - // mechRequestCount, - serviceInfo, - livenessPeriod, - livenessRatio, - rewardsPerSecond, - isEligibleForRewards, - availableRewardsForEpoch, - accruedServiceStakingRewards: parseFloat( - ethers.utils.formatEther(`${accruedStakingReward}`), - ), - minimumStakedAmount, - } as StakingRewardsInfo; -}; - -const getAvailableRewardsForEpoch = async ( - stakingProgramId: StakingProgramId, -): Promise => { - return 0; - - const contractCalls = [ - serviceStakingTokenMechUsageContracts[stakingProgramId].rewardsPerSecond(), - serviceStakingTokenMechUsageContracts[stakingProgramId].livenessPeriod(), // epoch length - serviceStakingTokenMechUsageContracts[stakingProgramId].tsCheckpoint(), // last checkpoint timestamp - ]; - - const multicallResponse = await optimismMulticallProvider.all(contractCalls); - const [rewardsPerSecond, livenessPeriod, tsCheckpoint] = multicallResponse; - const nowInSeconds = Math.floor(Date.now() / 1000); - - return Math.max( - rewardsPerSecond * livenessPeriod, // expected rewards - rewardsPerSecond * (nowInSeconds - tsCheckpoint), // incase of late checkpoint - ); -}; - -const getStakingContractInfoByServiceIdStakingProgram = async ( - serviceId: number, - stakingProgramId: StakingProgramId, -): Promise | undefined> => { - if (!serviceId) return; - - const contractCalls = [ - serviceStakingTokenMechUsageContracts[stakingProgramId].availableRewards(), - serviceStakingTokenMechUsageContracts[stakingProgramId].maxNumServices(), - serviceStakingTokenMechUsageContracts[stakingProgramId].getServiceIds(), - serviceStakingTokenMechUsageContracts[ - stakingProgramId - ].minStakingDuration(), - serviceStakingTokenMechUsageContracts[stakingProgramId].getServiceInfo( - serviceId, - ), - serviceStakingTokenMechUsageContracts[stakingProgramId].getStakingState( - serviceId, - ), - serviceStakingTokenMechUsageContracts[stakingProgramId].minStakingDeposit(), - ]; - - const multicallResponse = await optimismMulticallProvider.all(contractCalls); - const [ - availableRewardsInBN, - maxNumServicesInBN, - getServiceIdsInBN, - minStakingDurationInBN, - serviceInfo, - serviceStakingState, - minStakingDeposit, - ] = multicallResponse; - - const availableRewards = parseFloat( - ethers.utils.formatUnits(availableRewardsInBN, 18), - ); - const serviceIds = getServiceIdsInBN.map((id: BigNumber) => id.toNumber()); - const maxNumServices = maxNumServicesInBN.toNumber(); - - return { - availableRewards, - maxNumServices, - serviceIds, - minimumStakingDuration: minStakingDurationInBN.toNumber(), - serviceStakingStartTime: serviceInfo.tsStart.toNumber(), - serviceStakingState, - minStakingDeposit: parseFloat(ethers.utils.formatEther(minStakingDeposit)), - }; -}; - -/** - * Get staking contract info by staking program name - * eg. Alpha, Beta, Beta2 - */ -const getStakingContractInfoByStakingProgram = async ( - stakingProgram: StakingProgramId, -): Promise> => { - const contractCalls = [ - serviceStakingTokenMechUsageContracts[stakingProgram].availableRewards(), - serviceStakingTokenMechUsageContracts[stakingProgram].maxNumServices(), - serviceStakingTokenMechUsageContracts[stakingProgram].getServiceIds(), - serviceStakingTokenMechUsageContracts[stakingProgram].minStakingDuration(), - serviceStakingTokenMechUsageContracts[stakingProgram].minStakingDeposit(), - serviceStakingTokenMechUsageContracts[stakingProgram].rewardsPerSecond(), - serviceStakingTokenMechUsageContracts[stakingProgram].numAgentInstances(), - serviceStakingTokenMechUsageContracts[stakingProgram].livenessPeriod(), - ]; - - const multicallResponse = await optimismMulticallProvider.all(contractCalls); - const [ - availableRewardsInBN, - maxNumServicesInBN, - getServiceIdsInBN, - minStakingDurationInBN, - minStakingDeposit, - rewardsPerSecond, - numAgentInstances, - livenessPeriod, - ] = multicallResponse; - - const availableRewards = parseFloat( - ethers.utils.formatUnits(availableRewardsInBN, 18), - ); - - const serviceIds = getServiceIdsInBN.map((id: BigNumber) => id.toNumber()); - const maxNumServices = maxNumServicesInBN.toNumber(); - - // APY - const rewardsPerYear = rewardsPerSecond.mul(ONE_YEAR); - - let apy = 0; - - if (rewardsPerSecond.gt(0) && minStakingDeposit.gt(0)) { - apy = - Number(rewardsPerYear.mul(100).div(minStakingDeposit)) / - (1 + numAgentInstances.toNumber()); - } - - // Amount of OLAS required for Stake - const stakeRequiredInWei = minStakingDeposit.add( - minStakingDeposit.mul(numAgentInstances), - ); - - const olasStakeRequired = Number(formatEther(stakeRequiredInWei)); - - // Rewards per work period - const rewardsPerWorkPeriod = - Number(formatEther(rewardsPerSecond as BigNumber)) * - livenessPeriod.toNumber(); - - return { - availableRewards, - maxNumServices, - serviceIds, - minimumStakingDuration: minStakingDurationInBN.toNumber(), - minStakingDeposit: parseFloat(ethers.utils.formatEther(minStakingDeposit)), - apy, - olasStakeRequired, - rewardsPerWorkPeriod, - }; -}; - -const getServiceRegistryInfo = async ( - operatorAddress: Address, // generally masterSafeAddress - serviceId: number, -): Promise<{ - bondValue: number; - depositValue: number; - serviceState: ServiceRegistryL2ServiceState; -}> => { - const contractCalls = [ - serviceRegistryTokenUtilityContract.getOperatorBalance( - operatorAddress, - serviceId, - ), - serviceRegistryTokenUtilityContract.mapServiceIdTokenDeposit(serviceId), - serviceRegistryL2Contract.mapServices(serviceId), - ]; - - const [ - operatorBalanceResponse, - serviceIdTokenDepositResponse, - mapServicesResponse, - ] = await optimismMulticallProvider.all(contractCalls); - - const [bondValue, depositValue, serviceState] = [ - parseFloat(ethers.utils.formatUnits(operatorBalanceResponse, 18)), - parseFloat(ethers.utils.formatUnits(serviceIdTokenDepositResponse[1], 18)), - mapServicesResponse.state as ServiceRegistryL2ServiceState, - ]; - - return { - bondValue, - depositValue, - serviceState, - }; -}; - -/** - * @param serviceId - * @returns StakingProgram | null (null when not staked) - */ -const getCurrentStakingProgramByServiceId = async ( - serviceId: number, -): Promise => { - if (serviceId <= -1) return null; - - const contractCalls = Object.values(StakingProgramId).reduce( - (acc, stakingProgramId: StakingProgramId) => ({ - ...acc, - [stakingProgramId]: - serviceStakingTokenMechUsageContracts[stakingProgramId].getStakingState( - serviceId, - ), - }), - {}, - ); - - try { - const [ - isOptimusAlphaStaked, - // isAlphaStaked, - // isBetaStaked, - // isBeta2Staked, - // isBetaMechMarketplaceStaked, - ] = await optimismMulticallProvider.all(Object.values(contractCalls)); - - if (isOptimusAlphaStaked) { - return StakingProgramId.OptimusAlpha; - } - - // if (isAlphaStaked) { - // return StakingProgramId.Alpha; - // } - - // if (isBetaStaked) { - // return StakingProgramId.Beta; - // } - - // if (isBeta2Staked) { - // return StakingProgramId.Beta2; - // } - - // if (isBetaMechMarketplaceStaked) { - // return StakingProgramId.BetaMechMarketplace; - // } - - return null; - } catch (error) { - console.error('Error while getting current staking program', error); - return null; - } -}; - -export const AutonolasService = { - getAgentStakingRewardsInfo, - getAvailableRewardsForEpoch, - getCurrentStakingProgramByServiceId, - getServiceRegistryInfo, - getStakingContractInfoByServiceIdStakingProgram, - getStakingContractInfoByStakingProgram, -}; diff --git a/frontend/service/Ethers.ts b/frontend/service/Ethers.ts index be6f4a317..0ece1d23f 100644 --- a/frontend/service/Ethers.ts +++ b/frontend/service/Ethers.ts @@ -1,10 +1,8 @@ -import { ContractInterface, ethers, providers, utils } from 'ethers'; +import { providers, utils } from 'ethers'; +import { Contract as MulticallContract } from 'ethers-multicall'; -import { - baseProvider, - ethereumProvider, - optimismProvider, -} from '@/constants/providers'; +import { PROVIDERS } from '@/constants/providers'; +import { EvmChainId } from '@/enums/Chain'; import { Address } from '@/types/Address'; import { TransactionInfo } from '@/types/TransactionInfo'; @@ -16,14 +14,12 @@ import { TransactionInfo } from '@/types/TransactionInfo'; */ const getEthBalance = async ( address: Address, - rpc: string, + chainId: EvmChainId, ): Promise => { try { - const provider = new providers.StaticJsonRpcProvider(rpc, { - name: 'Gnosis', - chainId: 100, // we currently only support Gnosis Trader agent - }); - return provider.getBalance(address).then((balance) => { + const provider = PROVIDERS[chainId].multicallProvider; + + return provider.getEthBalance(address).then((balance: bigint) => { const formattedBalance = utils.formatEther(balance); return Number(formattedBalance); }); @@ -41,33 +37,28 @@ const getEthBalance = async ( */ const getErc20Balance = async ( address: Address, - rpc: string, - contractAddress?: Address, + contractAddress: Address, + chainId: EvmChainId, ): Promise => { try { if (!contractAddress) { throw new Error('Contract address is required for ERC20 balance'); } - const provider = new providers.StaticJsonRpcProvider(rpc, { - name: 'Gnosis', - chainId: 100, // we currently only support Gnosis Trader agent - }); - const contract = new ethers.Contract( - contractAddress, - [ - 'function balanceOf(address) view returns (uint256)', - 'function decimals() view returns (uint8)', - ], - provider, - ); - const [balance, decimals] = await Promise.all([ + const provider = PROVIDERS[chainId].multicallProvider; + + const contract = new MulticallContract(contractAddress, [ + 'function balanceOf(address) view returns (uint256)', + 'function decimals() view returns (uint8)', + ]); + + const [balance, decimals] = await provider.all([ contract.balanceOf(address), contract.decimals(), ]); if (!balance || !decimals) { - throw new Error('Failed to resolve balance or decimals'); + throw new Error('Failed to resolve erc20 balance'); } return Number(utils.formatUnits(balance, decimals)); @@ -76,68 +67,28 @@ const getErc20Balance = async ( } }; -/** - * Returns the Optimism balance of the given address - */ -const getOptimismBalance = async (address: Address): Promise => { - try { - return optimismProvider.getBalance(address).then((balance) => { - const formattedBalance = utils.formatEther(balance); - return Number(formattedBalance); - }); - } catch (e) { - return Promise.reject('Failed to get Optimism balance'); - } -}; - -/** - * Returns the Ethereum balance of the given address - */ -const getEthereumBalance = async (address: Address): Promise => { - try { - return ethereumProvider.getBalance(address).then((balance) => { - const formattedBalance = utils.formatEther(balance); - return Number(formattedBalance); - }); - } catch (e) { - return Promise.reject('Failed to get Ethereum balance'); - } -}; - -/** - * Returns the base balance of the given address - */ -const getBaseBalance = async (address: Address): Promise => { - try { - return baseProvider.getBalance(address).then((balance) => { - const formattedBalance = utils.formatEther(balance); - return Number(formattedBalance); - }); - } catch (e) { - return Promise.reject('Failed to get base balance'); - } -}; - /** * Checks if the given RPC is valid * @param rpc string * @returns Promise */ -const checkRpc = async (rpc: string): Promise => { +const checkRpc = async (chainId: EvmChainId): Promise => { + const provider = PROVIDERS[chainId].provider; try { - if (!rpc) throw new Error('RPC is required'); + if (!provider) throw new Error('Provider is required'); - const networkId = (await optimismProvider.getNetwork()).chainId; + const networkId = (await provider.getNetwork()).chainId; if (!networkId) throw new Error('Failed to get network ID'); - return Promise.resolve(true); + return chainId === networkId; } catch (e) { - return Promise.resolve(false); + return false; } }; // tenderly limits to 1000 -const BACK_TRACK_BLOCKS = process.env.NODE_ENV === 'development' ? 1000 : 9000; +const BLOCK_LOOKBACK_WINDOW = + process.env.NODE_ENV === 'development' ? 1000 : 9000; const MAX_ROUNDS = 5; const getLogsList = async ( @@ -145,7 +96,10 @@ const getLogsList = async ( fromBlock: number, toBlock: number, roundsLeft: number, + chainId: EvmChainId, ): Promise => { + const provider = PROVIDERS[chainId].provider; + // Limit the number of recursive calls to prevent too many requests if (roundsLeft === 0) return []; @@ -154,31 +108,37 @@ const getLogsList = async ( fromBlock, toBlock, }; - const list = await optimismProvider.getLogs(filter); + + const list = await provider.getLogs(filter); if (list.length > 0) return list; return getLogsList( contractAddress, - fromBlock - BACK_TRACK_BLOCKS, + fromBlock - BLOCK_LOOKBACK_WINDOW, fromBlock, roundsLeft - 1, + chainId, ); }; /** - * Get the latest transaction details for the given contract address + * Get the latest transaction details for the given address */ export const getLatestTransaction = async ( - contractAddress: Address, + address: Address, + chainId: EvmChainId, ): Promise => { - const latestBlock = await optimismProvider.getBlockNumber(); + const provider = PROVIDERS[chainId].provider; + + const latestBlock = await provider.getBlockNumber(); const logs = await getLogsList( - contractAddress, - latestBlock - BACK_TRACK_BLOCKS, + address, + latestBlock - BLOCK_LOOKBACK_WINDOW, latestBlock, MAX_ROUNDS, + chainId, ); // No transactions found @@ -187,31 +147,16 @@ export const getLatestTransaction = async ( // Get the last log entry and fetch the transaction details const lastLog = logs[logs.length - 1]; const txHash = lastLog.transactionHash; - const receipt = await optimismProvider.getTransactionReceipt(txHash); - const block = await optimismProvider.getBlock(receipt.blockNumber); + const receipt = await provider.getTransactionReceipt(txHash); + const block = await provider.getBlock(receipt.blockNumber); const timestamp = block.timestamp; return { hash: txHash, timestamp }; }; -const readContract = ({ - address, - abi, -}: { - address: string; - abi: ContractInterface; -}) => { - const contract = new ethers.Contract(address, abi, optimismProvider); - return contract; -}; - export const EthersService = { - getEthBalance, // gnosis + getEthBalance, getErc20Balance, checkRpc, - readContract, getLatestTransaction, - getOptimismBalance, - getEthereumBalance, - getBaseBalance, }; diff --git a/frontend/service/GnosisSafe.ts b/frontend/service/GnosisSafe.ts deleted file mode 100644 index a0f87deb9..000000000 --- a/frontend/service/GnosisSafe.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ethers } from 'ethers'; - -import { GNOSIS_SAFE_ABI } from '@/abis/gnosisSafe'; -import { optimismProvider } from '@/constants/providers'; -import { Address } from '@/types/Address'; - -const getOwners = async ({ - address, -}: { - address: Address; -}): Promise => { - const gnosisSafeContract = new ethers.Contract( - address, - GNOSIS_SAFE_ABI, - optimismProvider, - ); - - return gnosisSafeContract.getOwners(); -}; - -export const GnosisSafeService = { - getOwners, -}; diff --git a/frontend/service/Multicall.ts b/frontend/service/Multicall.ts index 1ae24a82b..15f04f69a 100644 --- a/frontend/service/Multicall.ts +++ b/frontend/service/Multicall.ts @@ -1,18 +1,13 @@ -import { BigNumber, ethers } from 'ethers'; +import { ethers } from 'ethers'; import { Contract as MulticallContract, ContractCall } from 'ethers-multicall'; -import { ERC20_BALANCEOF_FRAGMENT } from '@/abis/erc20'; -import { MULTICALL3_ABI } from '@/abis/multicall3'; -import { MULTICALL_CONTRACT_ADDRESS } from '@/constants/contractAddresses'; -import { optimismMulticallProvider } from '@/constants/providers'; +import { ERC20_BALANCE_OF_STRING_FRAGMENT } from '@/abis/erc20'; +import { Erc20TokenConfig } from '@/config/tokens'; +import { PROVIDERS } from '@/constants/providers'; +import { EvmChainId } from '@/enums/Chain'; import { Address } from '@/types/Address'; import { AddressNumberRecord } from '@/types/Records'; -const multicallContract = new MulticallContract( - MULTICALL_CONTRACT_ADDRESS, - MULTICALL3_ABI.filter((f) => f.type === 'function'), -); - /** * Gets ETH balances for a list of addresses * @param addresses @@ -21,19 +16,22 @@ const multicallContract = new MulticallContract( */ const getEthBalances = async ( addresses: Address[], + chainId: EvmChainId, ): Promise => { + const provider = PROVIDERS[chainId].multicallProvider; + if (addresses.length <= 0) return; const callData = addresses.map((address: Address) => - multicallContract.getEthBalance(address), + provider.getEthBalance(address), ); if (!callData.length) return {}; - const multicallResponse = await optimismMulticallProvider.all(callData); + const multicallResponse = await provider.all(callData); return multicallResponse.reduce( - (acc: AddressNumberRecord, balance: BigNumber, index: number) => ({ + (acc: AddressNumberRecord, balance: bigint, index: number) => ({ ...acc, [addresses[index]]: parseFloat(ethers.utils.formatUnits(balance, 18)), }), @@ -45,28 +43,38 @@ const getEthBalances = async ( * Gets ERC20 balances for a list of addresses * @param addresses * @param rpc - * @param contractAddress + * @param erc20TokenConfig * @returns Promise */ const getErc20Balances = async ( addresses: Address[], - contractAddress: Address, + erc20TokenConfig: Erc20TokenConfig, + chainId: EvmChainId, ): Promise => { - if (!contractAddress) return {}; + if (!erc20TokenConfig) return {}; if (!addresses.length) return {}; + const provider = PROVIDERS[chainId].multicallProvider; + const callData: ContractCall[] = addresses.map((address: Address) => - new MulticallContract(contractAddress, ERC20_BALANCEOF_FRAGMENT).balanceOf( - address, - ), + new MulticallContract( + erc20TokenConfig.address, + ERC20_BALANCE_OF_STRING_FRAGMENT, + ) + .balanceOf(address) + .then((balance: bigint) => + parseFloat( + ethers.utils.formatUnits(balance, erc20TokenConfig.decimals), + ), + ), ); - const multicallResponse = await optimismMulticallProvider.all(callData); + const multicallResponse = await provider.all(callData); return multicallResponse.reduce( - (acc: AddressNumberRecord, balance: BigNumber, index: number) => ({ + (acc: AddressNumberRecord, parsedBalance: number, index: number) => ({ ...acc, - [addresses[index]]: parseFloat(ethers.utils.formatUnits(balance, 18)), + [addresses[index]]: parsedBalance, }), {}, ); diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index cfbabf7c7..56e1b3cde 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -1,37 +1,42 @@ -import { Deployment, Service, ServiceHash, ServiceTemplate } from '@/client'; -import { CHAINS } from '@/constants/chains'; +import { + Deployment, + MiddlewareChain, + MiddlewareServiceResponse, + ServiceTemplate, +} from '@/client'; +import { CHAIN_CONFIG } from '@/config/chains'; import { CONTENT_TYPE_JSON_UTF8 } from '@/constants/headers'; -import { BACKEND_URL } from '@/constants/urls'; +import { BACKEND_URL_V2 } from '@/constants/urls'; +import { EvmChainId } from '@/enums/Chain'; import { StakingProgramId } from '@/enums/StakingProgram'; +import { asEvmChainId } from '@/utils/middlewareHelpers'; /** * Get a single service from the backend * @param serviceHash * @returns */ -const getService = async (serviceHash: ServiceHash): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}`, { +const getService = async ( + serviceConfigId: string, +): Promise => + fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { method: 'GET', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, + headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { return response.json(); } - throw new Error(`Failed to fetch service ${serviceHash}`); + throw new Error(`Failed to fetch service ${serviceConfigId}`); }); /** * Gets an array of services from the backend * @returns An array of services */ -const getServices = async (): Promise => - fetch(`${BACKEND_URL}/services`, { +const getServices = async (): Promise => + fetch(`${BACKEND_URL_V2}/services`, { method: 'GET', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, + headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { return response.json(); @@ -54,78 +59,103 @@ const createService = async ({ serviceTemplate: ServiceTemplate; stakingProgramId: StakingProgramId; useMechMarketplace?: boolean; -}): Promise => - new Promise((resolve, reject) => - fetch(`${BACKEND_URL}/services`, { - method: 'POST', - body: JSON.stringify({ - ...serviceTemplate, - deploy, - configurations: { - [CHAINS.OPTIMISM.chainId]: { - ...serviceTemplate.configurations[CHAINS.OPTIMISM.chainId], - staking_program_id: stakingProgramId, - rpc: `${process.env.OPTIMISM_RPC}`, - use_mech_marketplace: useMechMarketplace, +}): Promise => + fetch(`${BACKEND_URL_V2}/service`, { + method: 'POST', + body: JSON.stringify({ + ...serviceTemplate, + deploy, + configurations: { + ...serviceTemplate.configurations, + // overwrite defaults with chain-specific configurations + ...Object.entries(serviceTemplate.configurations).reduce( + (acc, [middlewareChain, config]) => { + acc[middlewareChain] = { + ...config, + rpc: CHAIN_CONFIG[asEvmChainId(MiddlewareChain.GNOSIS)].rpc, + staking_program_id: stakingProgramId, + use_mech_marketplace: useMechMarketplace, + }; + return acc; }, - }, - }), - headers: { - ...CONTENT_TYPE_JSON_UTF8, + {} as typeof serviceTemplate.configurations, + ), }, - }).then((response) => { - if (response.ok) { - resolve(response.json()); - } - reject(response); }), - ); - -// const deployOnChain = async (serviceHash: ServiceHash): Promise => -// fetch(`${BACKEND_URL}/services/${serviceHash}/onchain/deploy`, { -// method: 'POST', -// headers: { -// ...CONTENT_TYPE_JSON_UTF8, -// }, -// }).then((response) => { -// if (response.ok) { -// return response.json(); -// } -// throw new Error('Failed to deploy service on chain'); -// }); + headers: { ...CONTENT_TYPE_JSON_UTF8 }, + }).then((response) => { + if (response.ok) { + return response.json(); + } + throw new Error('Failed to create service'); + }); -// const buildDeployment = async (serviceHash: ServiceHash): Promise => -// fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/build`, { -// method: 'POST', -// headers: { -// ...CONTENT_TYPE_JSON_UTF8, -// }, -// }).then((response) => { -// if (response.ok) { -// return response.json(); -// } -// throw new Error('Failed to build deployment'); -// }); +/** + * Updates a service + * @param serviceTemplate + * @returns Promise + */ +const updateService = async ({ + deploy, + serviceTemplate, + serviceConfigId, + stakingProgramId, + useMechMarketplace = false, + chainId, +}: { + deploy: boolean; + serviceTemplate: ServiceTemplate; + serviceConfigId: string; + stakingProgramId: StakingProgramId; + useMechMarketplace?: boolean; + chainId: EvmChainId; +}): Promise => + fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { + method: 'PUT', + body: JSON.stringify({ + ...serviceTemplate, + deploy, + configurations: { + [CHAIN_CONFIG[chainId].middlewareChain]: { + ...serviceTemplate.configurations[ + CHAIN_CONFIG[chainId].middlewareChain + ], + staking_program_id: stakingProgramId, + rpc: CHAIN_CONFIG[chainId].rpc, + use_mech_marketplace: useMechMarketplace, + }, + }, + }), + headers: { ...CONTENT_TYPE_JSON_UTF8 }, + }).then((response) => { + if (response.ok) { + return response.json(); + } + throw new Error('Failed to update service'); + }); -// const startDeployment = async (serviceHash: ServiceHash): Promise => -// fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/start`, { -// method: 'POST', -// headers: { -// ...CONTENT_TYPE_JSON_UTF8, -// }, -// }).then((response) => { -// if (response.ok) { -// return response.json(); -// } -// throw new Error('Failed to start deployment'); -// }); +/** + * Starts a service + * @param serviceTemplate + * @returns Promise + */ +const startService = async ( + serviceConfigId: string, +): Promise => + fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { + method: 'POST', + headers: { ...CONTENT_TYPE_JSON_UTF8 }, + }).then((response) => { + if (response.ok) { + return response.json(); + } + throw new Error('Failed to start the service'); + }); -const stopDeployment = async (serviceHash: ServiceHash): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/stop`, { +const stopDeployment = async (serviceConfigId: string): Promise => + fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}/deployment/stop`, { method: 'POST', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, + headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { return response.json(); @@ -133,27 +163,10 @@ const stopDeployment = async (serviceHash: ServiceHash): Promise => throw new Error('Failed to stop deployment'); }); -// const deleteDeployment = async ( -// serviceHash: ServiceHash, -// ): Promise => -// fetch(`${BACKEND_URL}/services/${serviceHash}/deployment/delete`, { -// method: 'POST', -// headers: { -// ...CONTENT_TYPE_JSON_UTF8, -// }, -// }).then((response) => { -// if (response.ok) { -// return response.json(); -// } -// throw new Error('Failed to delete deployment'); -// }); - -const getDeployment = async (serviceHash: ServiceHash): Promise => - fetch(`${BACKEND_URL}/services/${serviceHash}/deployment`, { +const getDeployment = async (serviceConfigId: string): Promise => + fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}/deployment`, { method: 'GET', - headers: { - ...CONTENT_TYPE_JSON_UTF8, - }, + headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { return response.json(); @@ -165,11 +178,8 @@ export const ServicesService = { getService, getServices, getDeployment, + startService, createService, - // deployOnChain, - // stopOnChain, - // buildDeployment, - // startDeployment, + updateService, stopDeployment, - // deleteDeployment, }; diff --git a/frontend/service/Wallet.ts b/frontend/service/Wallet.ts index b9224ec9f..82a463fc1 100644 --- a/frontend/service/Wallet.ts +++ b/frontend/service/Wallet.ts @@ -1,4 +1,4 @@ -import { MiddlewareChain, Wallet } from '@/client'; +import { MiddlewareChain, MiddlewareWalletResponse } from '@/client'; import { CONTENT_TYPE_JSON_UTF8 } from '@/constants/headers'; import { BACKEND_URL } from '@/constants/urls'; @@ -9,39 +9,39 @@ const getWallets = async () => fetch(`${BACKEND_URL}/wallet`).then((res) => { if (res.ok) return res.json(); throw new Error('Failed to get wallets'); - }) as Promise; + }) as Promise; -const createEoa = async (chain: MiddlewareChain) => +const createEoa = async () => fetch(`${BACKEND_URL}/wallet`, { method: 'POST', headers: { ...CONTENT_TYPE_JSON_UTF8, }, - body: JSON.stringify({ chain_type: chain }), + body: JSON.stringify({ ledger_type: 'ethereum' }), }).then((res) => { if (res.ok) return res.json(); throw new Error('Failed to create EOA'); }); -const createSafe = async (chain: MiddlewareChain, owner?: string) => +const createSafe = async (chain: MiddlewareChain, backup_owner?: string) => fetch(`${BACKEND_URL}/wallet/safe`, { method: 'POST', headers: { ...CONTENT_TYPE_JSON_UTF8, }, - body: JSON.stringify({ chain_type: chain, owner: owner }), + body: JSON.stringify({ chain, backup_owner }), }).then((res) => { if (res.ok) return res.json(); throw new Error('Failed to create safe'); }); -const addBackupOwner = async (chain: MiddlewareChain, owner: string) => +const addBackupOwner = async (chain: MiddlewareChain, backup_owner: string) => fetch(`${BACKEND_URL}/wallet/safe`, { method: 'PUT', headers: { ...CONTENT_TYPE_JSON_UTF8, }, - body: JSON.stringify({ chain_type: chain, owner: owner }), + body: JSON.stringify({ chain, backup_owner }), }).then((res) => { if (res.ok) return res.json(); throw new Error('Failed to add backup owner'); diff --git a/frontend/service/agents/Mech.ts b/frontend/service/agents/Mech.ts new file mode 100644 index 000000000..b8d3c1a82 --- /dev/null +++ b/frontend/service/agents/Mech.ts @@ -0,0 +1,3 @@ +export abstract class MechService {} + +export abstract class MechMarketplaceService extends MechService {} diff --git a/frontend/service/agents/Optimus.ts b/frontend/service/agents/Optimus.ts new file mode 100644 index 000000000..882fd3008 --- /dev/null +++ b/frontend/service/agents/Optimus.ts @@ -0,0 +1,3 @@ +import { StakedAgentService } from './StakedAgentService'; + +export abstract class OptimusService extends StakedAgentService {} diff --git a/frontend/service/agents/PredictTrader.ts b/frontend/service/agents/PredictTrader.ts new file mode 100644 index 000000000..bb7315244 --- /dev/null +++ b/frontend/service/agents/PredictTrader.ts @@ -0,0 +1,261 @@ +import { ethers } from 'ethers'; +import { formatEther } from 'ethers/lib/utils'; + +import { MECHS } from '@/config/mechs'; +import { STAKING_PROGRAMS } from '@/config/stakingPrograms'; +import { PROVIDERS } from '@/constants/providers'; +import { EvmChainId } from '@/enums/Chain'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { Address } from '@/types/Address'; +import { + ServiceStakingDetails, + StakingContractDetails, + StakingRewardsInfo, +} from '@/types/Autonolas'; + +import { ONE_YEAR, StakedAgentService } from './StakedAgentService'; + +const MECH_REQUESTS_SAFETY_MARGIN = 1; + +export abstract class PredictTraderService extends StakedAgentService { + static getAgentStakingRewardsInfo = async ({ + agentMultisigAddress, + serviceId, + stakingProgramId, + chainId = EvmChainId.Gnosis, + }: { + agentMultisigAddress: Address; + serviceId: number; + stakingProgramId: StakingProgramId; + chainId?: EvmChainId; + }): Promise => { + if (!agentMultisigAddress) return; + if (!serviceId) return; + + const stakingProgramConfig = + STAKING_PROGRAMS[EvmChainId.Gnosis][stakingProgramId]; + + if (!stakingProgramConfig) throw new Error('Staking program not found'); + + const { activityChecker, contract: stakingTokenProxyContract } = + stakingProgramConfig; + + const provider = PROVIDERS[chainId].multicallProvider; + + const mechContract = + MECHS[chainId][stakingProgramConfig.mechType!].contract; + + const contractCalls = [ + mechContract.getRequestsCount(agentMultisigAddress), + stakingTokenProxyContract.getServiceInfo(serviceId), + stakingTokenProxyContract.livenessPeriod(), + activityChecker.livenessRatio(), + stakingTokenProxyContract.rewardsPerSecond(), + stakingTokenProxyContract.calculateStakingReward(serviceId), + stakingTokenProxyContract.minStakingDeposit(), + stakingTokenProxyContract.tsCheckpoint(), + ]; + const multicallResponse = await provider.all(contractCalls); + + const [ + mechRequestCount, + serviceInfo, + livenessPeriod, + livenessRatio, + rewardsPerSecond, + accruedStakingReward, + minStakingDeposit, + tsCheckpoint, + ] = multicallResponse; + + /** + * struct ServiceInfo { + // Service multisig address + address multisig; + // Service owner + address owner; + // Service multisig nonces + uint256[] nonces; <-- (we use this in the rewards eligibility check) + // Staking start time + uint256 tsStart; + // Accumulated service staking reward + uint256 reward; + // Accumulated inactivity that might lead to the service eviction + uint256 inactivity;} + */ + + const nowInSeconds = Math.floor(Date.now() / 1000); + + const requiredMechRequests = + (Math.ceil(Math.max(livenessPeriod, nowInSeconds - tsCheckpoint)) * + livenessRatio) / + 1e18 + + MECH_REQUESTS_SAFETY_MARGIN; + + const mechRequestCountOnLastCheckpoint = serviceInfo[2][1]; + const eligibleRequests = + mechRequestCount - mechRequestCountOnLastCheckpoint; + + const isEligibleForRewards = eligibleRequests >= requiredMechRequests; + + const availableRewardsForEpoch = Math.max( + rewardsPerSecond * livenessPeriod, // expected rewards for the epoch + rewardsPerSecond * (nowInSeconds - tsCheckpoint), // incase of late checkpoint + ); + + // Minimum staked amount is double the minimum staking deposit + // (all the bonds must be the same as deposit) + const minimumStakedAmount = + parseFloat(ethers.utils.formatEther(`${minStakingDeposit}`)) * 2; + + return { + // mechRequestCount, + serviceInfo, + livenessPeriod, + livenessRatio, + rewardsPerSecond, + isEligibleForRewards, + availableRewardsForEpoch, + accruedServiceStakingRewards: parseFloat( + ethers.utils.formatEther(`${accruedStakingReward}`), + ), + minimumStakedAmount, + } as StakingRewardsInfo; + }; + + static getAvailableRewardsForEpoch = async ( + stakingProgramId: StakingProgramId, + chainId: EvmChainId = EvmChainId.Gnosis, + ): Promise => { + const { contract: stakingTokenProxy } = + STAKING_PROGRAMS[chainId][stakingProgramId]; + const { multicallProvider } = PROVIDERS[chainId]; + + const contractCalls = [ + stakingTokenProxy.rewardsPerSecond(), + stakingTokenProxy.livenessPeriod(), // epoch length + stakingTokenProxy.tsCheckpoint(), // last checkpoint timestamp + ]; + + const multicallResponse = await multicallProvider.all(contractCalls); + const [rewardsPerSecond, livenessPeriod, tsCheckpoint] = multicallResponse; + const nowInSeconds = Math.floor(Date.now() / 1000); + + return Math.max( + rewardsPerSecond * livenessPeriod, // expected rewards + rewardsPerSecond * (nowInSeconds - tsCheckpoint), // incase of late checkpoint + ); + }; + + /** + * Get service details by it's NftTokenId on a provided staking contract + */ + + static getServiceStakingDetails = async ( + serviceNftTokenId: number, + stakingProgramId: StakingProgramId, + chainId: EvmChainId = EvmChainId.Gnosis, + ): Promise => { + const { multicallProvider } = PROVIDERS[chainId]; + + const { contract: stakingTokenProxy } = + STAKING_PROGRAMS[chainId][stakingProgramId]; + + const contractCalls = [ + stakingTokenProxy.getServiceInfo(serviceNftTokenId), + stakingTokenProxy.getStakingState(serviceNftTokenId), + ]; + + const multicallResponse = await multicallProvider.all(contractCalls); + const [serviceInfo, serviceStakingState] = multicallResponse; + + return { + serviceStakingStartTime: serviceInfo.tsStart.toNumber(), + serviceStakingState, + }; + }; + + /** + * Get staking contract info by staking program name + * eg. Alpha, Beta, Beta2 + */ + static getStakingContractDetails = async ( + stakingProgramId: StakingProgramId, + chainId: EvmChainId, + ): Promise => { + const { multicallProvider } = PROVIDERS[chainId]; + + const { contract: stakingTokenProxy } = + STAKING_PROGRAMS[chainId][stakingProgramId]; + + const contractCalls = [ + stakingTokenProxy.availableRewards(), + stakingTokenProxy.maxNumServices(), + stakingTokenProxy.getServiceIds(), + stakingTokenProxy.minStakingDuration(), + stakingTokenProxy.minStakingDeposit(), + stakingTokenProxy.rewardsPerSecond(), + stakingTokenProxy.numAgentInstances(), + stakingTokenProxy.livenessPeriod(), + stakingTokenProxy.epochCounter(), + ]; + + const multicallResponse = await multicallProvider.all(contractCalls); + + const [ + availableRewardsInBN, + maxNumServicesInBN, + getServiceIdsInBN, + minStakingDurationInBN, + minStakingDeposit, + rewardsPerSecond, + numAgentInstances, + livenessPeriod, + epochCounter, + ] = multicallResponse; + + const availableRewards = parseFloat( + ethers.utils.formatUnits(availableRewardsInBN, 18), + ); + + const serviceIds = getServiceIdsInBN.map((id: bigint) => id); + const maxNumServices = maxNumServicesInBN.toNumber(); + + // APY + const rewardsPerYear = rewardsPerSecond.mul(ONE_YEAR); + + let apy = 0; + + if (rewardsPerSecond.gt(0) && minStakingDeposit.gt(0)) { + apy = + Number(rewardsPerYear.mul(100).div(minStakingDeposit)) / + (1 + numAgentInstances.toNumber()); + } + + // Amount of OLAS required for Stake + const stakeRequiredInWei = minStakingDeposit.add( + minStakingDeposit.mul(numAgentInstances), + ); + + const olasStakeRequired = Number(formatEther(stakeRequiredInWei)); + + // Rewards per work period + const rewardsPerWorkPeriod = + Number(formatEther(rewardsPerSecond as bigint)) * + livenessPeriod.toNumber(); + + return { + availableRewards, + maxNumServices, + serviceIds, + minimumStakingDuration: minStakingDurationInBN.toNumber(), + minStakingDeposit: parseFloat( + ethers.utils.formatEther(minStakingDeposit), + ), + apy, + olasStakeRequired, + rewardsPerWorkPeriod, + epochCounter: epochCounter.toNumber(), + }; + }; +} diff --git a/frontend/service/agents/StakedAgentService.ts b/frontend/service/agents/StakedAgentService.ts new file mode 100644 index 000000000..32c652bb1 --- /dev/null +++ b/frontend/service/agents/StakedAgentService.ts @@ -0,0 +1,181 @@ +/** + * Generic staked agent service class. + * + * This class is intended to be extended by other classes and should not be used directly. + * It provides static methods and properties specific to staked agents. + * + * @note `noop` functions should be replaced with actual implementations in the extending classes. + * @warning DO NOT STORE STATE IN THESE CLASSES. THEY ARE SINGLETONS AND WILL BE SHARED ACROSS THE APPLICATION. + */ +import { ethers } from 'ethers'; +import { Contract as MulticallContract } from 'ethers-multicall'; + +import { OLAS_CONTRACTS } from '@/config/olasContracts'; +import { + STAKING_PROGRAM_ADDRESS, + STAKING_PROGRAMS, +} from '@/config/stakingPrograms'; +import { PROVIDERS } from '@/constants/providers'; +import { EvmChainId } from '@/enums/Chain'; +import { ContractType } from '@/enums/Contract'; +import { ServiceRegistryL2ServiceState } from '@/enums/ServiceRegistryL2ServiceState'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { Address } from '@/types/Address'; +import { Maybe, Nullable } from '@/types/Util'; + +export const ONE_YEAR = 1 * 24 * 60 * 60 * 365; + +export type GetServiceRegistryInfoResponse = { + bondValue: number; + depositValue: number; + serviceState: ServiceRegistryL2ServiceState; +}; + +/** + * Staked agent service class. + */ +export abstract class StakedAgentService { + abstract activityCheckerContract: MulticallContract; + abstract olasStakingTokenProxyContract: MulticallContract; + abstract serviceRegistryTokenUtilityContract: MulticallContract; + + abstract getStakingRewardsInfo: Promise; + abstract getAgentStakingRewardsInfo( + agentMultisigAddress: Address, + serviceId: number, + stakingProgramId: StakingProgramId, + chainId: EvmChainId, + ): Promise; + abstract getAvailableRewardsForEpoch( + stakingProgramId: StakingProgramId, + chainId: EvmChainId, + ): Promise; + abstract getServiceStakingDetails( + serviceId: number, + stakingProgramId: StakingProgramId, + chainId: EvmChainId, + ): Promise; + abstract getStakingContractDetails( + stakingProgramId: StakingProgramId, + chainId: EvmChainId, + ): Promise; + abstract getInstance(): StakedAgentService; + + static getCurrentStakingProgramByServiceId = async ( + serviceNftTokenId: number, + evmChainId: EvmChainId, + ): Promise> => { + if (!serviceNftTokenId || !evmChainId) return; + try { + const { multicallProvider } = PROVIDERS[evmChainId]; + + // filter out staking programs that are not on the chain + const stakingProgramEntries = Object.entries( + STAKING_PROGRAMS[evmChainId], + ).filter((entry) => { + const [, program] = entry; + return program.chainId === evmChainId; + }); + + // create contract calls + const contractCalls = stakingProgramEntries.map((entry) => { + const [, stakingProgram] = entry; + return stakingProgram.contract.getStakingState(serviceNftTokenId); + }); + + // get multicall response + const multicallResponse = await multicallProvider.all( + Object.values(contractCalls), + ); + + // find the first staking program that is active + const activeStakingProgramIndex = multicallResponse.findIndex(Boolean); + + // if no staking program is active, return null + if (activeStakingProgramIndex === -1) { + return null; + } + + // return the staking program id + const activeStakingProgramId = + stakingProgramEntries[activeStakingProgramIndex]?.[0]; + + return activeStakingProgramId + ? (activeStakingProgramId as StakingProgramId) + : null; + } catch (error) { + console.error('Error while getting current staking program', error); + return null; + } + }; + + /** + * Gets service registry info, including: + * - bondValue + * - depositValue + * - serviceState + */ + static getServiceRegistryInfo = async ( + address: Address, // generally masterSafeAddress + serviceId: number, + chainId: EvmChainId, + ): Promise => { + if (!OLAS_CONTRACTS[chainId]) { + throw new Error('Chain not supported'); + } + + const { + [ContractType.ServiceRegistryTokenUtility]: + serviceRegistryTokenUtilityContract, + [ContractType.ServiceRegistryL2]: serviceRegistryL2Contract, + } = OLAS_CONTRACTS[chainId]; + + const contractCalls = [ + serviceRegistryTokenUtilityContract.getOperatorBalance( + address, + serviceId, + ), + serviceRegistryTokenUtilityContract.mapServiceIdTokenDeposit(serviceId), + serviceRegistryL2Contract.mapServices(serviceId), + ]; + + const { multicallProvider } = PROVIDERS[chainId]; + + const [ + getOperatorBalanceResponse, + mapServiceIdTokenDepositResponse, + mapServicesResponse, + ] = await multicallProvider.all(contractCalls); + + const [bondValue, depositValue, serviceState] = [ + parseFloat(ethers.utils.formatUnits(getOperatorBalanceResponse, 18)), + parseFloat( + ethers.utils.formatUnits(mapServiceIdTokenDepositResponse[1], 18), + ), + mapServicesResponse.state as ServiceRegistryL2ServiceState, + ]; + + return { + bondValue, + depositValue, + serviceState, + }; + }; + + /** + * + * Get the staking program id by address + * @example getStakingProgramIdByAddress('0x3052451e1eAee78e62E169AfdF6288F8791F2918') // StakingProgramId.Beta4 + */ + static getStakingProgramIdByAddress = ( + chainId: number | EvmChainId, + contractAddress: Address, + ): Nullable => { + const addresses = STAKING_PROGRAM_ADDRESS[chainId]; + const entries = Object.entries(addresses) as [StakingProgramId, Address][]; + const foundEntry = entries.find( + ([, address]) => address.toLowerCase() === contractAddress.toLowerCase(), + ); + return foundEntry ? foundEntry[0] : null; + }; +} diff --git a/frontend/styles/globals.scss b/frontend/styles/globals.scss index 8ac389c5e..ee408e2ba 100644 --- a/frontend/styles/globals.scss +++ b/frontend/styles/globals.scss @@ -262,10 +262,12 @@ ul.alert-list { .w-3\/4 { width: 75% !important; } - .w-full { width: 100% !important; } +.max-width-200 { + max-width: 200px; +} .loading-ellipses:after { overflow: hidden; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index ca51cb094..d13230b55 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "baseUrl": ".", "target": "ES2015", "allowJs": true, "esModuleInterop": true, diff --git a/frontend/types/Abi.ts b/frontend/types/Abi.ts new file mode 100644 index 000000000..2987e1a08 --- /dev/null +++ b/frontend/types/Abi.ts @@ -0,0 +1,4 @@ +import { JsonFragment } from '@ethersproject/abi'; +import { Fragment } from 'ethers/lib/utils'; + +export type Abi = JsonFragment[] | string[] | Fragment[]; diff --git a/frontend/types/Agent.ts b/frontend/types/Agent.ts new file mode 100644 index 000000000..db7079a2b --- /dev/null +++ b/frontend/types/Agent.ts @@ -0,0 +1,14 @@ +import { MiddlewareChain } from '@/client'; +import { EvmChainId } from '@/enums/Chain'; +import { PredictTraderService } from '@/service/agents/PredictTrader'; + +export type StakedAgentServiceInstance = PredictTraderService; +export type AgentConfig = { + name: string; + evmHomeChainId: EvmChainId; + middlewareHomeChainId: MiddlewareChain; + requiresAgentSafesOn: EvmChainId[]; + agentSafeFundingRequirements: Record; + requiresMasterSafesOn: EvmChainId[]; + serviceApi: typeof PredictTraderService; +}; diff --git a/frontend/types/Autonolas.ts b/frontend/types/Autonolas.ts index 54f2b2d71..42619296c 100644 --- a/frontend/types/Autonolas.ts +++ b/frontend/types/Autonolas.ts @@ -1,25 +1,37 @@ -export type StakingRewardsInfo = { - // mechRequestCount: number; - serviceInfo: unknown[]; - livenessPeriod: number; - livenessRatio: number; - rewardsPerSecond: number; - isEligibleForRewards: boolean; - availableRewardsForEpoch: number; - accruedServiceStakingRewards: number; - minimumStakedAmount: number; -}; +import { z } from 'zod'; + +const zodBigNumber = z.object({ + _isBigNumber: z.boolean(), + _hex: z.string().startsWith('0x'), +}); + +export const StakingRewardsInfoSchema = z.object({ + // mechRequestCount: z.number(), + serviceInfo: z.array(z.unknown()), + livenessPeriod: zodBigNumber, + livenessRatio: zodBigNumber, + rewardsPerSecond: zodBigNumber, + isEligibleForRewards: z.boolean(), + availableRewardsForEpoch: z.number(), + accruedServiceStakingRewards: z.number(), + minimumStakedAmount: z.number(), +}); -export type StakingContractInfo = { +export type StakingRewardsInfo = z.infer; + +export enum StakingState { + NotStaked = 0, + Staked = 1, + Evicted = 2, +} + +export type StakingContractDetails = { availableRewards: number; + /* number of slots available for staking */ maxNumServices: number; serviceIds: number[]; /** minimum staking duration (in seconds) */ minimumStakingDuration: number; - /** time when service was staked (in seconds) - 0 = never staked */ - serviceStakingStartTime: number; - /** 0: not staked, 1: staked, 2: unstaked - current state of the service */ - serviceStakingState: number; /** OLAS cost of staking */ minStakingDeposit: number; /** estimated annual percentage yield */ @@ -28,4 +40,13 @@ export type StakingContractInfo = { olasStakeRequired: number; /** rewards per work period */ rewardsPerWorkPeriod: number; + /** current epoch */ + epochCounter: number; +}; + +export type ServiceStakingDetails = { + /** time when service was staked (in seconds) - 0 = never staked */ + serviceStakingStartTime: number; + /** 0: not staked, 1: staked, 2: evicted */ + serviceStakingState: StakingState; }; diff --git a/frontend/types/Epoch.ts b/frontend/types/Epoch.ts new file mode 100644 index 000000000..76ae7887f --- /dev/null +++ b/frontend/types/Epoch.ts @@ -0,0 +1,8 @@ +import { z } from 'zod'; + +export const EpochDetailsResponseSchema = z.object({ + epoch: z.string(), + epochLength: z.string(), + blockTimestamp: z.string(), +}); +export type EpochDetailsResponse = z.infer; diff --git a/frontend/types/Records.ts b/frontend/types/Records.ts index 20a8611a9..6a2ceeec8 100644 --- a/frontend/types/Records.ts +++ b/frontend/types/Records.ts @@ -1,4 +1,4 @@ -import { Token } from '@/enums/Token'; +import { TokenSymbol } from '@/enums/Token'; import { Address } from './Address'; @@ -8,5 +8,5 @@ export type AddressBooleanRecord = Record; // defines token balances in a wallet by token name export type WalletAddressNumberRecord = Record< Address, - Record + Record >; diff --git a/frontend/types/Service.ts b/frontend/types/Service.ts new file mode 100644 index 000000000..32042c7a6 --- /dev/null +++ b/frontend/types/Service.ts @@ -0,0 +1,8 @@ +import { + MiddlewareDeploymentStatus, + MiddlewareServiceResponse, +} from '@/client'; + +export type Service = MiddlewareServiceResponse & { + deploymentStatus?: MiddlewareDeploymentStatus; +}; diff --git a/frontend/types/Util.ts b/frontend/types/Util.ts new file mode 100644 index 000000000..e4bed10e6 --- /dev/null +++ b/frontend/types/Util.ts @@ -0,0 +1,40 @@ +export type Nullable = T | null; + +export type Optional = T | undefined; + +export type Maybe = Nullable>; + +/** + * function to strip off the null or undefined types from a type by making an assertion. + * @note This function should be used if you are confident that the value will never ever be null or undefined. + * + * @param value Value that should be assumed to be present + * @param reason Reason for the assumption + * @returns void + */ +export function assertRequired( + value: T | null | undefined, + reason: string, +): asserts value is T { + if (value === null || value === undefined) { + throw new Error( + `Failed, value is either null or undefined. Incorrect assumption: ${reason}`, + ); + } +} + +/** + * function to strip off the null or undefined types from a type by making an assertion at runtime. + * @note This function should be used if you are confident that the value will never ever be null or undefined. + * + * @param value Value that should be assumed to be present + * @param reason Reason for the assumption + * @returns `value` that is not null or undefined. + */ +export const ensureRequired = ( + value: T | null | undefined, + why: string, +): T => { + assertRequired(value, why); + return value; +}; diff --git a/frontend/utils/abi.ts b/frontend/utils/abi.ts new file mode 100644 index 000000000..8cbac60db --- /dev/null +++ b/frontend/utils/abi.ts @@ -0,0 +1,8 @@ +import { JsonFragment } from '@ethersproject/abi'; + +import { Abi } from '@/types/Abi'; + +export const extractFunctionsFromAbi = (abi: Abi) => + abi.filter( + (item) => (item as JsonFragment).type === 'function', + ) as JsonFragment[]; diff --git a/frontend/utils/middlewareHelpers.ts b/frontend/utils/middlewareHelpers.ts new file mode 100644 index 000000000..100334721 --- /dev/null +++ b/frontend/utils/middlewareHelpers.ts @@ -0,0 +1,36 @@ +import { MiddlewareChain } from '@/client'; +import { EvmChainId } from '@/enums/Chain'; + +/** + * Converts middleware chain enums to chain ids + * @param chain + * @returns ChainId + * @throws Error + */ +export const asEvmChainId = (chain?: MiddlewareChain | string): EvmChainId => { + switch (chain) { + case MiddlewareChain.ETHEREUM: + return EvmChainId.Ethereum; + case MiddlewareChain.OPTIMISM: + return EvmChainId.Optimism; + case MiddlewareChain.GNOSIS: + return EvmChainId.Gnosis; + case MiddlewareChain.BASE: + return EvmChainId.Base; + } + throw new Error(`Invalid middleware chain enum: ${chain}`); +}; + +export const asMiddlewareChain = (chainId?: EvmChainId | number) => { + switch (chainId) { + case EvmChainId.Ethereum: + return MiddlewareChain.ETHEREUM; + case EvmChainId.Optimism: + return MiddlewareChain.OPTIMISM; + case EvmChainId.Gnosis: + return MiddlewareChain.GNOSIS; + case EvmChainId.Base: + return MiddlewareChain.BASE; + } + throw new Error(`Invalid chain id: ${chainId}`); +}; diff --git a/frontend/utils/numberFormatters.ts b/frontend/utils/numberFormatters.ts index 7613469fa..88411c851 100644 --- a/frontend/utils/numberFormatters.ts +++ b/frontend/utils/numberFormatters.ts @@ -1,3 +1,8 @@ +import { BigNumberish, ethers } from 'ethers'; + +/** + * Displays balance in a human readable format + */ export const balanceFormat = ( balance: number | undefined, decimals: 2, @@ -9,3 +14,38 @@ export const balanceFormat = ( minimumFractionDigits: decimals, }).format(balance); }; + +/** + * Formats larger numbers into small numbers + * @note **divides** the input by 10^decimals + * @example `formatUnits('1000000000000000000', 18)` => '1.0' + */ +export const formatUnits = (value: BigNumberish, decimals = 18): string => { + return ethers.utils.formatUnits(value, decimals); +}; + +/** + * Assumes the input is in wei and converts it to ether + */ +export const formatEther = (wei: BigNumberish): string => { + return ethers.utils.formatEther(wei); +}; + +/** + * Converts small numbers into larger numbers + * @note **multiplies** the input by `10 ** decimals` + * @example parseUnits('1.0', 18) => '1000000000000000000' + */ +export const parseUnits = ( + value: BigNumberish, + decimals: number = 18, +): string => { + return ethers.utils.parseUnits(`${value}`, decimals).toString(); +}; + +/** + * Assumes the input is in ether and converts it to wei + */ +export const parseEther = (ether: BigNumberish): string => { + return ethers.utils.parseEther(`${ether}`).toString(); +}; diff --git a/frontend/utils/service.ts b/frontend/utils/service.ts deleted file mode 100644 index 0e929f6c2..000000000 --- a/frontend/utils/service.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { ServiceTemplate } from '@/client'; -import { DEFAULT_STAKING_PROGRAM_ID } from '@/context/StakingProgramProvider'; -import { StakingProgramId } from '@/enums/StakingProgram'; - -/** TODO: update from hardcoded, workaround for quick release */ -export const getMinimumStakedAmountRequired = ( - serviceTemplate?: ServiceTemplate, //TODO: remove, as unused - stakingProgramId: StakingProgramId = DEFAULT_STAKING_PROGRAM_ID, -): number | undefined => { - // if (stakingProgramId === StakingProgramId.Alpha) { - // return 20; - // } - - // if (stakingProgramId === StakingProgramId.Beta) { - // return 40; - // } - - // if (stakingProgramId === StakingProgramId.Beta2) { - // return 100; - // } - - // if (stakingProgramId === StakingProgramId.Beta3) { - // return 100; - // } - - // if (stakingProgramId === StakingProgramId.Beta4) { - // return 100; - // } - - // if (stakingProgramId === StakingProgramId.Beta5) { - // return 10; - // } - - // if (stakingProgramId === StakingProgramId.BetaMechMarketplace) { - // return 40; - // } - - if (stakingProgramId === StakingProgramId.OptimusAlpha) return 40; - - return; -}; diff --git a/frontend/utils/setupMulticall.ts b/frontend/utils/setupMulticall.ts new file mode 100644 index 000000000..95a282d0f --- /dev/null +++ b/frontend/utils/setupMulticall.ts @@ -0,0 +1,30 @@ +import { setMulticallAddress } from 'ethers-multicall'; + +import { EvmChainId } from '@/enums/Chain'; +import { Address } from '@/types/Address'; + +const DEFAULT_MULTICALL_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11'; + +type AddressesForAllChainIds = { + [chainId in EvmChainId]: Address; +}; + +const addresses: AddressesForAllChainIds = { + [EvmChainId.Ethereum]: DEFAULT_MULTICALL_ADDRESS, + [EvmChainId.Base]: DEFAULT_MULTICALL_ADDRESS, + [EvmChainId.Gnosis]: DEFAULT_MULTICALL_ADDRESS, + [EvmChainId.Optimism]: DEFAULT_MULTICALL_ADDRESS, +}; + +/** + * Override multicall address in ethers-multicall + * throws error if the address is not set for a given `ChainId` + */ +export const setupMulticallAddresses = async () => { + Object.entries(addresses).forEach(([chainId, address]) => { + if (!address) { + throw new Error(`Multicall address not set for chainId: ${chainId}`); + } + setMulticallAddress(+chainId as EvmChainId, address); + }); +}; diff --git a/frontend/utils/truncate.ts b/frontend/utils/truncate.ts index c43325abf..e60935f76 100644 --- a/frontend/utils/truncate.ts +++ b/frontend/utils/truncate.ts @@ -1,4 +1,7 @@ +import { NA } from '@/constants/symbols'; import { Address } from '@/types/Address'; export const truncateAddress = (address: Address, length = 4) => - `${address?.substring(0, 2 + length)}...${address?.substring(address.length - length, address.length)}`; + typeof address === 'string' + ? `${address?.substring(0, 2 + length)}...${address?.substring(address.length - length, address.length)}` + : NA; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 7723c1c38..ed10fce83 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -4,12 +4,12 @@ "@adobe/css-tools@^4.3.2": version "4.3.3" - resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff" + resolved "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz" integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ== "@ampproject/remapping@^2.2.0": version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz" integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: "@jridgewell/gen-mapping" "^0.3.5" @@ -17,14 +17,14 @@ "@ant-design/colors@^7.0.0", "@ant-design/colors@^7.0.2": version "7.0.2" - resolved "https://registry.yarnpkg.com/@ant-design/colors/-/colors-7.0.2.tgz#c5c753a467ce8d86ba7ca4736d2c01f599bb5492" + resolved "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.2.tgz" integrity sha512-7KJkhTiPiLHSu+LmMJnehfJ6242OCxSlR3xHVBecYxnMW8MS/878NXct1GqYARyL59fyeFdKRxXTfvR9SnDgJg== dependencies: "@ctrl/tinycolor" "^3.6.1" "@ant-design/cssinjs@^1.18.4", "@ant-design/cssinjs@^1.19.1": version "1.20.0" - resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.20.0.tgz#878bc6c5b08f73db76da54c347a7ebb3fa4858bb" + resolved "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.20.0.tgz" integrity sha512-uG3iWzJxgNkADdZmc6W0Ci3iQAUOvLMcM8SnnmWq3r6JeocACft4ChnY/YWvI2Y+rG/68QBla/O+udke1yH3vg== dependencies: "@babel/runtime" "^7.11.1" @@ -37,12 +37,12 @@ "@ant-design/icons-svg@^4.4.0": version "4.4.2" - resolved "https://registry.yarnpkg.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz#ed2be7fb4d82ac7e1d45a54a5b06d6cecf8be6f6" + resolved "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz" integrity sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA== "@ant-design/icons@^5.3.0", "@ant-design/icons@^5.3.7": version "5.3.7" - resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.3.7.tgz#d9f3654bf7934ee5faba43f91b5a187f5309ec68" + resolved "https://registry.npmjs.org/@ant-design/icons/-/icons-5.3.7.tgz" integrity sha512-bCPXTAg66f5bdccM4TT21SQBDO1Ek2gho9h3nO9DAKXJP4sq+5VBjrQMSxMVXSB3HyEz+cUbHQ5+6ogxCOpaew== dependencies: "@ant-design/colors" "^7.0.0" @@ -53,7 +53,7 @@ "@ant-design/react-slick@~1.1.2": version "1.1.2" - resolved "https://registry.yarnpkg.com/@ant-design/react-slick/-/react-slick-1.1.2.tgz#f84ce3e4d0dc941f02b16f1d1d6d7a371ffbb4f1" + resolved "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz" integrity sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA== dependencies: "@babel/runtime" "^7.10.4" @@ -64,7 +64,7 @@ "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.2": version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz" integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== dependencies: "@babel/highlight" "^7.24.2" @@ -72,12 +72,12 @@ "@babel/compat-data@^7.23.5": version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz" integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.5.tgz#15ab5b98e101972d171aeef92ac70d8d6718f06a" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz" integrity sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA== dependencies: "@ampproject/remapping" "^2.2.0" @@ -98,7 +98,7 @@ "@babel/generator@^7.24.5", "@babel/generator@^7.7.2": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.5.tgz#e5afc068f932f05616b66713e28d0f04e99daeb3" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz" integrity sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA== dependencies: "@babel/types" "^7.24.5" @@ -108,7 +108,7 @@ "@babel/helper-compilation-targets@^7.23.6": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz" integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== dependencies: "@babel/compat-data" "^7.23.5" @@ -119,12 +119,12 @@ "@babel/helper-environment-visitor@^7.22.20": version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== "@babel/helper-function-name@^7.23.0": version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz" integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: "@babel/template" "^7.22.15" @@ -132,21 +132,21 @@ "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: "@babel/types" "^7.22.5" "@babel/helper-module-imports@^7.24.3": version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz" integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== dependencies: "@babel/types" "^7.24.0" "@babel/helper-module-transforms@^7.24.5": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz#ea6c5e33f7b262a0ae762fd5986355c45f54a545" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz" integrity sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A== dependencies: "@babel/helper-environment-visitor" "^7.22.20" @@ -157,41 +157,41 @@ "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz#a924607dd254a65695e5bd209b98b902b3b2f11a" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz" integrity sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ== "@babel/helper-simple-access@^7.24.5": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz#50da5b72f58c16b07fbd992810be6049478e85ba" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz" integrity sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ== dependencies: "@babel/types" "^7.24.5" "@babel/helper-split-export-declaration@^7.24.5": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz#b9a67f06a46b0b339323617c8c6213b9055a78b6" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz" integrity sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q== dependencies: "@babel/types" "^7.24.5" "@babel/helper-string-parser@^7.24.1": version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz" integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== "@babel/helper-validator-identifier@^7.24.5": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz" integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== "@babel/helper-validator-option@^7.23.5": version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== "@babel/helpers@^7.24.5": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.5.tgz#fedeb87eeafa62b621160402181ad8585a22a40a" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz" integrity sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q== dependencies: "@babel/template" "^7.24.0" @@ -200,7 +200,7 @@ "@babel/highlight@^7.24.2": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz" integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw== dependencies: "@babel/helper-validator-identifier" "^7.24.5" @@ -210,117 +210,117 @@ "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0", "@babel/parser@^7.24.5": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.5.tgz#4a4d5ab4315579e5398a82dcf636ca80c3392790" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz" integrity sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-bigint@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz" integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== dependencies: "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz" integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw== dependencies: "@babel/helper-plugin-utils" "^7.24.0" "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.4", "@babel/runtime@^7.24.5", "@babel/runtime@^7.9.2": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz" integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g== dependencies: regenerator-runtime "^0.14.0" "@babel/template@^7.22.15", "@babel/template@^7.24.0", "@babel/template@^7.3.3": version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz" integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== dependencies: "@babel/code-frame" "^7.23.5" @@ -329,7 +329,7 @@ "@babel/traverse@^7.24.5": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.5.tgz#972aa0bc45f16983bf64aa1f877b2dd0eea7e6f8" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz" integrity sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA== dependencies: "@babel/code-frame" "^7.24.2" @@ -345,7 +345,7 @@ "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.24.5", "@babel/types@^7.3.3": version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz" integrity sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ== dependencies: "@babel/helper-string-parser" "^7.24.1" @@ -354,63 +354,63 @@ "@bcoe/v8-coverage@^0.2.3": version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== "@cspotcode/source-map-support@^0.8.0": version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: "@jridgewell/trace-mapping" "0.3.9" "@ctrl/tinycolor@^3.6.1": version "3.6.1" - resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31" + resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz" integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== "@emotion/hash@^0.8.0": version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== "@emotion/is-prop-valid@1.2.2": version "1.2.2" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337" + resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz" integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw== dependencies: "@emotion/memoize" "^0.8.1" "@emotion/memoize@^0.8.1": version "0.8.1" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz" integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== "@emotion/unitless@0.8.1": version "0.8.1" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz" integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== "@emotion/unitless@^0.7.5": version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== "@eslint/eslintrc@^2.1.4": version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz" integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" @@ -425,12 +425,12 @@ "@eslint/js@8.57.0": version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz" integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== dependencies: "@ethersproject/address" "^5.7.0" @@ -445,7 +445,7 @@ "@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + resolved "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz" integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== dependencies: "@ethersproject/bignumber" "^5.7.0" @@ -458,7 +458,7 @@ "@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + resolved "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz" integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== dependencies: "@ethersproject/abstract-provider" "^5.7.0" @@ -469,7 +469,7 @@ "@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + resolved "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== dependencies: "@ethersproject/bignumber" "^5.7.0" @@ -480,14 +480,14 @@ "@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + resolved "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz" integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== dependencies: "@ethersproject/bytes" "^5.7.0" "@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + resolved "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz" integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -495,7 +495,7 @@ "@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + resolved "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -504,21 +504,21 @@ "@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + resolved "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== dependencies: "@ethersproject/logger" "^5.7.0" "@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + resolved "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz" integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== dependencies: "@ethersproject/bignumber" "^5.7.0" "@ethersproject/contracts@5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + resolved "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz" integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== dependencies: "@ethersproject/abi" "^5.7.0" @@ -534,7 +534,7 @@ "@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + resolved "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz" integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== dependencies: "@ethersproject/abstract-signer" "^5.7.0" @@ -549,7 +549,7 @@ "@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + resolved "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz" integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== dependencies: "@ethersproject/abstract-signer" "^5.7.0" @@ -567,7 +567,7 @@ "@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + resolved "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz" integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== dependencies: "@ethersproject/abstract-signer" "^5.7.0" @@ -586,7 +586,7 @@ "@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + resolved "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -594,19 +594,19 @@ "@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + resolved "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== "@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + resolved "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz" integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== dependencies: "@ethersproject/logger" "^5.7.0" "@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + resolved "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz" integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -614,14 +614,14 @@ "@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + resolved "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz" integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== dependencies: "@ethersproject/logger" "^5.7.0" "@ethersproject/providers@5.7.2": version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + resolved "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== dependencies: "@ethersproject/abstract-provider" "^5.7.0" @@ -647,7 +647,7 @@ "@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + resolved "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz" integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -655,7 +655,7 @@ "@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + resolved "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz" integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -663,7 +663,7 @@ "@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + resolved "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz" integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -672,7 +672,7 @@ "@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + resolved "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz" integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -684,7 +684,7 @@ "@ethersproject/solidity@5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + resolved "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz" integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== dependencies: "@ethersproject/bignumber" "^5.7.0" @@ -696,7 +696,7 @@ "@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + resolved "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz" integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -705,7 +705,7 @@ "@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + resolved "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz" integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== dependencies: "@ethersproject/address" "^5.7.0" @@ -720,7 +720,7 @@ "@ethersproject/units@5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + resolved "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz" integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== dependencies: "@ethersproject/bignumber" "^5.7.0" @@ -729,7 +729,7 @@ "@ethersproject/wallet@5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + resolved "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz" integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== dependencies: "@ethersproject/abstract-provider" "^5.7.0" @@ -750,7 +750,7 @@ "@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + resolved "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz" integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== dependencies: "@ethersproject/base64" "^5.7.0" @@ -761,7 +761,7 @@ "@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + resolved "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz" integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== dependencies: "@ethersproject/bytes" "^5.7.0" @@ -772,17 +772,17 @@ "@fontsource/inter@^5.0.17": version "5.0.18" - resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-5.0.18.tgz#eaddac790ee74b70932030f37ebaa9fc76decbd8" + resolved "https://registry.npmjs.org/@fontsource/inter/-/inter-5.0.18.tgz" integrity sha512-YCsoYPTcs713sI7tLtxaPrIhXAXvEetGg5Ry02ivA8qUOb3fQHojbK/X9HLD5OOKvFUNR2Ynkwb1kR1hVKQHpw== "@graphql-typed-document-node/core@^3.2.0": version "3.2.0" - resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + resolved "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz" integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== "@humanwhocodes/config-array@^0.11.14": version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz" integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: "@humanwhocodes/object-schema" "^2.0.2" @@ -791,17 +791,17 @@ "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/object-schema@^2.0.2": version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@isaacs/cliui@^8.0.2": version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== dependencies: string-width "^5.1.2" @@ -813,7 +813,7 @@ "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" @@ -824,12 +824,12 @@ "@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== "@jest/console@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + resolved "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz" integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== dependencies: "@jest/types" "^29.6.3" @@ -841,7 +841,7 @@ "@jest/core@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + resolved "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz" integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== dependencies: "@jest/console" "^29.7.0" @@ -875,7 +875,7 @@ "@jest/environment@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== dependencies: "@jest/fake-timers" "^29.7.0" @@ -885,14 +885,14 @@ "@jest/expect-utils@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz" integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== dependencies: jest-get-type "^29.6.3" "@jest/expect@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + resolved "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz" integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== dependencies: expect "^29.7.0" @@ -900,7 +900,7 @@ "@jest/fake-timers@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== dependencies: "@jest/types" "^29.6.3" @@ -912,7 +912,7 @@ "@jest/globals@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== dependencies: "@jest/environment" "^29.7.0" @@ -922,7 +922,7 @@ "@jest/reporters@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz" integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== dependencies: "@bcoe/v8-coverage" "^0.2.3" @@ -952,14 +952,14 @@ "@jest/schemas@^29.6.3": version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== dependencies: "@sinclair/typebox" "^0.27.8" "@jest/source-map@^29.6.3": version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz" integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== dependencies: "@jridgewell/trace-mapping" "^0.3.18" @@ -968,7 +968,7 @@ "@jest/test-result@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz" integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== dependencies: "@jest/console" "^29.7.0" @@ -978,7 +978,7 @@ "@jest/test-sequencer@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz" integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== dependencies: "@jest/test-result" "^29.7.0" @@ -988,7 +988,7 @@ "@jest/transform@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + resolved "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz" integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== dependencies: "@babel/core" "^7.11.6" @@ -1009,7 +1009,7 @@ "@jest/types@^29.6.3": version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== dependencies: "@jest/schemas" "^29.6.3" @@ -1021,7 +1021,7 @@ "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz" integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: "@jridgewell/set-array" "^1.2.1" @@ -1030,22 +1030,22 @@ "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/set-array@^1.2.1": version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz" integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" @@ -1053,7 +1053,7 @@ "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" @@ -1061,64 +1061,64 @@ "@next/env@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.3.tgz#d6def29d1c763c0afb397343a15a82e7d92353a0" + resolved "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz" integrity sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA== "@next/eslint-plugin-next@14.1.0": version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz#29b041233fac7417e22eefa4146432d5cd910820" + resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz" integrity sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q== dependencies: glob "10.3.10" "@next/swc-darwin-arm64@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz#db1a05eb88c0224089b815ad10ac128ec79c2cdb" + resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz#db1a05eb88c0224089b815ad10ac128ec79c2cdb" integrity sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A== "@next/swc-darwin-x64@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz#a3f8af05b5f9a52ac3082e66ac29e125ab1d7b9c" + resolved "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz#a3f8af05b5f9a52ac3082e66ac29e125ab1d7b9c" integrity sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA== "@next/swc-linux-arm64-gnu@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz#4e63f43879285b52554bfd39e6e0cc78a9b27bbf" + resolved "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz#4e63f43879285b52554bfd39e6e0cc78a9b27bbf" integrity sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA== "@next/swc-linux-arm64-musl@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz#ebdaed26214448b1e6f2c3e8b3cd29bfba387990" + resolved "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz#ebdaed26214448b1e6f2c3e8b3cd29bfba387990" integrity sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw== "@next/swc-linux-x64-gnu@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz#19e3bcc137c3b582a1ab867106817e5c90a20593" + resolved "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz" integrity sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w== "@next/swc-linux-x64-musl@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz#794a539b98e064169cf0ff7741b2a4fb16adec7d" + resolved "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz" integrity sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ== "@next/swc-win32-arm64-msvc@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz#eda9fa0fbf1ff9113e87ac2668ee67ce9e5add5a" + resolved "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz#eda9fa0fbf1ff9113e87ac2668ee67ce9e5add5a" integrity sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A== "@next/swc-win32-ia32-msvc@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz#7c1190e3f640ab16580c6bdbd7d0e766b9920457" + resolved "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz#7c1190e3f640ab16580c6bdbd7d0e766b9920457" integrity sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw== "@next/swc-win32-x64-msvc@14.2.3": version "14.2.3" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz#2be4e39ee25bfbd85be78eea17c0e7751dc4323c" + resolved "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz#2be4e39ee25bfbd85be78eea17c0e7751dc4323c" integrity sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA== "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -1126,12 +1126,12 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" @@ -1139,24 +1139,24 @@ "@pkgjs/parseargs@^0.11.0": version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@pkgr/core@^0.1.0": version "0.1.1" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== "@rc-component/async-validator@^5.0.3": version "5.0.4" - resolved "https://registry.yarnpkg.com/@rc-component/async-validator/-/async-validator-5.0.4.tgz#5291ad92f00a14b6766fc81735c234277f83e948" + resolved "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz" integrity sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg== dependencies: "@babel/runtime" "^7.24.4" "@rc-component/color-picker@~1.5.3": version "1.5.3" - resolved "https://registry.yarnpkg.com/@rc-component/color-picker/-/color-picker-1.5.3.tgz#f3b0e14bb67ec5ee77d1fd5d261f63dd4fd00449" + resolved "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.5.3.tgz" integrity sha512-+tGGH3nLmYXTalVe0L8hSZNs73VTP5ueSHwUlDC77KKRaN7G4DS4wcpG5DTDzdcV/Yas+rzA6UGgIyzd8fS4cw== dependencies: "@babel/runtime" "^7.23.6" @@ -1166,7 +1166,7 @@ "@rc-component/context@^1.4.0": version "1.4.0" - resolved "https://registry.yarnpkg.com/@rc-component/context/-/context-1.4.0.tgz#dc6fb021d6773546af8f016ae4ce9aea088395e8" + resolved "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz" integrity sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w== dependencies: "@babel/runtime" "^7.10.1" @@ -1174,14 +1174,14 @@ "@rc-component/mini-decimal@^1.0.1": version "1.1.0" - resolved "https://registry.yarnpkg.com/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz#7b7a362b14a0a54cb5bc6fd2b82731f29f11d9b0" + resolved "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz" integrity sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ== dependencies: "@babel/runtime" "^7.18.0" "@rc-component/mutate-observer@^1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz#ee53cc88b78aade3cd0653609215a44779386fd8" + resolved "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz" integrity sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw== dependencies: "@babel/runtime" "^7.18.0" @@ -1190,7 +1190,7 @@ "@rc-component/portal@^1.0.0-8", "@rc-component/portal@^1.0.0-9", "@rc-component/portal@^1.0.2", "@rc-component/portal@^1.1.0", "@rc-component/portal@^1.1.1": version "1.1.2" - resolved "https://registry.yarnpkg.com/@rc-component/portal/-/portal-1.1.2.tgz#55db1e51d784e034442e9700536faaa6ab63fc71" + resolved "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz" integrity sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg== dependencies: "@babel/runtime" "^7.18.0" @@ -1199,7 +1199,7 @@ "@rc-component/tour@~1.15.0": version "1.15.0" - resolved "https://registry.yarnpkg.com/@rc-component/tour/-/tour-1.15.0.tgz#37a66ae5af8eefaf0ab0e22ddd8e6fecdbdc14a7" + resolved "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.0.tgz" integrity sha512-h6hyILDwL+In9GAgRobwRWihLqqsD7Uft3fZGrJ7L4EiyCoxbnNYwzPXDfz7vNDhWeVyvAWQJj9fJCzpI4+b4g== dependencies: "@babel/runtime" "^7.18.0" @@ -1210,7 +1210,7 @@ "@rc-component/trigger@^2.0.0", "@rc-component/trigger@^2.1.1": version "2.1.1" - resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-2.1.1.tgz#47973f1156ba63810c913eb46cbaedeba913874b" + resolved "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.1.1.tgz" integrity sha512-UjHkedkgtEcgQu87w1VuWug1idoDJV7VUt0swxHXRcmei2uu1AuUzGBPEUlmOmXGJ+YtTgZfVLi7kuAUKoZTMA== dependencies: "@babel/runtime" "^7.23.2" @@ -1222,36 +1222,36 @@ "@rushstack/eslint-patch@^1.3.3": version "1.10.3" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz#391d528054f758f81e53210f1a1eebcf1a8b1d20" + resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz" integrity sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg== "@sinclair/typebox@^0.27.8": version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== "@sinonjs/commons@^3.0.0": version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz" integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== dependencies: type-detect "4.0.8" "@sinonjs/fake-timers@^10.0.2": version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== dependencies: "@sinonjs/commons" "^3.0.0" "@swc/counter@^0.1.3": version "0.1.3" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== "@swc/helpers@0.5.5": version "0.5.5" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" + resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz" integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== dependencies: "@swc/counter" "^0.1.3" @@ -1259,19 +1259,19 @@ "@tanstack/query-core@5.56.2": version "5.56.2" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.56.2.tgz#2def2fb0290cd2836bbb08afb0c175595bb8109b" + resolved "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.56.2.tgz" integrity sha512-gor0RI3/R5rVV3gXfddh1MM+hgl0Z4G7tj6Xxpq6p2I03NGPaJ8dITY9Gz05zYYb/EJq9vPas/T4wn9EaDPd4Q== "@tanstack/react-query@^5.29.0": version "5.56.2" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.56.2.tgz#3a0241b9d010910905382f5e99160997b8795f91" + resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.56.2.tgz" integrity sha512-SR0GzHVo6yzhN72pnRhkEFRAHMsUo5ZPzAxfTMvUxFIDVS6W9LYUp6nXW3fcHVdg0ZJl8opSH85jqahvm6DSVg== dependencies: "@tanstack/query-core" "5.56.2" "@testing-library/dom@^9.0.0": version "9.3.4" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-9.3.4.tgz#50696ec28376926fec0a1bf87d9dbac5e27f60ce" + resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz" integrity sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ== dependencies: "@babel/code-frame" "^7.10.4" @@ -1285,7 +1285,7 @@ "@testing-library/jest-dom@^6.4.2": version "6.4.5" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz#badb40296477149136dabef32b572ddd3b56adf1" + resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz" integrity sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A== dependencies: "@adobe/css-tools" "^4.3.2" @@ -1299,7 +1299,7 @@ "@testing-library/react@^14.2.1": version "14.3.1" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.3.1.tgz#29513fc3770d6fb75245c4e1245c470e4ffdd830" + resolved "https://registry.npmjs.org/@testing-library/react/-/react-14.3.1.tgz" integrity sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ== dependencies: "@babel/runtime" "^7.12.5" @@ -1308,37 +1308,37 @@ "@tootallnate/once@2": version "2.0.0" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== "@tsconfig/node10@^1.0.7": version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz" integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== "@tsconfig/node12@^1.0.7": version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@types/aria-query@^5.0.1": version "5.0.4" - resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== "@types/babel__core@^7.1.14": version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== dependencies: "@babel/parser" "^7.20.7" @@ -1349,14 +1349,14 @@ "@types/babel__generator@*": version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz" integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz" integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== dependencies: "@babel/parser" "^7.1.0" @@ -1364,45 +1364,45 @@ "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": version "7.20.6" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz" integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== dependencies: "@babel/types" "^7.20.7" "@types/canvas-confetti@1.4.0": version "1.4.0" - resolved "https://registry.yarnpkg.com/@types/canvas-confetti/-/canvas-confetti-1.4.0.tgz#22127a1a9ed9d456e626d6e2b9a4d3b0a240e18b" + resolved "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.4.0.tgz" integrity sha512-Neq4mvVecrHmTdyo98EY5bnKCjkZGQ6Ma7VyOrxIcMHEZPmt4kfquccqfBMrpNrdryMHgk3oGQi7XtpZacltnw== "@types/graceful-fs@^4.1.3": version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz" integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== dependencies: "@types/node" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz" integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== "@types/istanbul-lib-report@*": version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz" integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz" integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== dependencies: "@types/istanbul-lib-report" "*" "@types/jest@^29.5.12": version "29.5.12" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz" integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== dependencies: expect "^29.0.0" @@ -1410,7 +1410,7 @@ "@types/jsdom@^20.0.0": version "20.0.1" - resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" + resolved "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz" integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ== dependencies: "@types/node" "*" @@ -1419,48 +1419,41 @@ "@types/json-schema@^7.0.9": version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/json5@^0.0.29": version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/lodash@^4.14.202": version "4.17.4" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.4.tgz#0303b64958ee070059e3a7184048a55159fe20b7" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.4.tgz" integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ== -"@types/node@*": - version "20.12.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" - integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== - dependencies: - undici-types "~5.26.4" - -"@types/node@20.14.10": +"@types/node@*", "@types/node@20.14.10": version "20.14.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.10.tgz#a1a218290f1b6428682e3af044785e5874db469a" + resolved "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz" integrity sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ== dependencies: undici-types "~5.26.4" "@types/prop-types@*": version "15.7.12" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" + resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz" integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== "@types/react-dom@^18", "@types/react-dom@^18.0.0": version "18.3.0" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" + resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz" integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== dependencies: "@types/react" "*" "@types/react@*", "@types/react@18.3.3": version "18.3.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" + resolved "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz" integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== dependencies: "@types/prop-types" "*" @@ -1468,46 +1461,46 @@ "@types/semver@^7.3.12": version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== "@types/stack-utils@^2.0.0": version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== "@types/stylis@4.2.5": version "4.2.5" - resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.5.tgz#1daa6456f40959d06157698a653a9ab0a70281df" + resolved "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz" integrity sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw== "@types/tough-cookie@*": version "4.0.5" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz" integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== "@types/yargs-parser@*": version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz" integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^7.0.1": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz#07854a236f107bb45cbf4f62b89474cbea617f50" - integrity sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw== +"@typescript-eslint/eslint-plugin@^7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz" + integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.10.0" - "@typescript-eslint/type-utils" "7.10.0" - "@typescript-eslint/utils" "7.10.0" - "@typescript-eslint/visitor-keys" "7.10.0" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/type-utils" "7.18.0" + "@typescript-eslint/utils" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" @@ -1515,7 +1508,7 @@ "@typescript-eslint/parser@^5.4.2 || ^6.0.0": version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz" integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== dependencies: "@typescript-eslint/scope-manager" "6.21.0" @@ -1524,20 +1517,20 @@ "@typescript-eslint/visitor-keys" "6.21.0" debug "^4.3.4" -"@typescript-eslint/parser@^7.0.1": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.10.0.tgz#e6ac1cba7bc0400a4459e7eb5b23115bd71accfb" - integrity sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w== +"@typescript-eslint/parser@^7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz" + integrity sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg== dependencies: - "@typescript-eslint/scope-manager" "7.10.0" - "@typescript-eslint/types" "7.10.0" - "@typescript-eslint/typescript-estree" "7.10.0" - "@typescript-eslint/visitor-keys" "7.10.0" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz" integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== dependencies: "@typescript-eslint/types" "5.62.0" @@ -1545,48 +1538,48 @@ "@typescript-eslint/scope-manager@6.21.0": version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz" integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== dependencies: "@typescript-eslint/types" "6.21.0" "@typescript-eslint/visitor-keys" "6.21.0" -"@typescript-eslint/scope-manager@7.10.0": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz#054a27b1090199337a39cf755f83d9f2ce26546b" - integrity sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg== +"@typescript-eslint/scope-manager@7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz" + integrity sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA== dependencies: - "@typescript-eslint/types" "7.10.0" - "@typescript-eslint/visitor-keys" "7.10.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" -"@typescript-eslint/type-utils@7.10.0": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz#8a75accce851d0a331aa9331268ef64e9b300270" - integrity sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g== +"@typescript-eslint/type-utils@7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz" + integrity sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA== dependencies: - "@typescript-eslint/typescript-estree" "7.10.0" - "@typescript-eslint/utils" "7.10.0" + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/utils" "7.18.0" debug "^4.3.4" ts-api-utils "^1.3.0" "@typescript-eslint/types@5.62.0": version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== "@typescript-eslint/types@6.21.0": version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz" integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== -"@typescript-eslint/types@7.10.0": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.10.0.tgz#da92309c97932a3a033762fd5faa8b067de84e3b" - integrity sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg== +"@typescript-eslint/types@7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz" + integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz" integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== dependencies: "@typescript-eslint/types" "5.62.0" @@ -1599,7 +1592,7 @@ "@typescript-eslint/typescript-estree@6.21.0": version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz" integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== dependencies: "@typescript-eslint/types" "6.21.0" @@ -1611,13 +1604,13 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/typescript-estree@7.10.0": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz#6dcdc5de3149916a6a599fa89dde5c471b88b8bb" - integrity sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g== +"@typescript-eslint/typescript-estree@7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz" + integrity sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA== dependencies: - "@typescript-eslint/types" "7.10.0" - "@typescript-eslint/visitor-keys" "7.10.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1625,19 +1618,19 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.10.0": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.10.0.tgz#8ee43e5608c9f439524eaaea8de5b358b15c51b3" - integrity sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg== +"@typescript-eslint/utils@7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz" + integrity sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.10.0" - "@typescript-eslint/types" "7.10.0" - "@typescript-eslint/typescript-estree" "7.10.0" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/typescript-estree" "7.18.0" "@typescript-eslint/utils@^5.10.0": version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -1651,7 +1644,7 @@ "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz" integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: "@typescript-eslint/types" "5.62.0" @@ -1659,33 +1652,33 @@ "@typescript-eslint/visitor-keys@6.21.0": version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz" integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== dependencies: "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" -"@typescript-eslint/visitor-keys@7.10.0": - version "7.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz#2af2e91e73a75dd6b70b4486c48ae9d38a485a78" - integrity sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg== +"@typescript-eslint/visitor-keys@7.18.0": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz" + integrity sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg== dependencies: - "@typescript-eslint/types" "7.10.0" + "@typescript-eslint/types" "7.18.0" eslint-visitor-keys "^3.4.3" "@ungap/structured-clone@^1.2.0": version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== abab@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== acorn-globals@^7.0.0: version "7.0.1" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" + resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz" integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== dependencies: acorn "^8.1.0" @@ -1693,34 +1686,34 @@ acorn-globals@^7.0.0: acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.0.2, acorn-walk@^8.1.1: version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== acorn@^8.1.0, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.9.0: version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== aes-js@3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== agent-base@6: version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" ajv@^6.12.4: version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -1730,48 +1723,48 @@ ajv@^6.12.4: ansi-escapes@^4.2.1: version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" ansi-styles@^5.0.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== ansi-styles@^6.1.0: version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== antd@^5.14.0: version "5.17.3" - resolved "https://registry.yarnpkg.com/antd/-/antd-5.17.3.tgz#c969755335cdef6fa671152602b7100557bff80c" + resolved "https://registry.npmjs.org/antd/-/antd-5.17.3.tgz" integrity sha512-U99hyy7t8dOQtNHzHifmwAXJLgmPMadavFBsd2mnfICD6m8l7u/NvCefRhd2jOf/SBNE2579YhwCEwTUiX2GnQ== dependencies: "@ant-design/colors" "^7.0.2" @@ -1825,7 +1818,7 @@ antd@^5.14.0: anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -1833,38 +1826,38 @@ anymatch@^3.0.3, anymatch@~3.1.2: arg@^4.1.0: version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== aria-query@5.1.3: version "5.1.3" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" + resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz" integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== dependencies: deep-equal "^2.0.5" aria-query@^5.0.0, aria-query@^5.3.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz" integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== dependencies: dequal "^2.0.3" array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz" integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== dependencies: call-bind "^1.0.5" @@ -1872,7 +1865,7 @@ array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: array-includes@^3.1.6, array-includes@^3.1.7: version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz" integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== dependencies: call-bind "^1.0.7" @@ -1884,17 +1877,17 @@ array-includes@^3.1.6, array-includes@^3.1.7: array-tree-filter@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/array-tree-filter/-/array-tree-filter-2.1.0.tgz#873ac00fec83749f255ac8dd083814b4f6329190" + resolved "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz" integrity sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw== array-union@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array.prototype.findlast@^1.2.4: version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + resolved "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz" integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== dependencies: call-bind "^1.0.7" @@ -1906,7 +1899,7 @@ array.prototype.findlast@^1.2.4: array.prototype.findlastindex@^1.2.3: version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" + resolved "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz" integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== dependencies: call-bind "^1.0.7" @@ -1918,7 +1911,7 @@ array.prototype.findlastindex@^1.2.3: array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz" integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== dependencies: call-bind "^1.0.2" @@ -1928,7 +1921,7 @@ array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: array.prototype.flatmap@^1.3.2: version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz" integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== dependencies: call-bind "^1.0.2" @@ -1938,7 +1931,7 @@ array.prototype.flatmap@^1.3.2: array.prototype.toreversed@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" + resolved "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz" integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== dependencies: call-bind "^1.0.2" @@ -1948,7 +1941,7 @@ array.prototype.toreversed@^1.1.2: array.prototype.tosorted@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz#c8c89348337e51b8a3c48a9227f9ce93ceedcba8" + resolved "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz" integrity sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg== dependencies: call-bind "^1.0.5" @@ -1959,7 +1952,7 @@ array.prototype.tosorted@^1.1.3: arraybuffer.prototype.slice@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz" integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== dependencies: array-buffer-byte-length "^1.0.1" @@ -1973,36 +1966,45 @@ arraybuffer.prototype.slice@^1.0.3: ast-types-flow@^0.0.8: version "0.0.8" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" + resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz" integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== available-typed-arrays@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz" integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== dependencies: possible-typed-array-names "^1.0.0" axe-core@=4.7.0: version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" + resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz" integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== +axios@^1.7.7: + version "1.7.7" + resolved "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axobject-query@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" + resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz" integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== dependencies: dequal "^2.0.3" babel-jest@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== dependencies: "@jest/transform" "^29.7.0" @@ -2015,7 +2017,7 @@ babel-jest@^29.7.0: babel-plugin-istanbul@^6.1.1: version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -2026,7 +2028,7 @@ babel-plugin-istanbul@^6.1.1: babel-plugin-jest-hoist@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz" integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== dependencies: "@babel/template" "^7.3.3" @@ -2036,7 +2038,7 @@ babel-plugin-jest-hoist@^29.6.3: babel-preset-current-node-syntax@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" @@ -2054,7 +2056,7 @@ babel-preset-current-node-syntax@^1.0.0: babel-preset-jest@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz" integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== dependencies: babel-plugin-jest-hoist "^29.6.3" @@ -2062,32 +2064,32 @@ babel-preset-jest@^29.6.3: balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== bech32@1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== binary-extensions@^2.0.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== bn.js@^4.11.9: version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== bn.js@^5.2.1: version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -2095,26 +2097,26 @@ brace-expansion@^1.1.7: brace-expansion@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== dependencies: balanced-match "^1.0.0" braces@^3.0.3, braces@~3.0.2: version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" brorand@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== browserslist@^4.22.2: version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz" integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== dependencies: caniuse-lite "^1.0.30001587" @@ -2124,26 +2126,26 @@ browserslist@^4.22.2: bser@2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: node-int64 "^0.4.0" buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== busboy@1.6.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz" integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== dependencies: streamsearch "^1.1.0" call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz" integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: es-define-property "^1.0.0" @@ -2154,37 +2156,37 @@ call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.2.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== camelize@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" + resolved "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz" integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001587: version "1.0.30001621" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001621.tgz#4adcb443c8b9c8303e04498318f987616b8fea2e" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001621.tgz" integrity sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA== canvas-confetti@1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/canvas-confetti/-/canvas-confetti-1.4.0.tgz#840f6db4a566f8f32abe28c00dcd82acf39c92bd" + resolved "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.4.0.tgz" integrity sha512-S18o4Y9PqI/uabdlT/jI3MY7XBJjNxnfapFIkjkMwpz6qNxLFZOm2b22OMf4ZYDL9lpNWI+Ih4fEMVPwO1KHFQ== chalk@^2.4.2: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -2193,7 +2195,7 @@ chalk@^2.4.2: chalk@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz" integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== dependencies: ansi-styles "^4.1.0" @@ -2201,7 +2203,7 @@ chalk@^3.0.0: chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -2209,12 +2211,12 @@ chalk@^4.0.0, chalk@^4.1.0: char-regex@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== "chokidar@>=3.0.0 <4.0.0": version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" @@ -2229,27 +2231,27 @@ char-regex@^1.0.2: ci-info@^3.2.0: version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== cjs-module-lexer@^1.0.0: version "1.3.1" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" + resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz" integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1, classnames@^2.3.2, classnames@^2.5.1: version "2.5.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== client-only@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== cliui@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -2258,70 +2260,70 @@ cliui@^8.0.1: co@^4.6.0: version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== collect-v8-coverage@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" compute-scroll-into-view@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz#753f11d972596558d8fe7c6bcbc8497690ab4c87" + resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz" integrity sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== convert-source-map@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== copy-to-clipboard@^3.3.3: version "3.3.3" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" + resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz" integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== dependencies: toggle-selection "^1.0.6" create-jest@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== dependencies: "@jest/types" "^29.6.3" @@ -2334,19 +2336,19 @@ create-jest@^29.7.0: create-require@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-fetch@^3.1.5: version "3.1.8" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz" integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== dependencies: node-fetch "^2.6.12" cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" @@ -2355,12 +2357,12 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: css-color-keywords@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz" integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== css-to-react-native@3.2.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" + resolved "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz" integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== dependencies: camelize "^1.0.0" @@ -2369,39 +2371,39 @@ css-to-react-native@3.2.0: css.escape@^1.5.1: version "1.5.1" - resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz" integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== cssom@^0.5.0: version "0.5.0" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + resolved "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz" integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== cssom@~0.3.6: version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== cssstyle@^2.3.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz" integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== dependencies: cssom "~0.3.6" csstype@3.1.3, csstype@^3.0.2, csstype@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== damerau-levenshtein@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== data-urls@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + resolved "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz" integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== dependencies: abab "^2.0.6" @@ -2410,7 +2412,7 @@ data-urls@^3.0.2: data-view-buffer@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz" integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== dependencies: call-bind "^1.0.6" @@ -2419,7 +2421,7 @@ data-view-buffer@^1.0.1: data-view-byte-length@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + resolved "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz" integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== dependencies: call-bind "^1.0.7" @@ -2428,7 +2430,7 @@ data-view-byte-length@^1.0.1: data-view-byte-offset@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + resolved "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz" integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== dependencies: call-bind "^1.0.6" @@ -2437,36 +2439,36 @@ data-view-byte-offset@^1.0.0: dayjs@^1.11.10: version "1.11.11" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz" integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" debug@^3.2.7: version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" decimal.js@^10.4.2: version "10.4.3" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== dedent@^1.0.0: version "1.5.3" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" + resolved "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz" integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== deep-equal@^2.0.5: version "2.2.3" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" + resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz" integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== dependencies: array-buffer-byte-length "^1.0.0" @@ -2490,17 +2492,17 @@ deep-equal@^2.0.5: deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deepmerge@^4.2.2: version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz" integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: es-define-property "^1.0.0" @@ -2509,7 +2511,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: define-data-property "^1.0.1" @@ -2518,80 +2520,80 @@ define-properties@^1.2.0, define-properties@^1.2.1: delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== dequal@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== detect-newline@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== diff-sequences@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== diff@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" doctrine@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" dom-accessibility-api@^0.5.9: version "0.5.16" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz" integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== dom-accessibility-api@^0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz" integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== domexception@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + resolved "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz" integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== dependencies: webidl-conversions "^7.0.0" eastasianwidth@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== electron-to-chromium@^1.4.668: version "1.4.780" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.780.tgz#8c6d7ff82b56b4219f2ae7918ee271ae25654f07" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.780.tgz" integrity sha512-NPtACGFe7vunRYzvYqVRhQvsDrTevxpgDKxG/Vcbe0BTNOY+5+/2mOXSw2ls7ToNbE5Bf/+uQbjTxcmwMozpCw== elliptic@6.5.4: version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: bn.js "^4.11.9" @@ -2604,22 +2606,22 @@ elliptic@6.5.4: emittery@^0.13.1: version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emoji-regex@^9.2.2: version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== enhanced-resolve@^5.12.0: version "5.16.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz#e8bc63d51b826d6f1cbc0a150ecb5a8b0c62e567" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz" integrity sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw== dependencies: graceful-fs "^4.2.4" @@ -2627,19 +2629,19 @@ enhanced-resolve@^5.12.0: entities@^4.4.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== dependencies: array-buffer-byte-length "^1.0.1" @@ -2691,19 +2693,19 @@ es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23 es-define-property@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz" integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== dependencies: get-intrinsic "^1.2.4" es-errors@^1.1.0, es-errors@^1.2.1, es-errors@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== es-get-iterator@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" + resolved "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz" integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== dependencies: call-bind "^1.0.2" @@ -2718,7 +2720,7 @@ es-get-iterator@^1.1.3: es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: version "1.0.19" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" + resolved "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz" integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== dependencies: call-bind "^1.0.7" @@ -2738,14 +2740,14 @@ es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: es-object-atoms@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz" integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== dependencies: es-errors "^1.3.0" es-set-tostringtag@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz" integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== dependencies: get-intrinsic "^1.2.4" @@ -2754,14 +2756,14 @@ es-set-tostringtag@^2.0.3: es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz" integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== dependencies: hasown "^2.0.0" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" @@ -2770,27 +2772,27 @@ es-to-primitive@^1.2.1: escalade@^3.1.1, escalade@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escodegen@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== dependencies: esprima "^4.0.1" @@ -2801,7 +2803,7 @@ escodegen@^2.0.0: eslint-config-next@14.1.0: version "14.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.1.0.tgz#7e309d426b8afacaba3b32fdbb02ba220b6d0a97" + resolved "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.1.0.tgz" integrity sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg== dependencies: "@next/eslint-plugin-next" "14.1.0" @@ -2816,12 +2818,12 @@ eslint-config-next@14.1.0: eslint-config-prettier@^9.1.0: version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz" integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz" integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== dependencies: debug "^3.2.7" @@ -2830,7 +2832,7 @@ eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: eslint-import-resolver-typescript@^3.5.2: version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" + resolved "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz" integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== dependencies: debug "^4.3.4" @@ -2843,14 +2845,14 @@ eslint-import-resolver-typescript@^3.5.2: eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" + resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz" integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== dependencies: debug "^3.2.7" eslint-plugin-import@^2.28.1, eslint-plugin-import@^2.29.1: version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz" integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== dependencies: array-includes "^3.1.7" @@ -2873,14 +2875,14 @@ eslint-plugin-import@^2.28.1, eslint-plugin-import@^2.29.1: eslint-plugin-jest@^27.6.3: version "27.9.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz#7c98a33605e1d8b8442ace092b60e9919730000b" + resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz" integrity sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug== dependencies: "@typescript-eslint/utils" "^5.10.0" eslint-plugin-jsx-a11y@^6.7.1: version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" + resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz" integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== dependencies: "@babel/runtime" "^7.23.2" @@ -2902,12 +2904,12 @@ eslint-plugin-jsx-a11y@^6.7.1: eslint-plugin-next@^0.0.0: version "0.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-next/-/eslint-plugin-next-0.0.0.tgz#f9ef680e8f68763c716ab44697c4b3cc3e0b2069" + resolved "https://registry.npmjs.org/eslint-plugin-next/-/eslint-plugin-next-0.0.0.tgz" integrity sha512-IldNDVb6WNduggwRbYzSGZhaskUwVecJ6fhmqwX01+S1aohwAWNzU4me6y47DDzpD/g0fdayNBGxEdt9vKkUtg== eslint-plugin-prettier@^5.1.3: version "5.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" + resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz" integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw== dependencies: prettier-linter-helpers "^1.0.0" @@ -2915,12 +2917,12 @@ eslint-plugin-prettier@^5.1.3: "eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": version "4.6.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" + resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz" integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== eslint-plugin-react@^7.33.2: version "7.34.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz#6806b70c97796f5bbfb235a5d3379ece5f4da997" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz" integrity sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw== dependencies: array-includes "^3.1.7" @@ -2944,24 +2946,24 @@ eslint-plugin-react@^7.33.2: eslint-plugin-simple-import-sort@^12.0.0: version "12.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.0.tgz#8186ad55474d2f5c986a2f1bf70625a981e30d05" + resolved "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.0.tgz" integrity sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig== eslint-plugin-unused-imports@^3.0.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz#63a98c9ad5f622cd9f830f70bc77739f25ccfe0d" + resolved "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz" integrity sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ== dependencies: eslint-rule-composer "^0.3.0" eslint-rule-composer@^0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + resolved "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz" integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -2969,7 +2971,7 @@ eslint-scope@^5.1.1: eslint-scope@^7.2.2: version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" @@ -2977,12 +2979,12 @@ eslint-scope@^7.2.2: eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.56.0: version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz" integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -3026,7 +3028,7 @@ eslint@^8.56.0: espree@^9.6.0, espree@^9.6.1: version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: acorn "^8.9.0" @@ -3035,48 +3037,48 @@ espree@^9.6.0, espree@^9.6.1: esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.4.2: version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== ethers-multicall@^0.2.3: version "0.2.3" - resolved "https://registry.yarnpkg.com/ethers-multicall/-/ethers-multicall-0.2.3.tgz#872b5ad7d6b5d4d7f2960c33bf36bd46d034ac41" + resolved "https://registry.npmjs.org/ethers-multicall/-/ethers-multicall-0.2.3.tgz" integrity sha512-RaWQuLy+HzeKOibptlc9RZ6j7bT1H6VnkdAKTHiLx2t/lpyfS2ckXHdQhhRbCaXNc1iu6CgoisgMejxKHg84tg== dependencies: ethers "^5.0.0" ethers@5.7.2, ethers@^5.0.0: version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + resolved "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== dependencies: "@ethersproject/abi" "5.7.0" @@ -3112,7 +3114,7 @@ ethers@5.7.2, ethers@^5.0.0: execa@^5.0.0: version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" @@ -3127,12 +3129,12 @@ execa@^5.0.0: exit@^0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== expect@^29.0.0, expect@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== dependencies: "@jest/expect-utils" "^29.7.0" @@ -3143,17 +3145,17 @@ expect@^29.0.0, expect@^29.7.0: fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2: version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.2.9, fast-glob@^3.3.1: version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -3164,45 +3166,45 @@ fast-glob@^3.2.9, fast-glob@^3.3.1: fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz" integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" fb-watchman@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -3210,7 +3212,7 @@ find-up@^4.0.0, find-up@^4.1.0: find-up@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -3218,7 +3220,7 @@ find-up@^5.0.0: flat-cache@^3.0.4: version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz" integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: flatted "^3.2.9" @@ -3227,19 +3229,24 @@ flat-cache@^3.0.4: flatted@^3.2.9: version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + for-each@^0.3.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" foreground-child@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz" integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== dependencies: cross-spawn "^7.0.0" @@ -3247,7 +3254,7 @@ foreground-child@^3.1.0: form-data@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== dependencies: asynckit "^0.4.0" @@ -3256,22 +3263,22 @@ form-data@^4.0.0: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz" integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" @@ -3281,22 +3288,22 @@ function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: functions-have-names@^1.2.3: version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz" integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: es-errors "^1.3.0" @@ -3307,17 +3314,17 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@ get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== get-stream@^6.0.0: version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== get-symbol-description@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz" integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== dependencies: call-bind "^1.0.5" @@ -3326,28 +3333,28 @@ get-symbol-description@^1.0.2: get-tsconfig@^4.5.0: version "4.7.5" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" + resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz" integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== dependencies: resolve-pkg-maps "^1.0.0" glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" glob@10.3.10: version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + resolved "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz" integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== dependencies: foreground-child "^3.1.0" @@ -3358,7 +3365,7 @@ glob@10.3.10: glob@^7.1.3, glob@^7.1.4: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -3370,19 +3377,19 @@ glob@^7.1.3, glob@^7.1.4: globals@^11.1.0: version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.19.0: version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz" integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" globalthis@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== dependencies: define-properties "^1.2.1" @@ -3390,7 +3397,7 @@ globalthis@^1.0.3: globby@^11.1.0: version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -3402,24 +3409,24 @@ globby@^11.1.0: gopd@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: get-intrinsic "^1.1.3" graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphemer@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== graphql-request@^6.1.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f" + resolved "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz" integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw== dependencies: "@graphql-typed-document-node/core" "^3.2.0" @@ -3427,51 +3434,51 @@ graphql-request@^6.1.0: graphql@^16.8.1: version "16.9.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" + resolved "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz" integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: es-define-property "^1.0.0" has-proto@^1.0.1, has-proto@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz" integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: has-symbols "^1.0.3" hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" @@ -3479,14 +3486,14 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" @@ -3495,19 +3502,19 @@ hmac-drbg@^1.0.1: html-encoding-sniffer@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz" integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== dependencies: whatwg-encoding "^2.0.0" html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== http-proxy-agent@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz" integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== dependencies: "@tootallnate/once" "2" @@ -3516,7 +3523,7 @@ http-proxy-agent@^5.0.0: https-proxy-agent@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -3524,29 +3531,29 @@ https-proxy-agent@^5.0.1: human-signals@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== iconv-lite@0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" ignore@^5.2.0, ignore@^5.3.1: version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== immutable@^4.0.0: version "4.3.6" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.6.tgz#6a05f7858213238e587fb83586ffa3b4b27f0447" + resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz" integrity sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ== import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -3554,7 +3561,7 @@ import-fresh@^3.2.1: import-local@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" @@ -3562,17 +3569,17 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -3580,12 +3587,12 @@ inflight@^1.0.4: inherits@2, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== internal-slot@^1.0.4, internal-slot@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz" integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== dependencies: es-errors "^1.3.0" @@ -3594,7 +3601,7 @@ internal-slot@^1.0.4, internal-slot@^1.0.7: is-arguments@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== dependencies: call-bind "^1.0.2" @@ -3602,7 +3609,7 @@ is-arguments@^1.1.1: is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz" integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== dependencies: call-bind "^1.0.2" @@ -3610,33 +3617,33 @@ is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-async-function@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + resolved "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz" integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== dependencies: has-tostringtag "^1.0.0" is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== dependencies: has-bigints "^1.0.1" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== dependencies: call-bind "^1.0.2" @@ -3644,101 +3651,101 @@ is-boolean-object@^1.1.0: is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: hasown "^2.0.0" is-data-view@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + resolved "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz" integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== dependencies: is-typed-array "^1.1.13" is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-finalizationregistry@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + resolved "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz" integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== dependencies: call-bind "^1.0.2" is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-generator-fn@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== is-generator-function@^1.0.10: version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== dependencies: has-tostringtag "^1.0.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-map@^2.0.2, is-map@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz" integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== is-negative-zero@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz" integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== is-number-object@^1.0.4: version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-path-inside@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== is-potential-custom-element-name@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" @@ -3746,57 +3753,57 @@ is-regex@^1.1.4: is-set@^2.0.2, is-set@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz" integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz" integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== dependencies: call-bind "^1.0.7" is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: has-symbols "^1.0.2" is-typed-array@^1.1.13: version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== dependencies: which-typed-array "^1.1.14" is-weakmap@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz" integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== is-weakref@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: call-bind "^1.0.2" is-weakset@^2.0.3: version "2.0.3" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" + resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz" integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== dependencies: call-bind "^1.0.7" @@ -3804,22 +3811,22 @@ is-weakset@^2.0.3: isarray@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== istanbul-lib-instrument@^5.0.4: version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: "@babel/core" "^7.12.3" @@ -3830,7 +3837,7 @@ istanbul-lib-instrument@^5.0.4: istanbul-lib-instrument@^6.0.0: version "6.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz" integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== dependencies: "@babel/core" "^7.23.9" @@ -3841,7 +3848,7 @@ istanbul-lib-instrument@^6.0.0: istanbul-lib-report@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" @@ -3850,7 +3857,7 @@ istanbul-lib-report@^3.0.0: istanbul-lib-source-maps@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: debug "^4.1.1" @@ -3859,7 +3866,7 @@ istanbul-lib-source-maps@^4.0.0: istanbul-reports@^3.1.3: version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz" integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== dependencies: html-escaper "^2.0.0" @@ -3867,7 +3874,7 @@ istanbul-reports@^3.1.3: iterator.prototype@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + resolved "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz" integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== dependencies: define-properties "^1.2.1" @@ -3878,7 +3885,7 @@ iterator.prototype@^1.1.2: jackspeak@^2.3.5: version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz" integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== dependencies: "@isaacs/cliui" "^8.0.2" @@ -3887,7 +3894,7 @@ jackspeak@^2.3.5: jest-changed-files@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz" integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== dependencies: execa "^5.0.0" @@ -3896,7 +3903,7 @@ jest-changed-files@^29.7.0: jest-circus@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz" integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== dependencies: "@jest/environment" "^29.7.0" @@ -3922,7 +3929,7 @@ jest-circus@^29.7.0: jest-cli@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz" integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== dependencies: "@jest/core" "^29.7.0" @@ -3939,7 +3946,7 @@ jest-cli@^29.7.0: jest-config@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + resolved "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz" integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== dependencies: "@babel/core" "^7.11.6" @@ -3967,7 +3974,7 @@ jest-config@^29.7.0: jest-diff@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz" integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== dependencies: chalk "^4.0.0" @@ -3977,14 +3984,14 @@ jest-diff@^29.7.0: jest-docblock@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz" integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== dependencies: detect-newline "^3.0.0" jest-each@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + resolved "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz" integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== dependencies: "@jest/types" "^29.6.3" @@ -3995,7 +4002,7 @@ jest-each@^29.7.0: jest-environment-jsdom@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f" + resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz" integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== dependencies: "@jest/environment" "^29.7.0" @@ -4009,7 +4016,7 @@ jest-environment-jsdom@^29.7.0: jest-environment-node@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== dependencies: "@jest/environment" "^29.7.0" @@ -4021,12 +4028,12 @@ jest-environment-node@^29.7.0: jest-get-type@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== jest-haste-map@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz" integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== dependencies: "@jest/types" "^29.6.3" @@ -4045,7 +4052,7 @@ jest-haste-map@^29.7.0: jest-leak-detector@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz" integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== dependencies: jest-get-type "^29.6.3" @@ -4053,7 +4060,7 @@ jest-leak-detector@^29.7.0: jest-matcher-utils@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz" integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== dependencies: chalk "^4.0.0" @@ -4063,7 +4070,7 @@ jest-matcher-utils@^29.7.0: jest-message-util@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== dependencies: "@babel/code-frame" "^7.12.13" @@ -4078,7 +4085,7 @@ jest-message-util@^29.7.0: jest-mock@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== dependencies: "@jest/types" "^29.6.3" @@ -4087,17 +4094,17 @@ jest-mock@^29.7.0: jest-pnp-resolver@^1.2.2: version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== jest-regex-util@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz" integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== jest-resolve-dependencies@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz" integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== dependencies: jest-regex-util "^29.6.3" @@ -4105,7 +4112,7 @@ jest-resolve-dependencies@^29.7.0: jest-resolve@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== dependencies: chalk "^4.0.0" @@ -4120,7 +4127,7 @@ jest-resolve@^29.7.0: jest-runner@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz" integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== dependencies: "@jest/console" "^29.7.0" @@ -4147,7 +4154,7 @@ jest-runner@^29.7.0: jest-runtime@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz" integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== dependencies: "@jest/environment" "^29.7.0" @@ -4175,7 +4182,7 @@ jest-runtime@^29.7.0: jest-snapshot@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz" integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== dependencies: "@babel/core" "^7.11.6" @@ -4201,7 +4208,7 @@ jest-snapshot@^29.7.0: jest-util@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== dependencies: "@jest/types" "^29.6.3" @@ -4213,7 +4220,7 @@ jest-util@^29.7.0: jest-validate@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== dependencies: "@jest/types" "^29.6.3" @@ -4225,7 +4232,7 @@ jest-validate@^29.7.0: jest-watcher@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz" integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== dependencies: "@jest/test-result" "^29.7.0" @@ -4239,7 +4246,7 @@ jest-watcher@^29.7.0: jest-worker@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== dependencies: "@types/node" "*" @@ -4249,7 +4256,7 @@ jest-worker@^29.7.0: jest@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + resolved "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz" integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: "@jest/core" "^29.7.0" @@ -4259,17 +4266,17 @@ jest@^29.7.0: js-sha3@0.8.0: version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" @@ -4277,14 +4284,14 @@ js-yaml@^3.13.1: js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsdom@^20.0.0: version "20.0.3" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db" + resolved "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz" integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== dependencies: abab "^2.0.6" @@ -4316,51 +4323,51 @@ jsdom@^20.0.0: jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== json-buffer@3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json2mq@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a" + resolved "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz" integrity sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA== dependencies: string-convert "^0.2.0" json5@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" json5@^2.2.3: version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz" integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== dependencies: array-includes "^3.1.6" @@ -4370,36 +4377,36 @@ json5@^2.2.3: keyv@^4.5.3: version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" kleur@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== language-subtag-registry@^0.3.20: version "0.3.23" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz" integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== language-tags@^1.0.9: version "1.0.9" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" + resolved "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz" integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== dependencies: language-subtag-registry "^0.3.20" leven@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== levn@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" @@ -4407,94 +4414,94 @@ levn@^0.4.1: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lodash@^4.17.21: version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lru-cache@^10.2.0: version "10.2.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz" integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" lz-string@^1.5.0: version "1.5.0" - resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== make-dir@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== dependencies: semver "^7.5.3" make-error@^1.1.1: version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== makeerror@1.0.12: version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: tmpl "1.0.5" merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz" integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: braces "^3.0.3" @@ -4502,90 +4509,97 @@ micromatch@^4.0.4: mime-db@1.52.0: version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12: version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== min-indent@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + resolved "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== minimatch@9.0.3: version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz" integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== dependencies: brace-expansion "^2.0.1" minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.1, minimatch@^9.0.4: +minimatch@^9.0.1: version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz" integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== "minipass@^5.0.0 || ^6.0.2 || ^7.0.0": version "7.1.1" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.1.tgz#f7f85aff59aa22f110b20e27692465cf3bf89481" + resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz" integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA== ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@^2.1.1: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== nanoid@^3.3.6, nanoid@^3.3.7: version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== next@^14.2.3: version "14.2.3" - resolved "https://registry.yarnpkg.com/next/-/next-14.2.3.tgz#f117dd5d5f20c307e7b8e4f9c1c97d961008925d" + resolved "https://registry.npmjs.org/next/-/next-14.2.3.tgz" integrity sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A== dependencies: "@next/env" "14.2.3" @@ -4608,51 +4622,51 @@ next@^14.2.3: node-fetch@^2.6.12: version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" node-int64@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-releases@^2.0.14: version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== npm-run-path@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" nwsapi@^2.2.2: version "2.2.10" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.10.tgz#0b77a68e21a0b483db70b11fad055906e867cda8" + resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz" integrity sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ== object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.13.1: version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-is@^1.1.5: version "1.1.6" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz" integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== dependencies: call-bind "^1.0.7" @@ -4660,12 +4674,12 @@ object-is@^1.1.5: object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.4, object.assign@^4.1.5: version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz" integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: call-bind "^1.0.5" @@ -4675,7 +4689,7 @@ object.assign@^4.1.4, object.assign@^4.1.5: object.entries@^1.1.7: version "1.1.8" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" + resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz" integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== dependencies: call-bind "^1.0.7" @@ -4684,7 +4698,7 @@ object.entries@^1.1.7: object.fromentries@^2.0.7: version "2.0.8" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz" integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== dependencies: call-bind "^1.0.7" @@ -4694,7 +4708,7 @@ object.fromentries@^2.0.7: object.groupby@^1.0.1: version "1.0.3" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" + resolved "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz" integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== dependencies: call-bind "^1.0.7" @@ -4703,7 +4717,7 @@ object.groupby@^1.0.1: object.hasown@^1.1.3: version "1.1.4" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" + resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz" integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== dependencies: define-properties "^1.2.1" @@ -4712,7 +4726,7 @@ object.hasown@^1.1.3: object.values@^1.1.6, object.values@^1.1.7: version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz" integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== dependencies: call-bind "^1.0.7" @@ -4721,21 +4735,21 @@ object.values@^1.1.6, object.values@^1.1.7: once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" onetime@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" optionator@^0.9.3: version "0.9.4" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== dependencies: deep-is "^0.1.3" @@ -4747,47 +4761,47 @@ optionator@^0.9.3: p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-json@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -4797,34 +4811,34 @@ parse-json@^5.2.0: parse5@^7.0.0, parse5@^7.1.1: version "7.1.2" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + resolved "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz" integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== dependencies: entities "^4.4.0" path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-scurry@^1.10.1: version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: lru-cache "^10.2.0" @@ -4832,44 +4846,44 @@ path-scurry@^1.10.1: path-type@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz" integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pirates@^4.0.4: version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" possible-typed-array-names@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== postcss-value-parser@^4.0.2: version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== postcss@8.4.31: version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== dependencies: nanoid "^3.3.6" @@ -4878,7 +4892,7 @@ postcss@8.4.31: postcss@8.4.38: version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz" integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== dependencies: nanoid "^3.3.7" @@ -4887,24 +4901,24 @@ postcss@8.4.38: prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== dependencies: fast-diff "^1.1.2" prettier@^3.2.5: version "3.2.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + resolved "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz" integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== pretty-format@^27.0.2: version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz" integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== dependencies: ansi-regex "^5.0.1" @@ -4913,7 +4927,7 @@ pretty-format@^27.0.2: pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== dependencies: "@jest/schemas" "^29.6.3" @@ -4922,7 +4936,7 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: prompts@^2.0.1: version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== dependencies: kleur "^3.0.3" @@ -4930,46 +4944,51 @@ prompts@^2.0.1: prop-types@^15.8.1: version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" object-assign "^4.1.1" react-is "^16.13.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + psl@^1.1.33: version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + resolved "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== punycode@^2.1.0, punycode@^2.1.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== pure-rand@^6.0.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== qrcode.react@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-3.1.0.tgz#5c91ddc0340f768316fbdb8fff2765134c2aecd8" + resolved "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz" integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q== querystringify@^2.1.1: version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== rc-cascader@~3.26.0: version "3.26.0" - resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.26.0.tgz#1bcc9c29451047dc99e28fdd125c94828d7ddf76" + resolved "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.26.0.tgz" integrity sha512-L1dml383TPSJD1I11YwxuVbmqaJY64psZqFp1ETlgl3LEOwDu76Cyl11fw5dmjJhMlUWwM5dECQfqJgfebhUjg== dependencies: "@babel/runtime" "^7.12.5" @@ -4981,7 +5000,7 @@ rc-cascader@~3.26.0: rc-checkbox@~3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/rc-checkbox/-/rc-checkbox-3.3.0.tgz#0ffcb65ab78c7d2fcd1a0d6554af36786516bd02" + resolved "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.3.0.tgz" integrity sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw== dependencies: "@babel/runtime" "^7.10.1" @@ -4990,7 +5009,7 @@ rc-checkbox@~3.3.0: rc-collapse@~3.7.3: version "3.7.3" - resolved "https://registry.yarnpkg.com/rc-collapse/-/rc-collapse-3.7.3.tgz#68161683d8fd1004bef4eb281fc106f3c8dc16eb" + resolved "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.3.tgz" integrity sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw== dependencies: "@babel/runtime" "^7.10.1" @@ -5000,7 +5019,7 @@ rc-collapse@~3.7.3: rc-dialog@~9.4.0: version "9.4.0" - resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-9.4.0.tgz#194c107d34cb36a56f1db4a49dc73f6d59eeae85" + resolved "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.4.0.tgz" integrity sha512-AScCexaLACvf8KZRqCPz12BJ8olszXOS4lKlkMyzDQHS1m0zj1KZMYgmMCh39ee0Dcv8kyrj8mTqxuLyhH+QuQ== dependencies: "@babel/runtime" "^7.10.1" @@ -5011,7 +5030,7 @@ rc-dialog@~9.4.0: rc-drawer@~7.1.0: version "7.1.0" - resolved "https://registry.yarnpkg.com/rc-drawer/-/rc-drawer-7.1.0.tgz#2beabb8bab1784aea255d0d850bc206c3dc715da" + resolved "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.1.0.tgz" integrity sha512-nBE1rF5iZvpavoyqhSSz2mk/yANltA7g3aF0U45xkx381n3we/RKs9cJfNKp9mSWCedOKWt9FLEwZDaAaOGn2w== dependencies: "@babel/runtime" "^7.23.9" @@ -5022,7 +5041,7 @@ rc-drawer@~7.1.0: rc-dropdown@~4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-4.2.0.tgz#c6052fcfe9c701487b141e411cdc277dc7c6f061" + resolved "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz" integrity sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng== dependencies: "@babel/runtime" "^7.18.3" @@ -5032,7 +5051,7 @@ rc-dropdown@~4.2.0: rc-field-form@~2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/rc-field-form/-/rc-field-form-2.0.1.tgz#97dc352f3899e9617f2abfd0c09bf0fcd17409e2" + resolved "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.0.1.tgz" integrity sha512-3WK/POHBcfMFKrzScrkmgMIXqoVQ0KgVwcVnej/ukwuQG4ZHCJaTi2KhM+tWTK4WODBXbmjKg5pKHj2IVmSg4A== dependencies: "@babel/runtime" "^7.18.0" @@ -5041,7 +5060,7 @@ rc-field-form@~2.0.1: rc-image@~7.6.0: version "7.6.0" - resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-7.6.0.tgz#2867087b77c8595ea9eb37d18ca863e47904b191" + resolved "https://registry.npmjs.org/rc-image/-/rc-image-7.6.0.tgz" integrity sha512-tL3Rvd1sS+frZQ01i+tkeUPaOeFz2iG9/scAt/Cfs0hyCRVA/w0Pu1J/JxIX8blalvmHE0bZQRYdOmRAzWu4Hg== dependencies: "@babel/runtime" "^7.11.2" @@ -5053,7 +5072,7 @@ rc-image@~7.6.0: rc-input-number@~9.1.0: version "9.1.0" - resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-9.1.0.tgz#fd577db284b65548c156500322a2feaa04321565" + resolved "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.1.0.tgz" integrity sha512-NqJ6i25Xn/AgYfVxynlevIhX3FuKlMwIFpucGG1h98SlK32wQwDK0zhN9VY32McOmuaqzftduNYWWooWz8pXQA== dependencies: "@babel/runtime" "^7.10.1" @@ -5064,7 +5083,7 @@ rc-input-number@~9.1.0: rc-input@~1.5.0: version "1.5.1" - resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-1.5.1.tgz#36d37eb045f1fa17de7da1a3fab94edfa331ab92" + resolved "https://registry.npmjs.org/rc-input/-/rc-input-1.5.1.tgz" integrity sha512-+nOzQJDeIfIpNP/SgY45LXSKbuMlp4Yap2y8c+ZpU7XbLmNzUd6+d5/S75sA/52jsVE6S/AkhkkDEAOjIu7i6g== dependencies: "@babel/runtime" "^7.11.1" @@ -5073,7 +5092,7 @@ rc-input@~1.5.0: rc-mentions@~2.13.1: version "2.13.1" - resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-2.13.1.tgz#14586ffa4a1ddd4079564f38abf2b4351671feca" + resolved "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.13.1.tgz" integrity sha512-DSyUDq/PPCleUX1eghIn371lTSRQsIuCs1N7xR9nZcHP9R1NkE7JjpWUP8Gy4EGVPu0JN0qIcokxYJaoGPnofg== dependencies: "@babel/runtime" "^7.22.5" @@ -5086,7 +5105,7 @@ rc-mentions@~2.13.1: rc-menu@~9.14.0: version "9.14.0" - resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-9.14.0.tgz#5e072cfc731a6dd95005d4247f02543679b0836b" + resolved "https://registry.npmjs.org/rc-menu/-/rc-menu-9.14.0.tgz" integrity sha512-La3LBCDMLMs9Q/8mTGbnscb+ZeJ26ebkLz9xJFHd2SD8vfsCKl1Z/k3mwbxyKL01lB40fel1s9Nn9LAv/nmVJQ== dependencies: "@babel/runtime" "^7.10.1" @@ -5098,7 +5117,7 @@ rc-menu@~9.14.0: rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.1, rc-motion@^2.6.2, rc-motion@^2.9.0, rc-motion@^2.9.1: version "2.9.1" - resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.1.tgz#5b405437f9f673ed1a59b6b797c2227c2d6b3d91" + resolved "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.1.tgz" integrity sha512-QD4bUqByjVQs7PhUT1d4bNxvtTcK9ETwtg7psbDfo6TmYalH/1hhjj4r2hbhW7g5OOEqYHhfwfj4noIvuOVRtQ== dependencies: "@babel/runtime" "^7.11.1" @@ -5107,7 +5126,7 @@ rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motio rc-notification@~5.4.0: version "5.4.0" - resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-5.4.0.tgz#c5ea20bfe4ed2dbacc7ef945777626c050945db8" + resolved "https://registry.npmjs.org/rc-notification/-/rc-notification-5.4.0.tgz" integrity sha512-li19y9RoYJciF3WRFvD+DvWS70jdL8Fr+Gfb/OshK+iY6iTkwzoigmSIp76/kWh5tF5i/i9im12X3nsF85GYdA== dependencies: "@babel/runtime" "^7.10.1" @@ -5117,7 +5136,7 @@ rc-notification@~5.4.0: rc-overflow@^1.3.1, rc-overflow@^1.3.2: version "1.3.2" - resolved "https://registry.yarnpkg.com/rc-overflow/-/rc-overflow-1.3.2.tgz#72ee49e85a1308d8d4e3bd53285dc1f3e0bcce2c" + resolved "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz" integrity sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw== dependencies: "@babel/runtime" "^7.11.1" @@ -5127,7 +5146,7 @@ rc-overflow@^1.3.1, rc-overflow@^1.3.2: rc-pagination@~4.0.4: version "4.0.4" - resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-4.0.4.tgz#ea401388ae86eac17ed5b41212d487f12b65b773" + resolved "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.0.4.tgz" integrity sha512-GGrLT4NgG6wgJpT/hHIpL9nELv27A1XbSZzECIuQBQTVSf4xGKxWr6I/jhpRPauYEWEbWVw22ObG6tJQqwJqWQ== dependencies: "@babel/runtime" "^7.10.1" @@ -5136,7 +5155,7 @@ rc-pagination@~4.0.4: rc-picker@~4.5.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/rc-picker/-/rc-picker-4.5.0.tgz#ae7a028ed6184e0ef40a2c8aaeb9d5dbef89d4b8" + resolved "https://registry.npmjs.org/rc-picker/-/rc-picker-4.5.0.tgz" integrity sha512-suqz9bzuhBQlf7u+bZd1bJLPzhXpk12w6AjQ9BTPTiFwexVZgUKViG1KNLyfFvW6tCUZZK0HmCCX7JAyM+JnCg== dependencies: "@babel/runtime" "^7.10.1" @@ -5148,7 +5167,7 @@ rc-picker@~4.5.0: rc-progress@~4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/rc-progress/-/rc-progress-4.0.0.tgz#5382147d9add33d3a5fbd264001373df6440e126" + resolved "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz" integrity sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw== dependencies: "@babel/runtime" "^7.10.1" @@ -5157,7 +5176,7 @@ rc-progress@~4.0.0: rc-rate@~2.12.0: version "2.12.0" - resolved "https://registry.yarnpkg.com/rc-rate/-/rc-rate-2.12.0.tgz#0182deffed3b009cdcc61660da8746c39ed91ed5" + resolved "https://registry.npmjs.org/rc-rate/-/rc-rate-2.12.0.tgz" integrity sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg== dependencies: "@babel/runtime" "^7.10.1" @@ -5166,7 +5185,7 @@ rc-rate@~2.12.0: rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.3.1, rc-resize-observer@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz#7bba61e6b3c604834980647cce6451914750d0cc" + resolved "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz" integrity sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q== dependencies: "@babel/runtime" "^7.20.7" @@ -5176,7 +5195,7 @@ rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.3.1, rc-segmented@~2.3.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/rc-segmented/-/rc-segmented-2.3.0.tgz#b3fe080fb434a266c02e30bb62a47d2c6e094341" + resolved "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.3.0.tgz" integrity sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg== dependencies: "@babel/runtime" "^7.11.1" @@ -5186,7 +5205,7 @@ rc-segmented@~2.3.0: rc-select@~14.14.0: version "14.14.0" - resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.14.0.tgz#110771fad72496843b245236bcb0007553b9fe0d" + resolved "https://registry.npmjs.org/rc-select/-/rc-select-14.14.0.tgz" integrity sha512-Uo2wulrjoPPRLCPd7zlK4ZFVJxlTN//yp1xWP/U+TUOQCyXrT+Duvq/Si5OzVcmQyWAUSbsplc2OwNNhvbOeKQ== dependencies: "@babel/runtime" "^7.10.1" @@ -5199,7 +5218,7 @@ rc-select@~14.14.0: rc-slider@~10.6.2: version "10.6.2" - resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-10.6.2.tgz#8bd3b63b24f2f3682ea1bf86d021073189cf33eb" + resolved "https://registry.npmjs.org/rc-slider/-/rc-slider-10.6.2.tgz" integrity sha512-FjkoFjyvUQWcBo1F3RgSglky3ar0+qHLM41PlFVYB4Bj3RD8E/Mv7kqMouLFBU+3aFglMzzctAIWRwajEuueSw== dependencies: "@babel/runtime" "^7.10.1" @@ -5208,7 +5227,7 @@ rc-slider@~10.6.2: rc-steps@~6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/rc-steps/-/rc-steps-6.0.1.tgz#c2136cd0087733f6d509209a84a5c80dc29a274d" + resolved "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz" integrity sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g== dependencies: "@babel/runtime" "^7.16.7" @@ -5217,7 +5236,7 @@ rc-steps@~6.0.1: rc-switch@~4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/rc-switch/-/rc-switch-4.1.0.tgz#f37d81b4e0c5afd1274fd85367b17306bf25e7d7" + resolved "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz" integrity sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg== dependencies: "@babel/runtime" "^7.21.0" @@ -5226,7 +5245,7 @@ rc-switch@~4.1.0: rc-table@~7.45.6: version "7.45.6" - resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.45.6.tgz#53286fc08cd18f0be704de76fdbf19d1de7749da" + resolved "https://registry.npmjs.org/rc-table/-/rc-table-7.45.6.tgz" integrity sha512-FYsTya3RQzLYct+o3fqHIZQIwrmsvrvhTg/I6hzlJZ1XoVAGoTmgkN1mMilVlYgksZTey9BCNYh94c6yhdjTXQ== dependencies: "@babel/runtime" "^7.10.1" @@ -5238,7 +5257,7 @@ rc-table@~7.45.6: rc-tabs@~15.1.0: version "15.1.0" - resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-15.1.0.tgz#6f6addf3ec4d0815f9f05d1317b47a579838e92f" + resolved "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.1.0.tgz" integrity sha512-xTNz4Km1025emtkv1q7xKhjPwAtXr/wycuXVTAcFJg+DKhnPDDbnwbA9KRW0SawAVOGvVEj8ZrBlU0u0FGLrbg== dependencies: "@babel/runtime" "^7.11.2" @@ -5251,7 +5270,7 @@ rc-tabs@~15.1.0: rc-textarea@~1.7.0: version "1.7.0" - resolved "https://registry.yarnpkg.com/rc-textarea/-/rc-textarea-1.7.0.tgz#115c421359dddee58c601008ec2209b41cb8f8df" + resolved "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.7.0.tgz" integrity sha512-UxizYJkWkmxP3zofXgc487QiGyDmhhheDLLjIWbFtDmiru1ls30KpO8odDaPyqNUIy9ugj5djxTEuezIn6t3Jg== dependencies: "@babel/runtime" "^7.10.1" @@ -5262,7 +5281,7 @@ rc-textarea@~1.7.0: rc-tooltip@~6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-6.2.0.tgz#4dd7575674137a5b14f118a5c16435d3f5e4a9c9" + resolved "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.0.tgz" integrity sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw== dependencies: "@babel/runtime" "^7.11.2" @@ -5271,7 +5290,7 @@ rc-tooltip@~6.2.0: rc-tree-select@~5.21.0: version "5.21.0" - resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-5.21.0.tgz#4ff94d5c28cba9810c4970d1f12ab7248c3b6e55" + resolved "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.21.0.tgz" integrity sha512-w+9qEu6zh0G3wt9N/hzWNSnqYH1i9mH1Nqxo0caxLRRFXF5yZWYmpCDoDTMdQM1Y4z3Q5yj08qyrPH/d4AtumA== dependencies: "@babel/runtime" "^7.10.1" @@ -5282,7 +5301,7 @@ rc-tree-select@~5.21.0: rc-tree@~5.8.1, rc-tree@~5.8.7: version "5.8.7" - resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-5.8.7.tgz#79fe560eca8a998a5cd866cdf374ffc3643754f1" + resolved "https://registry.npmjs.org/rc-tree/-/rc-tree-5.8.7.tgz" integrity sha512-cpsIQZ4nNYwpj6cqPRt52e/69URuNdgQF9wZ10InmEf8W3+i0A41OVmZWwHuX9gegQSqj+DPmaDkZFKQZ+ZV1w== dependencies: "@babel/runtime" "^7.10.1" @@ -5293,7 +5312,7 @@ rc-tree@~5.8.1, rc-tree@~5.8.7: rc-upload@~4.5.2: version "4.5.2" - resolved "https://registry.yarnpkg.com/rc-upload/-/rc-upload-4.5.2.tgz#ea493fbaaf57d9369ee954b20e1d8bc35c818a1a" + resolved "https://registry.npmjs.org/rc-upload/-/rc-upload-4.5.2.tgz" integrity sha512-QO3ne77DwnAPKFn0bA5qJM81QBjQi0e0NHdkvpFyY73Bea2NfITiotqJqVjHgeYPOJu5lLVR32TNGP084aSoXA== dependencies: "@babel/runtime" "^7.18.3" @@ -5302,7 +5321,7 @@ rc-upload@~4.5.2: rc-util@^5.0.1, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2.0, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.24.4, rc-util@^5.25.2, rc-util@^5.27.0, rc-util@^5.30.0, rc-util@^5.31.1, rc-util@^5.32.2, rc-util@^5.34.1, rc-util@^5.35.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.38.1, rc-util@^5.39.3, rc-util@^5.40.1: version "5.41.0" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.41.0.tgz#b1ba000d4f3a9e72563370a3243b59f89b40e1bd" + resolved "https://registry.npmjs.org/rc-util/-/rc-util-5.41.0.tgz" integrity sha512-xtlCim9RpmVv0Ar2Nnc3WfJCxjQkTf3xHPWoFdjp1fSs2NirQwqiQrfqdU9HUe0kdfb168M/T8Dq0IaX50xeKg== dependencies: "@babel/runtime" "^7.18.3" @@ -5310,7 +5329,7 @@ rc-util@^5.0.1, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2. rc-virtual-list@^3.11.1, rc-virtual-list@^3.5.1, rc-virtual-list@^3.5.2: version "3.14.2" - resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.14.2.tgz#8ffee57100eab1eeae8df6a67bf75d0b7fd176cc" + resolved "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.14.2.tgz" integrity sha512-rA+W5xryhklJAcmswNyuKB3ZGeB855io+yOFQK5u/RXhjdshGblfKpNkQr4/9fBhZns0+uiL/0/s6IP2krtSmg== dependencies: "@babel/runtime" "^7.20.0" @@ -5320,7 +5339,7 @@ rc-virtual-list@^3.11.1, rc-virtual-list@^3.5.1, rc-virtual-list@^3.5.2: react-canvas-confetti@1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/react-canvas-confetti/-/react-canvas-confetti-1.2.1.tgz#22ac64cbc478cf57cb5f61c130322e359b35389d" + resolved "https://registry.npmjs.org/react-canvas-confetti/-/react-canvas-confetti-1.2.1.tgz" integrity sha512-onNjQNkhQjrB2JVCeRpJW7o8VlBNJvo3Eht9zlQlofNLVvvOd1+PzBLU5Ev8n5sFBkTbKJmIUVG0eZnkAl5cpg== dependencies: "@types/canvas-confetti" "1.4.0" @@ -5328,7 +5347,7 @@ react-canvas-confetti@1.2.1: react-dom@^18.3.1: version "18.3.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" @@ -5336,36 +5355,36 @@ react-dom@^18.3.1: react-is@^16.13.1: version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-is@^17.0.1: version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== react-is@^18.0.0, react-is@^18.2.0: version "18.3.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== react@^18.3.1: version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" redent@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + resolved "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz" integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== dependencies: indent-string "^4.0.0" @@ -5373,7 +5392,7 @@ redent@^3.0.0: reflect.getprototypeof@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" + resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz" integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== dependencies: call-bind "^1.0.7" @@ -5386,12 +5405,12 @@ reflect.getprototypeof@^1.0.4: regenerator-runtime@^0.14.0: version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz" integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== dependencies: call-bind "^1.0.6" @@ -5401,49 +5420,49 @@ regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== requires-port@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== resize-observer-polyfill@^1.5.1: version "1.5.1" - resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve-pkg-maps@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== resolve.exports@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== resolve@^1.20.0, resolve@^1.22.4: version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: is-core-module "^2.13.0" @@ -5452,7 +5471,7 @@ resolve@^1.20.0, resolve@^1.22.4: resolve@^2.0.0-next.5: version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz" integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: is-core-module "^2.13.0" @@ -5461,26 +5480,26 @@ resolve@^2.0.0-next.5: reusify@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" safe-array-concat@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz" integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== dependencies: call-bind "^1.0.7" @@ -5490,7 +5509,7 @@ safe-array-concat@^1.1.2: safe-regex-test@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz" integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== dependencies: call-bind "^1.0.6" @@ -5499,12 +5518,12 @@ safe-regex-test@^1.0.3: "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sass@^1.72.0: version "1.77.2" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.2.tgz#18d4ed2eefc260cdc8099c5439ec1303fd5863aa" + resolved "https://registry.npmjs.org/sass/-/sass-1.77.2.tgz" integrity sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA== dependencies: chokidar ">=3.0.0 <4.0.0" @@ -5513,48 +5532,43 @@ sass@^1.72.0: saxes@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + resolved "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz" integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== dependencies: xmlchars "^2.2.0" scheduler@^0.23.2: version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz" integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" scroll-into-view-if-needed@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz#fa9524518c799b45a2ef6bbffb92bcad0296d01f" + resolved "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz" integrity sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ== dependencies: compute-scroll-into-view "^3.0.2" scrypt-js@3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== semver@^6.3.0, semver@^6.3.1: version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -semver@^7.6.3: +semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== set-function-length@^1.2.1: version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== dependencies: define-data-property "^1.1.4" @@ -5566,7 +5580,7 @@ set-function-length@^1.2.1: set-function-name@^2.0.1, set-function-name@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== dependencies: define-data-property "^1.1.4" @@ -5576,24 +5590,24 @@ set-function-name@^2.0.1, set-function-name@^2.0.2: shallowequal@1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== side-channel@^1.0.4, side-channel@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz" integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: call-bind "^1.0.7" @@ -5603,32 +5617,32 @@ side-channel@^1.0.4, side-channel@^1.0.6: signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signal-exit@^4.0.1: version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== sisteransi@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== slash@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== source-map-support@0.5.13: version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== dependencies: buffer-from "^1.0.0" @@ -5636,50 +5650,58 @@ source-map-support@0.5.13: source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stack-utils@^2.0.3: version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" stop-iteration-iterator@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" + resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz" integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== dependencies: internal-slot "^1.0.4" streamsearch@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== string-convert@^0.2.0: version "0.2.1" - resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" + resolved "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz" integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A== string-length@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== dependencies: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - name string-width-cjs +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -5688,7 +5710,7 @@ string-length@^4.0.1: string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: eastasianwidth "^0.2.0" @@ -5697,7 +5719,7 @@ string-width@^5.0.1, string-width@^5.1.2: string.prototype.matchall@^4.0.10: version "4.0.11" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" + resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz" integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== dependencies: call-bind "^1.0.7" @@ -5715,7 +5737,7 @@ string.prototype.matchall@^4.0.10: string.prototype.trim@^1.2.9: version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz" integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== dependencies: call-bind "^1.0.7" @@ -5725,7 +5747,7 @@ string.prototype.trim@^1.2.9: string.prototype.trimend@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz" integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== dependencies: call-bind "^1.0.7" @@ -5734,57 +5756,64 @@ string.prototype.trimend@^1.0.8: string.prototype.trimstart@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz" integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== dependencies: call-bind "^1.0.7" define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-ansi@^7.0.1: version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: ansi-regex "^6.0.1" strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== strip-indent@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz" integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== dependencies: min-indent "^1.0.0" strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== styled-components@^6.1.8: version "6.1.11" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-6.1.11.tgz#01948e5195bf1d39e57e0a85b41958c80e40cfb8" + resolved "https://registry.npmjs.org/styled-components/-/styled-components-6.1.11.tgz" integrity sha512-Ui0jXPzbp1phYij90h12ksljKGqF8ncGx+pjrNPsSPhbUUjWT2tD1FwGo2LF6USCnbrsIhNngDfodhxbegfEOA== dependencies: "@emotion/is-prop-valid" "1.2.2" @@ -5799,50 +5828,50 @@ styled-components@^6.1.8: styled-jsx@5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" + resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz" integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== dependencies: client-only "0.0.1" stylis@4.3.2, stylis@^4.0.13: version "4.3.2" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" + resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz" integrity sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg== supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-color@^8.0.0: version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== symbol-tree@^3.2.4: version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== synckit@^0.8.6: version "0.8.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" + resolved "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz" integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== dependencies: "@pkgr/core" "^0.1.0" @@ -5850,12 +5879,12 @@ synckit@^0.8.6: tapable@^2.2.0: version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" @@ -5864,39 +5893,39 @@ test-exclude@^6.0.0: text-table@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== throttle-debounce@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz#a17a4039e82a2ed38a5e7268e4132d6960d41933" + resolved "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz" integrity sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg== tmpl@1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" toggle-selection@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz" integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== tough-cookie@^4.1.2: version "4.1.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz" integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== dependencies: psl "^1.1.33" @@ -5906,24 +5935,24 @@ tough-cookie@^4.1.2: tr46@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + resolved "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz" integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== dependencies: punycode "^2.1.1" tr46@~0.0.3: version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== ts-node@^10.9.2: version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== dependencies: "@cspotcode/source-map-support" "^0.8.0" @@ -5942,7 +5971,7 @@ ts-node@^10.9.2: tsconfig-paths@^3.15.0: version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz" integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: "@types/json5" "^0.0.29" @@ -5952,46 +5981,46 @@ tsconfig-paths@^3.15.0: tslib@2.6.2, tslib@^2.4.0, tslib@^2.6.2: version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== tslib@^1.8.1: version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-detect@4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== typed-array-buffer@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz" integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== dependencies: call-bind "^1.0.7" @@ -6000,7 +6029,7 @@ typed-array-buffer@^1.0.2: typed-array-byte-length@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz" integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== dependencies: call-bind "^1.0.7" @@ -6011,7 +6040,7 @@ typed-array-byte-length@^1.0.1: typed-array-byte-offset@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz" integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== dependencies: available-typed-arrays "^1.0.7" @@ -6023,7 +6052,7 @@ typed-array-byte-offset@^1.0.2: typed-array-length@^1.0.6: version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz" integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== dependencies: call-bind "^1.0.7" @@ -6033,14 +6062,14 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -typescript@5.5.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa" - integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ== +typescript@5.3.x: + version "5.3.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== unbox-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: call-bind "^1.0.2" @@ -6050,17 +6079,17 @@ unbox-primitive@^1.0.2: undici-types@~5.26.4: version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== universalify@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== update-browserslist-db@^1.0.13: version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz" integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== dependencies: escalade "^3.1.2" @@ -6068,14 +6097,14 @@ update-browserslist-db@^1.0.13: uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" url-parse@^1.5.3: version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" @@ -6083,19 +6112,19 @@ url-parse@^1.5.3: usehooks-ts@^2.14.0: version "2.16.0" - resolved "https://registry.yarnpkg.com/usehooks-ts/-/usehooks-ts-2.16.0.tgz#31deaa2f1147f65666aae925bd890b54e63b0d3f" + resolved "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.16.0.tgz" integrity sha512-bez95WqYujxp6hFdM/CpRDiVPirZPxlMzOH2QB8yopoKQMXpscyZoxOjpEdaxvV+CAWUDSM62cWnqHE0E/MZ7w== dependencies: lodash.debounce "^4.0.8" v8-compile-cache-lib@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== v8-to-istanbul@^9.0.1: version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz" integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" @@ -6104,43 +6133,43 @@ v8-to-istanbul@^9.0.1: w3c-xmlserializer@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" + resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz" integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== dependencies: xml-name-validator "^4.0.0" walker@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: makeerror "1.0.12" webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== webidl-conversions@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== whatwg-encoding@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz" integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== dependencies: iconv-lite "0.6.3" whatwg-mimetype@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== whatwg-url@^11.0.0: version "11.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz" integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== dependencies: tr46 "^3.0.0" @@ -6148,7 +6177,7 @@ whatwg-url@^11.0.0: whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" @@ -6156,7 +6185,7 @@ whatwg-url@^5.0.0: which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== dependencies: is-bigint "^1.0.1" @@ -6167,7 +6196,7 @@ which-boxed-primitive@^1.0.2: which-builtin-type@^1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + resolved "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz" integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== dependencies: function.prototype.name "^1.1.5" @@ -6185,7 +6214,7 @@ which-builtin-type@^1.1.3: which-collection@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz" integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== dependencies: is-map "^2.0.3" @@ -6195,7 +6224,7 @@ which-collection@^1.0.1: which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== dependencies: available-typed-arrays "^1.0.7" @@ -6206,20 +6235,28 @@ which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15, which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" word-wrap@^1.2.5: version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -6228,7 +6265,7 @@ word-wrap@^1.2.5: wrap-ansi@^8.1.0: version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: ansi-styles "^6.1.0" @@ -6237,12 +6274,12 @@ wrap-ansi@^8.1.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^4.0.2: version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== dependencies: imurmurhash "^0.1.4" @@ -6250,42 +6287,42 @@ write-file-atomic@^4.0.2: ws@7.4.6: version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== ws@^8.11.0: version "8.17.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" + resolved "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz" integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== xml-name-validator@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz" integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== xmlchars@^2.2.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^3.0.2: version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^17.3.1: version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -6298,15 +6335,15 @@ yargs@^17.3.1: yn@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== zod@^3.23.8: version "3.23.8" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" + resolved "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz" integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== diff --git a/operate/cli.py b/operate/cli.py index e8fab9015..6526e3462 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -42,8 +42,7 @@ from operate import services from operate.account.user import UserAccount from operate.constants import KEY, KEYS, OPERATE, SERVICES -from operate.ledger import get_ledger_type_from_chain_type -from operate.operate_types import ChainType, DeploymentStatus +from operate.operate_types import Chain, DeploymentStatus, LedgerType from operate.services.health_checker import HealthChecker from operate.wallet.master import MasterWalletManager @@ -57,10 +56,10 @@ ) -def service_not_found_error(service: str) -> JSONResponse: +def service_not_found_error(service_config_id: str) -> JSONResponse: """Service not found error response""" return JSONResponse( - content={"error": f"Service {service} not found"}, status_code=404 + content={"error": f"Service {service_config_id} not found"}, status_code=404 ) @@ -152,8 +151,19 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st logger = setup_logger(name="operate") if HEALTH_CHECKER_OFF: - logger.warning("healthchecker is off!!!") + logger.warning("Healthchecker is off!!!") operate = OperateApp(home=home, logger=logger) + + operate.service_manager().log_directories() + logger.info("Migrating service configs...") + operate.service_manager().migrate_service_configs() + logger.info("Migrating service configs done.") + operate.service_manager().log_directories() + + logger.info("Migrating wallet configs...") + operate.wallet_manager.migrate_wallet_configs() + logger.info("Migrating wallet configs done.") + funding_jobs: t.Dict[str, asyncio.Task] = {} health_checker = HealthChecker( operate.service_manager(), number_of_fails=number_of_fails @@ -175,39 +185,39 @@ async def run_in_executor(fn: t.Callable, *args: t.Any) -> t.Any: return res def schedule_funding_job( - service: str, + service_config_id: str, from_safe: bool = True, ) -> None: """Schedule a funding job.""" - logger.info(f"Starting funding job for {service}") - if service in funding_jobs: - logger.info(f"Cancelling existing funding job for {service}") - cancel_funding_job(service=service) + logger.info(f"Starting funding job for {service_config_id}") + if service_config_id in funding_jobs: + logger.info(f"Cancelling existing funding job for {service_config_id}") + cancel_funding_job(service_config_id=service_config_id) loop = asyncio.get_running_loop() - funding_jobs[service] = loop.create_task( + funding_jobs[service_config_id] = loop.create_task( operate.service_manager().funding_job( - hash=service, + service_config_id=service_config_id, loop=loop, from_safe=from_safe, ) ) def schedule_healthcheck_job( - service: str, + service_config_id: str, ) -> None: """Schedule a healthcheck job.""" if not HEALTH_CHECKER_OFF: # dont start health checker if it's switched off - health_checker.start_for_service(service) + health_checker.start_for_service(service_config_id) - def cancel_funding_job(service: str) -> None: + def cancel_funding_job(service_config_id: str) -> None: """Cancel funding job.""" - if service not in funding_jobs: + if service_config_id not in funding_jobs: return - status = funding_jobs[service].cancel() + status = funding_jobs[service_config_id].cancel() if not status: - logger.info(f"Funding job cancellation for {service} failed") + logger.info(f"Funding job cancellation for {service_config_id} failed") def pause_all_services_on_startup() -> None: logger.info("Stopping services on startup...") @@ -215,19 +225,28 @@ def pause_all_services_on_startup() -> None: logger.info("Stopping services on startup done.") def pause_all_services() -> None: - service_hashes = [i["hash"] for i in operate.service_manager().json] - - for service in service_hashes: - if not operate.service_manager().exists(service=service): + service_config_ids = [ + i["service_config_id"] for i in operate.service_manager().json + ] + + for service_config_id in service_config_ids: + logger.info(f"Stopping service {service_config_id=}") + if not operate.service_manager().exists( + service_config_id=service_config_id + ): continue - deployment = operate.service_manager().load_or_create(service).deployment + deployment = ( + operate.service_manager() + .load(service_config_id=service_config_id) + .deployment + ) if deployment.status == DeploymentStatus.DELETED: continue - logger.info(f"stopping service {service}") + logger.info(f"stopping service {service_config_id}") deployment.stop(force=True) - logger.info(f"Cancelling funding job for {service}") - cancel_funding_job(service=service) - health_checker.stop_for_service(service=service) + logger.info(f"Cancelling funding job for {service_config_id}") + cancel_funding_job(service_config_id=service_config_id) + health_checker.stop_for_service(service_config_id=service_config_id) def pause_all_services_on_exit(signum: int, frame: t.Optional[FrameType]) -> None: logger.info("Stopping services on exit...") @@ -283,12 +302,23 @@ async def _kill_server(request: Request) -> JSONResponse: """Kill backend server from inside.""" os.kill(os.getpid(), signal.SIGINT) + @app.post("/api/v2/services/stop") @app.get("/stop_all_services") async def _stop_all_services(request: Request) -> JSONResponse: """Kill backend server from inside.""" - logger.info("Stopping services on demand...") - pause_all_services() - logger.info("Stopping services on demand done.") + + # No authentication required to stop services. + + try: + logger.info("Stopping services on demand...") + pause_all_services() + logger.info("Stopping services on demand done.") + return JSONResponse(content={"message": "Services stopped."}) + except Exception as e: # pylint: disable=broad-except + return JSONResponse( + content={"error": str(e), "traceback": traceback.format_exc()}, + status_code=500, + ) @app.get("/api") @with_retries @@ -377,9 +407,7 @@ async def _get_wallets(request: Request) -> t.List[t.Dict]: @with_retries async def _get_wallet_by_chain(request: Request) -> t.List[t.Dict]: """Create wallet safe""" - ledger_type = get_ledger_type_from_chain_type( - chain=ChainType.from_string(request.path_params["chain"]) - ) + ledger_type = Chain.from_string(request.path_params["chain"]).ledger_type manager = operate.wallet_manager if not manager.exists(ledger_type=ledger_type): return JSONResponse( @@ -407,8 +435,7 @@ async def _create_wallet(request: Request) -> t.List[t.Dict]: ) data = await request.json() - chain_type = ChainType(data["chain_type"]) - ledger_type = get_ledger_type_from_chain_type(chain=chain_type) + ledger_type = LedgerType(data["ledger_type"]) manager = operate.wallet_manager if manager.exists(ledger_type=ledger_type): return JSONResponse( @@ -420,6 +447,15 @@ async def _create_wallet(request: Request) -> t.List[t.Dict]: wallet, mnemonic = manager.create(ledger_type=ledger_type) return JSONResponse(content={"wallet": wallet.json, "mnemonic": mnemonic}) + @app.get("/api/extended/wallet") + @with_retries + async def _get_wallet_safe(request: Request) -> t.List[t.Dict]: + """Get wallets.""" + wallets = [] + for wallet in operate.wallet_manager: + wallets.append(wallet.extended_json) + return JSONResponse(content=wallets) + @app.get("/api/wallet/safe") @with_retries async def _get_safes(request: Request) -> t.List[t.Dict]: @@ -436,8 +472,8 @@ async def _get_safes(request: Request) -> t.List[t.Dict]: @with_retries async def _get_safe(request: Request) -> t.List[t.Dict]: """Create wallet safe""" - chain_type = ChainType.from_string(request.path_params["chain"]) - ledger_type = get_ledger_type_from_chain_type(chain=chain_type) + chain = Chain.from_string(request.path_params["chain"]) + ledger_type = chain.ledger_type manager = operate.wallet_manager if not manager.exists(ledger_type=ledger_type): return JSONResponse( @@ -445,12 +481,12 @@ async def _get_safe(request: Request) -> t.List[t.Dict]: status_code=404, ) safes = manager.load(ledger_type=ledger_type).safes - if safes is None or safes.get(chain_type) is None: + if safes is None or safes.get(chain) is None: return JSONResponse(content={"error": "No safes found"}) return JSONResponse( content={ - "safe": safes[chain_type], + "safe": safes[chain], }, ) @@ -471,34 +507,34 @@ async def _create_safe(request: Request) -> t.List[t.Dict]: ) data = await request.json() - chain_type = ChainType(data["chain_type"]) - ledger_type = get_ledger_type_from_chain_type(chain=chain_type) + chain = Chain(data["chain"]) + ledger_type = chain.ledger_type manager = operate.wallet_manager if not manager.exists(ledger_type=ledger_type): return JSONResponse(content={"error": "Wallet does not exist"}) wallet = manager.load(ledger_type=ledger_type) - if wallet.safes is not None and wallet.safes.get(chain_type) is not None: + if wallet.safes is not None and wallet.safes.get(chain) is not None: return JSONResponse( content={ - "safe": wallet.safes.get(chain_type), - "message": "Safe already exists!", + "safe": wallet.safes.get(chain), + "message": f"Safe already exists {chain=}.", } ) - safes = t.cast(t.Dict[ChainType, str], wallet.safes) + safes = t.cast(t.Dict[Chain, str], wallet.safes) wallet.create_safe( # pylint: disable=no-member - chain_type=chain_type, - owner=data.get("owner"), + chain=chain, + backup_owner=data.get("backup_owner"), ) wallet.transfer( - to=t.cast(str, safes.get(chain_type)), + to=t.cast(str, safes.get(chain)), amount=int(1e18), - chain_type=chain_type, + chain=chain, from_safe=False, ) return JSONResponse( - content={"safe": safes.get(chain_type), "message": "Safe created!"} + content={"safe": safes.get(chain), "message": "Safe created!"} ) @app.post("/api/wallet/safes") @@ -518,304 +554,243 @@ async def _create_safes(request: Request) -> t.List[t.Dict]: ) data = await request.json() - chain_types = [ChainType(chain_type) for chain_type in data["chain_types"]] + chains = [Chain(chain_str) for chain_str in data["chains"]] # check that all chains are supported - for chain_type in chain_types: - ledger_type = get_ledger_type_from_chain_type(chain=chain_type) + for chain in chains: + ledger_type = chain.ledger_type manager = operate.wallet_manager if not manager.exists(ledger_type=ledger_type): return JSONResponse( content={ - "error": f"Wallet does not exist for chain_type {chain_type}" + "error": f"A wallet of type {ledger_type} does not exist for chain {chain}." } ) # mint the safes - for chain_type in chain_types: - ledger_type = get_ledger_type_from_chain_type(chain=chain_type) + for chain in chains: + ledger_type = chain.ledger_type manager = operate.wallet_manager wallet = manager.load(ledger_type=ledger_type) - if wallet.safes is not None and wallet.safes.get(chain_type) is not None: - logger.info(f"Safe already exists for chain_type {chain_type}") + if wallet.safes is not None and wallet.safes.get(chain) is not None: + logger.info(f"Safe already exists for chain {chain}") continue - safes = t.cast(t.Dict[ChainType, str], wallet.safes) + safes = t.cast(t.Dict[Chain, str], wallet.safes) wallet.create_safe( # pylint: disable=no-member - chain_type=chain_type, - owner=data.get("owner"), + chain=chain, + owner=data.get("backup_owner"), ) wallet.transfer( - to=t.cast(str, safes.get(chain_type)), + to=t.cast(str, safes.get(chain)), amount=int(1e18), - chain_type=chain_type, + chain=chain, from_safe=False, ) - return JSONResponse(content={"safes": safes, "message": "Safes created!"}) + return JSONResponse(content={"safes": safes, "message": "Safes created."}) @app.put("/api/wallet/safe") @with_retries async def _update_safe(request: Request) -> t.List[t.Dict]: - """Create wallet safe""" + """Update wallet safe""" # TODO: Extract login check as decorator if operate.user_account is None: return JSONResponse( - content={"error": "Cannot create safe; User account does not exist!"}, + content={"error": "Cannot update safe; User account does not exist!"}, status_code=400, ) if operate.password is None: return JSONResponse( - content={"error": "You need to login before creating a safe"}, + content={"error": "You need to login before updating a safe."}, status_code=401, ) data = await request.json() - chain_type = ChainType(data["chain_type"]) - ledger_type = get_ledger_type_from_chain_type(chain=chain_type) + + if "chain" not in data: + return JSONResponse( + content={"error": "You need to specify a chain to updae a safe."}, + status_code=401, + ) + + chain = Chain(data["chain"]) + ledger_type = chain.ledger_type manager = operate.wallet_manager if not manager.exists(ledger_type=ledger_type): - return JSONResponse(content={"error": "Wallet does not exist"}) + return JSONResponse( + content={"error": "Wallet does not exist"}, + status_code=401, + ) wallet = manager.load(ledger_type=ledger_type) - wallet.add_or_swap_owner( - chain_type=chain_type, - owner=data.get("owner"), + backup_owner_updated = wallet.update_backup_owner( + chain=chain, + backup_owner=data.get( + "backup_owner" + ), # Optional value, it's fine to provide 'None' (set no backup owner/remove backup owner) + ) + message = ( + "Backup owner updated." + if backup_owner_updated + else "No changes on backup owner. The backup owner provided matches the current one." + ) + return JSONResponse( + content={ + "wallet": wallet.json, + "chain": chain.value, + "backup_owner_updated": backup_owner_updated, + "message": message, + } ) - return JSONResponse(content=wallet.json) - @app.get("/api/services") + @app.get("/api/v2/services") @with_retries async def _get_services(request: Request) -> JSONResponse: - """Get available services.""" + """Get all services.""" return JSONResponse(content=operate.service_manager().json) - @app.post("/api/services") + @app.get("/api/v2/service/{service_config_id}") @with_retries - async def _create_services(request: Request) -> JSONResponse: - """Create a service.""" - if operate.password is None: - return USER_NOT_LOGGED_IN_ERROR - template = await request.json() - manager = operate.service_manager() - if len(manager.json) > 0: - old_hash = manager.json[0]["hash"] - if old_hash == template["hash"]: - logger.info(f'Loading service {template["hash"]}') - service = manager.load_or_create( - hash=template["hash"], - service_template=template, - ) - else: - logger.info(f"Updating service from {old_hash} to " + template["hash"]) - service = manager.update_service( - old_hash=old_hash, - new_hash=template["hash"], - service_template=template, + async def _get_service(request: Request) -> JSONResponse: + """Get a service.""" + service_config_id = request.path_params["service_config_id"] + + if not operate.service_manager().exists(service_config_id=service_config_id): + return service_not_found_error(service_config_id=service_config_id) + return JSONResponse( + content=( + operate.service_manager() + .load( + service_config_id=service_config_id, ) - else: - logger.info(f'Creating service {template["hash"]}') - service = manager.load_or_create( - hash=template["hash"], - service_template=template, + .json ) + ) - if template.get("deploy", False): - - def _fn() -> None: - # deploy_service_onchain_from_safe includes stake_service_on_chain_from_safe - manager.deploy_service_onchain_from_safe(hash=service.hash) - manager.fund_service(hash=service.hash) - - # TODO Optimus patch, chain_id="10" - chain_id = "10" - manager.deploy_service_locally(hash=service.hash, chain_id=chain_id) - - await run_in_executor(_fn) - schedule_funding_job(service=service.hash) - schedule_healthcheck_job(service=service.hash) + @app.get("/api/v2/service/{service_config_id}/deployment") + @with_retries + async def _get_service_deployment(request: Request) -> JSONResponse: + """Get a service deployment.""" + service_config_id = request.path_params["service_config_id"] + if not operate.service_manager().exists(service_config_id=service_config_id): + return service_not_found_error(service_config_id=service_config_id) return JSONResponse( - content=operate.service_manager().load_or_create(hash=service.hash).json + content=operate.service_manager() + .load( + service_config_id=service_config_id, + ) + .deployment.json ) - @app.put("/api/services") + @app.post("/api/v2/service") @with_retries - async def _update_services(request: Request) -> JSONResponse: + async def _create_services_v2(request: Request) -> JSONResponse: """Create a service.""" if operate.password is None: return USER_NOT_LOGGED_IN_ERROR template = await request.json() - service = operate.service_manager().update_service( - old_hash=template["old_service_hash"], - new_hash=template["new_service_hash"], - ) - if template.get("deploy", False): - manager = operate.service_manager() + manager = operate.service_manager() + output = manager.create(service_template=template) - # deploy_service_onchain_from_safe includes stake_service_on_chain_from_safe - manager.deploy_service_onchain_from_safe(hash=service.hash) - manager.fund_service(hash=service.hash) + return JSONResponse(content=output.json) - # TODO Optimus patch, chain_id="10" - chain_id = "10" - manager.deploy_service_locally(hash=service.hash, chain_id=chain_id) + @app.post("/api/v2/service/{service_config_id}") + @with_retries + async def _deploy_and_run_service(request: Request) -> JSONResponse: + """Deploy a service.""" + if operate.password is None: + return USER_NOT_LOGGED_IN_ERROR - schedule_funding_job(service=service.hash) - schedule_healthcheck_job(service=service.hash) + pause_all_services() + service_config_id = request.path_params["service_config_id"] + manager = operate.service_manager() - return JSONResponse(content=service.json) + if not manager.exists(service_config_id=service_config_id): + return service_not_found_error(service_config_id=service_config_id) - @app.get("/api/services/{service}") - @with_retries - async def _get_service(request: Request) -> JSONResponse: - """Create a service.""" - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) - return JSONResponse( - content=( - operate.service_manager() - .load_or_create( - hash=request.path_params["service"], - ) - .json + def _fn() -> None: + # deploy_service_onchain_from_safe includes stake_service_on_chain_from_safe + manager.deploy_service_onchain_from_safe( + service_config_id=service_config_id ) - ) + manager.fund_service(service_config_id=service_config_id) + manager.deploy_service_locally(service_config_id=service_config_id) + + await run_in_executor(_fn) + schedule_funding_job(service_config_id=service_config_id) + schedule_healthcheck_job(service_config_id=service_config_id) - # TODO this endpoint is possibly not used - @app.post("/api/services/{service}/onchain/deploy") - @with_retries - async def _deploy_service_onchain(request: Request) -> JSONResponse: - """Create a service.""" - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) - if operate.password is None: - return USER_NOT_LOGGED_IN_ERROR - operate.service_manager().deploy_service_onchain( - hash=request.path_params["service"] - ) - operate.service_manager().stake_service_on_chain( - hash=request.path_params["service"] - ) return JSONResponse( content=( - operate.service_manager() - .load_or_create(hash=request.path_params["service"]) - .json + operate.service_manager().load(service_config_id=service_config_id).json ) ) - @app.post("/api/services/{service}/onchain/stop") + @app.put("/api/v2/service/{service_config_id}") @with_retries - async def _stop_service_onchain(request: Request) -> JSONResponse: - """Create a service.""" - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) + async def _update_service(request: Request) -> JSONResponse: + """Update a service.""" if operate.password is None: return USER_NOT_LOGGED_IN_ERROR - operate.service_manager().terminate_service_on_chain( - hash=request.path_params["service"] - ) - operate.service_manager().unbond_service_on_chain( - hash=request.path_params["service"] - ) - operate.service_manager().unstake_service_on_chain( - hash=request.path_params["service"] - ) - return JSONResponse( - content=( - operate.service_manager() - .load_or_create(hash=request.path_params["service"]) - .json - ) - ) - @app.get("/api/services/{service}/deployment") - @with_retries - async def _get_service_deployment(request: Request) -> JSONResponse: - """Create a service.""" - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) - return JSONResponse( - content=operate.service_manager() - .load_or_create( - request.path_params["service"], - ) - .deployment.json - ) + service_config_id = request.path_params["service_config_id"] + manager = operate.service_manager() - @app.post("/api/services/{service}/deployment/build") - @with_retries - async def _build_service_locally(request: Request) -> JSONResponse: - """Create a service.""" - # TODO: add support for chain id. - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) - deployment = ( - operate.service_manager() - .load_or_create( - request.path_params["service"], - ) - .deployment - ) + print(service_config_id) + if not manager.exists(service_config_id=service_config_id): + return service_not_found_error(service_config_id=service_config_id) - def _fn() -> None: - deployment.build(force=True) + template = await request.json() + allow_different_service_public_id = template.get( + "allow_different_service_public_id", False + ) + output = manager.update( + service_config_id=service_config_id, + service_template=template, + allow_different_service_public_id=allow_different_service_public_id, + ) - await run_in_executor(_fn) - return JSONResponse(content=deployment.json) + return JSONResponse(content=output.json) - @app.post("/api/services/{service}/deployment/start") + @app.put("/api/v2/services") @with_retries - async def _start_service_locally(request: Request) -> JSONResponse: - """Create a service.""" - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) - service = request.path_params["service"] - manager = operate.service_manager() + async def _update_all_services(request: Request) -> JSONResponse: + """Update all services of matching the public id referenced in the hash.""" + if operate.password is None: + return USER_NOT_LOGGED_IN_ERROR - def _fn() -> None: - manager.deploy_service_onchain(hash=service) - manager.stake_service_on_chain(hash=service) - manager.fund_service(hash=service) - manager.deploy_service_locally(hash=service, force=True) + manager = operate.service_manager() + template = await request.json() + updated_services = manager.update_all_matching(service_template=template) - await run_in_executor(_fn) - schedule_funding_job(service=service) - schedule_healthcheck_job(service=service.hash) - return JSONResponse(content=manager.load_or_create(service).deployment) + return JSONResponse(content=updated_services) - @app.post("/api/services/{service}/deployment/stop") + @app.post("/api/v2/service/{service_config_id}/deployment/stop") @with_retries async def _stop_service_locally(request: Request) -> JSONResponse: - """Create a service.""" - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) - service = request.path_params["service"] - deployment = operate.service_manager().load_or_create(service).deployment - health_checker.stop_for_service(service=service) + """Stop a service deployment.""" - await run_in_executor(deployment.stop) - logger.info(f"Cancelling funding job for {service}") - cancel_funding_job(service=service) - return JSONResponse(content=deployment.json) + # No authentication required to stop services. + + service_config_id = request.path_params["service_config_id"] + manager = operate.service_manager() + + if not manager.exists(service_config_id=service_config_id): + return service_not_found_error(service_config_id=service_config_id) - @app.post("/api/services/{service}/deployment/delete") - @with_retries - async def _delete_service_locally(request: Request) -> JSONResponse: - """Create a service.""" - if not operate.service_manager().exists(service=request.path_params["service"]): - return service_not_found_error(service=request.path_params["service"]) - # TODO: Drain safe before deleting service deployment = ( operate.service_manager() - .load_or_create( - request.path_params["service"], - ) + .load(service_config_id=service_config_id) .deployment ) - deployment.delete() + health_checker.stop_for_service(service_config_id=service_config_id) + + await run_in_executor(deployment.stop) + logger.info(f"Cancelling funding job for {service_config_id}") + cancel_funding_job(service_config_id=service_config_id) return JSONResponse(content=deployment.json) return app diff --git a/operate/constants.py b/operate/constants.py index 4a2b77f24..50d756353 100644 --- a/operate/constants.py +++ b/operate/constants.py @@ -37,3 +37,5 @@ ON_CHAIN_INTERACT_SLEEP = 3.0 HEALTH_CHECK_URL = "http://127.0.0.1:8716/healthcheck" # possible DNS issues on windows so use IP address + +TM_CONTROL_URL = "http://localhost:8080" diff --git a/operate/data/README.md b/operate/data/README.md new file mode 100644 index 000000000..7860c2ac2 --- /dev/null +++ b/operate/data/README.md @@ -0,0 +1,8 @@ +# Contracts Data + +This directory contains packages that are used in the middleware. + +- `contracts/staking_token` is copied from [valory/trader](https://github.com/valory-xyz/trader/tree/main/packages/valory/contracts/staking_token) +- `contracts/uniswap_v2_erc20` is copied from [valory/optimus-quickstart](https://github.com/valory-xyz/optimus-quickstart/tree/main/operate/data/contracts/uniswap_v2_erc20) + +TODO: Have a better way to import and reuse packages in the middleware. diff --git a/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json b/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json deleted file mode 100644 index fe98dab74..000000000 --- a/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json +++ /dev/null @@ -1,1273 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "ServiceStakingToken", - "sourceName": "contracts/staking/ServiceStakingToken.sol", - "abi": [ - { - "inputs": [], - "name": "AlreadyInitialized", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "activityChecker", - "type": "address" - } - ], - "name": "ContractOnly", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "provided", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "LowerThan", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxNumServices", - "type": "uint256" - } - ], - "name": "MaxNumServicesReached", - "type": "error" - }, - { - "inputs": [], - "name": "NoRewardsAvailable", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tsProvided", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tsExpected", - "type": "uint256" - } - ], - "name": "NotEnoughTimeStaked", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnerOnly", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "ServiceNotUnstaked", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TokenTransferFailed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "multisig", - "type": "address" - } - ], - "name": "UnauthorizedMultisig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "provided", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "ValueLowerThan", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "agentId", - "type": "uint256" - } - ], - "name": "WrongAgentId", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "WrongServiceConfiguration", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "state", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "WrongServiceState", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "expected", - "type": "address" - }, - { - "internalType": "address", - "name": "provided", - "type": "address" - } - ], - "name": "WrongStakingToken", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroTokenAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroValue", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "availableRewards", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "serviceIds", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "rewards", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "epochLength", - "type": "uint256" - } - ], - "name": "Checkpoint", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "availableRewards", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "nonces", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "reward", - "type": "uint256" - } - ], - "name": "RewardClaimed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "serviceInactivity", - "type": "uint256" - } - ], - "name": "ServiceInactivityWarning", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "nonces", - "type": "uint256[]" - } - ], - "name": "ServiceStaked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "nonces", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "reward", - "type": "uint256" - } - ], - "name": "ServiceUnstaked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "serviceIds", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "owners", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "multisigs", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "serviceInactivity", - "type": "uint256[]" - } - ], - "name": "ServicesEvicted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "activityChecker", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "agentIds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "availableRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "balance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "calculateStakingLastReward", - "outputs": [ - { - "internalType": "uint256", - "name": "reward", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "calculateStakingReward", - "outputs": [ - { - "internalType": "uint256", - "name": "reward", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkpoint", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[][]", - "name": "", - "type": "uint256[][]" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "evictServiceIds", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "checkpointAndClaim", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "claim", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "configHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "emissionsAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "epochCounter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAgentIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNextRewardCheckpointTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "tsNext", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getServiceIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "getServiceInfo", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "nonces", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "tsStart", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reward", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "inactivity", - "type": "uint256" - } - ], - "internalType": "struct ServiceInfo", - "name": "sInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "getStakingState", - "outputs": [ - { - "internalType": "enum StakingBase.StakingState", - "name": "stakingState", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "metadataHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "maxNumServices", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rewardsPerSecond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minStakingDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minNumStakingPeriods", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxNumInactivityPeriods", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "livenessPeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timeForEmissions", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numAgentInstances", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "agentIds", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "configHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "proxyHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "serviceRegistry", - "type": "address" - }, - { - "internalType": "address", - "name": "activityChecker", - "type": "address" - } - ], - "internalType": "struct StakingBase.StakingParams", - "name": "_stakingParams", - "type": "tuple" - }, - { - "internalType": "address", - "name": "_serviceRegistryTokenUtility", - "type": "address" - }, - { - "internalType": "address", - "name": "_stakingToken", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "livenessPeriod", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "mapServiceInfo", - "outputs": [ - { - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tsStart", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reward", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "inactivity", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxInactivityDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxNumInactivityPeriods", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxNumServices", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "metadataHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minStakingDeposit", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minStakingDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "numAgentInstances", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "proxyHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rewardsPerSecond", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceRegistry", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceRegistryTokenUtility", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "setServiceIds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "stake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "stakingToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "threshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "timeForEmissions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "tsCheckpoint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "unstake", - "outputs": [ - { - "internalType": "uint256", - "name": "reward", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "6080604052348015600e575f80fd5b506135e88061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102c2575f3560e01c80638f9e0a621161017c578063c5a1d7f0116100dd578063eb338c9611610093578063f86ad2b61161006e578063f86ad2b6146105be578063fd0bba8c146105c7578063ffa1ad74146105e7575f80fd5b8063eb338c961461059b578063f189e85a146105ae578063f4dce714146105b6575f80fd5b8063e1f1176d116100c3578063e1f1176d14610580578063e77cdcc914610589578063eacdaabc14610592575f80fd5b8063c5a1d7f014610565578063cbcf252a1461056d575f80fd5b8063b150876011610132578063b69ef8a811610118578063b69ef8a814610530578063b6b55f2514610539578063c2c4c5c11461054c575f80fd5b8063b150876014610508578063b267c67b1461051d575f80fd5b8063a0ed60e011610162578063a0ed60e01461046f578063a694fc3a14610478578063a74466ad1461048d575f80fd5b80638f9e0a62146104535780639573236114610466575f80fd5b806352c824f5116102265780637fbe2833116101dc57806382a8ea58116101c257806382a8ea581461041757806383f9eb2214610437578063879d90901461044a575f80fd5b80637fbe2833146103fb578063809cee2f1461040e575f80fd5b806356e760581161020c57806356e76058146103cc5780635829c5ec146103df57806372f702f3146103e8575f80fd5b806352c824f5146103b0578063546af2e0146103b9575f80fd5b8063287140511161027b578063379607f511610261578063379607f51461038b5780633e7329971461039e57806342cde4e8146103a7575f80fd5b8063287140511461034d5780632e17de7814610378575f80fd5b8063150b7a02116102ab578063150b7a02146102eb57806316a751721461033b5780631f77940814610344575f80fd5b806308ae7e54146102c657806314b19c5a146102e2575b5f80fd5b6102cf600d5481565b6040519081526020015b60405180910390f35b6102cf600f5481565b61030a6102f9366004612bdb565b630a85bd0160e11b95945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016102d9565b6102cf60015481565b6102cf60065481565b601754610360906001600160a01b031681565b6040516001600160a01b0390911681526020016102d9565b6102cf610386366004612c72565b610618565b6102cf610399366004612c72565b610991565b6102cf60135481565b6102cf60085481565b6102cf60055481565b6102cf6103c7366004612c72565b6109a2565b6102cf6103da366004612c72565b6109ae565b6102cf60075481565b601854610360906001600160a01b031681565b6102cf610409366004612c72565b6109cd565b6102cf600a5481565b61042a610425366004612c72565b610a94565b6040516102d99190612cc3565b6102cf610445366004612c72565b610b83565b6102cf60115481565b600c54610360906001600160a01b031681565b6102cf60125481565b6102cf60045481565b61048b610486366004612c72565b610c3b565b005b6104d561049b366004612c72565b60156020525f9081526040902080546001820154600383015460048401546005909401546001600160a01b03938416949390921692909185565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a0016102d9565b61051061111a565b6040516102d99190612d29565b61048b61052b366004612e5d565b611170565b6102cf60105481565b61048b610547366004612c72565b6111e6565b610554611273565b6040516102d9959493929190612f91565b6102cf5f5481565b600b54610360906001600160a01b031681565b6102cf60095481565b6102cf60035481565b6102cf60025481565b6102cf6105a9366004612c72565b6118df565b6105106118ee565b6102cf611942565b6102cf600e5481565b6105da6105d5366004612c72565b611958565b6040516102d99190613052565b61060b604051806040016040528060058152602001640302e322e360dc1b81525081565b6040516102d99190613078565b5f81815260156020526040812060018101546001600160a01b0316331461066e57600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b60038101545f61067e82426130c1565b9050600d54811115801561069357505f601154115b156106c657600d5460405163ba2bbc6b60e01b815260048101879052602481018390526044810191909152606401610665565b5f806106d0611273565b9450505050915081515f03610730576106e76118ee565b9150815167ffffffffffffffff81111561070357610703612d3b565b60405190808252806020026020018201604052801561072c578160200160208202803683370190505b5090505b5f805b8351821015610790578883838151811061074f5761074f6130d4565b602002602001015103156107905788848381518110610770576107706130d4565b60200260200101510361078557506001610790565b816001019150610733565b866004015497505f876002018054806020026020016040519081016040528092919081815260200182805480156107e457602002820191905f5260205f20905b8154815260200190600101908083116107d0575b50508b545f8f815260156020526040812080546001600160a01b0319908116825560018201805490911690559596506001600160a01b03909116949350915061083290506002830182612b3c565b505f600382018190556004820181905560059091015582156108ba576016805461085e906001906130c1565b8154811061086e5761086e6130d4565b905f5260205f2001546016858154811061088a5761088a6130d4565b5f9182526020909120015560168054806108a6576108a66130e8565b600190038181905f5260205f20015f905590555b600b54604051632142170760e11b8152306004820152336024820152604481018d90526001600160a01b03909116906342842e0e906064015f604051808303815f87803b158015610909575f80fd5b505af115801561091b573d5f803e3d5ffd5b505050505f8a111561093157610931818b611a2a565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae81600f54868f60405161097b939291906130fc565b60405180910390a4505050505050505050919050565b5f61099c825f611a9e565b92915050565b5f61099c826001611a9e565b601481815481106109bd575f80fd5b5f91825260209091200154905081565b5f818152601560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610a4a57602002820191905f5260205f20905b815481526020019060010190808311610a36575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610a8383610b83565b610a8d9083613124565b9392505050565b610ada6040518060c001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081526020015f81526020015f81526020015f81525090565b5f82815260156020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610b5557602002820191905f5260205f20905b815481526020019060010190808311610b41575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b5f805f805f80610b91611ba2565b505050945094509450945094505f5b84811015610c305787838281518110610bbb57610bbb6130d4565b602002602001015103610c285785841115610c07578386838381518110610be457610be46130d4565b6020026020010151610bf69190613137565b610c009190613162565b9650610c30565b818181518110610c1957610c196130d4565b60200260200101519650610c30565b600101610ba0565b505050505050919050565b6011545f03610c5d5760405163afb0be3360e01b815260040160405180910390fd5b5f818152601560205260409020600381015415610c905760405163b4817ce760e01b815260048101839052602401610665565b6016546001548103610cbb5760015460405163fd20861560e01b815260040161066591815260200190565b600b5460405163ef0e239b60e01b8152600481018590525f916001600160a01b03169063ef0e239b906024015f60405180830381865afa158015610d01573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d28919081019061321f565b9050806080015163ffffffff1660075414610d5957604051637ad404bf60e11b815260048101859052602401610665565b60095415801590610d705750806040015160095414155b15610d9157604051637ad404bf60e11b815260048101859052602401610665565b5f600854118015610dae5750806060015163ffffffff1660085414155b15610dcf57604051637ad404bf60e11b815260048101859052602401610665565b60048160c001516005811115610de757610de761303e565b14610e26578060c001516005811115610e0257610e0261303e565b604051633c053f9d60e21b8152600481019190915260248101859052604401610665565b5f81602001516001600160a01b0316803b806020016040519081016040528181525f908060200190933c80519060200120905080600a5414610e8b57602082015160405162a2307960e51b81526001600160a01b039091166004820152602401610665565b6014548015610f4f5760e083015151818114610ebd57604051637ad404bf60e11b815260048101889052602401610665565b5f5b81811015610f4c578460e001518181518110610edd57610edd6130d4565b602002602001015163ffffffff1660148281548110610efe57610efe6130d4565b905f5260205f20015414610f445760148181548110610f1f57610f1f6130d4565b905f5260205f200154604051632ab10b0b60e21b815260040161066591815260200190565b600101610ebf565b50505b610f6f86845f01516bffffffffffffffffffffffff168560e00151611f38565b602083015185546001600160a01b039182166001600160a01b0319918216811788556001880180549092163317909155600c5460405163d564c4bf60e01b815260048101929092525f92169063d564c4bf906024015f60405180830381865afa158015610fde573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261100591908101906132f8565b805190915061101d9060028801906020840190612b5a565b50426003870155601680546001810182555f919091527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901879055600b54604051632142170760e11b8152336004820152306024820152604481018990526001600160a01b03909116906342842e0e906064015f604051808303815f87803b1580156110a7575f80fd5b505af11580156110b9573d5f803e3d5ffd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb600f5485604051611109929190613384565b60405180910390a450505050505050565b6060601480548060200260200160405190810160405280929190818152602001828054801561116657602002820191905f5260205f20905b815481526020019060010190808311611152575b5050505050905090565b61117983612121565b6001600160a01b038116158061119657506001600160a01b038216155b156111b457604051636b093aad60e01b815260040160405180910390fd5b601880546001600160a01b039283166001600160a01b0319918216179091556017805493909216921691909117905550565b5f816010546111f59190613124565b90505f826011546112069190613124565b6010839055601181905560185490915061122b906001600160a01b031633308661249f565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b60608060608060605f805f805f805f8061128b611ba2565b97509750975097509750975097509750606080845167ffffffffffffffff8111156112b8576112b8612d3b565b6040519080825280602002602001820160405280156112e1578160200160208202803683370190505b509a505f8915611662578967ffffffffffffffff81111561130457611304612d3b565b60405190808252806020026020018201604052801561132d578160200160208202803683370190505b5092508967ffffffffffffffff81111561134957611349612d3b565b604051908082528060200260200182016040528015611372578160200160208202803683370190505b5091508a89111561156f575f8060015b8c81101561146b578b8e8b838151811061139e5761139e6130d4565b60200260200101516113b09190613137565b6113ba9190613162565b92506113c68383613124565b91508a81815181106113da576113da6130d4565b602002602001015193508a81815181106113f6576113f66130d4565b6020026020010151868281518110611410576114106130d4565b6020026020010181815250508285828151811061142f5761142f6130d4565b6020026020010181815250508260155f8681526020019081526020015f206004015f82825461145e9190613124565b9091555050600101611382565b508a8d8a5f81518110611480576114806130d4565b60200260200101516114929190613137565b61149c9190613162565b91506114a88282613124565b9050895f815181106114bc576114bc6130d4565b60200260200101519250895f815181106114d8576114d86130d4565b6020026020010151855f815181106114f2576114f26130d4565b602002602001018181525050808d111561151d57611510818e6130c1565b61151a9083613124565b91505b81845f81518110611530576115306130d4565b6020026020010181815250508160155f8581526020019081526020015f206004015f82825461155f9190613124565b909155505f9d5061165c92505050565b5f5b8a81101561164e5788818151811061158b5761158b6130d4565b602002602001015191508881815181106115a7576115a76130d4565b60200260200101518482815181106115c1576115c16130d4565b6020026020010181815250508781815181106115df576115df6130d4565b60200260200101518382815181106115f9576115f96130d4565b602002602001018181525050878181518110611617576116176130d4565b602002602001015160155f8481526020019081526020015f206004015f8282546116419190613124565b9091555050600101611571565b50611659898c6130c1565b9a505b60118b90555b8551156118c957600f545f9a508a5b87518110156118505787818151811061168c5761168c6130d4565b602002602001015192508681815181106116a8576116a86130d4565b602002602001015160155f8581526020019081526020015f2060020190805190602001906116d7929190612b5a565b505f8682815181106116eb576116eb6130d4565b602002602001015111156118365785818151811061170b5761170b6130d4565b602002602001015160155f8581526020019081526020015f20600501546117329190613124565b868281518110611744576117446130d4565b602002602001018181525050858181518110611762576117626130d4565b602002602001015160155f8581526020019081526020015f2060050181905550600e54868281518110611797576117976130d4565b602002602001015111156117d557828e82815181106117b8576117b86130d4565b60209081029190910101528b6117cd816133a4565b9c5050611848565b827f33dc5cdf1e035de8a7fe16ad7a30a441d30ee51719d3f07703ee35d4348f07798388848151811061180a5761180a6130d4565b6020026020010151604051611829929190918252602082015260400190565b60405180910390a2611848565b5f838152601560205260408120600501555b600101611671565b508a15611862576118628d868d612523565b5f6013544261187191906130c1565b426013559050611882826001613124565b600f81905550817f48b735a18ed32318d316214e41387be29c52e29df4598f2b8e40fa843be3f9408e8787856040516118be94939291906133bc565b60405180910390a250505b50939e929d509b50919950969750505050505050565b601681815481106109bd575f80fd5b6060601680548060200260200160405190810160405280929190818152602001828054801561116657602002820191905f5260205f2090815481526020019060010190808311611152575050505050905090565b5f6005546013546119539190613124565b905090565b5f818152601560209081526040808320815160c08101835281546001600160a01b03908116825260018301541681850152600282018054845181870281018701865281815287969395860193909291908301828280156119d557602002820191905f5260205f20905b8154815260200190600101908083116119c1575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050600e548160a001511115611a155760029150611a24565b606081015115611a2457600191505b50919050565b8060105f828254611a3b91906130c1565b9091555050601854611a57906001600160a01b031683836128d8565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611a9291815260200190565b60405180910390a25050565b5f82815260156020526040812060018101546001600160a01b03163314611aef57600181015460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610665565b8215611b0357611afd611273565b50505050505b80600401549150815f03611b2a57604051637c946ed760e01b815260040160405180910390fd5b5f600482015580546001600160a01b0316611b458184611a2a565b806001600160a01b0316336001600160a01b0316867f31add0166dae59ea66bbc180e4fae85b72fc9b7b5fc7b0f7257e4721a840c96e600f548660020188604051611b92939291906133f8565b60405180910390a4505092915050565b5f805f60608060608060605f601354905060115498506005548142611bc791906130c1565b10158015611bd457505f89115b15611f2d576016548067ffffffffffffffff811115611bf557611bf5612d3b565b604051908082528060200260200182016040528015611c1e578160200160208202803683370190505b5094508067ffffffffffffffff811115611c3a57611c3a612d3b565b604051908082528060200260200182016040528015611c63578160200160208202803683370190505b5096508067ffffffffffffffff811115611c7f57611c7f612d3b565b604051908082528060200260200182016040528015611ca8578160200160208202803683370190505b5095508067ffffffffffffffff811115611cc457611cc4612d3b565b604051908082528060200260200182016040528015611cf757816020015b6060815260200190600190039081611ce25790505b5093508067ffffffffffffffff811115611d1357611d13612d3b565b604051908082528060200260200182016040528015611d3c578160200160208202803683370190505b5092505f5b81811015611f2a5760168181548110611d5c57611d5c6130d4565b905f5260205f200154868281518110611d7757611d776130d4565b6020026020010181815250505f60155f888481518110611d9957611d996130d4565b602002602001015181526020019081526020015f2090505f8490505f8260030154905081811115611dc8578091505b611dd282426130c1565b8354600285018054604080516020808402820181019092528281529495505f94611e3c946001600160a01b03169390929091830182828015611e3157602002820191905f5260205f20905b815481526020019060010190808311611e1d575b505050505084612955565b8a8781518110611e4e57611e4e6130d4565b602090810291909101015290508015611efb5781600254611e6f9190613137565b8b8f81518110611e8157611e816130d4565b6020026020010181815250508a8e81518110611e9f57611e9f6130d4565b60200260200101518d611eb29190613124565b9c50898581518110611ec657611ec66130d4565b60200260200101518c8f81518110611ee057611ee06130d4565b6020908102919091010152611ef48e6133a4565b9d50611f1b565b81888681518110611f0e57611f0e6130d4565b6020026020010181815250505b50505050806001019050611d41565b50505b509091929394959697565b601754604051633cebfa4f60e01b8152600481018590525f9182916001600160a01b0390911690633cebfa4f906024016040805180830381865afa158015611f82573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa69190613452565b60185491935091506001600160a01b03808416911614611ff057601854604051630b80380d60e31b81526001600160a01b0391821660048201529083166024820152604401610665565b6003546bffffffffffffffffffffffff821681111561203957604051632b30b24760e21b81526bffffffffffffffffffffffff8316600482015260248101829052604401610665565b5f5b84518110156121185760175485515f916001600160a01b0316906375c1f934908a9089908690811061206f5761206f6130d4565b60200260200101516040518363ffffffff1660e01b81526004016120a392919091825263ffffffff16602082015260400190565b602060405180830381865afa1580156120be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120e29190613485565b90508281101561210f57604051632b30b24760e21b81526004810182905260248101849052604401610665565b5060010161203b565b50505050505050565b600b546001600160a01b03161561214a5760405162dc149f60e41b815260040160405180910390fd5b8051158061215a57506020810151155b8061216757506040810151155b80612174575060c0810151155b806121825750610100810151155b8061218f575060e0810151155b8061219c57506080810151155b806121a9575060a0810151155b156121c757604051637c946ed760e01b815260040160405180910390fd5b8060a001518160800151101561220357608081015160a082015160405163491a2bb160e01b815260048101929092526024820152604401610665565b60028160600151101561223957606081015160405163491a2bb160e01b8152600481019190915260026024820152604401610665565b6101a08101516001600160a01b0316158061226057506101c08101516001600160a01b0316155b1561227e5760405163d92e233d60e01b815260040160405180910390fd5b806101c001516001600160a01b03163b5f036122bf576101c081015160405163601c0c2160e01b81526001600160a01b039091166004820152602401610665565b80515f90815560208201516001556040820151600255606082015160035560a082015160045560c082015160055560e08201516006556101008201516007556101a0820151600b80546001600160a01b039283166001600160a01b0319918216179091556101c0840151600c8054919093169116179055610140820151600855610160820151600955805b8261012001515181101561241857818361012001518281518110612370576123706130d4565b6020026020010151116123b8578261012001518181518110612394576123946130d4565b6020026020010151604051632ab10b0b60e21b815260040161066591815260200190565b82610120015181815181106123cf576123cf6130d4565b602090810291909101015160148054600181810183555f929092527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec018290559092500161234a565b506101808201515f0361243e57604051637c946ed760e01b815260040160405180910390fd5b610180820151600a5560055460808301516124599190613137565b600d5560055460a083015161246e9190613137565b600e5560e08201516020830151604084015161248a9190613137565b6124949190613137565b601255505042601355565b5f6040516323b872dd60e01b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f60605280604052508061251c5760405163abae3d6d60e01b81526001600160a01b03808716600483015280861660248301528416604482015260648101839052608401610665565b5050505050565b82515f8267ffffffffffffffff81111561253f5761253f612d3b565b604051908082528060200260200182016040528015612568578160200160208202803683370190505b5090505f8367ffffffffffffffff81111561258557612585612d3b565b6040519080825280602002602001820160405280156125ae578160200160208202803683370190505b5090505f8467ffffffffffffffff8111156125cb576125cb612d3b565b6040519080825280602002602001820160405280156125f4578160200160208202803683370190505b5090505f8567ffffffffffffffff81111561261157612611612d3b565b60405190808252806020026020018201604052801561263a578160200160208202803683370190505b5090505f8667ffffffffffffffff81111561265757612657612d3b565b604051908082528060200260200182016040528015612680578160200160208202803683370190505b5090505f805f5b888110156127dc575f8c82815181106126a2576126a26130d4565b602002602001015111156127d4578b81815181106126c2576126c26130d4565b60200260200101519150818884815181106126df576126df6130d4565b6020908102919091018101919091525f838152601590915260409020600181015488516001600160a01b0390911690899086908110612720576127206130d4565b6001600160a01b0392831660209182029290920101528154885191169088908690811061274f5761274f6130d4565b60200260200101906001600160a01b031690816001600160a01b0316815250508b8281518110612781576127816130d4565b602002602001015186858151811061279b5761279b6130d4565b602002602001018181525050818585815181106127ba576127ba6130d4565b6020908102919091010152836127cf816133a4565b945050505b600101612687565b50885b801561288a57886127ef8161349c565b99505f9050846128006001846130c1565b81518110612810576128106130d4565b6020026020010151905060168a8154811061282d5761282d6130d4565b905f5260205f20015460168281548110612849576128496130d4565b5f918252602090912001556016805480612865576128656130e8565b600190038181905f5260205f20015f9055905550806128839061349c565b90506127df565b50600f547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd56952888888886040516128c394939291906134e9565b60405180910390a25050505050505050505050565b5f60405163a9059cbb60e01b5f52836004528260245260205f60445f80895af13d15601f3d1160015f511416171691505f60605280604052508061294f5760405163abae3d6d60e01b81526001600160a01b0380861660048301523060248301528416604482015260648101839052608401610665565b50505050565b6040516001600160a01b03841660248201525f90606090829060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663d564c4bf60e01b179052600c5490519192505f9182916001600160a01b0316906129d1908590613535565b5f60405180830381855afa9150503d805f8114612a09576040519150601f19603f3d011682016040523d82523d5f602084013e612a0e565b606091505b5091509150818015612a215750603f8151115b8015612a38575060208151612a36919061354b565b155b15612b315780806020019051810190612a5191906132f8565b9350838787604051602401612a689392919061355e565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663184023a560e01b179052600c5490519194506001600160a01b031690612ac4908590613535565b5f60405180830381855afa9150503d805f8114612afc576040519150601f19603f3d011682016040523d82523d5f602084013e612b01565b606091505b509092509050818015612b15575080516020145b15612b315780806020019051810190612b2e9190613593565b94505b505050935093915050565b5080545f8255905f5260205f2090810190612b579190612ba3565b50565b828054828255905f5260205f20908101928215612b93579160200282015b82811115612b93578251825591602001919060010190612b78565b50612b9f929150612ba3565b5090565b5b80821115612b9f575f8155600101612ba4565b6001600160a01b0381168114612b57575f80fd5b8035612bd681612bb7565b919050565b5f805f805f60808688031215612bef575f80fd5b8535612bfa81612bb7565b94506020860135612c0a81612bb7565b935060408601359250606086013567ffffffffffffffff80821115612c2d575f80fd5b818801915088601f830112612c40575f80fd5b813581811115612c4e575f80fd5b896020828501011115612c5f575f80fd5b9699959850939650602001949392505050565b5f60208284031215612c82575f80fd5b5035919050565b5f815180845260208085019450602084015f5b83811015612cb857815187529582019590820190600101612c9c565b509495945050505050565b602081525f6001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612cff60e0840182612c89565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081525f610a8d6020830184612c89565b634e487b7160e01b5f52604160045260245ffd5b6040516101e0810167ffffffffffffffff81118282101715612d7357612d73612d3b565b60405290565b604051610100810167ffffffffffffffff81118282101715612d7357612d73612d3b565b604051601f8201601f1916810167ffffffffffffffff81118282101715612dc657612dc6612d3b565b604052919050565b5f67ffffffffffffffff821115612de757612de7612d3b565b5060051b60200190565b5f82601f830112612e00575f80fd5b81356020612e15612e1083612dce565b612d9d565b8083825260208201915060208460051b870101935086841115612e36575f80fd5b602086015b84811015612e525780358352918301918301612e3b565b509695505050505050565b5f805f60608486031215612e6f575f80fd5b833567ffffffffffffffff80821115612e86575f80fd5b908501906101e08288031215612e9a575f80fd5b612ea2612d4f565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013583811115612f0b575f80fd5b612f178a828701612df1565b91830191909152506101408381013590820152610160808401359082015261018080840135908201526101a09150612f50828401612bcb565b828201526101c09150612f64828401612bcb565b82820152809550505050612f7a60208501612bcb565b9150612f8860408501612bcb565b90509250925092565b60a081525f612fa360a0830188612c89565b6020838203818501528188518084528284019150828160051b850101838b015f5b83811015612ff257601f19878403018552612fe0838351612c89565b94860194925090850190600101612fc4565b50508681036040880152613006818b612c89565b945050505050828103606084015261301e8186612c89565b905082810360808401526130328185612c89565b98975050505050505050565b634e487b7160e01b5f52602160045260245ffd5b602081016003831061307257634e487b7160e01b5f52602160045260245ffd5b91905290565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561099c5761099c6130ad565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b838152606060208201525f6131146060830185612c89565b9050826040830152949350505050565b8082018082111561099c5761099c6130ad565b808202811582820484141761099c5761099c6130ad565b634e487b7160e01b5f52601260045260245ffd5b5f826131705761317061314e565b500490565b80516bffffffffffffffffffffffff81168114612bd6575f80fd5b8051612bd681612bb7565b805163ffffffff81168114612bd6575f80fd5b805160068110612bd6575f80fd5b5f82601f8301126131cb575f80fd5b815160206131db612e1083612dce565b8083825260208201915060208460051b8701019350868411156131fc575f80fd5b602086015b84811015612e52576132128161319b565b8352918301918301613201565b5f6020828403121561322f575f80fd5b815167ffffffffffffffff80821115613246575f80fd5b90830190610100828603121561325a575f80fd5b613262612d79565b61326b83613175565b815261327960208401613190565b6020820152604083015160408201526132946060840161319b565b60608201526132a56080840161319b565b60808201526132b660a0840161319b565b60a08201526132c760c084016131ae565b60c082015260e0830151828111156132dd575f80fd5b6132e9878286016131bc565b60e08301525095945050505050565b5f6020808385031215613309575f80fd5b825167ffffffffffffffff81111561331f575f80fd5b8301601f8101851361332f575f80fd5b805161333d612e1082612dce565b81815260059190911b8201830190838101908783111561335b575f80fd5b928401925b8284101561337957835182529284019290840190613360565b979650505050505050565b828152604060208201525f61339c6040830184612c89565b949350505050565b5f600182016133b5576133b56130ad565b5060010190565b848152608060208201525f6133d46080830186612c89565b82810360408401526133e68186612c89565b91505082606083015295945050505050565b5f60608201858352602060606020850152818654808452608086019150875f5260205f2093505f5b8181101561343c57845483526001948501949284019201613420565b5050809350505050826040830152949350505050565b5f8060408385031215613463575f80fd5b825161346e81612bb7565b915061347c60208401613175565b90509250929050565b5f60208284031215613495575f80fd5b5051919050565b5f816134aa576134aa6130ad565b505f190190565b5f815180845260208085019450602084015f5b83811015612cb85781516001600160a01b0316875295820195908201906001016134c4565b608081525f6134fb6080830187612c89565b828103602084015261350d81876134b1565b9050828103604084015261352181866134b1565b905082810360608401526133798185612c89565b5f82518060208501845e5f920191825250919050565b5f826135595761355961314e565b500690565b606081525f6135706060830186612c89565b82810360208401526135828186612c89565b915050826040830152949350505050565b5f602082840312156135a3575f80fd5b81518015158114610a8d575f80fdfea264697066735822122072ecd1722ad55173c3de0af850e7d10c36277b036879ee73341951b05ec8f40e64736f6c63430008190033", - "linkReferences": {}, - "deployedLinkReferences": {} -} \ No newline at end of file diff --git a/operate/data/contracts/service_staking_token/contract.yaml b/operate/data/contracts/service_staking_token/contract.yaml deleted file mode 100644 index a0a0069a4..000000000 --- a/operate/data/contracts/service_staking_token/contract.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: service_staking_token -author: valory -version: 0.1.0 -type: contract -description: Service staking token contract -license: Apache-2.0 -aea_version: '>=1.0.0, <2.0.0' -fingerprint: - __init__.py: bafybeid3wfzglolebuo6jrrsopswzu4lk77bm76mvw3euizlsjtnt3wmgu - build/ServiceStakingToken.json: bafybeifptgh2dpse3l7lscjdvy24t7svqnflj3n2txehu7zerdeaszldsi - contract.py: bafybeiff62bquzeisbd6iptqdjetrhlkt2ut5d7j6md2kqinrqgmbveceu -fingerprint_ignore_patterns: [] -contracts: [] -class_name: ServiceStakingTokenContract -contract_interface_paths: - ethereum: build/ServiceStakingToken.json -dependencies: - open-aea-ledger-ethereum: - version: ==1.42.0 - open-aea-test-autonomy: - version: ==0.13.6 - web3: - version: <7,>=6.0.0 diff --git a/operate/data/contracts/service_staking_token/__init__.py b/operate/data/contracts/staking_token/__init__.py similarity index 87% rename from operate/data/contracts/service_staking_token/__init__.py rename to operate/data/contracts/staking_token/__init__.py index cf1e8467e..4682f8155 100644 --- a/operate/data/contracts/service_staking_token/__init__.py +++ b/operate/data/contracts/staking_token/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2023 Valory AG +# Copyright 2024 Valory AG # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,4 +17,4 @@ # # ------------------------------------------------------------------------------ -"""This module contains the support resources for the agent registry contract.""" +"""This module contains the support resources for the staking contract.""" diff --git a/operate/data/contracts/staking_token/build/StakingToken.json b/operate/data/contracts/staking_token/build/StakingToken.json new file mode 100644 index 000000000..070508dba --- /dev/null +++ b/operate/data/contracts/staking_token/build/StakingToken.json @@ -0,0 +1,1336 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "StakingToken", + "sourceName": "contracts/staking/StakingToken.sol", + "abi": [ + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "activityChecker", + "type": "address" + } + ], + "name": "ContractOnly", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "LowerThan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxNumServices", + "type": "uint256" + } + ], + "name": "MaxNumServicesReached", + "type": "error" + }, + { + "inputs": [], + "name": "NoRewardsAvailable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tsProvided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tsExpected", + "type": "uint256" + } + ], + "name": "NotEnoughTimeStaked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerOnly", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "ServiceNotUnstaked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TokenTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + } + ], + "name": "UnauthorizedMultisig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "ValueLowerThan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + } + ], + "name": "WrongAgentId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongServiceConfiguration", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "state", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongServiceState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expected", + "type": "address" + }, + { + "internalType": "address", + "name": "provided", + "type": "address" + } + ], + "name": "WrongStakingToken", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "serviceIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "rewards", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochLength", + "type": "uint256" + } + ], + "name": "Checkpoint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + } + ], + "name": "ServiceForceUnstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "serviceInactivity", + "type": "uint256" + } + ], + "name": "ServiceInactivityWarning", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + } + ], + "name": "ServiceStaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + } + ], + "name": "ServiceUnstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "serviceIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "multisigs", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "serviceInactivity", + "type": "uint256[]" + } + ], + "name": "ServicesEvicted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "activityChecker", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "agentIds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "availableRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "calculateStakingLastReward", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "calculateStakingReward", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "evictServiceIds", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "checkpointAndClaim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "configHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emissionsAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "forcedUnstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAgentIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextRewardCheckpointTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "tsNext", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getServiceIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "getServiceInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "tsStart", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inactivity", + "type": "uint256" + } + ], + "internalType": "struct ServiceInfo", + "name": "sInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "getStakingState", + "outputs": [ + { + "internalType": "enum StakingBase.StakingState", + "name": "stakingState", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "metadataHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxNumServices", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardsPerSecond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minStakingDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minNumStakingPeriods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxNumInactivityPeriods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "livenessPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timeForEmissions", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numAgentInstances", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "agentIds", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "configHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "proxyHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "serviceRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "activityChecker", + "type": "address" + } + ], + "internalType": "struct StakingBase.StakingParams", + "name": "_stakingParams", + "type": "tuple" + }, + { + "internalType": "address", + "name": "_serviceRegistryTokenUtility", + "type": "address" + }, + { + "internalType": "address", + "name": "_stakingToken", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "livenessPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "mapServiceInfo", + "outputs": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tsStart", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inactivity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxInactivityDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumInactivityPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumServices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "metadataHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minStakingDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minStakingDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numAgentInstances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsPerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "serviceRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "serviceRegistryTokenUtility", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "setServiceIds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "threshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timeForEmissions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tsCheckpoint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f80fd5b50600436106102cd575f3560e01c806393ac752f1161017c578063c5a1d7f0116100dd578063eb338c9611610093578063f86ad2b61161006e578063f86ad2b6146105db578063fd0bba8c146105e4578063ffa1ad7414610604575f80fd5b8063eb338c96146105b8578063f189e85a146105cb578063f4dce714146105d3575f80fd5b8063e1f1176d116100c3578063e1f1176d1461059d578063e77cdcc9146105a6578063eacdaabc146105af575f80fd5b8063c5a1d7f014610582578063cbcf252a1461058a575f80fd5b8063b150876011610132578063b69ef8a811610118578063b69ef8a81461054e578063b6b55f2514610557578063c2c4c5c11461056a575f80fd5b8063b150876014610526578063b267c67b1461053b575f80fd5b8063a0ed60e011610162578063a0ed60e01461048f578063a694fc3a14610498578063a74466ad146104ab575f80fd5b806393ac752f146104715780639573236114610486575f80fd5b806352c824f5116102315780637fbe2833116101e757806383f9eb22116101c257806383f9eb2214610442578063879d9090146104555780638f9e0a621461045e575f80fd5b80637fbe283314610406578063809cee2f1461041957806382a8ea5814610422575f80fd5b806356e760581161021757806356e76058146103d75780635829c5ec146103ea57806372f702f3146103f3575f80fd5b806352c824f5146103bb578063546af2e0146103c4575f80fd5b80632871405111610286578063379607f51161026c578063379607f5146103965780633e732997146103a957806342cde4e8146103b2575f80fd5b806328714051146103585780632e17de7814610383575f80fd5b8063150b7a02116102b6578063150b7a02146102f657806316a75172146103465780631f7794081461034f575f80fd5b806308ae7e54146102d157806314b19c5a146102ed575b5f80fd5b6102da600d5481565b6040519081526020015b60405180910390f35b6102da600f5481565b610315610304366004612c65565b630a85bd0160e11b95945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016102e4565b6102da60015481565b6102da60065481565b60175461036b906001600160a01b031681565b6040516001600160a01b0390911681526020016102e4565b6102da610391366004612cfc565b610635565b6102da6103a4366004612cfc565b610646565b6102da60135481565b6102da60085481565b6102da60055481565b6102da6103d2366004612cfc565b610651565b6102da6103e5366004612cfc565b61065d565b6102da60075481565b60185461036b906001600160a01b031681565b6102da610414366004612cfc565b61067c565b6102da600a5481565b610435610430366004612cfc565b610743565b6040516102e49190612d13565b6102da610450366004612cfc565b610832565b6102da60115481565b600c5461036b906001600160a01b031681565b61048461047f366004612cfc565b6108ea565b005b6102da60125481565b6102da60045481565b6104846104a6366004612cfc565b6108f9565b6104f36104b9366004612cfc565b60156020525f9081526040902080546001820154600383015460048401546005909401546001600160a01b03938416949390921692909185565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a0016102e4565b61052e610de9565b6040516102e49190612ddf565b610484610549366004612f13565b610e3f565b6102da60105481565b610484610565366004612cfc565b610eb5565b610572610f42565b6040516102e49493929190613047565b6102da5f5481565b600b5461036b906001600160a01b031681565b6102da60095481565b6102da60035481565b6102da60025481565b6102da6105c6366004612cfc565b6115d6565b61052e6115e5565b6102da611639565b6102da600e5481565b6105f76105f2366004612cfc565b61164f565b6040516102e491906130b2565b610628604051806040016040528060058152602001640302e322e360dc1b81525081565b6040516102e491906130d8565b5f610640825f611721565b92915050565b5f610640825f611aa8565b5f610640826001611aa8565b6014818154811061066c575f80fd5b5f91825260209091200154905081565b5f818152601560209081526040808320815160c08101835281546001600160a01b03908116825260018301541681850152600282018054845181870281018701865281815287969395860193909291908301828280156106f957602002820191905f5260205f20905b8154815260200190600101908083116106e5575b50505050508152602001600382015481526020016004820154815260200160058201548152505090508060800151915061073283610832565b61073c9083613121565b9392505050565b6107896040518060c001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081526020015f81526020015f81526020015f81525090565b5f82815260156020908152604091829020825160c08101845281546001600160a01b039081168252600183015416818401526002820180548551818602810186018752818152929593949386019383018282801561080457602002820191905f5260205f20905b8154815260200190600101908083116107f0575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b5f805f805f80610840611bab565b505050945094509450945094505f5b848110156108df578783828151811061086a5761086a613134565b6020026020010151036108d757858411156108b657838683838151811061089357610893613134565b60200260200101516108a59190613148565b6108af9190613173565b96506108df565b8181815181106108c8576108c8613134565b602002602001015196506108df565b60010161084f565b505050505050919050565b6108f5816001611721565b5050565b610901610f42565b505050506011545f036109275760405163afb0be3360e01b815260040160405180910390fd5b5f81815260156020526040902060038101541561095f5760405163b4817ce760e01b8152600481018390526024015b60405180910390fd5b601654600154810361098a5760015460405163fd20861560e01b815260040161095691815260200190565b600b5460405163ef0e239b60e01b8152600481018590525f916001600160a01b03169063ef0e239b906024015f60405180830381865afa1580156109d0573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109f79190810190613230565b9050806080015163ffffffff1660075414610a2857604051637ad404bf60e11b815260048101859052602401610956565b60095415801590610a3f5750806040015160095414155b15610a6057604051637ad404bf60e11b815260048101859052602401610956565b5f600854118015610a7d5750806060015163ffffffff1660085414155b15610a9e57604051637ad404bf60e11b815260048101859052602401610956565b60048160c001516005811115610ab657610ab661309e565b14610af5578060c001516005811115610ad157610ad161309e565b604051633c053f9d60e21b8152600481019190915260248101859052604401610956565b5f81602001516001600160a01b0316803b806020016040519081016040528181525f908060200190933c80519060200120905080600a5414610b5a57602082015160405162a2307960e51b81526001600160a01b039091166004820152602401610956565b6014548015610c1e5760e083015151818114610b8c57604051637ad404bf60e11b815260048101889052602401610956565b5f5b81811015610c1b578460e001518181518110610bac57610bac613134565b602002602001015163ffffffff1660148281548110610bcd57610bcd613134565b905f5260205f20015414610c135760148181548110610bee57610bee613134565b905f5260205f200154604051632ab10b0b60e21b815260040161095691815260200190565b600101610b8e565b50505b610c3e86845f01516bffffffffffffffffffffffff168560e00151611f4b565b602083015185546001600160a01b039182166001600160a01b0319918216811788556001880180549092163317909155600c5460405163d564c4bf60e01b815260048101929092525f92169063d564c4bf906024015f60405180830381865afa158015610cad573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610cd49190810190613309565b8051909150610cec9060028801906020840190612bc6565b50426003870155601680546001810182555f919091527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901879055600b54604051632142170760e11b8152336004820152306024820152604481018990526001600160a01b03909116906342842e0e906064015f604051808303815f87803b158015610d76575f80fd5b505af1158015610d88573d5f803e3d5ffd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb600f5485604051610dd892919061338a565b60405180910390a450505050505050565b60606014805480602002602001604051908101604052809291908181526020018280548015610e3557602002820191905f5260205f20905b815481526020019060010190808311610e21575b5050505050905090565b610e4883612134565b6001600160a01b0381161580610e6557506001600160a01b038216155b15610e8357604051636b093aad60e01b815260040160405180910390fd5b601880546001600160a01b039283166001600160a01b0319918216179091556017805493909216921691909117905550565b5f81601054610ec49190613121565b90505f82601154610ed59190613121565b60108390556011819055601854909150610efa906001600160a01b03163330866124b2565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b6060806060805f805f805f805f80610f58611bab565b97509750975097509750975097509750606080845167ffffffffffffffff811115610f8557610f85612df1565b604051908082528060200260200182016040528015610fae578160200160208202803683370190505b509a505f891561132f578967ffffffffffffffff811115610fd157610fd1612df1565b604051908082528060200260200182016040528015610ffa578160200160208202803683370190505b5092508967ffffffffffffffff81111561101657611016612df1565b60405190808252806020026020018201604052801561103f578160200160208202803683370190505b5091508a89111561123c575f8060015b8c811015611138578b8e8b838151811061106b5761106b613134565b602002602001015161107d9190613148565b6110879190613173565b92506110938383613121565b91508a81815181106110a7576110a7613134565b602002602001015193508a81815181106110c3576110c3613134565b60200260200101518682815181106110dd576110dd613134565b602002602001018181525050828582815181106110fc576110fc613134565b6020026020010181815250508260155f8681526020019081526020015f206004015f82825461112b9190613121565b909155505060010161104f565b508a8d8a5f8151811061114d5761114d613134565b602002602001015161115f9190613148565b6111699190613173565b91506111758282613121565b9050895f8151811061118957611189613134565b60200260200101519250895f815181106111a5576111a5613134565b6020026020010151855f815181106111bf576111bf613134565b602002602001018181525050808d11156111ea576111dd818e6133aa565b6111e79083613121565b91505b81845f815181106111fd576111fd613134565b6020026020010181815250508160155f8581526020019081526020015f206004015f82825461122c9190613121565b909155505f9d5061132992505050565b5f5b8a81101561131b5788818151811061125857611258613134565b6020026020010151915088818151811061127457611274613134565b602002602001015184828151811061128e5761128e613134565b6020026020010181815250508781815181106112ac576112ac613134565b60200260200101518382815181106112c6576112c6613134565b6020026020010181815250508781815181106112e4576112e4613134565b602002602001015160155f8481526020019081526020015f206004015f82825461130e9190613121565b909155505060010161123e565b50611326898c6133aa565b9a505b60118b90555b8551156115a257600f545f9a508a5b875181101561151d5787818151811061135957611359613134565b6020026020010151925086818151811061137557611375613134565b602002602001015160155f8581526020019081526020015f2060020190805190602001906113a4929190612bc6565b505f8682815181106113b8576113b8613134565b60200260200101511115611503578581815181106113d8576113d8613134565b602002602001015160155f8581526020019081526020015f20600501546113ff9190613121565b86828151811061141157611411613134565b60200260200101818152505085818151811061142f5761142f613134565b602002602001015160155f8581526020019081526020015f2060050181905550600e5486828151811061146457611464613134565b602002602001015111156114a257828e828151811061148557611485613134565b60209081029190910101528b61149a816133bd565b9c5050611515565b827f33dc5cdf1e035de8a7fe16ad7a30a441d30ee51719d3f07703ee35d4348f0779838884815181106114d7576114d7613134565b60200260200101516040516114f6929190918252602082015260400190565b60405180910390a2611515565b5f838152601560205260408120600501555b60010161133e565b508a156115365761152f8d868d612536565b9c5061153b565b60609c505b5f6013544261154a91906133aa565b42601355905061155b826001613121565b600f81905550817f48b735a18ed32318d316214e41387be29c52e29df4598f2b8e40fa843be3f9408e87878560405161159794939291906133d5565b60405180910390a250505b855115806115b057505f8c51115b156115c0576115bd6115e5565b95505b50939c509a509198505050505050505090919293565b6016818154811061066c575f80fd5b60606016805480602002602001604051908101604052809291908181526020018280548015610e3557602002820191905f5260205f2090815481526020019060010190808311610e21575050505050905090565b5f60055460135461164a9190613121565b905090565b5f818152601560209081526040808320815160c08101835281546001600160a01b03908116825260018301541681850152600282018054845181870281018701865281815287969395860193909291908301828280156116cc57602002820191905f5260205f20905b8154815260200190600101908083116116b8575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050600e548160a00151111561170c576002915061171b565b60608101511561171b57600191505b50919050565b5f82815260156020526040812060018101546001600160a01b0316331461177257600181015460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610956565b5f61177b610f42565b505050600483015460115460038501549195509192505f9061179d90426133aa565b9050600d5481111580156117b057505f82115b156117e357600d5460405163ba2bbc6b60e01b815260048101899052602481018390526044810191909152606401610956565b5f805b8451821015611822578885838151811061180257611802613134565b60200260200101510361181757506001611822565b8160010191506117e6565b5f8660020180548060200260200160405190810160405280929190818152602001828054801561186f57602002820191905f5260205f20905b81548152602001906001019080831161185b575b50508a545f8f815260156020526040812080546001600160a01b0319908116825560018201805490911690559596506001600160a01b0390911694935091506118bd90506002830182612c0f565b505f60038201819055600482018190556005909101558215611953576016545f906118ea906001906133aa565b9050801561192d576016818154811061190557611905613134565b905f5260205f2001546016868154811061192157611921613134565b5f918252602090912001555b601680548061193e5761193e613411565b600190038181905f5260205f20015f90559055505b600b546040516323b872dd60e01b8152306004820152336024820152604481018d90526001600160a01b03909116906323b872dd906064015f604051808303815f87803b1580156119a2575f80fd5b505af11580156119b4573d5f803e3d5ffd5b505050505f8911156119e65789156119dc576119d08987613121565b601181905595506119e6565b6119e6818a6128ee565b8915611a4557806001600160a01b0316336001600160a01b03168c7f91c9f7c7f307bcc0ae02ba613bd8d07c29e94952f0a28803ded176fcd7d96d64600f54868e8c604051611a389493929190613425565b60405180910390a4611a9a565b806001600160a01b0316336001600160a01b03168c7f6d789d063e079a4c156e77a20008529fc448dca2cd7e5e7a20abf969fffb9226600f54868e8c604051611a919493929190613425565b60405180910390a45b505050505050505092915050565b5f82815260156020526040812060018101546001600160a01b03163314611af957600181015460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610956565b8215611b0c57611b07610f42565b505050505b80600401549150815f03611b3357604051637c946ed760e01b815260040160405180910390fd5b5f600482015580546001600160a01b0316611b4e81846128ee565b806001600160a01b0316336001600160a01b0316867f31add0166dae59ea66bbc180e4fae85b72fc9b7b5fc7b0f7257e4721a840c96e600f548660020188604051611b9b93929190613450565b60405180910390a4505092915050565b60135460115460165490915f91829160609182918291829182918015801590611bdf5750600554611bdc83426133aa565b10155b8015611bea57505f8a115b15611f3f578067ffffffffffffffff811115611c0857611c08612df1565b604051908082528060200260200182016040528015611c31578160200160208202803683370190505b5094508067ffffffffffffffff811115611c4d57611c4d612df1565b604051908082528060200260200182016040528015611c76578160200160208202803683370190505b5096508067ffffffffffffffff811115611c9257611c92612df1565b604051908082528060200260200182016040528015611cbb578160200160208202803683370190505b5095508067ffffffffffffffff811115611cd757611cd7612df1565b604051908082528060200260200182016040528015611d0a57816020015b6060815260200190600190039081611cf55790505b5093508067ffffffffffffffff811115611d2657611d26612df1565b604051908082528060200260200182016040528015611d4f578160200160208202803683370190505b5092505f5b81811015611f3d5760168181548110611d6f57611d6f613134565b905f5260205f200154868281518110611d8a57611d8a613134565b6020026020010181815250505f60155f888481518110611dac57611dac613134565b602002602001015181526020019081526020015f2090505f8490505f8260030154905081811115611ddb578091505b611de582426133aa565b8354600285018054604080516020808402820181019092528281529495505f94611e4f946001600160a01b03169390929091830182828015611e4457602002820191905f5260205f20905b815481526020019060010190808311611e30575b505050505084612962565b8a8781518110611e6157611e61613134565b602090810291909101015290508015611f0e5781600254611e829190613148565b8b8f81518110611e9457611e94613134565b6020026020010181815250508a8e81518110611eb257611eb2613134565b60200260200101518d611ec59190613121565b9c50898581518110611ed957611ed9613134565b60200260200101518c8f81518110611ef357611ef3613134565b6020908102919091010152611f078e6133bd565b9d50611f2e565b81888681518110611f2157611f21613134565b6020026020010181815250505b50505050806001019050611d54565b505b50509091929394959697565b601754604051633cebfa4f60e01b8152600481018590525f9182916001600160a01b0390911690633cebfa4f906024016040805180830381865afa158015611f95573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fb991906134aa565b60185491935091506001600160a01b0380841691161461200357601854604051630b80380d60e31b81526001600160a01b0391821660048201529083166024820152604401610956565b6003546bffffffffffffffffffffffff821681111561204c57604051632b30b24760e21b81526bffffffffffffffffffffffff8316600482015260248101829052604401610956565b5f5b845181101561212b5760175485515f916001600160a01b0316906375c1f934908a9089908690811061208257612082613134565b60200260200101516040518363ffffffff1660e01b81526004016120b692919091825263ffffffff16602082015260400190565b602060405180830381865afa1580156120d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120f591906134dd565b90508281101561212257604051632b30b24760e21b81526004810182905260248101849052604401610956565b5060010161204e565b50505050505050565b600b546001600160a01b03161561215d5760405162dc149f60e41b815260040160405180910390fd5b8051158061216d57506020810151155b8061217a57506040810151155b80612187575060c0810151155b806121955750610100810151155b806121a2575060e0810151155b806121af57506080810151155b806121bc575060a0810151155b156121da57604051637c946ed760e01b815260040160405180910390fd5b8060a001518160800151101561221657608081015160a082015160405163491a2bb160e01b815260048101929092526024820152604401610956565b60028160600151101561224c57606081015160405163491a2bb160e01b8152600481019190915260026024820152604401610956565b6101a08101516001600160a01b0316158061227357506101c08101516001600160a01b0316155b156122915760405163d92e233d60e01b815260040160405180910390fd5b806101c001516001600160a01b03163b5f036122d2576101c081015160405163601c0c2160e01b81526001600160a01b039091166004820152602401610956565b80515f90815560208201516001556040820151600255606082015160035560a082015160045560c082015160055560e08201516006556101008201516007556101a0820151600b80546001600160a01b039283166001600160a01b0319918216179091556101c0840151600c8054919093169116179055610140820151600855610160820151600955805b8261012001515181101561242b5781836101200151828151811061238357612383613134565b6020026020010151116123cb5782610120015181815181106123a7576123a7613134565b6020026020010151604051632ab10b0b60e21b815260040161095691815260200190565b82610120015181815181106123e2576123e2613134565b602090810291909101015160148054600181810183555f929092527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec018290559092500161235d565b506101808201515f0361245157604051637c946ed760e01b815260040160405180910390fd5b610180820151600a55600554608083015161246c9190613148565b600d5560055460a08301516124819190613148565b600e5560e08201516020830151604084015161249d9190613148565b6124a79190613148565b601255505042601355565b5f6040516323b872dd60e01b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f60605280604052508061252f5760405163abae3d6d60e01b81526001600160a01b03808716600483015280861660248301528416604482015260648101839052608401610956565b5050505050565b82516060908267ffffffffffffffff81111561255457612554612df1565b60405190808252806020026020018201604052801561257d578160200160208202803683370190505b5091505f8367ffffffffffffffff81111561259a5761259a612df1565b6040519080825280602002602001820160405280156125c3578160200160208202803683370190505b5090505f8467ffffffffffffffff8111156125e0576125e0612df1565b604051908082528060200260200182016040528015612609578160200160208202803683370190505b5090505f8567ffffffffffffffff81111561262657612626612df1565b60405190808252806020026020018201604052801561264f578160200160208202803683370190505b5090505f8667ffffffffffffffff81111561266c5761266c612df1565b604051908082528060200260200182016040528015612695578160200160208202803683370190505b5090505f805f5b878110156127f1575f8c82815181106126b7576126b7613134565b602002602001015111156127e9578b81815181106126d7576126d7613134565b60200260200101519150818984815181106126f4576126f4613134565b6020908102919091018101919091525f838152601590915260409020600181015488516001600160a01b039091169089908690811061273557612735613134565b6001600160a01b0392831660209182029290920101528154885191169088908690811061276457612764613134565b60200260200101906001600160a01b031690816001600160a01b0316815250508b828151811061279657612796613134565b60200260200101518685815181106127b0576127b0613134565b602002602001018181525050818585815181106127cf576127cf613134565b6020908102919091010152836127e4816133bd565b945050505b60010161269c565b50885b801561289f5787612804816134f4565b98505f9050846128156001846133aa565b8151811061282557612825613134565b602002602001015190506016898154811061284257612842613134565b905f5260205f2001546016828154811061285e5761285e613134565b5f91825260209091200155601680548061287a5761287a613411565b600190038181905f5260205f20015f905590555080612898906134f4565b90506127f4565b50600f547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd56952898888886040516128d89493929190613541565b60405180910390a2505050505050509392505050565b8060105f8282546128ff91906133aa565b909155505060185461291b906001600160a01b03168383612b49565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648260405161295691815260200190565b60405180910390a25050565b6040516001600160a01b03841660248201525f90606090829060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663d564c4bf60e01b179052600c5490519192505f9182916001600160a01b0316906129de908590613579565b5f60405180830381855afa9150503d805f8114612a16576040519150601f19603f3d011682016040523d82523d5f602084013e612a1b565b606091505b5091509150818015612a2e5750603f8151115b8015612a45575060208151612a43919061358f565b155b15612b3e5780806020019051810190612a5e9190613309565b9350838787604051602401612a75939291906135a2565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663184023a560e01b179052600c5490519194506001600160a01b031690612ad1908590613579565b5f60405180830381855afa9150503d805f8114612b09576040519150601f19603f3d011682016040523d82523d5f602084013e612b0e565b606091505b509092509050818015612b22575080516020145b15612b3e5780806020019051810190612b3b91906135d7565b94505b505050935093915050565b5f60405163a9059cbb60e01b5f52836004528260245260205f60445f80895af13d15601f3d1160015f511416171691505f606052806040525080612bc05760405163abae3d6d60e01b81526001600160a01b0380861660048301523060248301528416604482015260648101839052608401610956565b50505050565b828054828255905f5260205f20908101928215612bff579160200282015b82811115612bff578251825591602001919060010190612be4565b50612c0b929150612c2d565b5090565b5080545f8255905f5260205f2090810190612c2a9190612c2d565b50565b5b80821115612c0b575f8155600101612c2e565b6001600160a01b0381168114612c2a575f80fd5b8035612c6081612c41565b919050565b5f805f805f60808688031215612c79575f80fd5b8535612c8481612c41565b94506020860135612c9481612c41565b935060408601359250606086013567ffffffffffffffff80821115612cb7575f80fd5b818801915088601f830112612cca575f80fd5b813581811115612cd8575f80fd5b896020828501011115612ce9575f80fd5b9699959850939650602001949392505050565b5f60208284031215612d0c575f80fd5b5035919050565b602080825282516001600160a01b0390811683830152838201511660408084019190915283015160c06060840152805160e084018190525f929182019083906101008601905b80831015612d795783518252928401926001929092019190840190612d59565b5060608701516080870152608087015160a087015260a087015160c08701528094505050505092915050565b5f815180845260208085019450602084015f5b83811015612dd457815187529582019590820190600101612db8565b509495945050505050565b602081525f61073c6020830184612da5565b634e487b7160e01b5f52604160045260245ffd5b6040516101e0810167ffffffffffffffff81118282101715612e2957612e29612df1565b60405290565b604051610100810167ffffffffffffffff81118282101715612e2957612e29612df1565b604051601f8201601f1916810167ffffffffffffffff81118282101715612e7c57612e7c612df1565b604052919050565b5f67ffffffffffffffff821115612e9d57612e9d612df1565b5060051b60200190565b5f82601f830112612eb6575f80fd5b81356020612ecb612ec683612e84565b612e53565b8083825260208201915060208460051b870101935086841115612eec575f80fd5b602086015b84811015612f085780358352918301918301612ef1565b509695505050505050565b5f805f60608486031215612f25575f80fd5b833567ffffffffffffffff80821115612f3c575f80fd5b908501906101e08288031215612f50575f80fd5b612f58612e05565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013583811115612fc1575f80fd5b612fcd8a828701612ea7565b91830191909152506101408381013590820152610160808401359082015261018080840135908201526101a09150613006828401612c55565b828201526101c0915061301a828401612c55565b8282015280955050505061303060208501612c55565b915061303e60408501612c55565b90509250925092565b608081525f6130596080830187612da5565b828103602084015261306b8187612da5565b9050828103604084015261307f8186612da5565b905082810360608401526130938185612da5565b979650505050505050565b634e487b7160e01b5f52602160045260245ffd5b60208101600383106130d257634e487b7160e01b5f52602160045260245ffd5b91905290565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156106405761064061310d565b634e487b7160e01b5f52603260045260245ffd5b80820281158282048414176106405761064061310d565b634e487b7160e01b5f52601260045260245ffd5b5f826131815761318161315f565b500490565b80516bffffffffffffffffffffffff81168114612c60575f80fd5b8051612c6081612c41565b805163ffffffff81168114612c60575f80fd5b805160068110612c60575f80fd5b5f82601f8301126131dc575f80fd5b815160206131ec612ec683612e84565b8083825260208201915060208460051b87010193508684111561320d575f80fd5b602086015b84811015612f0857613223816131ac565b8352918301918301613212565b5f60208284031215613240575f80fd5b815167ffffffffffffffff80821115613257575f80fd5b90830190610100828603121561326b575f80fd5b613273612e2f565b61327c83613186565b815261328a602084016131a1565b6020820152604083015160408201526132a5606084016131ac565b60608201526132b6608084016131ac565b60808201526132c760a084016131ac565b60a08201526132d860c084016131bf565b60c082015260e0830151828111156132ee575f80fd5b6132fa878286016131cd565b60e08301525095945050505050565b5f602080838503121561331a575f80fd5b825167ffffffffffffffff811115613330575f80fd5b8301601f81018513613340575f80fd5b805161334e612ec682612e84565b81815260059190911b8201830190838101908783111561336c575f80fd5b928401925b8284101561309357835182529284019290840190613371565b828152604060208201525f6133a26040830184612da5565b949350505050565b818103818111156106405761064061310d565b5f600182016133ce576133ce61310d565b5060010190565b848152608060208201525f6133ed6080830186612da5565b82810360408401526133ff8186612da5565b91505082606083015295945050505050565b634e487b7160e01b5f52603160045260245ffd5b848152608060208201525f61343d6080830186612da5565b6040830194909452506060015292915050565b5f60608201858352602060606020850152818654808452608086019150875f5260205f2093505f5b8181101561349457845483526001948501949284019201613478565b5050809350505050826040830152949350505050565b5f80604083850312156134bb575f80fd5b82516134c681612c41565b91506134d460208401613186565b90509250929050565b5f602082840312156134ed575f80fd5b5051919050565b5f816135025761350261310d565b505f190190565b5f815180845260208085019450602084015f5b83811015612dd45781516001600160a01b03168752958201959082019060010161351c565b608081525f6135536080830187612da5565b82810360208401526135658187613509565b9050828103604084015261307f8186613509565b5f82518060208501845e5f920191825250919050565b5f8261359d5761359d61315f565b500690565b606081525f6135b46060830186612da5565b82810360208401526135c68186612da5565b915050826040830152949350505050565b5f602082840312156135e7575f80fd5b8151801515811461073c575f80fdfea26469706673582212205776961a63fdaa13bebe3a0b2e71165c50721be211795e8926959409ae3d540364736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/operate/data/contracts/service_staking_token/contract.py b/operate/data/contracts/staking_token/contract.py similarity index 84% rename from operate/data/contracts/service_staking_token/contract.py rename to operate/data/contracts/staking_token/contract.py index 0326255a4..8bc883783 100644 --- a/operate/data/contracts/service_staking_token/contract.py +++ b/operate/data/contracts/staking_token/contract.py @@ -17,7 +17,7 @@ # # ------------------------------------------------------------------------------ -"""This module contains the class to connect to the `ServiceStakingTokenMechUsage` contract.""" +"""This module contains the class to connect to the `StakingToken` contract.""" from enum import Enum @@ -27,18 +27,10 @@ from aea.crypto.base import LedgerApi -class StakingState(Enum): - """Staking state enumeration for the staking.""" +class StakingTokenContract(Contract): + """The Staking Token contract.""" - UNSTAKED = 0 - STAKED = 1 - EVICTED = 2 - - -class ServiceStakingTokenContract(Contract): - """The Service Staking contract.""" - - contract_id = PublicId.from_str("valory/service_staking_token:0.1.0") + contract_id = PublicId.from_str("valory/staking_token:0.1.0") @classmethod def get_service_staking_state( @@ -50,7 +42,7 @@ def get_service_staking_state( """Check whether the service is staked.""" contract_instance = cls.get_instance(ledger_api, contract_address) res = contract_instance.functions.getStakingState(service_id).call() - return dict(data=StakingState(res)) + return dict(data=res) @classmethod def build_stake_tx( @@ -121,6 +113,28 @@ def get_next_checkpoint_ts( ts = contract.functions.getNextRewardCheckpointTimestamp().call() return dict(data=ts) + @classmethod + def ts_checkpoint( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Retrieve the checkpoint's timestamp.""" + contract = cls.get_instance(ledger_api, contract_address) + ts_checkpoint = contract.functions.tsCheckpoint().call() + return dict(data=ts_checkpoint) + + @classmethod + def liveness_ratio( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Retrieve the liveness ratio.""" + contract = cls.get_instance(ledger_api, contract_address) + liveness_ratio = contract.functions.livenessRatio().call() + return dict(data=liveness_ratio) + @classmethod def get_liveness_period( cls, diff --git a/operate/data/contracts/staking_token/contract.yaml b/operate/data/contracts/staking_token/contract.yaml new file mode 100644 index 000000000..e1a858361 --- /dev/null +++ b/operate/data/contracts/staking_token/contract.yaml @@ -0,0 +1,23 @@ +name: staking_token +author: valory +version: 0.1.0 +type: contract +description: Service staking token contract +license: Apache-2.0 +aea_version: '>=1.0.0, <2.0.0' +fingerprint: + __init__.py: bafybeicmgkagyhgwn2ktcdjbprijalbdyj26cvza4d3b7uvmehvy4mmr3i + build/StakingToken.json: bafybeibhcwyawq377innrpq4ytpw5kotufjqo7cyd2rjhyit34mnbks5b4 + contract.py: bafybeigjt7a2biiorp4vmj4d3qkm3xbbohnawoetywojye5akhavlvkrxm +fingerprint_ignore_patterns: [] +contracts: [] +class_name: StakingTokenContract +contract_interface_paths: + ethereum: build/StakingToken.json +dependencies: + open-aea-ledger-ethereum: + version: <2,>=1.53.0 + open-aea-test-autonomy: + version: <1,>=0.14.14.post1 + web3: + version: <7,>=6.0.0 diff --git a/operate/data/contracts/uniswap_v2_erc20/contract.py b/operate/data/contracts/uniswap_v2_erc20/contract.py index e1fd2f3a9..76a10d8f0 100644 --- a/operate/data/contracts/uniswap_v2_erc20/contract.py +++ b/operate/data/contracts/uniswap_v2_erc20/contract.py @@ -198,6 +198,7 @@ def get_transaction_transfer_logs( # type: ignore # pylint: disable=too-many-a transfer_logs: List = [] if transfer_logs_data: + transfer_logs = cast( List, transfer_logs_data["logs"], diff --git a/operate/data/contracts/uniswap_v2_erc20/contract.yaml b/operate/data/contracts/uniswap_v2_erc20/contract.yaml index 311f5cabc..0c99a3faa 100644 --- a/operate/data/contracts/uniswap_v2_erc20/contract.yaml +++ b/operate/data/contracts/uniswap_v2_erc20/contract.yaml @@ -8,7 +8,9 @@ aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeia75xbvf6zogcloppdcu2zrwcl6d46ebj2zmm6dkge6eno3k6ysw4 build/IUniswapV2ERC20.json: bafybeid45gy6x5ah5ub5p2obdhph36skpoy5qdhikwwfso7f3655iqnpc4 - contract.py: bafybeiarfpumhdmxh24xuiv6jprjq5f6qlrfrlxisz5enbvvbhotafp37e + contract.py: bafybeidxnb72n5xz4fvvxogbk2xk2vz4jvtsqa3berolr34v7cug3snism + tests/__init__.py: bafybeigj3ngmfmyy4nw4xipxbqnx4nd42aqidqmmduwpx6hurssjqqkirq + tests/test_contract.py: bafybeigaf7kyhuy4qn5dww2r62hffhytab3uhmjummsaiazzvqetvomyi4 fingerprint_ignore_patterns: [] contracts: [] class_name: UniswapV2ERC20Contract diff --git a/operate/data/contracts/uniswap_v2_erc20/tests/__init__.py b/operate/data/contracts/uniswap_v2_erc20/tests/__init__.py new file mode 100644 index 000000000..fb07e2b7d --- /dev/null +++ b/operate/data/contracts/uniswap_v2_erc20/tests/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2021-2022 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""Tests package for valory/uniswap_v2_erc20 contract.""" diff --git a/operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py b/operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py new file mode 100644 index 000000000..5fc9562ef --- /dev/null +++ b/operate/data/contracts/uniswap_v2_erc20/tests/test_contract.py @@ -0,0 +1,363 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2021-2022 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""Tests for valory/uniswap_v2_erc20 contract.""" + +from pathlib import Path +from typing import Dict +from unittest import mock + +from aea.test_tools.test_contract import BaseContractTestCase + +from operate.data.contracts.uniswap_v2_erc20.contract import UniswapV2ERC20Contract + +PACKAGE_DIR = Path(__file__).parent.parent + + +CONTRACT_ADDRESS = "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2" +ADDRESS_ONE = "0x46F415F7BF30f4227F98def9d2B22ff62738fD68" +ADDRESS_TWO = "0x7A1236d5195e31f1F573AD618b2b6FEFC85C5Ce6" +ADDRESS_THREE = "0x7A1236d5195e31f1F573AD618b2b6FEFC85C5Ce6" +NONCE = 0 +CHAIN_ID = 1 +MAX_ALLOWANCE = 2 ** 256 - 1 + + +class TestUniswapV2ERC20Contract(BaseContractTestCase): + """Test TestUniswapV2ERC20Contract.""" + + path_to_contract = PACKAGE_DIR + ledger_identifier = "ethereum" + contract: UniswapV2ERC20Contract + owner_address = ADDRESS_ONE + sender_address = ADDRESS_TWO + gas_price = 100 + + @classmethod + def finish_contract_deployment(cls) -> str: + """Finish the contract deployment.""" + contract_address = CONTRACT_ADDRESS + return contract_address + + @classmethod + def _deploy_contract(cls, contract, ledger_api, deployer_crypto, gas) -> Dict: # type: ignore + """Deploy contract.""" + return {} + + def test_approve(self) -> None: + """Test approve.""" + eth_value = 0 + gas = 100 + spender_address = ADDRESS_THREE + approval_value = 100 + data = self.contract.get_instance( + self.ledger_api, self.contract_address + ).encodeABI(fn_name="approve", args=[spender_address, approval_value]) + with mock.patch.object( + self.ledger_api.api.eth, "get_transaction_count", return_value=NONCE + ): + with mock.patch.object( + self.ledger_api.api.manager, "request_blocking", return_value=CHAIN_ID + ): + result = self.contract.approve( + self.ledger_api, + self.contract_address, + spender_address, + approval_value, + sender_address=self.sender_address, + gas=gas, + gasPrice=self.gas_price, + ) + assert result == { + "chainId": CHAIN_ID, + "data": data, + "gas": gas, + "gasPrice": self.gas_price, + "nonce": NONCE, + "to": CONTRACT_ADDRESS, + "value": eth_value, + } + + def test_transfer(self) -> None: + """Test transfer.""" + eth_value = 0 + gas = 100 + spender_address = ADDRESS_THREE + value = 100 + data = self.contract.get_instance( + self.ledger_api, self.contract_address + ).encodeABI(fn_name="transfer", args=[spender_address, value]) + with mock.patch.object( + self.ledger_api.api.eth, "get_transaction_count", return_value=NONCE + ): + with mock.patch.object( + self.ledger_api.api.manager, "request_blocking", return_value=CHAIN_ID + ): + result = self.contract.transfer( + self.ledger_api, + self.contract_address, + spender_address, + value, + sender_address=self.sender_address, + gas=gas, + gasPrice=self.gas_price, + ) + assert result == { + "chainId": CHAIN_ID, + "data": data, + "gas": gas, + "gasPrice": self.gas_price, + "nonce": NONCE, + "to": CONTRACT_ADDRESS, + "value": eth_value, + } + + def test_transfer_from(self) -> None: + """Test transfer_from.""" + eth_value = 0 + gas = 100 + from_address = ADDRESS_THREE + to_address = ADDRESS_ONE + value = 100 + data = self.contract.get_instance( + self.ledger_api, self.contract_address + ).encodeABI(fn_name="transferFrom", args=[from_address, to_address, value]) + with mock.patch.object( + self.ledger_api.api.eth, "get_transaction_count", return_value=NONCE + ): + with mock.patch.object( + self.ledger_api.api.manager, "request_blocking", return_value=CHAIN_ID + ): + result = self.contract.transfer_from( + self.ledger_api, + self.contract_address, + from_address, + to_address, + value, + sender_address=self.sender_address, + gas=gas, + gasPrice=self.gas_price, + ) + assert result == { + "chainId": CHAIN_ID, + "data": data, + "gas": gas, + "gasPrice": self.gas_price, + "nonce": NONCE, + "to": CONTRACT_ADDRESS, + "value": eth_value, + } + + def test_permit(self) -> None: + """Test permit.""" + eth_value = 0 + gas = 100 + owner_address = ADDRESS_THREE + spender_address = CONTRACT_ADDRESS + value = 100 + deadline = 10 + v = 10 + r = b"" + s = b"" + data = self.contract.get_instance( + self.ledger_api, self.contract_address + ).encodeABI( + fn_name="permit", + args=[owner_address, spender_address, value, deadline, v, r, s], + ) + with mock.patch.object( + self.ledger_api.api.eth, "get_transaction_count", return_value=NONCE + ): + with mock.patch.object( + self.ledger_api.api.manager, "request_blocking", return_value=CHAIN_ID + ): + result = self.contract.permit( + self.ledger_api, + self.contract_address, + owner_address, + spender_address, + value, + deadline, + v, + r, + s, + sender_address=self.sender_address, + gas=gas, + gasPrice=self.gas_price, + ) + assert result == { + "chainId": CHAIN_ID, + "data": data, + "gas": gas, + "gasPrice": self.gas_price, + "nonce": NONCE, + "to": CONTRACT_ADDRESS, + "value": eth_value, + } + + def test_allowance(self) -> None: + """Test allowance.""" + owner_address = ADDRESS_ONE + spender_address = ADDRESS_THREE + with mock.patch.object( + self.ledger_api.api.manager, + "request_blocking", + return_value="0x0000000000000000000000000000000000000000000000000000000000000000", + ): + result = self.contract.allowance( + self.ledger_api, + self.contract_address, + owner_address, + spender_address, + ) + assert result == 0 + + def test_balance_of(self) -> None: + """Test balance_of.""" + owner_address = ADDRESS_THREE + with mock.patch.object( + self.ledger_api.api.manager, + "request_blocking", + return_value="0x0000000000000000000000000000000000000000000000000000000000000000", + ): + result = self.contract.balance_of( + self.ledger_api, self.contract_address, owner_address + ) + assert result == 0 + + def test_get_approve_data(self) -> None: + """Test get_method_data with approve.""" + + result = self.contract.get_method_data( + ledger_api=self.ledger_api, + contract_address=self.contract_address, + method_name="approve", + spender=ADDRESS_ONE, + value=MAX_ALLOWANCE, + ) + assert result == { + "data": b"\t^\xa7\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"F\xf4\x15\xf7\xbf0\xf4\"\x7f\x98\xde\xf9\xd2\xb2/\xf6'8\xfdh" + b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + } + + def test_get_transfer_data(self) -> None: + """Test get_method_data with transfer.""" + + result = self.contract.get_method_data( + ledger_api=self.ledger_api, + contract_address=self.contract_address, + method_name="transfer", + to=ADDRESS_ONE, + value=1, + ) + assert result == { + "data": b"\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"F\xf4\x15\xf7\xbf0\xf4\"\x7f\x98\xde\xf9\xd2\xb2/\xf6'8\xfdh" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + } + + def test_get_transfer_from_data(self) -> None: + """Test get_method_data with transfer_from.""" + + # "from" is a reserved word, so must be passed as kwargs + kwargs = {"from": ADDRESS_TWO, "to": ADDRESS_ONE, "value": 1} + + result = self.contract.get_method_data( + ledger_api=self.ledger_api, + contract_address=self.contract_address, + method_name="transfer_from", + **kwargs + ) + assert result == { + "data": b"#\xb8r\xdd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x126\xd5" + b"\x19^1\xf1\xf5s\xada\x8b+o\xef\xc8\\\\\xe6\x00\x00\x00\x00" + b'\x00\x00\x00\x00\x00\x00\x00\x00F\xf4\x15\xf7\xbf0\xf4"' + b"\x7f\x98\xde\xf9\xd2\xb2/\xf6'8\xfdh\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x01" + } + + def test_get_permit_data(self) -> None: + """Test get_method_data with permit.""" + + result = self.contract.get_method_data( + ledger_api=self.ledger_api, + contract_address=self.contract_address, + method_name="permit", + owner=ADDRESS_ONE, + spender=ADDRESS_TWO, + value=1, + deadline=300, + v=0, + r=b"0", + s=b"0", + ) + + assert result == { + "data": b"\xd5\x05\xac\xcf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"F\xf4\x15\xf7\xbf0\xf4\"\x7f\x98\xde\xf9\xd2\xb2/\xf6'8\xfdh" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x126\xd5\x19^1\xf1" + b"\xf5s\xada\x8b+o\xef\xc8\\\\\xe6\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x01,\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00" + } + + def test_get_allowance_data(self) -> None: + """Test get_method_data with allowance.""" + + result = self.contract.get_method_data( + ledger_api=self.ledger_api, + contract_address=self.contract_address, + method_name="allowance", + owner=ADDRESS_ONE, + spender=ADDRESS_TWO, + ) + + assert result == { + "data": b"\xddb\xed>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"F\xf4\x15\xf7\xbf0\xf4\"\x7f\x98\xde\xf9\xd2\xb2/\xf6'8\xfdh" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x126\xd5\x19^1\xf1" + b"\xf5s\xada\x8b+o\xef\xc8\\\\\xe6" + } + + def test_get_balance_of_data(self) -> None: + """Test get_method_data with balance_of.""" + + result = self.contract.get_method_data( + ledger_api=self.ledger_api, + contract_address=self.contract_address, + method_name="balance_of", + owner=ADDRESS_ONE, + ) + + assert result == { + "data": b"p\xa0\x821\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"F\xf4\x15\xf7\xbf0\xf4\"\x7f\x98\xde\xf9\xd2\xb2/\xf6'8\xfdh" + } diff --git a/operate/ledger/__init__.py b/operate/ledger/__init__.py index 7238257f8..becd45f4f 100644 --- a/operate/ledger/__init__.py +++ b/operate/ledger/__init__.py @@ -25,63 +25,55 @@ from operate.ledger.base import LedgerHelper from operate.ledger.ethereum import Ethereum from operate.ledger.solana import Solana -from operate.operate_types import ChainType, LedgerType +from operate.operate_types import Chain, LedgerType -ETHEREUM_PUBLIC_RPC = os.environ.get( - "ETHEREUM_DEV_RPC", "https://ethereum.publicnode.com" -) -GNOSIS_PUBLIC_RPC = os.environ.get( - "GNOSIS_DEV_RPC", "https://gnosis-rpc.publicnode.com" -) +ETHEREUM_PUBLIC_RPC = os.environ.get("ETHEREUM_RPC", "https://ethereum.publicnode.com") +GNOSIS_PUBLIC_RPC = os.environ.get("GNOSIS_RPC", "https://gnosis-rpc.publicnode.com") GOERLI_PUBLIC_RPC = os.environ.get( - "GOERLI_DEV_RPC", "https://ethereum-goerli.publicnode.com" + "GOERLI_RPC", "https://ethereum-goerli.publicnode.com" ) -SOLANA_PUBLIC_RPC = os.environ.get( - "SOLANA_DEV_RPC", "https://api.mainnet-beta.solana.com" -) -BASE_PUBLIC_RPC = os.environ.get("BASE_DEV_RPC", "https://mainnet.base.org") -OPTIMISM_PUBLIC_RPC = os.environ.get("OPTIMISM_DEV_RPC", "https://mainnet.optimism.io") -MODE_PUBLIC_RPC = os.environ.get("MODE_DEV_RPC", "https://rpc.mode.network") - -ETHEREUM_RPC = os.environ.get("ETHEREUM_DEV_RPC", "https://ethereum.publicnode.com") -GNOSIS_RPC = os.environ.get( - "GNOSIS_DEV_RPC", "https://rpc-gate.autonolas.tech/gnosis-rpc/" -) -GOERLI_RPC = os.environ.get("GOERLI_DEV_RPC", "https://ethereum-goerli.publicnode.com") -SOLANA_RPC = os.environ.get("SOLANA_DEV_RPC", "https://api.mainnet-beta.solana.com") -BASE_RPC = os.environ.get("BASE_DEV_RPC", "https://mainnet.base.org") -OPTIMISM_RPC = os.environ.get("OPTIMISM_DEV_RPC", "https://mainnet.optimism.io") -MODE_RPC = os.environ.get("MODE_DEV_RPC", "https://rpc.mode.network") +SOLANA_PUBLIC_RPC = os.environ.get("SOLANA_RPC", "https://api.mainnet-beta.solana.com") +BASE_PUBLIC_RPC = os.environ.get("BASE_RPC", "https://mainnet.base.org") +OPTIMISM_PUBLIC_RPC = os.environ.get("OPTIMISM_RPC", "https://mainnet.optimism.io") +MODE_PUBLIC_RPC = os.environ.get("MODE_RPC", "https://rpc.mode.network") + +ETHEREUM_RPC = os.environ.get("ETHEREUM_RPC", "https://ethereum.publicnode.com") +GNOSIS_RPC = os.environ.get("GNOSIS_RPC", "https://rpc-gate.autonolas.tech/gnosis-rpc/") +GOERLI_RPC = os.environ.get("GOERLI_RPC", "https://ethereum-goerli.publicnode.com") +SOLANA_RPC = os.environ.get("SOLANA_RPC", "https://api.mainnet-beta.solana.com") +BASE_RPC = os.environ.get("BASE_RPC", "https://mainnet.base.org") +OPTIMISM_RPC = os.environ.get("OPTIMISM_RPC", "https://mainnet.optimism.io") +MODE_RPC = os.environ.get("MODE_RPC", "https://rpc.mode.network") PUBLIC_RPCS = { - ChainType.ETHEREUM: ETHEREUM_PUBLIC_RPC, - ChainType.GNOSIS: GNOSIS_PUBLIC_RPC, - ChainType.GOERLI: GOERLI_PUBLIC_RPC, - ChainType.SOLANA: SOLANA_PUBLIC_RPC, - ChainType.BASE: BASE_PUBLIC_RPC, - ChainType.OPTIMISM: OPTIMISM_PUBLIC_RPC, - ChainType.MODE: MODE_PUBLIC_RPC, + Chain.ETHEREUM: ETHEREUM_PUBLIC_RPC, + Chain.GNOSIS: GNOSIS_PUBLIC_RPC, + Chain.GOERLI: GOERLI_PUBLIC_RPC, + Chain.SOLANA: SOLANA_PUBLIC_RPC, + Chain.BASE: BASE_PUBLIC_RPC, + Chain.OPTIMISTIC: OPTIMISM_PUBLIC_RPC, + Chain.MODE: MODE_PUBLIC_RPC, } DEFAULT_RPCS = { - ChainType.ETHEREUM: ETHEREUM_RPC, - ChainType.GNOSIS: GNOSIS_RPC, - ChainType.GOERLI: GOERLI_RPC, - ChainType.SOLANA: SOLANA_RPC, - ChainType.BASE: BASE_RPC, - ChainType.OPTIMISM: OPTIMISM_RPC, - ChainType.MODE: MODE_RPC, + Chain.ETHEREUM: ETHEREUM_RPC, + Chain.GNOSIS: GNOSIS_RPC, + Chain.GOERLI: GOERLI_RPC, + Chain.SOLANA: SOLANA_RPC, + Chain.BASE: BASE_RPC, + Chain.OPTIMISTIC: OPTIMISM_RPC, + Chain.MODE: MODE_RPC, } -CHAIN_HELPERS: t.Dict[ChainType, t.Type[LedgerHelper]] = { - ChainType.ETHEREUM: Ethereum, - ChainType.GNOSIS: Ethereum, - ChainType.GOERLI: Ethereum, - ChainType.SOLANA: Solana, - ChainType.BASE: Ethereum, - ChainType.OPTIMISM: Ethereum, - ChainType.MODE: Ethereum, +CHAIN_HELPERS: t.Dict[Chain, t.Type[LedgerHelper]] = { + Chain.ETHEREUM: Ethereum, + Chain.GNOSIS: Ethereum, + Chain.GOERLI: Ethereum, + Chain.SOLANA: Solana, + Chain.BASE: Ethereum, + Chain.OPTIMISTIC: Ethereum, + Chain.MODE: Ethereum, } LEDGER_HELPERS: t.Dict[LedgerType, t.Type[LedgerHelper]] = { @@ -90,36 +82,22 @@ } CURRENCY_DENOMS = { - ChainType.ETHEREUM: "Wei", - ChainType.GNOSIS: "xDai", - ChainType.GOERLI: "GWei", - ChainType.SOLANA: "Lamp", - ChainType.BASE: "Wei", - ChainType.OPTIMISM: "Wei", - ChainType.MODE: "Wei", + Chain.ETHEREUM: "Wei", + Chain.GNOSIS: "xDai", + Chain.GOERLI: "GWei", + Chain.SOLANA: "Lamp", + Chain.BASE: "Wei", + Chain.OPTIMISTIC: "Wei", + Chain.MODE: "Wei", } -def get_default_rpc(chain: ChainType) -> str: +def get_default_rpc(chain: Chain) -> str: """Get default RPC chain type.""" return DEFAULT_RPCS.get(chain, ETHEREUM_RPC) -def get_ledger_type_from_chain_type(chain: ChainType) -> LedgerType: - """Get LedgerType from ChainType.""" - if chain in ( - ChainType.ETHEREUM, - ChainType.GOERLI, - ChainType.GNOSIS, - ChainType.BASE, - ChainType.OPTIMISM, - ChainType.MODE, - ): - return LedgerType.ETHEREUM - return LedgerType.SOLANA - - -def get_ledger_helper_by_chain(rpc: str, chain: ChainType) -> LedgerHelper: +def get_ledger_helper_by_chain(rpc: str, chain: Chain) -> LedgerHelper: """Get ledger helper by chain type.""" return CHAIN_HELPERS.get(chain, Ethereum)(rpc=rpc) @@ -129,6 +107,6 @@ def get_ledger_helper_by_ledger(rpc: str, ledger: LedgerHelper) -> LedgerHelper: return LEDGER_HELPERS.get(ledger, Ethereum)(rpc=rpc) # type: ignore -def get_currency_denom(chain: ChainType) -> str: +def get_currency_denom(chain: Chain) -> str: """Get currency denom by chain type.""" return CURRENCY_DENOMS.get(chain, "Wei") diff --git a/operate/ledger/profiles.py b/operate/ledger/profiles.py index db1c53a37..1c66ef6c2 100644 --- a/operate/ledger/profiles.py +++ b/operate/ledger/profiles.py @@ -19,11 +19,13 @@ """Chain profiles.""" -from operate.operate_types import ChainType, ContractAddresses +import typing as t +from operate.operate_types import Chain, ContractAddresses -CONTRACTS = { - ChainType.GNOSIS: ContractAddresses( + +CONTRACTS: t.Dict[Chain, ContractAddresses] = { + Chain.GNOSIS: ContractAddresses( { "service_manager": "0x04b0007b2aFb398015B76e5f22993a1fddF83644", "service_registry": "0x9338b5153AE39BB89f50468E608eD9d764B755fD", @@ -33,7 +35,7 @@ "multisend": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", } ), - ChainType.OPTIMISM: ContractAddresses( + Chain.OPTIMISTIC: ContractAddresses( { "service_manager": "0xFbBEc0C8b13B38a9aC0499694A69a10204c5E2aB", "service_registry": "0x3d77596beb0f130a4415df3D2D8232B3d3D31e44", @@ -43,7 +45,7 @@ "multisend": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", } ), - ChainType.ETHEREUM: ContractAddresses( + Chain.ETHEREUM: ContractAddresses( { "service_manager": "0x2EA682121f815FBcF86EA3F3CaFdd5d67F2dB143", "service_registry": "0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA", @@ -53,7 +55,7 @@ "multisend": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", } ), - ChainType.BASE: ContractAddresses( + Chain.BASE: ContractAddresses( { "service_manager": "0x63e66d7ad413C01A7b49C7FF4e3Bb765C4E4bd1b", "service_registry": "0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE", @@ -63,7 +65,7 @@ "multisend": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", } ), - ChainType.MODE: ContractAddresses( + Chain.MODE: ContractAddresses( { "service_manager": "0x63e66d7ad413C01A7b49C7FF4e3Bb765C4E4bd1b", "service_registry": "0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE", @@ -75,8 +77,8 @@ ), } -STAKING = { - ChainType.GNOSIS: { +STAKING: t.Dict[Chain, t.Dict[str, str]] = { + Chain.GNOSIS: { "pearl_alpha": "0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A", "pearl_beta": "0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d", "pearl_beta_2": "0x1c2F82413666d2a3fD8bC337b0268e62dDF67434", @@ -85,18 +87,28 @@ "pearl_beta_5": "0x4Abe376Fda28c2F43b84884E5f822eA775DeA9F4", "pearl_beta_mech_marketplace": "0xDaF34eC46298b53a3d24CBCb431E84eBd23927dA", }, - ChainType.OPTIMISM: { + Chain.OPTIMISTIC: { "optimus_alpha": "0x88996bbdE7f982D93214881756840cE2c77C4992", }, - ChainType.ETHEREUM: {}, - ChainType.BASE: {}, - ChainType.MODE: {}, + Chain.ETHEREUM: {}, + Chain.BASE: {}, + Chain.MODE: { + "optimus_alpha": "0x5fc25f50E96857373C64dC0eDb1AbCBEd4587e91", + }, +} + +OLAS: t.Dict[Chain, str] = { + Chain.GNOSIS: "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f", + Chain.OPTIMISTIC: "0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527", + Chain.BASE: "0x54330d28ca3357F294334BDC454a032e7f353416", + Chain.ETHEREUM: "0x0001A500A6B18995B03f44bb040A5fFc28E45CB0", + Chain.MODE: "0xcfD1D50ce23C46D3Cf6407487B2F8934e96DC8f9", } -OLAS = { - ChainType.GNOSIS: "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f", - ChainType.OPTIMISM: "0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527", - ChainType.BASE: "0x54330d28ca3357F294334BDC454a032e7f353416", - ChainType.ETHEREUM: "0x0001A500A6B18995B03f44bb040A5fFc28E45CB0", - ChainType.MODE: "0xcfD1D50ce23C46D3Cf6407487B2F8934e96DC8f9", +USDC: t.Dict[Chain, str] = { + Chain.GNOSIS: "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83", + Chain.OPTIMISTIC: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", + Chain.BASE: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + Chain.ETHEREUM: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + Chain.MODE: "0xd988097fb8612cc24eeC14542bC03424c656005f", } diff --git a/operate/operate_types.py b/operate/operate_types.py index aa995c0a0..9a6838377 100644 --- a/operate/operate_types.py +++ b/operate/operate_types.py @@ -20,9 +20,12 @@ """Types module.""" import enum +import os import typing as t from dataclasses import dataclass +from autonomy.chain.config import ChainType +from autonomy.chain.constants import CHAIN_NAME_TO_CHAIN_ID from typing_extensions import TypedDict from operate.resource import LocalResource @@ -35,45 +38,19 @@ "stop": 3, } - -_CHAIN_NAME_TO_ENUM = { - "ethereum": 0, - "goerli": 1, - "gnosis": 2, - "solana": 3, - "optimism": 4, - "base": 5, - "mode": 6, -} +CHAIN_NAME_TO_CHAIN_ID["mode"] = 34443 # TODO: update open-autonomy and remove this +CHAIN_NAME_TO_CHAIN_ID["solana"] = 900 _CHAIN_ID_TO_CHAIN_NAME = { - 1: "ethereum", - 5: "goerli", - 100: "gnosis", - 1399811149: "solana", - 10: "optimism", - 8453: "base", - 34443: "mode", + chain_id: chain_name for chain_name, chain_id in CHAIN_NAME_TO_CHAIN_ID.items() } -_CHAIN_NAME_TO_ID = {val: key for key, val in _CHAIN_ID_TO_CHAIN_NAME.items()} - -_LEDGER_TYPE_TO_ENUM = { - "ethereum": 0, - "solana": 1, -} - -class LedgerType(enum.IntEnum): +class LedgerType(str, enum.Enum): """Ledger type enum.""" - ETHEREUM = 0 - SOLANA = 1 - - @classmethod - def from_string(cls, chain: str) -> "LedgerType": - """Load from string.""" - return cls(_LEDGER_TYPE_TO_ENUM[chain.lower()]) + ETHEREUM = "ethereum" + SOLANA = "solana" @property def config_file(self) -> str: @@ -85,32 +62,78 @@ def key_file(self) -> str: """Key filename.""" return f"{self.name.lower()}.txt" + @classmethod + def from_id(cls, chain_id: int) -> "LedgerType": + """Load from chain ID.""" + return Chain(_CHAIN_ID_TO_CHAIN_NAME[chain_id]).ledger_type + + +# Dynamically create the Chain enum from the ChainType +# TODO: Migrate this to open-autonomy and remove this modified version of Chain here and use the one from open-autonomy +# This version of open-autonomy must support the LedgerType to support SOLANA in the future +# If solana support is not fuly implemented, decide to keep this half-baked feature. +# +# TODO: Once the above issue is properly implemented in Open Autonomy, remove the following +# lines from tox.ini: +# +# exclude = ^(operate/operate_types\.py|scripts/setup_wallet\.py|operate/ledger/profiles\.py|operate/ledger/__init__\.py|operate/wallet/master\.py|operate/services/protocol\.py|operate/services/manage\.py|operate/cli\.py)$ +# +# [mypy-operate.*] +# follow_imports = skip # noqa +# +# These lines were itroduced to resolve mypy issues with the temporary Chain/ChainType solution. +Chain = enum.Enum( + "Chain", + [(member.name, member.value) for member in ChainType] + + [ + ("MODE", "mode"), # TODO: update open-autonomy version and remove this + ("SOLANA", "solana"), + ], +) + -class ChainType(enum.IntEnum): - """Chain type enum.""" +class ChainMixin: + """Mixin for some new functions in the ChainType class.""" - ETHEREUM = 0 - GOERLI = 1 - GNOSIS = 2 - SOLANA = 3 - OPTIMISM = 4 - BASE = 5 - MODE = 6 + @property + def id(self) -> t.Optional[int]: + """Chain ID""" + if self == Chain.CUSTOM: + chain_id = os.environ.get("CUSTOM_CHAIN_ID") + if chain_id is None: + return None + return int(chain_id) + return CHAIN_NAME_TO_CHAIN_ID[self.value] @property - def id(self) -> int: - """Returns chain id.""" - return _CHAIN_NAME_TO_ID[self.name.lower()] + def ledger_type(self) -> LedgerType: + """Ledger type.""" + if self in ( + Chain.ETHEREUM, + Chain.GOERLI, + Chain.GNOSIS, + Chain.BASE, + Chain.OPTIMISTIC, + Chain.MODE, + ): + return LedgerType.ETHEREUM + return LedgerType.SOLANA @classmethod - def from_string(cls, chain: str) -> "ChainType": + def from_string(cls, chain: str) -> "Chain": """Load from string.""" - return cls(_CHAIN_NAME_TO_ENUM[chain.lower()]) + return Chain(chain.lower()) @classmethod - def from_id(cls, cid: int) -> "ChainType": + def from_id(cls, chain_id: int) -> "Chain": """Load from chain ID.""" - return cls(_CHAIN_NAME_TO_ENUM[_CHAIN_ID_TO_CHAIN_NAME[cid]]) + return Chain(_CHAIN_ID_TO_CHAIN_NAME[chain_id]) + + +# Add the ChainMixin methods to the Chain enum +for name in dir(ChainMixin): + if not name.startswith("__"): + setattr(Chain, name, getattr(ChainMixin, name)) class Action(enum.IntEnum): @@ -168,8 +191,7 @@ class LedgerConfig(LocalResource): """Ledger config.""" rpc: str - type: LedgerType - chain: ChainType + chain: Chain LedgerConfigs = t.Dict[str, LedgerConfig] @@ -203,7 +225,25 @@ class ConfigurationTemplate(TypedDict): fallback_chain_params: t.Optional[t.Dict] +class ServiceEnvProvisionType(str, enum.Enum): + """Service environment variable provision type.""" + + FIXED = "fixed" + USER = "user" + COMPUTED = "computed" + + +class EnvVariableAttributes(TypedDict): + """Service environment variable template.""" + + name: str + description: str + value: str + provision_type: ServiceEnvProvisionType + + ConfigurationTemplates = t.Dict[str, ConfigurationTemplate] +EnvVariables = t.Dict[str, EnvVariableAttributes] class ServiceTemplate(TypedDict): @@ -214,8 +254,9 @@ class ServiceTemplate(TypedDict): image: str description: str service_version: str - home_chain_id: str + home_chain: str configurations: ConfigurationTemplates + env_variables: EnvVariables @dataclass diff --git a/operate/resource.py b/operate/resource.py index a82db9ad5..b0ddc6909 100644 --- a/operate/resource.py +++ b/operate/resource.py @@ -32,11 +32,11 @@ def serialize(obj: t.Any) -> t.Any: """Serialize object.""" if is_dataclass(obj): - return asdict(obj) + return serialize(asdict(obj)) if isinstance(obj, Path): return str(obj) if isinstance(obj, dict): - return {key: serialize(obj=value) for key, value in obj.items()} + return {serialize(key): serialize(obj=value) for key, value in obj.items()} if isinstance(obj, list): return [serialize(obj=value) for value in obj] if isinstance(obj, enum.Enum): diff --git a/operate/services/deployment_runner.py b/operate/services/deployment_runner.py index ac5aeb156..997e971d4 100644 --- a/operate/services/deployment_runner.py +++ b/operate/services/deployment_runner.py @@ -28,12 +28,16 @@ import typing as t from abc import ABC, ABCMeta, abstractmethod from pathlib import Path +from traceback import print_exc from typing import Any from venv import main as venv_cli import psutil from aea.__version__ import __version__ as aea_version from autonomy.__version__ import __version__ as autonomy_version +from requests import get + +from operate import constants class AbstractDeploymentRunner(ABC): @@ -86,6 +90,9 @@ def kill_process(pid: int) -> None: class BaseDeploymentRunner(AbstractDeploymentRunner, metaclass=ABCMeta): """Base deployment with aea support.""" + TM_CONTROL_URL = constants.TM_CONTROL_URL + SLEEP_BEFORE_TM_KILL = 2 # seconds + def _run_aea(self, *args: str, cwd: Path) -> Any: """Run aea command.""" return self._run_cmd(args=[self._aea_bin, *args], cwd=cwd) @@ -128,7 +135,7 @@ def _prepare_agent_env(self) -> Any: for var in env: # Fix tendermint connection params if var.endswith("MODELS_PARAMS_ARGS_TENDERMINT_COM_URL"): - env[var] = "http://localhost:8080" + env[var] = self.TM_CONTROL_URL if var.endswith("MODELS_PARAMS_ARGS_TENDERMINT_URL"): env[var] = "http://localhost:26657" @@ -194,8 +201,17 @@ def _stop_agent(self) -> None: return kill_process(int(pid.read_text(encoding="utf-8"))) + def _get_tm_exit_url(self) -> str: + return f"{self.TM_CONTROL_URL}/exit" + def _stop_tendermint(self) -> None: """Start tendermint process.""" + try: + get(self._get_tm_exit_url()) + time.sleep(self.SLEEP_BEFORE_TM_KILL) + except Exception: # pylint: disable=broad-except + print_exc() + pid = self._work_directory / "tendermint.pid" if not pid.exists(): return diff --git a/operate/services/health_checker.py b/operate/services/health_checker.py index 6e56ed61c..86bd5353b 100644 --- a/operate/services/health_checker.py +++ b/operate/services/health_checker.py @@ -56,30 +56,32 @@ def __init__( self.sleep_period = sleep_period or self.SLEEP_PERIOD_DEFAULT self.number_of_fails = number_of_fails or self.NUMBER_OF_FAILS_DEFAULT - def start_for_service(self, service: str) -> None: + def start_for_service(self, service_config_id: str) -> None: """Start for a specific service.""" - self.logger.info(f"[HEALTH_CHECKER]: Starting healthcheck job for {service}") - if service in self._jobs: - self.stop_for_service(service=service) + self.logger.info( + f"[HEALTH_CHECKER]: Starting healthcheck job for {service_config_id}" + ) + if service_config_id in self._jobs: + self.stop_for_service(service_config_id=service_config_id) loop = asyncio.get_running_loop() - self._jobs[service] = loop.create_task( + self._jobs[service_config_id] = loop.create_task( self.healthcheck_job( - service=service, + service_config_id=service_config_id, ) ) - def stop_for_service(self, service: str) -> None: + def stop_for_service(self, service_config_id: str) -> None: """Stop for a specific service.""" - if service not in self._jobs: + if service_config_id not in self._jobs: return self.logger.info( - f"[HEALTH_CHECKER]: Cancelling existing healthcheck_jobs job for {service}" + f"[HEALTH_CHECKER]: Cancelling existing healthcheck_jobs job for {service_config_id}" ) - status = self._jobs[service].cancel() + status = self._jobs[service_config_id].cancel() if not status: self.logger.info( - f"[HEALTH_CHECKER]: Healthcheck job cancellation for {service} failed" + f"[HEALTH_CHECKER]: Healthcheck job cancellation for {service_config_id} failed" ) @classmethod @@ -96,20 +98,20 @@ async def check_service_health(cls, service: str) -> bool: async def healthcheck_job( self, - service: str, + service_config_id: str, ) -> None: """Start a background health check job.""" try: self.logger.info( - f"[HEALTH_CHECKER] Start healthcheck job for service: {service}" + f"[HEALTH_CHECKER] Start healthcheck job for service: {service_config_id}" ) async def _wait_for_port(sleep_period: int = 15) -> None: self.logger.info("[HEALTH_CHECKER]: wait port is up") while True: try: - await self.check_service_health(service) + await self.check_service_health(service_config_id) self.logger.info("[HEALTH_CHECKER]: port is UP") return except aiohttp.ClientConnectionError: @@ -136,40 +138,44 @@ async def _check_health( while True: try: # Check the service health - healthy = await self.check_service_health(service) + healthy = await self.check_service_health(service_config_id) except aiohttp.ClientConnectionError as e: print_exc() self.logger.warning( - f"[HEALTH_CHECKER] {service} port read failed. assume not healthy {e}" + f"[HEALTH_CHECKER] {service_config_id} port read failed. assume not healthy {e}" ) healthy = False if not healthy: fails += 1 self.logger.warning( - f"[HEALTH_CHECKER] {service} not healthy for {fails} time in a row" + f"[HEALTH_CHECKER] {service_config_id} not healthy for {fails} time in a row" ) else: - self.logger.info(f"[HEALTH_CHECKER] {service} is HEALTHY") + self.logger.info( + f"[HEALTH_CHECKER] {service_config_id} is HEALTHY" + ) # reset fails if comes healty fails = 0 if fails >= number_of_fails: # too much fails, exit self.logger.error( - f"[HEALTH_CHECKER] {service} failed {fails} times in a row. restart" + f"[HEALTH_CHECKER] {service_config_id} failed {fails} times in a row. restart" ) return await asyncio.sleep(sleep_period) - async def _restart(service_manager: ServiceManager, service: str) -> None: + async def _restart( + service_manager: ServiceManager, service_config_id: str + ) -> None: def _do_restart() -> None: - service_manager.stop_service_locally(hash=service) - # TODO Optimus patch, chain_id="10" - chain_id = "10" + service_manager.stop_service_locally( + service_config_id=service_config_id + ) service_manager.deploy_service_locally( - hash=service, chain_id=chain_id + service_config_id=service_config_id ) loop = asyncio.get_event_loop() @@ -182,11 +188,13 @@ def _do_restart() -> None: # upper cycle while True: - self.logger.info(f"[HEALTH_CHECKER] {service} wait for port ready") + self.logger.info( + f"[HEALTH_CHECKER] {service_config_id} wait for port ready" + ) if await _check_port_ready(timeout=self.port_up_timeout): # blocking till restart needed self.logger.info( - f"[HEALTH_CHECKER] {service} port is ready, checking health every {self.sleep_period}" + f"[HEALTH_CHECKER] {service_config_id} port is ready, checking health every {self.sleep_period}" ) await _check_health( number_of_fails=self.number_of_fails, @@ -200,7 +208,9 @@ def _do_restart() -> None: # perform restart # TODO: blocking!!!!!!! - await _restart(self._service_manager, service) + await _restart(self._service_manager, service_config_id) except Exception: - self.logger.exception(f"problems running healthcheckr for {service}") + self.logger.exception( + f"Problems running healthcheck job for {service_config_id}" + ) raise diff --git a/operate/services/manage.py b/operate/services/manage.py index 1b2954dbb..62e87083f 100644 --- a/operate/services/manage.py +++ b/operate/services/manage.py @@ -38,7 +38,7 @@ from operate.keys import Key, KeysManager from operate.ledger import PUBLIC_RPCS from operate.ledger.profiles import CONTRACTS, OLAS, STAKING -from operate.operate_types import ChainType, LedgerConfig, ServiceTemplate +from operate.operate_types import Chain, LedgerConfig, ServiceTemplate from operate.services.protocol import EthSafeTxBuilder, OnChainManager, StakingState from operate.services.service import ( ChainConfig, @@ -47,7 +47,7 @@ NON_EXISTENT_TOKEN, OnChainData, OnChainState, - OnChainUserParams, + SERVICE_CONFIG_PREFIX, Service, ) from operate.utils.gnosis import NULL_ADDRESS @@ -93,30 +93,26 @@ def __init__( self.keys_manager = keys_manager self.wallet_manager = wallet_manager self.logger = logger or setup_logger(name="operate.manager") - self._log_directories() def setup(self) -> None: """Setup service manager.""" self.path.mkdir(exist_ok=True) - @property - def json(self) -> t.List[t.Dict]: - """Returns the list of available services.""" - data = [] + def _get_all_services(self) -> t.List[Service]: + services = [] for path in self.path.iterdir(): - if path.name.startswith(DELETE_PREFIX): - shutil.rmtree(path) - continue - if not path.name.startswith("bafybei"): + if not path.name.startswith(SERVICE_CONFIG_PREFIX): continue try: service = Service.load(path=path) - data.append(service.json) + services.append(service) + except ValueError as e: + raise e except Exception as e: # pylint: disable=broad-except - self.logger.warning( - f"Failed to load service: {path.name}. Exception: {e}" + self.logger.error( + f"Failed to load service: {path.name}. Exception {e}: {traceback.format_exc()}" ) - # rename the invalid path + # Rename the invalid path timestamp = int(time.time()) invalid_path = path.parent / f"invalid_{timestamp}_{path.name}" os.rename(path, invalid_path) @@ -124,17 +120,22 @@ def json(self) -> t.List[t.Dict]: f"Renamed invalid service: {path.name} to {invalid_path.name}" ) - return data + return services - def exists(self, service: str) -> bool: + @property + def json(self) -> t.List[t.Dict]: + """Returns the list of available services.""" + return [service.json for service in self._get_all_services()] + + def exists(self, service_config_id: str) -> bool: """Check if service exists.""" - return (self.path / service).exists() + return (self.path / service_config_id).exists() def get_on_chain_manager(self, ledger_config: LedgerConfig) -> OnChainManager: """Get OnChainManager instance.""" return OnChainManager( rpc=ledger_config.rpc, - wallet=self.wallet_manager.load(ledger_config.type), + wallet=self.wallet_manager.load(ledger_config.chain.ledger_type), contracts=CONTRACTS[ledger_config.chain], ) @@ -142,7 +143,7 @@ def get_eth_safe_tx_builder(self, ledger_config: LedgerConfig) -> EthSafeTxBuild """Get EthSafeTxBuilder instance.""" return EthSafeTxBuilder( rpc=ledger_config.rpc, - wallet=self.wallet_manager.load(ledger_config.type), + wallet=self.wallet_manager.load(ledger_config.chain.ledger_type), contracts=CONTRACTS[ledger_config.chain], ) @@ -177,7 +178,6 @@ def load_or_create( ) service = Service.new( - hash=hash, keys=keys or [], storage=self.path, service_template=service_template, @@ -192,8 +192,48 @@ def load_or_create( return service - def _get_on_chain_state(self, service: Service, chain_id: str) -> OnChainState: - chain_config = service.chain_configs[chain_id] + def load( + self, + service_config_id: str, + ) -> Service: + """ + Load a service + + :param service_id: Service id + :return: Service instance + """ + path = self.path / service_config_id + return Service.load(path=path) + + def create( + self, + service_template: ServiceTemplate, + keys: t.Optional[t.List[Key]] = None, + ) -> Service: + """ + Create a service + + :param service_template: Service template + :param keys: Keys + :return: Service instance + """ + service = Service.new( + keys=keys or [], + storage=self.path, + service_template=service_template, + ) + + if not service.keys: + service.keys = [ + self.keys_manager.get(self.keys_manager.create()) + for _ in range(service.helper.config.number_of_agents) + ] + service.store() + + return service + + def _get_on_chain_state(self, service: Service, chain: str) -> OnChainState: + chain_config = service.chain_configs[chain] chain_data = chain_config.chain_data ledger_config = chain_config.ledger_config if chain_data.token == NON_EXISTENT_TOKEN: @@ -227,38 +267,29 @@ def _get_on_chain_hash(self, chain_config: ChainConfig) -> t.Optional[str]: def deploy_service_onchain( # pylint: disable=too-many-statements,too-many-locals self, - hash: str, + service_config_id: str, ) -> None: - """ - Deploy as service on-chain - - :param hash: Service hash - """ + """Deploy service on-chain""" # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version. - service = self.load_or_create(hash=hash) - for chain_id in service.chain_configs.keys(): + service = self.load(service_config_id=service_config_id) + for chain in service.chain_configs.keys(): self._deploy_service_onchain( - hash=hash, - chain_id=chain_id, + service_config_id=service_config_id, + chain=chain, ) def _deploy_service_onchain( # pylint: disable=too-many-statements,too-many-locals self, - hash: str, - chain_id: str, + service_config_id: str, + chain: str, ) -> None: - """ - Deploy as service on-chain - - :param hash: Service hash - :param update: Update the existing deployment - """ + """Deploy as service on-chain""" # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version. - self.logger.info(f"_deploy_service_onchain_from_safe {chain_id=}") - service = self.load_or_create(hash=hash) - chain_config = service.chain_configs[chain_id] + self.logger.info(f"_deploy_service_onchain {chain=}") + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data user_params = chain_config.chain_data.user_params @@ -336,7 +367,7 @@ def _deploy_service_onchain( # pylint: disable=too-many-statements,too-many-loc "min_staking_deposit" ] # TODO fixme, read from service registry token utility contract is_first_mint = ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.NON_EXISTENT ) is_update = ( @@ -380,6 +411,7 @@ def _deploy_service_onchain( # pylint: disable=too-many-statements,too-many-loc token=( OLAS[ledger_config.chain] if user_params.use_staking else None ), + metadata_description=service.description, ).get("token"), ) chain_data.on_chain_state = OnChainState.PRE_REGISTRATION @@ -438,43 +470,35 @@ def _deploy_service_onchain( # pylint: disable=too-many-statements,too-many-loc def deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,too-many-locals self, - hash: str, + service_config_id: str, ) -> None: - """ - Deploy as service on-chain + """Deploy as service on-chain""" - :param hash: Service hash - """ - service = self.load_or_create(hash=hash) - for chain_id in service.chain_configs.keys(): + service = self.load(service_config_id=service_config_id) + for chain in service.chain_configs.keys(): self._deploy_service_onchain_from_safe( - hash=hash, - chain_id=chain_id, + service_config_id=service_config_id, + chain=chain, ) def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,too-many-locals self, - hash: str, - chain_id: str, + service_config_id: str, + chain: str, ) -> None: - """ - Deploy as service on-chain - - :param hash: Service hash - """ + """Deploy service on-chain""" - self.logger.info(f"_deploy_service_onchain_from_safe {chain_id=}") - service = self.load_or_create(hash=hash) - chain_config = service.chain_configs[chain_id] + self.logger.info(f"_deploy_service_onchain_from_safe {chain=}") + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data user_params = chain_config.chain_data.user_params keys = service.keys instances = [key.address for key in keys] - wallet = self.wallet_manager.load(ledger_config.type) + wallet = self.wallet_manager.load(ledger_config.chain.ledger_type) sftxb = self.get_eth_safe_tx_builder(ledger_config=ledger_config) - chain_type = ChainType.from_id(int(chain_id)) - safe = wallet.safes[chain_type] + safe = wallet.safes[Chain(chain)] # TODO fix this os.environ["CUSTOM_CHAIN_RPC"] = ledger_config.rpc @@ -507,23 +531,32 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to agent_mech="0x77af31De935740567Cf4fF1986D04B2c964A786a", # nosec ) - # Override service.yaml variables for the deployment - os.environ["STAKING_CONTRACT_ADDRESS"] = staking_params["staking_contract"] - os.environ["MECH_ACTIVITY_CHECKER_CONTRACT"] = staking_params[ - "activity_checker" - ] - os.environ["MECH_CONTRACT_ADDRESS"] = staking_params["agent_mech"] - os.environ["MECH_REQUEST_PRICE"] = "10000000000000000" - os.environ["USE_MECH_MARKETPLACE"] = str( - chain_data.user_params.use_mech_marketplace - ) - os.environ["REQUESTER_STAKING_INSTANCE_ADDRESS"] = staking_params[ - "staking_contract" - ] - os.environ["PRIORITY_MECH_ADDRESS"] = staking_params["agent_mech"] - os.environ["ETHEREUM_LEDGER_RPC"] = PUBLIC_RPCS[ChainType.ETHEREUM] - os.environ["BASE_LEDGER_RPC"] = PUBLIC_RPCS[ChainType.BASE] - os.environ["OPTIMISM_LEDGER_RPC"] = PUBLIC_RPCS[ChainType.OPTIMISM] + # TODO A customized, arbitrary computation mechanism should be devised. + if chain == service.home_chain: + env_var_to_value = { + "ETHEREUM_LEDGER_RPC": PUBLIC_RPCS[Chain.ETHEREUM], + "GNOSIS_LEDGER_RPC": PUBLIC_RPCS[Chain.GNOSIS], + "BASE_LEDGER_RPC": PUBLIC_RPCS[Chain.BASE], + "OPTIMISM_LEDGER_RPC": PUBLIC_RPCS[Chain.OPTIMISTIC], + "STAKING_CONTRACT_ADDRESS": staking_params.get("staking_contract"), + "MECH_ACTIVITY_CHECKER_CONTRACT": staking_params.get( + "activity_checker" + ), + "MECH_CONTRACT_ADDRESS": staking_params.get("agent_mech"), + "MECH_REQUEST_PRICE": "10000000000000000", + "USE_MECH_MARKETPLACE": str( + "mech_marketplace" + in service.chain_configs[ + service.home_chain + ].chain_data.user_params.staking_program_id + ), + "REQUESTER_STAKING_INSTANCE_ADDRESS": staking_params.get( + "staking_contract" + ), + "PRIORITY_MECH_ADDRESS": staking_params.get("agent_mech"), + } + + service.update_env_variables_values(env_var_to_value) if user_params.use_staking: self.logger.info("Checking staking compatibility") @@ -572,9 +605,15 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to ) is_first_mint = ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.NON_EXISTENT ) + + # TODO Determine if the mint metadata hash changed - if so, it requires + # an on-chain update. + # This has to be implemented. Temporarily added as a placeholder (ignored). + has_metadata_changed = False + is_update = ( (not is_first_mint) and (on_chain_hash is not None) @@ -583,8 +622,9 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to # on_chain_hash != service.hash or # noqa current_agent_id != staking_params["agent_ids"][0] - # TODO Temporary removed for Optimus. Needs to be put back! - # or current_agent_bond != staking_params["min_staking_deposit"] + # TODO This has to be removed for Optimus (needs to be properly implemented). Needs to be put back for Trader! + or current_agent_bond != staking_params["min_staking_deposit"] + or has_metadata_changed ) ) current_staking_program = self._get_current_staking_program( @@ -604,10 +644,12 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to self.logger.info(f"{is_update=}") if is_update: - self._terminate_service_on_chain_from_safe(hash=hash, chain_id=chain_id) + self._terminate_service_on_chain_from_safe( + service_config_id=service_config_id, chain=chain + ) # Update service if ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.PRE_REGISTRATION ): self.logger.info("Updating service") @@ -631,6 +673,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to if user_params.use_staking else None ), + metadata_description=service.description, ) ) .settle() @@ -649,7 +692,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to # Mint service if ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.NON_EXISTENT ): if user_params.use_staking and not sftxb.staking_slots_available( @@ -680,6 +723,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to if user_params.use_staking else None ), + metadata_description=service.description, ) ) .settle() @@ -698,10 +742,10 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to service.store() if ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.PRE_REGISTRATION ): - # cost_of_bond = staking_params["min_staking_deposit"] + # TODO Verify that this is incorrect: cost_of_bond = staking_params["min_staking_deposit"] cost_of_bond = user_params.cost_of_bond if user_params.use_staking: token_utility = staking_params["service_registry_token_utility"] @@ -751,7 +795,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to service.store() if ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.ACTIVE_REGISTRATION ): cost_of_bond = user_params.cost_of_bond @@ -807,7 +851,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to service.store() if ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.FINISHED_REGISTRATION ): self.logger.info("Deploying service") @@ -839,25 +883,20 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to chain_data.on_chain_state = OnChainState(info["service_state"]) service.store() if user_params.use_staking: - self.stake_service_on_chain_from_safe(hash=hash, chain_id=chain_id) + self.stake_service_on_chain_from_safe( + service_config_id=service_config_id, chain=chain + ) def terminate_service_on_chain( - self, hash: str, chain_id: t.Optional[str] = None + self, service_config_id: str, chain: t.Optional[str] = None ) -> None: - """ - Terminate service on-chain - - :param hash: Service hash - """ + """Terminate service on-chain""" # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version. self.logger.info("terminate_service_on_chain") - service = self.load_or_create(hash=hash) + service = self.load(service_config_id=service_config_id) - if chain_id is None: - chain_id = service.home_chain_id - - chain_config = service.chain_configs[chain_id] + chain_config = service.chain_configs[chain or service.home_chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data ocm = self.get_on_chain_manager(ledger_config=ledger_config) @@ -881,23 +920,19 @@ def terminate_service_on_chain( service.store() def _terminate_service_on_chain_from_safe( # pylint: disable=too-many-locals - self, hash: str, chain_id: str + self, service_config_id: str, chain: str ) -> None: - """ - Terminate service on-chain + """Terminate service on-chain""" - :param hash: Service hash - """ self.logger.info("terminate_service_on_chain_from_safe") - service = self.load_or_create(hash=hash) - chain_config = service.chain_configs[chain_id] + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data keys = service.keys instances = [key.address for key in keys] - wallet = self.wallet_manager.load(ledger_config.type) - chain_type = ChainType.from_id(int(chain_id)) - safe = wallet.safes[chain_type] + wallet = self.wallet_manager.load(ledger_config.chain.ledger_type) + safe = wallet.safes[Chain(chain)] # type: ignore # TODO fixme os.environ["CUSTOM_CHAIN_RPC"] = ledger_config.rpc @@ -927,10 +962,12 @@ def _terminate_service_on_chain_from_safe( # pylint: disable=too-many-locals # Unstake the service if applies if is_staked and can_unstake: self.unstake_service_on_chain_from_safe( - hash=hash, chain_id=chain_id, staking_program_id=current_staking_program + service_config_id=service_config_id, + chain=chain, + staking_program_id=current_staking_program, ) - if self._get_on_chain_state(service=service, chain_id=chain_id) in ( + if self._get_on_chain_state(service=service, chain=chain) in ( OnChainState.ACTIVE_REGISTRATION, OnChainState.FINISHED_REGISTRATION, OnChainState.DEPLOYED, @@ -943,7 +980,7 @@ def _terminate_service_on_chain_from_safe( # pylint: disable=too-many-locals ).settle() if ( - self._get_on_chain_state(service=service, chain_id=chain_id) + self._get_on_chain_state(service=service, chain=chain) == OnChainState.TERMINATED_BONDED ): self.logger.info("Unbonding service") @@ -961,7 +998,7 @@ def _terminate_service_on_chain_from_safe( # pylint: disable=too-many-locals if counter_current_safe_owners == counter_instances: self.logger.info("Service funded for safe swap") self.fund_service( - hash=hash, + service_config_id=service_config_id, rpc=ledger_config.rpc, agent_topup=chain_data.user_params.fund_requirements.agent, agent_fund_threshold=chain_data.user_params.fund_requirements.agent, @@ -1001,21 +1038,14 @@ def _get_current_staking_program( return current_staking_program def unbond_service_on_chain( - self, hash: str, chain_id: t.Optional[str] = None + self, service_config_id: str, chain: t.Optional[str] = None ) -> None: - """ - Unbond service on-chain - - :param hash: Service hash - """ + """Unbond service on-chain""" # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version. - service = self.load_or_create(hash=hash) - - if chain_id is None: - chain_id = service.home_chain_id + service = self.load(service_config_id=service_config_id) - chain_config = service.chain_configs[chain_id] + chain_config = service.chain_configs[chain or service.home_chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data ocm = self.get_on_chain_manager(ledger_config=ledger_config) @@ -1047,17 +1077,12 @@ def stake_service_on_chain(self, hash: str) -> None: raise NotImplementedError def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too-many-locals - self, hash: str, chain_id: str + self, service_config_id: str, chain: str ) -> None: - """ - Stake service on-chain + """Stake service on-chain""" - :param hash: Service hash - :param chain_id: The chain id to use. - :param target_staking_program_id: The staking program id the agent should be on. - """ - service = self.load_or_create(hash=hash) - chain_config = service.chain_configs[chain_id] + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data user_params = chain_data.user_params @@ -1089,8 +1114,8 @@ def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too f"Use staking is set to false, but service {chain_config.chain_data.token} is staked and can be unstaked. Unstaking..." ) self.unstake_service_on_chain_from_safe( - hash=hash, - chain_id=chain_id, + service_config_id=service_config_id, + chain=chain, staking_program_id=current_staking_program, ) @@ -1106,8 +1131,8 @@ def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too f"Service {chain_config.chain_data.token} has been evicted and can be unstaked. Unstaking..." ) self.unstake_service_on_chain_from_safe( - hash=hash, - chain_id=chain_id, + service_config_id=service_config_id, + chain=chain, staking_program_id=current_staking_program, ) @@ -1121,8 +1146,8 @@ def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too f"is already staked and can be unstaked. Unstaking..." ) self.unstake_service_on_chain_from_safe( - hash=hash, - chain_id=chain_id, + service_config_id=service_config_id, + chain=chain, staking_program_id=current_staking_program, ) @@ -1135,8 +1160,8 @@ def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too f"{chain_config.chain_data.token} is staked in a different staking program. Unstaking..." ) self.unstake_service_on_chain_from_safe( - hash=hash, - chain_id=chain_id, + service_config_id=service_config_id, + chain=chain, staking_program_id=current_staking_program, ) @@ -1150,7 +1175,7 @@ def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too target_staking_contract ) staking_slots_available = sftxb.staking_slots_available(target_staking_contract) - on_chain_state = self._get_on_chain_state(service=service, chain_id=chain_id) + on_chain_state = self._get_on_chain_state(service=service, chain=chain) current_staking_program = self._get_current_staking_program( chain_data, ledger_config, sftxb ) @@ -1198,21 +1223,13 @@ def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too self.logger.info(f"{current_staking_program=}") def unstake_service_on_chain( - self, hash: str, chain_id: t.Optional[str] = None + self, service_config_id: str, chain: t.Optional[str] = None ) -> None: - """ - Unbond service on-chain - - :param hash: Service hash - """ + """Unbond service on-chain""" # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version. - service = self.load_or_create(hash=hash) - - if chain_id is None: - chain_id = service.home_chain_id - - chain_config = service.chain_configs[chain_id] + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain or service.home_chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data ocm = self.get_on_chain_manager(ledger_config=ledger_config) @@ -1240,17 +1257,16 @@ def unstake_service_on_chain( service.store() def unstake_service_on_chain_from_safe( - self, hash: str, chain_id: str, staking_program_id: t.Optional[str] = None + self, + service_config_id: str, + chain: str, + staking_program_id: t.Optional[str] = None, ) -> None: - """ - Unbond service on-chain - - :param hash: Service hash - """ + """Unbond service on-chain""" self.logger.info("unstake_service_on_chain_from_safe") - service = self.load_or_create(hash=hash) - chain_config = service.chain_configs[chain_id] + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data @@ -1288,7 +1304,7 @@ def unstake_service_on_chain_from_safe( def fund_service( # pylint: disable=too-many-arguments,too-many-locals self, - hash: str, + service_config_id: str, rpc: t.Optional[str] = None, agent_topup: t.Optional[float] = None, safe_topup: t.Optional[float] = None, @@ -1297,62 +1313,68 @@ def fund_service( # pylint: disable=too-many-arguments,too-many-locals from_safe: bool = True, ) -> None: """Fund service if required.""" - service = self.load_or_create(hash=hash) + service = self.load(service_config_id=service_config_id) - for chain_id in service.chain_configs.keys(): - self.logger.info(f"Funding chain_id {chain_id}") + for chain in service.chain_configs.keys(): + self.logger.info(f"Funding {chain=}") self.fund_service_single_chain( - hash=hash, + service_config_id=service_config_id, rpc=rpc, agent_topup=agent_topup, safe_topup=safe_topup, agent_fund_threshold=agent_fund_threshold, safe_fund_treshold=safe_fund_treshold, from_safe=from_safe, - chain_id=chain_id, + chain=chain, ) def fund_service_single_chain( # pylint: disable=too-many-arguments,too-many-locals self, - hash: str, + service_config_id: str, rpc: t.Optional[str] = None, agent_topup: t.Optional[float] = None, safe_topup: t.Optional[float] = None, agent_fund_threshold: t.Optional[float] = None, safe_fund_treshold: t.Optional[float] = None, from_safe: bool = True, - chain_id: str = "100", + chain: str = "gnosis", ) -> None: """Fund service if required.""" - service = self.load_or_create(hash=hash) - chain_config = service.chain_configs[chain_id] + + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data - wallet = self.wallet_manager.load(ledger_config.type) + wallet = self.wallet_manager.load(ledger_config.chain.ledger_type) ledger_api = wallet.ledger_api( - chain_type=ledger_config.chain, rpc=rpc or ledger_config.rpc + chain=ledger_config.chain, rpc=rpc or ledger_config.rpc ) agent_fund_threshold = ( - agent_fund_threshold or chain_data.user_params.fund_requirements.agent + agent_fund_threshold + if agent_fund_threshold is not None + else chain_data.user_params.fund_requirements.agent ) for key in service.keys: agent_balance = ledger_api.get_balance(address=key.address) self.logger.info(f"Agent {key.address} balance: {agent_balance}") - self.logger.info(f"Required balance: {agent_fund_threshold}") - if agent_balance < agent_fund_threshold: - self.logger.info("Funding agents") - to_transfer = ( - agent_topup or chain_data.user_params.fund_requirements.agent - ) - self.logger.info(f"Transferring {to_transfer} units to {key.address}") - wallet.transfer( - to=key.address, - amount=int(to_transfer), - chain_type=ledger_config.chain, - from_safe=from_safe, - rpc=rpc or ledger_config.rpc, - ) + if agent_fund_threshold > 0: + self.logger.info(f"Required balance: {agent_fund_threshold}") + if agent_balance < agent_fund_threshold: + self.logger.info("Funding agents") + to_transfer = ( + agent_topup or chain_data.user_params.fund_requirements.agent + ) + self.logger.info( + f"Transferring {to_transfer} units to {key.address}" + ) + wallet.transfer( + to=key.address, + amount=int(to_transfer), + chain=ledger_config.chain, + from_safe=from_safe, + rpc=rpc or ledger_config.rpc, + ) safe_balance = ledger_api.get_balance(chain_data.multisig) safe_fund_treshold = ( @@ -1369,13 +1391,13 @@ def fund_service_single_chain( # pylint: disable=too-many-arguments,too-many-lo wallet.transfer( to=t.cast(str, chain_data.multisig), amount=int(to_transfer), - chain_type=ledger_config.chain, + chain=ledger_config.chain, rpc=rpc or ledger_config.rpc, ) def fund_service_erc20( # pylint: disable=too-many-arguments,too-many-locals self, - hash: str, + service_config_id: str, token: str, rpc: t.Optional[str] = None, agent_topup: t.Optional[float] = None, @@ -1383,16 +1405,16 @@ def fund_service_erc20( # pylint: disable=too-many-arguments,too-many-locals agent_fund_threshold: t.Optional[float] = None, safe_fund_treshold: t.Optional[float] = None, from_safe: bool = True, - chain_id: str = "100", + chain: str = "gnosis", ) -> None: """Fund service if required.""" - service = self.load_or_create(hash=hash) - chain_config = service.chain_configs[chain_id] + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[chain] ledger_config = chain_config.ledger_config chain_data = chain_config.chain_data - wallet = self.wallet_manager.load(ledger_config.type) + wallet = self.wallet_manager.load(ledger_config.chain.ledger_type) ledger_api = wallet.ledger_api( - chain_type=ledger_config.chain, rpc=rpc or ledger_config.rpc + chain=ledger_config.chain, rpc=rpc or ledger_config.rpc ) agent_fund_threshold = ( agent_fund_threshold or chain_data.user_params.fund_requirements.agent @@ -1412,7 +1434,7 @@ def fund_service_erc20( # pylint: disable=too-many-arguments,too-many-locals token=token, to=key.address, amount=int(to_transfer), - chain_type=ledger_config.chain, + chain=ledger_config.chain, from_safe=from_safe, rpc=rpc or ledger_config.rpc, ) @@ -1437,21 +1459,20 @@ def fund_service_erc20( # pylint: disable=too-many-arguments,too-many-locals token=token, to=t.cast(str, chain_data.multisig), amount=int(to_transfer), - chain_type=ledger_config.chain, + chain=ledger_config.chain, rpc=rpc or ledger_config.rpc, ) async def funding_job( self, - hash: str, + service_config_id: str, loop: t.Optional[asyncio.AbstractEventLoop] = None, from_safe: bool = True, ) -> None: """Start a background funding job.""" loop = loop or asyncio.get_event_loop() - service = self.load_or_create(hash=hash) - chain_id = service.home_chain_id - chain_config = service.chain_configs[chain_id] + service = self.load(service_config_id=service_config_id) + chain_config = service.chain_configs[service.home_chain] ledger_config = chain_config.ledger_config with ThreadPoolExecutor() as executor: while True: @@ -1459,7 +1480,7 @@ async def funding_job( await loop.run_in_executor( executor, self.fund_service, - hash, # Service hash + service_config_id, # Service id PUBLIC_RPCS[ledger_config.chain], # RPC 100000000000000000, # agent_topup 2000000000000000000, # safe_topup @@ -1473,14 +1494,14 @@ async def funding_job( ) await asyncio.sleep(60) - def _set_env_variables(self, hash: str) -> None: - self.logger.info(f"_set_env_variables {hash} - not implemented") + def _set_env_variables(self, service_config_id: str) -> None: + self.logger.info(f"_set_env_variables {service_config_id} - not implemented") def deploy_service_locally( self, - hash: str, + service_config_id: str, force: bool = True, - chain_id: str = "100", + chain: t.Optional[str] = None, use_docker: bool = False, ) -> Deployment: """ @@ -1488,79 +1509,112 @@ def deploy_service_locally( :param hash: Service hash :param force: Remove previous deployment and start a new one. + :param chain: Chain to set runtime parameters on the deployment (home_chain if not provided). + :param use_docker: Use a Docker Compose deployment (True) or Host deployment (False). :return: Deployment instance """ - self._set_env_variables(hash=hash) - deployment = self.load_or_create(hash=hash).deployment - deployment.build(use_docker=use_docker, force=force, chain_id=chain_id) + self._set_env_variables(service_config_id=service_config_id) + service = self.load(service_config_id=service_config_id) + + deployment = service.deployment + deployment.build( + use_docker=use_docker, force=force, chain=chain or service.home_chain + ) deployment.start(use_docker=use_docker) return deployment def stop_service_locally( - self, hash: str, delete: bool = False, use_docker: bool = False + self, service_config_id: str, delete: bool = False, use_docker: bool = False ) -> Deployment: """ Stop service locally - :param hash: Service hash + :param service_id: Service id :param delete: Delete local deployment. :return: Deployment instance """ - deployment = self.load_or_create(hash=hash).deployment + deployment = self.load(service_config_id=service_config_id).deployment deployment.stop(use_docker) if delete: deployment.delete() return deployment - def update_service( + def log_directories(self) -> None: + """Log directories.""" + directories = [f" - {str(p)}" for p in self.path.iterdir() if p.is_dir()] + directories_str = "\n".join(directories) + self.logger.info(f"Directories in {self.path}\n: {directories_str}") + + def update( self, - old_hash: str, - new_hash: str, - service_template: t.Optional[ServiceTemplate] = None, + service_config_id: str, + service_template: ServiceTemplate, + allow_different_service_public_id: bool = False, ) -> Service: """Update a service.""" - self.logger.info("-----Entering update local service-----") - old_service = self.load_or_create(hash=old_hash) - new_service = self.load_or_create( - hash=new_hash, service_template=service_template - ) - new_service.keys = old_service.keys - - # TODO Ensure this is as intended. - new_service.home_chain_id = old_service.home_chain_id - - # new_service must copy all chain_data from old_service. - # Additionally, if service_template is not None, it must overwrite - # the user_params on all chain_data by the values passed through the - # service_template. - new_service.chain_configs = {} - for chain_id, config in old_service.chain_configs.items(): - new_service.chain_configs[chain_id] = config - if service_template: - new_service.chain_configs[ - chain_id - ].chain_data.user_params = OnChainUserParams.from_json( - service_template["configurations"][chain_id] # type: ignore # TODO fix mypy + self.logger.info(f"Updating {service_config_id=}") + service = self.load(service_config_id=service_config_id) + service.update(service_template, allow_different_service_public_id) + return service + + def update_all_matching( + self, + service_template: ServiceTemplate, + ) -> t.List[t.Dict]: + """Update all services with service id matching the service id from the template hash.""" + + self.logger.info("update_all_matching") + self.logger.info(f"{service_template['hash']=}") + updated_services: t.List[t.Dict] = [] + for service in self._get_all_services(): + try: + service.update(service_template=service_template) + updated_services.append(service.json) + self.logger.info( + f"Updated service_config_id={service.service_config_id}" + ) + except ValueError: + self.logger.info( + f"Not updated service_config_id={service.service_config_id}" ) - new_service.store() - - # The following logging has been added to identify OS issues when - # deleting old service folder - try: - self._log_directories() - self.logger.info("Trying to delete old service") - old_service.delete() - except Exception as e: # pylint: disable=broad-except - self.logger.error( - f"An error occurred while trying to delete {old_service.path}: {e}" - ) - self.logger.error(traceback.format_exc()) + return updated_services - self._log_directories() - return new_service + def migrate_service_configs(self) -> None: + """Migrate old service config formats to new ones, if applies.""" - def _log_directories(self) -> None: - directories = [str(p) for p in self.path.iterdir() if p.is_dir()] - self.logger.info(f"Directories in {self.path}: {', '.join(directories)}") + bafybei_count = sum( + 1 for path in self.path.iterdir() if path.name.startswith("bafybei") + ) + if bafybei_count > 1: + self.log_directories() + raise RuntimeError( + f"Your services folder contains {bafybei_count} folders starting with 'bafybei'. This is an unintended situation. Please contact support." + ) + + paths = list(self.path.iterdir()) + for path in paths: + try: + if path.name.startswith(DELETE_PREFIX): + shutil.rmtree(path) + self.logger.info(f"Deleted folder: {path.name}") + + if path.name.startswith(SERVICE_CONFIG_PREFIX) or path.name.startswith( + "bafybei" + ): + self.logger.info(f"migrate_service_configs {str(path)}") + migrated = Service.migrate_format(path) + if migrated: + self.logger.info(f"Folder {str(path)} has been migrated.") + except Exception as e: # pylint: disable=broad-except + self.logger.error( + f"Failed to migrate service: {path.name}. Exception {e}: {traceback.format_exc()}" + ) + # Rename the invalid path + timestamp = int(time.time()) + invalid_path = path.parent / f"invalid_{timestamp}_{path.name}" + os.rename(path, invalid_path) + self.logger.info( + f"Renamed invalid service: {path.name} to {invalid_path.name}" + ) diff --git a/operate/services/protocol.py b/operate/services/protocol.py index 67aed9167..c34913371 100644 --- a/operate/services/protocol.py +++ b/operate/services/protocol.py @@ -24,14 +24,13 @@ import io import json import logging -import os import tempfile import time import typing as t from datetime import datetime from enum import Enum from pathlib import Path -from typing import Optional, Union +from typing import Optional, Union, cast from aea.configurations.data_types import PackageType from aea.crypto.base import Crypto, LedgerApi @@ -44,6 +43,7 @@ GNOSIS_SAFE_SAME_ADDRESS_MULTISIG_CONTRACT, MULTISEND_CONTRACT, ) +from autonomy.chain.metadata import publish_metadata from autonomy.chain.service import ( get_agent_instances, get_delployment_payload, @@ -52,8 +52,7 @@ get_token_deposit_amount, ) from autonomy.chain.tx import TxSettler -from autonomy.cli.helpers.chain import MintHelper as MintManager -from autonomy.cli.helpers.chain import OnChainHelper +from autonomy.cli.helpers.chain import MintHelper, OnChainHelper from autonomy.cli.helpers.chain import ServiceHelper as ServiceManager from eth_utils import to_bytes from hexbytes import HexBytes @@ -66,11 +65,9 @@ ON_CHAIN_INTERACT_TIMEOUT, ) from operate.data import DATA_DIR -from operate.data.contracts.service_staking_token.contract import ( - ServiceStakingTokenContract, -) +from operate.data.contracts.staking_token.contract import StakingTokenContract from operate.ledger.profiles import STAKING -from operate.operate_types import ChainType as OperateChainType +from operate.operate_types import Chain as OperateChain from operate.operate_types import ContractAddresses from operate.utils.gnosis import ( MultiSendOperation, @@ -204,9 +201,9 @@ def __init__( """Initialize object.""" super().__init__(key=key, chain_type=chain_type, password=password) self.staking_ctr = t.cast( - ServiceStakingTokenContract, - ServiceStakingTokenContract.from_dir( - directory=str(DATA_DIR / "contracts" / "service_staking_token") + StakingTokenContract, + StakingTokenContract.from_dir( + directory=str(DATA_DIR / "contracts" / "staking_token") ), ) @@ -494,6 +491,51 @@ def get_unstake_tx_data(self, service_id: int, staking_contract: str) -> bytes: ) +# TODO Backport this to Open Autonomy MintHelper class +# MintHelper should support passing custom 'description', 'name' and 'attributes'. +# If some of these fields are not defined, then it can take the current default values. +# (Version is included as an attribute.) +# The current code here is a workaround and just addresses the description, +# because modifying the name and attributes requires touching lower-level code. +# A proper refactor of this should be done in Open Autonomy. +class MintManager(MintHelper): + """MintManager""" + + metadata_description: t.Optional[str] = None + metadata_name: t.Optional[str] = None + metadata_attributes: t.Optional[t.Dict[str, str]] = None + + def set_metadata_fields( + self, + name: t.Optional[str] = None, + description: t.Optional[str] = None, + attributes: t.Optional[t.Dict[str, str]] = None, + ) -> "MintManager": + """Set metadata fields.""" + self.metadata_name = ( + name # Not used currently, just an indication for the OA refactor + ) + self.metadata_description = description + self.metadata_attributes = ( + attributes # Not used currently, just an indication for the OA refactor + ) + return self + + def publish_metadata(self) -> "MintManager": + """Publish metadata.""" + self.metadata_hash, self.metadata_string = publish_metadata( + package_id=self.package_configuration.package_id, + package_path=self.package_path, + nft=cast(str, self.nft), + description=self.metadata_description + or self.package_configuration.description, + ) + return self + + +# End Backport + + class _ChainUtil: """On chain service management.""" @@ -523,12 +565,12 @@ def _patch(self) -> None: def safe(self) -> str: """Get safe address.""" chain_id = self.ledger_api.api.eth.chain_id - chain_type = OperateChainType.from_id(chain_id) + chain = OperateChain.from_id(chain_id) if self.wallet.safes is None: raise ValueError("Safes not initialized") - if chain_type not in self.wallet.safes: - raise ValueError(f"Safe for chain type {chain_type} not found") - return self.wallet.safes[chain_type] + if chain not in self.wallet.safes: + raise ValueError(f"Safe for chain type {chain} not found") + return self.wallet.safes[chain] @property def crypto(self) -> Crypto: @@ -810,7 +852,7 @@ def get_staking_params(self, staking_contract: str) -> t.Dict: # TODO Read from activity checker contract. Read remaining variables for marketplace. if ( staking_contract - == STAKING[operate.operate_types.ChainType.GNOSIS][ + == STAKING[operate.operate_types.Chain.GNOSIS][ "pearl_beta_mech_marketplace" ] ): @@ -843,6 +885,7 @@ def mint( # pylint: disable=too-many-arguments,too-many-locals nft: Optional[Union[Path, IPFSHash]], update_token: t.Optional[int] = None, token: t.Optional[str] = None, + metadata_description: t.Optional[str] = None, ) -> t.Dict: """Mint service.""" # TODO: Support for update @@ -863,6 +906,7 @@ def mint( # pylint: disable=too-many-arguments,too-many-locals package_path=package_path, package_type=PackageType.SERVICE ) .load_metadata() + .set_metadata_fields(description=metadata_description) .verify_nft(nft=nft) .verify_service_dependencies(agent_id=agent_id) .publish_metadata() @@ -1064,6 +1108,7 @@ def get_mint_tx_data( # pylint: disable=too-many-arguments nft: Optional[Union[Path, IPFSHash]], update_token: t.Optional[int] = None, token: t.Optional[str] = None, + metadata_description: t.Optional[str] = None, ) -> t.Dict: """Build mint transaction.""" # TODO: Support for update @@ -1083,6 +1128,7 @@ def get_mint_tx_data( # pylint: disable=too-many-arguments package_path=package_path, package_type=PackageType.SERVICE ) .load_metadata() + .set_metadata_fields(description=metadata_description) .verify_nft(nft=nft) .verify_service_dependencies(agent_id=agent_id) .publish_metadata() diff --git a/operate/services/service.py b/operate/services/service.py index b53cfda22..3af20fe83 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -25,12 +25,14 @@ import shutil import subprocess # nosec import sys +import tempfile +import time import typing as t -from copy import copy, deepcopy +import uuid +from copy import copy from dataclasses import dataclass from json import JSONDecodeError from pathlib import Path -from time import sleep from traceback import print_exc from aea.configurations.constants import ( @@ -40,7 +42,6 @@ PRIVATE_KEY_PATH_SCHEMA, SKILL, ) -from aea.configurations.data_types import PackageType from aea.helpers.yaml_utils import yaml_dump, yaml_load, yaml_load_all from aea_cli_ipfs.ipfs_utils import IPFSTool from autonomy.cli.helpers.deployment import run_deployment, stop_deployment @@ -66,21 +67,21 @@ KEYS_JSON, ) from operate.keys import Keys -from operate.ledger import PUBLIC_RPCS from operate.operate_http.exceptions import NotAllowed from operate.operate_types import ( + Chain, ChainConfig, ChainConfigs, - ChainType, DeployedNodes, DeploymentConfig, DeploymentStatus, + EnvVariables, LedgerConfig, LedgerConfigs, - LedgerType, OnChainData, OnChainState, OnChainUserParams, + ServiceEnvProvisionType, ServiceTemplate, ) from operate.resource import LocalResource @@ -94,7 +95,8 @@ ALL_PARTICIPANTS = "all_participants" CONSENSUS_THRESHOLD = "consensus_threshold" DELETE_PREFIX = "delete_" -SERVICE_CONFIG_VERSION = 3 +SERVICE_CONFIG_VERSION = 4 +SERVICE_CONFIG_PREFIX = "sc-" DUMMY_MULTISIG = "0xm" NON_EXISTENT_TOKEN = -1 @@ -143,42 +145,6 @@ def remove_service_network(service_name: str, force: bool = True) -> None: class ServiceBuilder(BaseServiceBuilder): """Service builder patch.""" - def try_update_ledger_params(self, chain: str, address: str) -> None: - """Try to update the ledger params.""" - - for override in deepcopy(self.service.overrides): - ( - override, - component_id, - _, - ) = self.service.process_metadata( - configuration=override, - ) - - if ( - component_id.package_type == PackageType.CONNECTION - and component_id.name == "ledger" - ): - ledger_connection_overrides = deepcopy(override) - break - else: - return - - # TODO: Support for multiple overrides - ledger_connection_overrides["config"]["ledger_apis"][chain]["address"] = address - service_overrides = deepcopy(self.service.overrides) - service_overrides = [ - override - for override in service_overrides - if override["public_id"] != str(component_id.public_id) - or override["type"] != PackageType.CONNECTION.value - ] - - ledger_connection_overrides["type"] = PackageType.CONNECTION.value - ledger_connection_overrides["public_id"] = str(component_id.public_id) - service_overrides.append(ledger_connection_overrides) - self.service.overrides = service_overrides - def try_update_runtime_params( self, multisig_address: t.Optional[str] = None, @@ -244,7 +210,9 @@ def __init__(self, path: Path) -> None: """Initialize object.""" self.path = path self.config = load_service_config(service_path=path) - self.config.overrides = apply_env_variables(self.config.overrides, os.environ.copy()) + self.config.overrides = apply_env_variables( + self.config.overrides, os.environ.copy() + ) def ledger_configs(self) -> LedgerConfigs: """Get ledger configs.""" @@ -256,11 +224,10 @@ def ledger_configs(self) -> LedgerConfigs: ): for _, config in override["config"]["ledger_apis"].items(): # TODO chain name is inferred from the chain_id. The actual id provided on service.yaml is ignored. - chain = ChainType.from_id(cid=config["chain_id"]) - ledger_configs[str(config["chain_id"])] = LedgerConfig( + chain = Chain.from_id(chain_id=config["chain_id"]) # type: ignore + ledger_configs[chain.value] = LedgerConfig( rpc=config["address"], chain=chain, - type=LedgerType.ETHEREUM, ) return ledger_configs @@ -389,7 +356,7 @@ def load(cls, path: Path) -> "Deployment": def _build_docker( self, force: bool = True, - chain_id: str = "100", + chain: t.Optional[str] = None, ) -> None: """Build docker deployment.""" service = Service.load(path=self.path) @@ -423,6 +390,7 @@ def _build_docker( encoding="utf-8", ) try: + service.consume_env_variables() builder = ServiceBuilder.from_dir( path=service.service_path, keys_file=keys_file, @@ -431,21 +399,18 @@ def _build_docker( builder.deplopyment_type = DockerComposeGenerator.deployment_type builder.try_update_abci_connection_params() - home_chain_data = service.chain_configs[service.home_chain_id].chain_data - home_chain_ledger_config = service.chain_configs[ - service.home_chain_id - ].ledger_config + if not chain: + chain = service.home_chain + + chain_config = service.chain_configs[chain] + chain_data = chain_config.chain_data + builder.try_update_runtime_params( - multisig_address=home_chain_data.multisig, - agent_instances=home_chain_data.instances, - service_id=home_chain_data.token, + multisig_address=chain_data.multisig, + agent_instances=chain_data.instances, + service_id=chain_data.token, consensus_threshold=None, ) - # TODO: Support for multiledger - builder.try_update_ledger_params( - chain=LedgerType(home_chain_ledger_config.type).name.lower(), - address=home_chain_ledger_config.rpc, - ) # build deployment ( @@ -492,7 +457,7 @@ def _build_docker( self.status = DeploymentStatus.BUILT self.store() - def _build_host(self, force: bool = True, chain_id: str = "100") -> None: + def _build_host(self, force: bool = True, chain: t.Optional[str] = None) -> None: """Build host depployment.""" build = self.path / DEPLOYMENT if build.exists() and not force: @@ -502,12 +467,12 @@ def _build_host(self, force: bool = True, chain_id: str = "100") -> None: stop_host_deployment(build_dir=build) try: # sleep needed to ensure all processes closed/killed otherwise it will block directory removal on windows - sleep(3) + time.sleep(3) shutil.rmtree(build) except: # noqa # pylint: disable=bare-except # sleep and try again. exception if fails print_exc() - sleep(3) + time.sleep(3) shutil.rmtree(build) service = Service.load(path=self.path) @@ -516,8 +481,10 @@ def _build_host(self, force: bool = True, chain_id: str = "100") -> None: "Host deployment currently only supports single agent deployments" ) - chain_config = service.chain_configs[chain_id] - ledger_config = chain_config.ledger_config + if not chain: + chain = service.home_chain + + chain_config = service.chain_configs[chain] chain_data = chain_config.chain_data keys_file = self.path / KEYS_JSON @@ -536,6 +503,7 @@ def _build_host(self, force: bool = True, chain_id: str = "100") -> None: encoding="utf-8", ) try: + service.consume_env_variables() builder = ServiceBuilder.from_dir( path=service.service_path, keys_file=keys_file, @@ -549,11 +517,6 @@ def _build_host(self, force: bool = True, chain_id: str = "100") -> None: service_id=chain_data.token, consensus_threshold=None, ) - # TODO: Support for multiledger - builder.try_update_ledger_params( - chain=LedgerType(ledger_config.type).name.lower(), - address=ledger_config.rpc, - ) ( HostDeploymentGenerator( @@ -578,19 +541,20 @@ def build( self, use_docker: bool = False, force: bool = True, - chain_id: str = "100", + chain: t.Optional[str] = None, ) -> None: """ Build a deployment - :param use_docker: Use docker deployment + :param use_docker: Use a Docker Compose deployment (True) or Host deployment (False). :param force: Remove existing deployment and build a new one + :param chain: Chain to set runtime parameters on the deployment (home_chain if not provided). :return: Deployment object """ - # TODO: chain_id should be used properly! Added as a hotfix for now. + # TODO: Maybe remove usage of chain and use home_chain always? if use_docker: - return self._build_docker(force=force, chain_id=chain_id) - return self._build_host(force=force, chain_id=chain_id) + return self._build_docker(force=force, chain=chain) + return self._build_host(force=force, chain=chain) def start(self, use_docker: bool = False) -> None: """Start the service""" @@ -643,10 +607,14 @@ class Service(LocalResource): """Service class.""" version: int + service_config_id: str hash: str + hash_history: t.Dict[int, str] keys: Keys - home_chain_id: str + home_chain: str chain_configs: ChainConfigs + description: str + env_variables: EnvVariables path: Path service_path: Path @@ -659,38 +627,46 @@ class Service(LocalResource): _file = "config.json" @classmethod - def migrate_format(cls, path: Path) -> None: + def migrate_format(cls, path: Path) -> bool: """Migrate the JSON file format if needed.""" - file_path = ( - path / Service._file - if Service._file is not None and path.name != Service._file - else path - ) - with open(file_path, "r", encoding="utf-8") as file: + if not path.is_dir(): + return False + + if not path.name.startswith(SERVICE_CONFIG_PREFIX) and not path.name.startswith( + "bafybei" + ): + return False + + if path.name.startswith("bafybei"): + backup_name = f"backup_{int(time.time())}_{path.name}" + backup_path = path.parent / backup_name + shutil.copytree(path, backup_path) + deployment_path = backup_path / "deployment" + if deployment_path.is_dir(): + shutil.rmtree(deployment_path) + + with open(path / Service._file, "r", encoding="utf-8") as file: data = json.load(file) version = data.get("version", 0) - if version >= 3: - return - - # Migrate from old formats to new format - if version == 2: - data["chain_configs"]["100"]["chain_data"]["user_params"][ - "use_mech_marketplace" - ] = data["chain_configs"]["100"]["chain_data"]["user_params"].get( - "use_mech_marketplace", False + if version > SERVICE_CONFIG_VERSION: + raise RuntimeError( + f"Service configuration in {path} has version {version}, which means it was created with a newer version of olas-operate-middleware. Only configuration versions <= {SERVICE_CONFIG_VERSION} are supported by this version of olas-operate-middleware." ) - data["version"] = 3 - new_data = data - elif version == 0: + + if version == SERVICE_CONFIG_VERSION: + return False + + # Migration steps for older versions + if version == 0: new_data = { - "version": 3, + "version": 2, "hash": data.get("hash"), "keys": data.get("keys"), - "home_chain_id": "100", # Assuming a default value for home_chain_id + "home_chain_id": "100", # This is the default value for version 2 - do not change, will be corrected below "chain_configs": { - "100": { + "100": { # This is the default value for version 2 - do not change, will be corrected below "ledger_config": { "rpc": data.get("ledger_config", {}).get("rpc"), "type": data.get("ledger_config", {}).get("type"), @@ -717,13 +693,15 @@ def migrate_format(cls, path: Path) -> None: "use_staking": data.get("chain_data", {}) .get("user_params", {}) .get("use_staking"), - "use_mech_marketplace": False, "cost_of_bond": data.get("chain_data", {}) .get("user_params", {}) .get("cost_of_bond"), "fund_requirements": data.get("chain_data", {}) .get("user_params", {}) .get("fund_requirements", {}), + "agent_id": data.get("chain_data", {}) + .get("user_params", {}) + .get("agent_id", "14"), }, }, } @@ -731,14 +709,80 @@ def migrate_format(cls, path: Path) -> None: "service_path": data.get("service_path", ""), "name": data.get("name", ""), } + data = new_data + + # Add missing fields introduced in later versions, if necessary. + for _, chain_data in data.get("chain_configs", {}).items(): + chain_data.setdefault("chain_data", {}).setdefault( + "user_params", {} + ).setdefault("use_mech_marketplace", False) + chain_data.setdefault("chain_data", {}).setdefault( + "user_params", {} + ).setdefault("agent_id", 14) + + data["description"] = data.setdefault("description", data.get("name")) + data["hash_history"] = data.setdefault( + "hash_history", {int(time.time()): data["hash"]} + ) + + if "service_config_id" not in data: + service_config_id = Service.get_new_service_config_id(path) + new_path = path.parent / service_config_id + data["service_config_id"] = service_config_id + path = path.rename(new_path) + + old_to_new_ledgers = ["ethereum", "solana"] + for key_data in data["keys"]: + key_data["ledger"] = old_to_new_ledgers[key_data["ledger"]] + + old_to_new_chains = [ + "ethereum", + "goerli", + "gnosis", + "solana", + "optimistic", + "base", + "mode", + ] + new_chain_configs = {} + for chain_id, chain_data in data["chain_configs"].items(): + chain_data["ledger_config"]["chain"] = old_to_new_chains[ + chain_data["ledger_config"]["chain"] + ] + del chain_data["ledger_config"]["type"] + new_chain_configs[Chain.from_id(int(chain_id)).value] = chain_data # type: ignore + + data["chain_configs"] = new_chain_configs + data["home_chain"] = data.setdefault("home_chain", Chain.from_id(int(data.get("home_chain_id", "100"))).value) # type: ignore + del data["home_chain_id"] - with open(file_path, "w", encoding="utf-8") as file: - json.dump(new_data, file, indent=2) + if "env_variables" not in data: + data["env_variables"] = {} + + data["version"] = SERVICE_CONFIG_VERSION + + # Redownload service path + service_path = path / Path(data["service_path"]).name + if service_path.exists() and service_path.is_dir(): + print("EXISTS") + shutil.rmtree(service_path) + + service_path = Path( + IPFSTool().download( + hash_id=data["hash"], + target_dir=path, + ) + ) + data["service_path"] = str(service_path) + + with open(path / Service._file, "w", encoding="utf-8") as file: + json.dump(data, file, indent=2) + + return True @classmethod def load(cls, path: Path) -> "Service": """Load a service""" - cls.migrate_format(path) return super().load(path) # type: ignore @property @@ -761,22 +805,21 @@ def deployment(self) -> Deployment: @staticmethod def new( # pylint: disable=too-many-locals - hash: str, keys: Keys, service_template: ServiceTemplate, storage: Path, ) -> "Service": """Create a new service.""" - path = storage / hash + + service_config_id = Service.get_new_service_config_id(storage) + path = storage / service_config_id path.mkdir() service_path = Path( IPFSTool().download( - hash_id=hash, + hash_id=service_template["hash"], target_dir=path, ) ) - with (service_path / "service.yaml").open("r", encoding="utf-8") as fp: - service_yaml, *_ = yaml_load_all(fp) ledger_configs = ServiceHelper(path=service_path).ledger_configs() @@ -799,19 +842,147 @@ def new( # pylint: disable=too-many-locals chain_data=chain_data, ) + current_timestamp = int(time.time()) service = Service( version=SERVICE_CONFIG_VERSION, - name=service_yaml["author"] + "/" + service_yaml["name"], + service_config_id=service_config_id, + name=service_template["name"], + description=service_template["description"], hash=service_template["hash"], keys=keys, - home_chain_id=service_template["home_chain_id"], + home_chain=service_template["home_chain"], + hash_history={current_timestamp: service_template["hash"]}, chain_configs=chain_configs, path=service_path.parent, service_path=service_path, + env_variables=service_template["env_variables"], ) service.store() return service + def service_public_id(self, include_version: bool = True) -> str: + """Get the public id (based on the service hash).""" + with (self.service_path / "service.yaml").open("r", encoding="utf-8") as fp: + service_yaml, *_ = yaml_load_all(fp) + + public_id = f"{service_yaml['author']}/{service_yaml['name']}" + + if include_version: + public_id += f":{service_yaml['version']}" + + return public_id + + @staticmethod + def get_service_public_id( + hash: str, temp_dir: t.Optional[Path] = None, include_version: bool = True + ) -> str: + """ + Get the service public ID from IPFS based on the hash. + + :param hash: The IPFS hash of the service. + :param dir: Optional directory path where the temporary download folder will be created. + If None, a system-default temporary directory will be used. + :return: The public ID of the service in the format "author/name:version". + """ + with tempfile.TemporaryDirectory(dir=temp_dir) as path: + package_path = Path( + IPFSTool().download( + hash_id=hash, + target_dir=path, + ) + ) + + with (package_path / "service.yaml").open("r", encoding="utf-8") as fp: + service_yaml, *_ = yaml_load_all(fp) + + public_id = f"{service_yaml['author']}/{service_yaml['name']}" + + if include_version: + public_id += f":{service_yaml['version']}" + + return public_id + + @staticmethod + def get_new_service_config_id(path: Path) -> str: + """Get a new service config id that does not clash with any directory in path.""" + while True: + service_config_id = f"{SERVICE_CONFIG_PREFIX}{uuid.uuid4()}" + new_path = path.parent / service_config_id + if not new_path.exists(): + return service_config_id + + def update( + self, + service_template: ServiceTemplate, + allow_different_service_public_id: bool = False, + ) -> None: + """Update service.""" + + target_hash = service_template["hash"] + target_service_public_id = Service.get_service_public_id(target_hash, self.path) + + if not allow_different_service_public_id and ( + self.service_public_id() != target_service_public_id + ): + raise ValueError( + f"Trying to update a service with a different public id: {self.service_public_id()=} {self.hash=} {target_service_public_id=} {target_hash=}." + ) + + shutil.rmtree(self.service_path) + service_path = Path( + IPFSTool().download( + hash_id=service_template["hash"], + target_dir=self.path, + ) + ) + self.service_path = service_path + self.name = service_template["name"] + self.hash = service_template["hash"] + self.description = service_template["description"] + self.env_variables = service_template["env_variables"] + + # Only update hash_history if latest inserted hash is different + if self.hash_history[max(self.hash_history.keys())] != service_template["hash"]: + current_timestamp = int(time.time()) + self.hash_history[current_timestamp] = service_template["hash"] + + self.description = service_template["description"] + self.home_chain = service_template["home_chain"] + + ledger_configs = ServiceHelper(path=self.service_path).ledger_configs() + for chain, config in service_template["configurations"].items(): + if chain in self.chain_configs: + # The template is providing a chain configuration that already + # exists in this service - update only the user parameters. + # This is to avoid losing on-chain data like safe, token, etc. + self.chain_configs[ + chain + ].chain_data.user_params = OnChainUserParams.from_json( + config # type: ignore + ) + else: + # The template is providing a chain configuration that does + # not currently exist in this service - copy all config as + # when creating a new service. + ledger_config = ledger_configs[chain] + ledger_config.rpc = config["rpc"] + + chain_data = OnChainData( + instances=[], + token=NON_EXISTENT_TOKEN, + multisig=DUMMY_MULTISIG, + staked=False, + on_chain_state=OnChainState.NON_EXISTENT, + user_params=OnChainUserParams.from_json(config), # type: ignore + ) + + self.chain_configs[chain] = ChainConfig( + ledger_config=ledger_config, + chain_data=chain_data, + ) + + self.store() + def update_user_params_from_template( self, service_template: ServiceTemplate ) -> None: @@ -825,6 +996,41 @@ def update_user_params_from_template( self.store() + def consume_env_variables(self) -> None: + """Consume (apply) environment variables.""" + for env_var, attributes in self.env_variables.items(): + os.environ[env_var] = str(attributes["value"]) + + def update_env_variables_values( + self, env_var_to_value: t.Dict[str, t.Any], except_if_undefined: bool = False + ) -> None: + """ + Updates and stores the values of the env variables to override service.yaml on the deployment. + + This method does not apply the variables to the environment. Use consume_env_variables to apply the + env variables. + """ + + updated = False + for var, value in env_var_to_value.items(): + value_str = str(value) + attributes = self.env_variables.get(var) + if ( + attributes + and self.env_variables[var]["provision_type"] + == ServiceEnvProvisionType.COMPUTED + and attributes["value"] != value_str + ): + attributes["value"] = value_str + updated = True + elif except_if_undefined: + raise ValueError( + f"Trying to set value for an environment variable ({var}) not present on service configuration {self.service_config_id}." + ) + + if updated: + self.store() + def delete(self) -> None: """Delete a service.""" parent_directory = self.path.parent diff --git a/operate/services/utils/tendermint.py b/operate/services/utils/tendermint.py index 9fa90d439..e9782a67d 100644 --- a/operate/services/utils/tendermint.py +++ b/operate/services/utils/tendermint.py @@ -18,8 +18,10 @@ # ------------------------------------------------------------------------------ """Tendermint manager.""" +import contextlib import json import logging +import multiprocessing import os import platform import re @@ -32,6 +34,7 @@ from logging import Logger from pathlib import Path from threading import Event, Thread +from time import sleep from typing import Any, Callable, Dict, List, Optional, Tuple, cast import requests @@ -310,8 +313,8 @@ def _stop_monitoring_thread(self) -> None: def stop(self) -> None: """Stop a Tendermint node process.""" - self._stop_tm_process() self._stop_monitoring_thread() + self._stop_tm_process() @staticmethod def _write_to_console(line: str) -> None: @@ -503,6 +506,9 @@ def create_app( # pylint: disable=too-many-statements ) app = Flask(__name__) # pylint: disable=redefined-outer-name + app._is_on_exit = ( # pylint: disable=protected-access + False # ugly but better than global ver + ) period_dumper = PeriodDumper( logger=app.logger, dump_dir=Path(os.environ["TMSTATE"]), @@ -570,6 +576,8 @@ def update_params() -> Dict: @app.route("/gentle_reset") def gentle_reset() -> Tuple[Any, int]: """Reset the tendermint node gently.""" + if app._is_on_exit: # pylint: disable=protected-access + raise RuntimeError("server exit now") try: tendermint_node.stop() tendermint_node.start() @@ -597,6 +605,8 @@ def app_hash() -> Tuple[Any, int]: @app.route("/hard_reset") def hard_reset() -> Tuple[Any, int]: """Reset the node forcefully, and prune the blocks""" + if app._is_on_exit: # pylint: disable=protected-access + raise RuntimeError("server exit now") try: tendermint_node.stop() if IS_DEV_MODE: @@ -639,7 +649,46 @@ def create_server() -> Any: return flask_app -if __name__ == "__main__": - # Start the Flask server programmatically +def run_app_in_subprocess(q: multiprocessing.Queue) -> None: + """Run flask app in a subprocess to kill it when needed.""" + print("app in subprocess") + app, tendermint_node = create_app() + + @app.route("/exit") + def handle_server_exit() -> Response: + """Handle server exit.""" + app._is_on_exit = True # pylint: disable=protected-access + tendermint_node.stop() + + q.put(True) + return {"node": "stopped"} + + app.run(host="localhost", port=8080) + + +def run_stoppable_main() -> None: + """Main to spawn flask in a subprocess.""" + print("run stoppable main!") + q: multiprocessing.Queue = multiprocessing.Queue() + p = multiprocessing.Process(target=run_app_in_subprocess, args=(q,)) + p.start() + # wait for stop marker + q.get(block=True) + sleep(1) + p.terminate() + + +def main() -> None: + """Main entrance.""" app = create_server() app.run(host="localhost", port=8080) + + +if __name__ == "__main__": + # Start the Flask server programmatically + + with contextlib.suppress(Exception): + # support for pyinstaller multiprocessing + multiprocessing.freeze_support() + + run_stoppable_main() diff --git a/operate/utils/gnosis.py b/operate/utils/gnosis.py index 51d8ee58f..7dbf8d9ba 100644 --- a/operate/utils/gnosis.py +++ b/operate/utils/gnosis.py @@ -40,6 +40,7 @@ NULL_ADDRESS: str = "0x" + "0" * 40 MAX_UINT256 = 2**256 - 1 ZERO_ETH = 0 +SENTINEL_OWNERS = "0x0000000000000000000000000000000000000001" class SafeOperation(Enum): @@ -157,7 +158,7 @@ def _get_nonce() -> int: def create_safe( ledger_api: LedgerApi, crypto: Crypto, - owner: t.Optional[str] = None, + backup_owner: t.Optional[str] = None, salt_nonce: t.Optional[int] = None, ) -> t.Tuple[str, int]: """Create gnosis safe.""" @@ -169,7 +170,9 @@ def _build( # pylint: disable=unused-argument tx = registry_contracts.gnosis_safe.get_deploy_transaction( ledger_api=ledger_api, deployer_address=crypto.address, - owners=[crypto.address] if owner is None else [crypto.address, owner], + owners=[crypto.address] + if backup_owner is None + else [crypto.address, backup_owner], threshold=1, salt_nonce=salt_nonce, ) @@ -294,14 +297,81 @@ def add_owner( ) -def swap_owner( # pylint: disable=unused-argument +def get_prev_owner(ledger_api: LedgerApi, safe: str, owner: str) -> str: + """Retrieve the previous owner in the owners list of the Safe.""" + + owners = get_owners(ledger_api=ledger_api, safe=safe) + + try: + index = owners.index(owner) - 1 + except ValueError as e: + raise ValueError( + f"Owner {owner} not found in the owners' list of the Safe." + ) from e + + if index < 0: + return SENTINEL_OWNERS + return owners[index] + + +def swap_owner( ledger_api: LedgerApi, crypto: Crypto, safe: str, old_owner: str, new_owner: str, ) -> None: - """Swap owner on a safe.""" + """Swap owner of a safe.""" + + prev_owner = get_prev_owner(ledger_api=ledger_api, safe=safe, owner=old_owner) + instance = registry_contracts.gnosis_safe.get_instance( + ledger_api=ledger_api, + contract_address=safe, + ) + txd = instance.encodeABI( + fn_name="swapOwner", + args=[ + prev_owner, + old_owner, + new_owner, + ], + ) + send_safe_txs( + txd=bytes.fromhex(txd[2:]), + safe=safe, + ledger_api=ledger_api, + crypto=crypto, + ) + + +def remove_owner( + ledger_api: LedgerApi, + crypto: Crypto, + safe: str, + owner: str, + threshold: int, +) -> None: + """Remove owner from a safe.""" + + prev_owner = get_prev_owner(ledger_api=ledger_api, safe=safe, owner=owner) + instance = registry_contracts.gnosis_safe.get_instance( + ledger_api=ledger_api, + contract_address=safe, + ) + txd = instance.encodeABI( + fn_name="removeOwner", + args=[ + prev_owner, + owner, + threshold, + ], + ) + send_safe_txs( + txd=bytes.fromhex(txd[2:]), + safe=safe, + ledger_api=ledger_api, + crypto=crypto, + ) def transfer( diff --git a/operate/wallet/master.py b/operate/wallet/master.py index 2bf16fcc8..4092c60ff 100644 --- a/operate/wallet/master.py +++ b/operate/wallet/master.py @@ -20,6 +20,7 @@ """Master key implementation""" import json +import logging import os import typing as t from dataclasses import dataclass, field @@ -27,7 +28,9 @@ from aea.crypto.base import Crypto, LedgerApi from aea.crypto.registries import make_ledger_api +from aea.helpers.logging import setup_logger from aea_ledger_ethereum.ethereum import EthereumApi, EthereumCrypto +from autonomy.chain.base import registry_contracts from autonomy.chain.config import ChainType as ChainProfile from autonomy.chain.tx import TxSettler from web3 import Account @@ -38,11 +41,12 @@ ON_CHAIN_INTERACT_TIMEOUT, ) from operate.ledger import get_default_rpc -from operate.operate_types import ChainType, LedgerType +from operate.ledger.profiles import OLAS, USDC +from operate.operate_types import Chain, LedgerType from operate.resource import LocalResource -from operate.utils.gnosis import add_owner +from operate.utils.gnosis import NULL_ADDRESS, add_owner from operate.utils.gnosis import create_safe as create_gnosis_safe -from operate.utils.gnosis import get_owners, swap_owner +from operate.utils.gnosis import get_owners, remove_owner, swap_owner from operate.utils.gnosis import transfer as transfer_from_safe from operate.utils.gnosis import transfer_erc20_from_safe @@ -51,7 +55,8 @@ class MasterWallet(LocalResource): """Master wallet.""" path: Path - safes: t.Optional[t.Dict[ChainType, str]] = {} + safes: t.Optional[t.Dict[Chain, str]] = {} + safe_chains: t.List[Chain] = [] ledger_type: LedgerType _key: str @@ -85,21 +90,21 @@ def key_path(self) -> Path: def ledger_api( self, - chain_type: ChainType, + chain: Chain, rpc: t.Optional[str] = None, ) -> LedgerApi: """Get ledger api object.""" return make_ledger_api( self.ledger_type.name.lower(), - address=(rpc or get_default_rpc(chain=chain_type)), - chain_id=chain_type.id, + address=(rpc or get_default_rpc(chain=chain)), + chain_id=chain.id, ) def transfer( self, to: str, amount: int, - chain_type: ChainType, + chain: Chain, from_safe: bool = True, rpc: t.Optional[str] = None, ) -> None: @@ -112,7 +117,7 @@ def transfer_erc20( token: str, to: str, amount: int, - chain_type: ChainType, + chain: Chain, from_safe: bool = True, rpc: t.Optional[str] = None, ) -> None: @@ -126,40 +131,32 @@ def new(password: str, path: Path) -> t.Tuple["MasterWallet", t.List[str]]: def create_safe( self, - chain_type: ChainType, - owner: t.Optional[str] = None, + chain: Chain, + backup_owner: t.Optional[str] = None, rpc: t.Optional[str] = None, ) -> None: """Create safe.""" raise NotImplementedError() - def add_backup_owner( + def update_backup_owner( self, - chain_type: ChainType, - owner: str, + chain: Chain, + backup_owner: t.Optional[str] = None, rpc: t.Optional[str] = None, - ) -> None: - """Create safe.""" + ) -> bool: + """Update backup owner.""" raise NotImplementedError() - def swap_backup_owner( - self, - chain_type: ChainType, - old_owner: str, - new_owner: str, - rpc: t.Optional[str] = None, - ) -> None: - """Create safe.""" - raise NotImplementedError() + # TODO move to resource.py if used in more resources similarly + @property + def extended_json(self) -> t.Dict: + """Get JSON representation with extended information (e.g., safe owners).""" + raise NotImplementedError - def add_or_swap_owner( - self, - chain_type: ChainType, - owner: str, - rpc: t.Optional[str] = None, - ) -> None: - """Add or swap backup owner.""" - raise NotImplementedError() + @classmethod + def migrate_format(cls, path: Path) -> bool: + """Migrate the JSON file format if needed.""" + raise NotImplementedError @dataclass @@ -168,10 +165,10 @@ class EthereumMasterWallet(MasterWallet): path: Path address: str - safe_chains: t.List[ChainType] # For cross-chain support + safes: t.Optional[t.Dict[Chain, str]] = field(default_factory=dict) # type: ignore + safe_chains: t.List[Chain] = field(default_factory=list) # type: ignore ledger_type: LedgerType = LedgerType.ETHEREUM - safes: t.Optional[t.Dict[ChainType, str]] = field(default_factory=dict) # type: ignore safe_nonce: t.Optional[int] = None # For cross-chain reusability _file = ledger_type.config_file @@ -179,12 +176,10 @@ class EthereumMasterWallet(MasterWallet): _crypto_cls = EthereumCrypto def _transfer_from_eoa( - self, to: str, amount: int, chain_type: ChainType, rpc: t.Optional[str] = None + self, to: str, amount: int, chain: Chain, rpc: t.Optional[str] = None ) -> None: """Transfer funds from EOA wallet.""" - ledger_api = t.cast( - EthereumApi, self.ledger_api(chain_type=chain_type, rpc=rpc) - ) + ledger_api = t.cast(EthereumApi, self.ledger_api(chain=chain, rpc=rpc)) tx_helper = TxSettler( ledger_api=ledger_api, crypto=self.crypto, @@ -206,7 +201,7 @@ def _build_tx( # pylint: disable=unused-argument amount=amount, tx_fee=50000, tx_nonce="0x", - chain_id=chain_type.id, + chain_id=chain.id, raise_on_try=True, max_fee_per_gas=int(max_fee_per_gas) if max_fee_per_gas else None, max_priority_fee_per_gas=int(max_priority_fee_per_gas) @@ -222,14 +217,14 @@ def _build_tx( # pylint: disable=unused-argument tx_helper.transact(lambda x: x, "", kwargs={}) def _transfer_from_safe( - self, to: str, amount: int, chain_type: ChainType, rpc: t.Optional[str] = None + self, to: str, amount: int, chain: Chain, rpc: t.Optional[str] = None ) -> None: """Transfer funds from safe wallet.""" if self.safes is not None: transfer_from_safe( - ledger_api=self.ledger_api(chain_type=chain_type, rpc=rpc), + ledger_api=self.ledger_api(chain=chain, rpc=rpc), crypto=self.crypto, - safe=t.cast(str, self.safes[chain_type]), + safe=t.cast(str, self.safes[chain]), to=to, amount=amount, ) @@ -241,15 +236,15 @@ def _transfer_erc20_from_safe( token: str, to: str, amount: int, - chain_type: ChainType, + chain: Chain, rpc: t.Optional[str] = None, ) -> None: """Transfer funds from safe wallet.""" transfer_erc20_from_safe( - ledger_api=self.ledger_api(chain_type=chain_type, rpc=rpc), + ledger_api=self.ledger_api(chain=chain, rpc=rpc), crypto=self.crypto, token=token, - safe=t.cast(str, self.safes[chain_type]), # type: ignore + safe=t.cast(str, self.safes[chain]), # type: ignore to=to, amount=amount, ) @@ -258,7 +253,7 @@ def transfer( self, to: str, amount: int, - chain_type: ChainType, + chain: Chain, from_safe: bool = True, rpc: t.Optional[str] = None, ) -> None: @@ -267,13 +262,13 @@ def transfer( return self._transfer_from_safe( to=to, amount=amount, - chain_type=chain_type, + chain=chain, rpc=rpc, ) return self._transfer_from_eoa( to=to, amount=amount, - chain_type=chain_type, + chain=chain, rpc=rpc, ) @@ -283,7 +278,7 @@ def transfer_erc20( token: str, to: str, amount: int, - chain_type: ChainType, + chain: Chain, from_safe: bool = True, rpc: t.Optional[str] = None, ) -> None: @@ -294,7 +289,7 @@ def transfer_erc20( token=token, to=to, amount=amount, - chain_type=chain_type, + chain=chain, rpc=rpc, ) @@ -326,104 +321,198 @@ def new( def create_safe( self, - chain_type: ChainType, - owner: t.Optional[str] = None, + chain: Chain, + backup_owner: t.Optional[str] = None, rpc: t.Optional[str] = None, ) -> None: """Create safe.""" - if chain_type in self.safe_chains: + if chain in self.safe_chains: return safe, self.safe_nonce = create_gnosis_safe( - ledger_api=self.ledger_api(chain_type=chain_type, rpc=rpc), + ledger_api=self.ledger_api(chain=chain, rpc=rpc), crypto=self.crypto, - owner=owner, + backup_owner=backup_owner, salt_nonce=self.safe_nonce, ) - self.safe_chains.append(chain_type) + self.safe_chains.append(chain) if self.safes is None: self.safes = {} - self.safes[chain_type] = safe + self.safes[chain] = safe self.store() - def add_backup_owner( + def update_backup_owner( self, - chain_type: ChainType, - owner: str, + chain: Chain, + backup_owner: t.Optional[str] = None, rpc: t.Optional[str] = None, - ) -> None: - """Add a backup owner.""" - ledger_api = self.ledger_api(chain_type=chain_type, rpc=rpc) - if chain_type not in self.safes: # type: ignore - raise ValueError(f"Safes not created for chain_type {chain_type}!") - safe = t.cast(str, self.safes[chain_type]) # type: ignore - if len(get_owners(ledger_api=ledger_api, safe=safe)) == 2: - raise ValueError("Backup owner already exist!") - add_owner( - ledger_api=ledger_api, - safe=safe, - owner=owner, - crypto=self.crypto, - ) + ) -> bool: + """Adds a backup owner if not present, or updates it by the provided backup owner. Setting a None backup owner will remove the current one, if any.""" + ledger_api = self.ledger_api(chain=chain, rpc=rpc) + if chain not in self.safes: # type: ignore + raise ValueError(f"Safes not created for chain {chain}!") + safe = t.cast(str, self.safes[chain]) # type: ignore + owners = get_owners(ledger_api=ledger_api, safe=safe) - def swap_backup_owner( - self, - chain_type: ChainType, - old_owner: str, - new_owner: str, - rpc: t.Optional[str] = None, - ) -> None: - """Swap backup owner.""" - ledger_api = self.ledger_api(chain_type=chain_type, rpc=rpc) - if chain_type not in self.safes: # type: ignore - raise ValueError(f"Safes not created for chain_type {chain_type}!") - safe = t.cast(str, self.safes[chain_type]) # type: ignore - if len(get_owners(ledger_api=ledger_api, safe=safe)) == 1: - raise ValueError("Backup owner does not exist, cannot swap!") - swap_owner( - ledger_api=ledger_api, - safe=safe, - old_owner=old_owner, - new_owner=new_owner, - crypto=self.crypto, - ) + if len(owners) > 2: + raise RuntimeError( + f"Safe {safe} on chain {chain} has more than 2 owners: {owners}." + ) - def add_or_swap_owner( - self, - chain_type: ChainType, - owner: str, - rpc: t.Optional[str] = None, - ) -> None: - """Add or swap backup owner.""" - ledger_api = self.ledger_api(chain_type=chain_type, rpc=rpc) - if self.safes is None or chain_type not in self.safes: - raise ValueError(f"Safes not created for chain_type {chain_type}!") - safe = t.cast(str, self.safes[chain_type]) - owners = get_owners(ledger_api=ledger_api, safe=safe) - if len(owners) == 1: - return self.add_backup_owner(chain_type=chain_type, owner=owner, rpc=rpc) + if backup_owner == safe: + raise ValueError("The Safe address cannot be set as the Safe backup owner.") + + if backup_owner == self.address: + raise ValueError( + "The master wallet cannot be set as the Safe backup owner." + ) owners.remove(self.address) - (old_owner,) = owners - if old_owner == owner: - return None - - return self.swap_backup_owner( - chain_type=chain_type, - old_owner=old_owner, - new_owner=owner, - rpc=rpc, - ) + old_backup_owner = owners[0] if owners else None + + if old_backup_owner == backup_owner: + return False + + if not old_backup_owner and backup_owner: + add_owner( + ledger_api=ledger_api, + safe=safe, + owner=backup_owner, + crypto=self.crypto, + ) + return True + if old_backup_owner and not backup_owner: + remove_owner( + ledger_api=ledger_api, + safe=safe, + owner=old_backup_owner, + crypto=self.crypto, + threshold=1, + ) + return True + if old_backup_owner and backup_owner: + swap_owner( + ledger_api=ledger_api, + safe=safe, + old_owner=old_backup_owner, + new_owner=backup_owner, + crypto=self.crypto, + ) + return True + + return False + + @property + def extended_json(self) -> t.Dict: + """Get JSON representation with extended information (e.g., safe owners).""" + rpc = None + tokens = (OLAS, USDC) + wallet_json = self.json + + if not self.safes: + return wallet_json + + owner_sets = set() + for chain, safe in self.safes.items(): + ledger_api = self.ledger_api(chain=chain, rpc=rpc) + owners = get_owners(ledger_api=ledger_api, safe=safe) + owners.remove(self.address) + + balances: t.Dict[str, int] = {} + balances[NULL_ADDRESS] = ledger_api.get_balance(safe) or 0 + for token in tokens: + balance = ( + registry_contracts.erc20.get_instance( + ledger_api=ledger_api, + contract_address=token[chain], + ) + .functions.balanceOf(safe) + .call() + ) + balances[token[chain]] = balance + + wallet_json["safes"][chain.value] = { + wallet_json["safes"][chain.value]: { + "backup_owners": owners, + "balances": balances, + } + } + owner_sets.add(frozenset(owners)) + + wallet_json["extended_json"] = True + wallet_json["consistent_safe_address"] = len(set(self.safes.values())) == 1 + wallet_json["consistent_backup_owner"] = len(owner_sets) == 1 + wallet_json["consistent_backup_owner_count"] = all( + len(owner) == 1 for owner in owner_sets + ) or all(len(owner) == 0 for owner in owner_sets) + return wallet_json @classmethod def load(cls, path: Path) -> "EthereumMasterWallet": """Load master wallet.""" - raw_ethereum_wallet = super().load(path) # type: ignore + # TODO: This is a complex way to read the 'safes' dictionary. + # The reason for that is that wallet.safes[chain] would fail + # (for example in service manager) when passed a ChainType key. + + raw_ethereum_wallet = t.cast(EthereumMasterWallet, super().load(path)) # type: ignore safes = {} - for id_, safe_address in raw_ethereum_wallet.safes.items(): # type: ignore - safes[ChainType(int(id_))] = safe_address + for chain, safe_address in raw_ethereum_wallet.safes.items(): + safes[Chain(chain)] = safe_address - raw_ethereum_wallet.safes = safes # type: ignore - return t.cast(EthereumMasterWallet, raw_ethereum_wallet) + raw_ethereum_wallet.safes = safes + return raw_ethereum_wallet + + @classmethod + def migrate_format(cls, path: Path) -> bool: + """Migrate the JSON file format if needed.""" + wallet_path = path / cls._file + with open(wallet_path, "r", encoding="utf-8") as file: + data = json.load(file) + + migrated = False + if "safes" not in data: + safes = {} + for chain in data["safe_chains"]: + safes[chain] = data["safe"] + data.pop("safe") + data["safes"] = safes + migrated = True + + old_to_new_chains = [ + "ethereum", + "goerli", + "gnosis", + "solana", + "optimistic", + "base", + "mode", + ] + safe_chains = [] + for chain in data["safe_chains"]: + if isinstance(chain, int): + safe_chains.append(old_to_new_chains[chain]) + migrated = True + else: + safe_chains.append(chain) + data["safe_chains"] = safe_chains + + if isinstance(data["ledger_type"], int): + old_to_new_ledgers = [ledger_type.value for ledger_type in LedgerType] + data["ledger_type"] = old_to_new_ledgers[data["ledger_type"]] + migrated = True + + safes = {} + for chain, address in data["safes"].items(): + if str(chain).isnumeric(): + safes[old_to_new_chains[int(chain)]] = address + migrated = True + else: + safes[chain] = address + data["safes"] = safes + + with open(wallet_path, "w", encoding="utf-8") as file: + json.dump(data, file, indent=2) + + return migrated LEDGER_TYPE_TO_WALLET_CLASS = { @@ -434,10 +523,16 @@ def load(cls, path: Path) -> "EthereumMasterWallet": class MasterWalletManager: """Master wallet manager.""" - def __init__(self, path: Path, password: t.Optional[str] = None) -> None: + def __init__( + self, + path: Path, + password: t.Optional[str] = None, + logger: t.Optional[logging.Logger] = None, + ) -> None: """Initialize master wallet manager.""" self.path = path self._password = password + self.logger = logger or setup_logger(name="operate.master_wallet_manager") @property def json(self) -> t.List[t.Dict]: @@ -503,3 +598,20 @@ def __iter__(self) -> t.Iterator[MasterWallet]: if not self.exists(ledger_type=ledger_type): continue yield LEDGER_TYPE_TO_WALLET_CLASS[ledger_type].load(path=self.path) + + def migrate_wallet_configs(self) -> None: + """Migrate old wallet config formats to new ones, if applies.""" + + print(self.path) + + for ledger_type in LedgerType: + if not self.exists(ledger_type=ledger_type): + continue + + wallet_class = LEDGER_TYPE_TO_WALLET_CLASS.get(ledger_type) + if wallet_class is None: + continue + + migrated = wallet_class.migrate_format(path=self.path) + if migrated: + self.logger.info(f"Wallet {wallet_class} has been migrated.") diff --git a/package.json b/package.json index 2d290e65f..2c43427d8 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@tanstack/react-query": "^5.29.0", "adm-zip": "^0.5.12", "antd": "^5.14.0", - "axios": "^1.7.2", + "axios": "^1.7.7", "child_process": "^1.0.2", "cross-env": "^7.0.3", "dotenv": "^16.4.5", @@ -27,15 +27,16 @@ "semver": "^7.6.3", "styled-components": "^6.1.8", "sudo-prompt": "9.2.1", + "typescript": "5.3.x", "usehooks-ts": "^2.14.0", "winston": "^3.13.0", "zod": "^3.23.8" }, "devDependencies": { - "@electron/notarize": "^2.3.0", + "@electron/notarize": "^2.5.0", "dotenv-cli": "^7.4.2", - "electron": "30.0.6", - "electron-builder": "^24.12.0", + "electron": "^33.2.0", + "electron-builder": "^25.1.8", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", @@ -45,7 +46,7 @@ }, "main": "electron/main.js", "name": "olas-operate-app", - "productName": "Pearl (Optimus)", + "productName": "Pearl", "description": "An all-in-one application designed to streamline your entry into the world of autonomous agents and earning OLAS through staking.", "scripts": { "build:frontend": "cd frontend && yarn build && rm -rf ../electron/.next && cp -r .next ../electron/.next && rm -rf ../electron/public && cp -r public ../electron/public", @@ -63,5 +64,11 @@ "download-binaries": "sh download_binaries.sh", "build:pearl": "sh build_pearl.sh" }, - "version": "0.1.0-rc184" + "version": "0.2.0-rc9", + "engines": { + "node": ">=20", + "yarn": ">=1.22.0", + "npm": "please-use-yarn" + }, + "engineStrict": true } \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 5fce400d8..e493fe912 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohttp" @@ -134,13 +134,13 @@ files = [ [[package]] name = "anyio" -version = "4.4.0" +version = "4.6.2.post1" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, + {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"}, + {file = "anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c"}, ] [package.dependencies] @@ -150,9 +150,9 @@ sniffio = ">=1.1" typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] +trio = ["trio (>=0.26.1)"] [[package]] name = "asn1crypto" @@ -222,38 +222,36 @@ tests = ["PyHamcrest (>=2.0.2)", "mypy", "pytest (>=4.6)", "pytest-benchmark", " [[package]] name = "bcrypt" -version = "4.2.0" +version = "4.2.1" description = "Modern password hashing for your software and your servers" optional = false python-versions = ">=3.7" files = [ - {file = "bcrypt-4.2.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:096a15d26ed6ce37a14c1ac1e48119660f21b24cba457f160a4b830f3fe6b5cb"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c02d944ca89d9b1922ceb8a46460dd17df1ba37ab66feac4870f6862a1533c00"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d84cf6d877918620b687b8fd1bf7781d11e8a0998f576c7aa939776b512b98d"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1bb429fedbe0249465cdd85a58e8376f31bb315e484f16e68ca4c786dcc04291"}, - {file = "bcrypt-4.2.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:655ea221910bcac76ea08aaa76df427ef8625f92e55a8ee44fbf7753dbabb328"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:1ee38e858bf5d0287c39b7a1fc59eec64bbf880c7d504d3a06a96c16e14058e7"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0da52759f7f30e83f1e30a888d9163a81353ef224d82dc58eb5bb52efcabc399"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3698393a1b1f1fd5714524193849d0c6d524d33523acca37cd28f02899285060"}, - {file = "bcrypt-4.2.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:762a2c5fb35f89606a9fde5e51392dad0cd1ab7ae64149a8b935fe8d79dd5ed7"}, - {file = "bcrypt-4.2.0-cp37-abi3-win32.whl", hash = "sha256:5a1e8aa9b28ae28020a3ac4b053117fb51c57a010b9f969603ed885f23841458"}, - {file = "bcrypt-4.2.0-cp37-abi3-win_amd64.whl", hash = "sha256:8f6ede91359e5df88d1f5c1ef47428a4420136f3ce97763e31b86dd8280fbdf5"}, - {file = "bcrypt-4.2.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:c52aac18ea1f4a4f65963ea4f9530c306b56ccd0c6f8c8da0c06976e34a6e841"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3bbbfb2734f0e4f37c5136130405332640a1e46e6b23e000eeff2ba8d005da68"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3413bd60460f76097ee2e0a493ccebe4a7601918219c02f503984f0a7ee0aebe"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8d7bb9c42801035e61c109c345a28ed7e84426ae4865511eb82e913df18f58c2"}, - {file = "bcrypt-4.2.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d3a6d28cb2305b43feac298774b997e372e56c7c7afd90a12b3dc49b189151c"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9c1c4ad86351339c5f320ca372dfba6cb6beb25e8efc659bedd918d921956bae"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:27fe0f57bb5573104b5a6de5e4153c60814c711b29364c10a75a54bb6d7ff48d"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8ac68872c82f1add6a20bd489870c71b00ebacd2e9134a8aa3f98a0052ab4b0e"}, - {file = "bcrypt-4.2.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cb2a8ec2bc07d3553ccebf0746bbf3d19426d1c6d1adbd4fa48925f66af7b9e8"}, - {file = "bcrypt-4.2.0-cp39-abi3-win32.whl", hash = "sha256:77800b7147c9dc905db1cba26abe31e504d8247ac73580b4aa179f98e6608f34"}, - {file = "bcrypt-4.2.0-cp39-abi3-win_amd64.whl", hash = "sha256:61ed14326ee023917ecd093ee6ef422a72f3aec6f07e21ea5f10622b735538a9"}, - {file = "bcrypt-4.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:39e1d30c7233cfc54f5c3f2c825156fe044efdd3e0b9d309512cc514a263ec2a"}, - {file = "bcrypt-4.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f4f4acf526fcd1c34e7ce851147deedd4e26e6402369304220250598b26448db"}, - {file = "bcrypt-4.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:1ff39b78a52cf03fdf902635e4c81e544714861ba3f0efc56558979dd4f09170"}, - {file = "bcrypt-4.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:373db9abe198e8e2c70d12b479464e0d5092cc122b20ec504097b5f2297ed184"}, - {file = "bcrypt-4.2.0.tar.gz", hash = "sha256:cf69eaf5185fd58f268f805b505ce31f9b9fc2d64b376642164e9244540c1221"}, + {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea"}, + {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6"}, + {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139"}, + {file = "bcrypt-4.2.1-cp37-abi3-win32.whl", hash = "sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005"}, + {file = "bcrypt-4.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526"}, + {file = "bcrypt-4.2.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99"}, + {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84"}, + {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d"}, + {file = "bcrypt-4.2.1-cp39-abi3-win32.whl", hash = "sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf"}, + {file = "bcrypt-4.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e"}, + {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f"}, + {file = "bcrypt-4.2.1.tar.gz", hash = "sha256:6765386e3ab87f569b276988742039baab087b2cdb01e809d74e74503c2faafe"}, ] [package.extras] @@ -273,133 +271,148 @@ files = [ [[package]] name = "bitarray" -version = "2.9.2" +version = "2.9.3" description = "efficient arrays of booleans -- C extension" optional = false python-versions = "*" files = [ - {file = "bitarray-2.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:917905de565d9576eb20f53c797c15ba88b9f4f19728acabec8d01eee1d3756a"}, - {file = "bitarray-2.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b35bfcb08b7693ab4bf9059111a6e9f14e07d57ac93cd967c420db58ab9b71e1"}, - {file = "bitarray-2.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ea1923d2e7880f9e1959e035da661767b5a2e16a45dfd57d6aa831e8b65ee1bf"}, - {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0b63a565e8a311cc8348ff1262d5784df0f79d64031d546411afd5dd7ef67d"}, - {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cf0620da2b81946d28c0b16f3e3704d38e9837d85ee4f0652816e2609aaa4fed"}, - {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79a9b8b05f2876c7195a2b698c47528e86a73c61ea203394ff8e7a4434bda5c8"}, - {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:345c76b349ff145549652436235c5532e5bfe9db690db6f0a6ad301c62b9ef21"}, - {file = "bitarray-2.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e2936f090bf3f4d1771f44f9077ebccdbc0415d2b598d51a969afcb519df505"}, - {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f9346e98fc2abcef90b942973087e2462af6d3e3710e82938078d3493f7fef52"}, - {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e6ec283d4741befb86e8c3ea2e9ac1d17416c956d392107e45263e736954b1f7"}, - {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:962892646599529917ef26266091e4cb3077c88b93c3833a909d68dcc971c4e3"}, - {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e8da5355d7d75a52df5b84750989e34e39919ec7e59fafc4c104cc1607ab2d31"}, - {file = "bitarray-2.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:603e7d640e54ad764d2b4da6b61e126259af84f253a20f512dd10689566e5478"}, - {file = "bitarray-2.9.2-cp310-cp310-win32.whl", hash = "sha256:f00079f8e69d75c2a417de7961a77612bb77ef46c09bc74607d86de4740771ef"}, - {file = "bitarray-2.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:1bb33673e7f7190a65f0a940c1ef63266abdb391f4a3e544a47542d40a81f536"}, - {file = "bitarray-2.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fe71fd4b76380c2772f96f1e53a524da7063645d647a4fcd3b651bdd80ca0f2e"}, - {file = "bitarray-2.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d527172919cdea1e13994a66d9708a80c3d33dedcf2f0548e4925e600fef3a3a"}, - {file = "bitarray-2.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:052c5073bdcaa9dd10628d99d37a2f33ec09364b86dd1f6281e2d9f8d3db3060"}, - {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e064caa55a6ed493aca1eda06f8b3f689778bc780a75e6ad7724642ba5dc62f7"}, - {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:508069a04f658210fdeee85a7a0ca84db4bcc110cbb1d21f692caa13210f24a7"}, - {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4da73ebd537d75fa7bccfc2228fcaedea0803f21dd9d0bf0d3b67fef3c4af294"}, - {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cb378eaa65cd43098f11ff5d27e48ee3b956d2c00d2d6b5bfc2a09fe183be47"}, - {file = "bitarray-2.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d14c790b91f6cbcd9b718f88ed737c78939980c69ac8c7f03dd7e60040c12951"}, - {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7eea9318293bc0ea6447e9ebfba600a62f3428bea7e9c6d42170ae4f481dbab3"}, - {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b76ffec27c7450b8a334f967366a9ebadaea66ee43f5b530c12861b1a991f503"}, - {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:76b76a07d4ee611405045c6950a1e24c4362b6b44808d4ad6eea75e0dbc59af4"}, - {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c7d16beeaaab15b075990cd26963d6b5b22e8c5becd131781514a00b8bdd04bd"}, - {file = "bitarray-2.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60df43e868a615c7e15117a1e1c2e5e11f48f6457280eba6ddf8fbefbec7da99"}, - {file = "bitarray-2.9.2-cp311-cp311-win32.whl", hash = "sha256:e788608ed7767b7b3bbde6d49058bccdf94df0de9ca75d13aa99020cc7e68095"}, - {file = "bitarray-2.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:a23397da092ef0a8cfe729571da64c2fc30ac18243caa82ac7c4f965087506ff"}, - {file = "bitarray-2.9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:90e3a281ffe3897991091b7c46fca38c2675bfd4399ffe79dfeded6c52715436"}, - {file = "bitarray-2.9.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bed637b674db5e6c8a97a4a321e3e4d73e72d50b5c6b29950008a93069cc64cd"}, - {file = "bitarray-2.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e49066d251dbbe4e6e3a5c3937d85b589e40e2669ad0eef41a00f82ec17d844b"}, - {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4344e96642e2211fb3a50558feff682c31563a4c64529a931769d40832ca79"}, - {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aeb60962ec4813c539a59fbd4f383509c7222b62c3fb1faa76b54943a613e33a"}, - {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed0f7982f10581bb16553719e5e8f933e003f5b22f7d25a68bdb30fac630a6ff"}, - {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71d1cabdeee0cdda4669168618f0e46b7dace207b29da7b63aaa1adc2b54081"}, - {file = "bitarray-2.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0ef2d0a6f1502d38d911d25609b44c6cc27bee0a4363dd295df78b075041b60"}, - {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6f71d92f533770fb027388b35b6e11988ab89242b883f48a6fe7202d238c61f8"}, - {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ba0734aa300757c924f3faf8148e1b8c247176a0ac8e16aefdf9c1eb19e868f7"}, - {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:d91406f413ccbf4af6ab5ae7bc78f772a95609f9ddd14123db36ef8c37116d95"}, - {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:87abb7f80c0a042f3fe8e5264da1a2756267450bb602110d5327b8eaff7682e7"}, - {file = "bitarray-2.9.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b558ce85579b51a2e38703877d1e93b7728a7af664dd45a34e833534f0b755d"}, - {file = "bitarray-2.9.2-cp312-cp312-win32.whl", hash = "sha256:dac2399ee2889fbdd3472bfc2ede74c34cceb1ccf29a339964281a16eb1d3188"}, - {file = "bitarray-2.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:48a30d718d1a6dfc22a49547450107abe8f4afdf2abdcbe76eb9ed88edc49498"}, - {file = "bitarray-2.9.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2c6be1b651fad8f3adb7a5aa12c65b612cd9b89530969af941844ae680f7d981"}, - {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5b399ae6ab975257ec359f03b48fc00b1c1cd109471e41903548469b8feae5c"}, - {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b3543c8a1cb286ad105f11c25d8d0f712f41c5c55f90be39f0e5a1376c7d0b0"}, - {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:03adaacb79e2fb8f483ab3a67665eec53bb3fd0cd5dbd7358741aef124688db3"}, - {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ae5b0657380d2581e13e46864d147a52c1e2bbac9f59b59c576e42fa7d10cf0"}, - {file = "bitarray-2.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1f4bf6ea8eb9d7f30808c2e9894237a96650adfecbf5f3643862dc5982f89e"}, - {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a8873089be2aa15494c0f81af1209f6e1237d762c5065bc4766c1b84321e1b50"}, - {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:677e67f50e2559efc677a4366707070933ad5418b8347a603a49a070890b19bc"}, - {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:a620d8ce4ea2f1c73c6b6b1399e14cb68c6915e2be3fad5808c2998ed55b4acf"}, - {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:64115ccabbdbe279c24c367b629c6b1d3da9ed36c7420129e27c338a3971bfee"}, - {file = "bitarray-2.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5d6fb422772e75385b76ad1c52f45a68bd4efafd8be8d0061c11877be74c4d43"}, - {file = "bitarray-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:852e202875dd6dfd6139ce7ec4e98dac2b17d8d25934dc99900831e81c3adaef"}, - {file = "bitarray-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:7dfefdcb0dc6a3ba9936063cec65a74595571b375beabe18742b3d91d087eefd"}, - {file = "bitarray-2.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b306c4cf66912511422060f7f5e1149c8bdb404f8e00e600561b0749fdd45659"}, - {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a09c4f81635408e3387348f415521d4b94198c562c23330f560596a6aaa26eaf"}, - {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5361413fd2ecfdf44dc8f065177dc6aba97fa80a91b815586cb388763acf7f8d"}, - {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e8a9475d415ef1eaae7942df6f780fa4dcd48fce32825eda591a17abba869299"}, - {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b87baa7bfff9a5878fcc1bffe49ecde6e647a72a64b39a69cd8a2992a43a34"}, - {file = "bitarray-2.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb6b86cfdfc503e92cb71c68766a24565359136961642504a7cc9faf936d9c88"}, - {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cd56b8ae87ebc71bcacbd73615098e8a8de952ecbb5785b6b4e2b07da8a06e1f"}, - {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3fa909cfd675004aed8b4cc9df352415933656e0155a6209d878b7cb615c787e"}, - {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b069ca9bf728e0c5c5b60e00a89df9af34cc170c695c3bfa3b372d8f40288efb"}, - {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:6067f2f07a7121749858c7daa93c8774325c91590b3e81a299621e347740c2ae"}, - {file = "bitarray-2.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:321841cdad1dd0f58fe62e80e9c9c7531f8ebf8be93f047401e930dc47425b1e"}, - {file = "bitarray-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:54e16e32e60973bb83c315de9975bc1bcfc9bd50bb13001c31da159bc49b0ca1"}, - {file = "bitarray-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:f4dcadb7b8034aa3491ee8f5a69b3d9ba9d7d1e55c3cc1fc45be313e708277f8"}, - {file = "bitarray-2.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c8919fdbd3bb596b104388b56ae4b266eb28da1f2f7dff2e1f9334a21840fe96"}, - {file = "bitarray-2.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eb7a9d8a2e400a1026de341ad48e21670a6261a75b06df162c5c39b0d0e7c8f4"}, - {file = "bitarray-2.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6ec84668dd7b937874a2b2c293cd14ba84f37be0d196dead852e0ada9815d807"}, - {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2de9a31c34e543ae089fd2a5ced01292f725190e379921384f695e2d7184bd3"}, - {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9521f49ae121a17c0a41e5112249e6fa7f6a571245b1118de81fb86e7c1bc1ce"}, - {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6cc6545d6d76542aee3d18c1c9485fb7b9812b8df4ebe52c4535ec42081b48f"}, - {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:856bbe1616425f71c0df5ef2e8755e878d9504d5a531acba58ab4273c52c117a"}, - {file = "bitarray-2.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4bba8042ea6ab331ade91bc435d81ad72fddb098e49108610b0ce7780c14e68"}, - {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a035da89c959d98afc813e3c62f052690d67cfd55a36592f25d734b70de7d4b0"}, - {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6d70b1579da7fb71be5a841a1f965d19aca0ef27f629cfc07d06b09aafd0a333"}, - {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:405b83bed28efaae6d86b6ab287c75712ead0adbfab2a1075a1b7ab47dad4d62"}, - {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7eb8be687c50da0b397d5e0ab7ca200b5ebb639e79a9f5e285851d1944c94be9"}, - {file = "bitarray-2.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eceb551dfeaf19c609003a69a0cf8264b0efd7abc3791a11dfabf4788daf0d19"}, - {file = "bitarray-2.9.2-cp38-cp38-win32.whl", hash = "sha256:bb198c6ed1edbcdaf3d1fa3c9c9d1cdb7e179a5134ef5ee660b53cdec43b34e7"}, - {file = "bitarray-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:648d2f2685590b0103c67a937c2fb9e09bcc8dfb166f0c7c77bd341902a6f5b3"}, - {file = "bitarray-2.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ea816dc8f8e65841a8bbdd30e921edffeeb6f76efe6a1eb0da147b60d539d1cf"}, - {file = "bitarray-2.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4d0e32530f941c41eddfc77600ec89b65184cb909c549336463a738fab3ed285"}, - {file = "bitarray-2.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a22266fb416a3b6c258bf7f83c9fe531ba0b755a56986a81ad69dc0f3bcc070"}, - {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc6d3e80dd8239850f2604833ff3168b28909c8a9357abfed95632cccd17e3e7"}, - {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f135e804986b12bf14f2cd1eb86674c47dea86c4c5f0fa13c88978876b97ebe6"}, - {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87580c7f7d14f7ec401eda7adac1e2a25e95153e9c339872c8ae61b3208819a1"}, - {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64b433e26993127732ac7b66a7821b2537c3044355798de7c5fcb0af34b8296f"}, - {file = "bitarray-2.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e497c535f2a9b68c69d36631bf2dba243e05eb343b00b9c7bbdc8c601c6802d"}, - {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e40b3cb9fa1edb4e0175d7c06345c49c7925fe93e39ef55ecb0bc40c906b0c09"}, - {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f2f8692f95c9e377eb19ca519d30d1f884b02feb7e115f798de47570a359e43f"}, - {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f0b84fc50b6dbeced4fa390688c07c10a73222810fb0e08392bd1a1b8259de36"}, - {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d656ad38c942e38a470ddbce26b5020e08e1a7ea86b8fd413bb9024b5189993a"}, - {file = "bitarray-2.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6ab0f1dbfe5070db98771a56aa14797595acd45a1af9eadfb193851a270e7996"}, - {file = "bitarray-2.9.2-cp39-cp39-win32.whl", hash = "sha256:0a99b23ac845a9ea3157782c97465e6ae026fe0c7c4c1ed1d88f759fd6ea52d9"}, - {file = "bitarray-2.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:9bbcfc7c279e8d74b076e514e669b683f77b4a2a328585b3f16d4c5259c91222"}, - {file = "bitarray-2.9.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:43847799461d8ba71deb4d97b47250c2c2fb66d82cd3cb8b4caf52bb97c03034"}, - {file = "bitarray-2.9.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f44381b0a4bdf64416082f4f0e7140377ae962c0ced6f983c6d7bbfc034040"}, - {file = "bitarray-2.9.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a484061616fb4b158b80789bd3cb511f399d2116525a8b29b6334c68abc2310f"}, - {file = "bitarray-2.9.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ff9e38356cc803e06134cf8ae9758e836ccd1b793135ef3db53c7c5d71e93bc"}, - {file = "bitarray-2.9.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b44105792fbdcfbda3e26ee88786790fda409da4c71f6c2b73888108cf8f062f"}, - {file = "bitarray-2.9.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7e913098de169c7fc890638ce5e171387363eb812579e637c44261460ac00aa2"}, - {file = "bitarray-2.9.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6fe315355cdfe3ed22ef355b8bdc81a805ca4d0949d921576560e5b227a1112"}, - {file = "bitarray-2.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f708e91fdbe443f3bec2df394ed42328fb9b0446dff5cb4199023ac6499e09fd"}, - {file = "bitarray-2.9.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b7b09489b71f9f1f64c0fa0977e250ec24500767dab7383ba9912495849cadf"}, - {file = "bitarray-2.9.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:128cc3488176145b9b137fdcf54c1c201809bbb8dd30b260ee40afe915843b43"}, - {file = "bitarray-2.9.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:21f21e7f56206be346bdbda2a6bdb2165a5e6a11821f88fd4911c5a6bbbdc7e2"}, - {file = "bitarray-2.9.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f4dd3af86dd8a617eb6464622fb64ca86e61ce99b59b5c35d8cd33f9c30603d"}, - {file = "bitarray-2.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6465de861aff7a2559f226b37982007417eab8c3557543879987f58b453519bd"}, - {file = "bitarray-2.9.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbaf2bb71d6027152d603f1d5f31e0dfd5e50173d06f877bec484e5396d4594b"}, - {file = "bitarray-2.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2f32948c86e0d230a296686db28191b67ed229756f84728847daa0c7ab7406e3"}, - {file = "bitarray-2.9.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be94e5a685e60f9d24532af8fe5c268002e9016fa80272a94727f435de3d1003"}, - {file = "bitarray-2.9.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5cc9381fd54f3c23ae1039f977bfd6d041a5c3c1518104f616643c3a5a73b15"}, - {file = "bitarray-2.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd926e8ae4d1ed1ac4a8f37212a62886292f692bc1739fde98013bf210c2d175"}, - {file = "bitarray-2.9.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:461a3dafb9d5fda0bb3385dc507d78b1984b49da3fe4c6d56c869a54373b7008"}, - {file = "bitarray-2.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:393cb27fd859af5fd9c16eb26b1c59b17b390ff66b3ae5d0dd258270191baf13"}, - {file = "bitarray-2.9.2.tar.gz", hash = "sha256:a8f286a51a32323715d77755ed959f94bef13972e9a2fe71b609e40e6d27957e"}, + {file = "bitarray-2.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2cf5f5400636c7dda797fd681795ce63932458620fe8c40955890380acba9f62"}, + {file = "bitarray-2.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3487b4718ffa5942fab777835ee36085f8dda7ec4bd0b28433efb117f84852b6"}, + {file = "bitarray-2.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10f44b1e4994035408bea54d7bf0aec79744cad709706bedf28091a48bb7f1a4"}, + {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5c16f97c65add6535748a9c98c70e7ca79759c38a2eb990127fef72f76111a"}, + {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13dbfc42971ba84e9c4ba070f720df6570285a3f89187f07ef422efcb611c19f"}, + {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c28076acfbe7f9a5494d7ae98094a6e209c390c340938845f294818ebf5e4d3"}, + {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7cdd21835936d9a66477836ca23b2cb63295142cb9d9158883e2c0f1f8f6bd"}, + {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f60887ab3a46e507fa6f8544d8d4b0748da48718591dfe3fe80c62bdea60f10"}, + {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f75e1abd4a37cba3002521d3f5e2b50ef4f4a74342207cad3f52468411d5d8ba"}, + {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dc63da9695383c048b83f5ab77eab35a55bbb2e77c7b6e762eba219929b45b84"}, + {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6fe5a57b859d9bc9c2fd27c78c4b7b83158faf984202de6fb44618caeebfff10"}, + {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1fe5a37bd9441a5ecc2f6e71b43df7176fa376a542ef97484310b8b46a45649a"}, + {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8a16e42c169ca818d6a15b5dd5acd5d2a26af0fa0588e1036e0e58d01f8387d4"}, + {file = "bitarray-2.9.3-cp310-cp310-win32.whl", hash = "sha256:5e6b5e7940af3474ffaa930cd1ce8215181cbe864d6b5ddb67a15d3c15e935cd"}, + {file = "bitarray-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:c63dbb99ef2ab1281871678624f9c9a5f1682b826e668ce559275ec488b3fa8b"}, + {file = "bitarray-2.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:49fb93b488d180f5c84b79fe687c585a84bf0295ff035d63e09ee24ce1da0558"}, + {file = "bitarray-2.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c2944fb83bbc2aa7f29a713bc4f8c1318e54fa0d06a72bedd350a3fb4a4b91d8"}, + {file = "bitarray-2.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3612d9d3788dc62f1922c917b1539f1cdf02cecc9faef8ae213a8b36093136ca"}, + {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90a9300cdb7c99b1e692bb790cba8acecee1a345a83e58e28c94a0d87c522237"}, + {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1211ed66acbbb221fd7554abf4206a384d79e6192d5cb95325c5c361bbb52a74"}, + {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67757279386accf93eba76b8f97b5acf1664a3e350cbea5f300f53490f8764fd"}, + {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64e19c6a99c32f460c2613f797f77aa37d8e298891d00ea5355158cce80e11ec"}, + {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72734bd3775f43c5a75385730abb9f84fee6c627eb14f579de4be478f1615c8c"}, + {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a92703471b5d3316c7481bc1852f620f42f7a1b62be27f39d13694827635786f"}, + {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d5d77c81300ca430d4b195ccfbb629d6858258f541b6e96c6b11ec1563cd2681"}, + {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:3ba8a29c0d091c952ced1607ce715f5e0524899f24333a493807d00f5938463d"}, + {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:418171d035b191dbe5e86cd2bfb5c3e1ae7d947edc22857a897d1c7251674ae5"}, + {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e0bd272eba256183be2a17488f9cb096d2e6d3435ecf2e28c1e0857c6d20749"}, + {file = "bitarray-2.9.3-cp311-cp311-win32.whl", hash = "sha256:cc3fd2b0637a619cf13e122bbcf4729ae214d5f25623675597e67c25f9edfe61"}, + {file = "bitarray-2.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:e1fc2a81a585dbe5e367682156e6350d908a56e2ffd6ca651b0af01994db596f"}, + {file = "bitarray-2.9.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dc47be026f76f1728af00dc7140cec8483fe2f0c476bbf2a59ef47865e00ff96"}, + {file = "bitarray-2.9.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:82b091742ff511cdb06f90af0d2c22e7af3dbff9b8212e2e0d88dfef6a8570b3"}, + {file = "bitarray-2.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d5edb4302a0e3a3d1d0eeb891de3c615d4cb7a446fb41c21eecdcfb29400a6f"}, + {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4786c5525069c19820549dd2f42d33632bc42959ad167138bd8ee5024b922b"}, + {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bfe2de2b4df61ccb9244871a0fdf1fff83be0c1bd7187048c3cf7f81c5fe631"}, + {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31e4f69538f95d2934587d957eea0d283162322dd1af29e57122b20b8cd60f92"}, + {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ca44908b2bc08d8995770018638d62626706864f9c599b7818225a12f3dbc2c"}, + {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:279f8de5d251ee521e365df29c927d9b5732f1ed4f373d2dbbd278fcbad94ff5"}, + {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49bb631b38431c09ecd534d56ef04264397d24d18c4ee6653c84e14ae09d92d"}, + {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:192bffc93ee9a5b6c833c98d1dcc81f5633ddd726b85e18341387d0c1d51f691"}, + {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c516cec28c6511df51d87033f40ec420324a2247469b0c989d344f4d27ea37d2"}, + {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:66241cb9a1c1db294f46cd440141e57e8242874e38f3f61877f72d92ae14768a"}, + {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ab1f0e7631110c89bea7b605c0c35832333eb9cc97e5de05d71c76d42a1858c9"}, + {file = "bitarray-2.9.3-cp312-cp312-win32.whl", hash = "sha256:42aa5bee6fe8ad3385eaf5c6585016bbc38a7b75efb52ce5c6f8e00e05237dfa"}, + {file = "bitarray-2.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:dc3fd647d845b94fac3652390866f921f914a17f3807a031c826f68dae3f43e3"}, + {file = "bitarray-2.9.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fcfcc1989e3e021a282624017b7fb754210f5332e933b1c3ebc79643727b6551"}, + {file = "bitarray-2.9.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:71b1e229a706798a9e106ca7b03d4c63455deb40b18c92950ec073a05a8f8285"}, + {file = "bitarray-2.9.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4bb49556d3d505d24c942a4206ad4d0d40e89fa3016a7ea6edc994d5c08d4a8e"}, + {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4466aa1e533a59d5f7fd37219d154ec3f2ba73fce3d8a2e11080ec475bc15fb"}, + {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a9b75adc0fd0bf278bea89dc3d679d74e10d2df98d3d074b7f3d36f323138818"}, + {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:701582bbbeac372b1cd8a3c9daf6c2336dc2d22e14373a6271d788bc4f2b6edc"}, + {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea1f119668bbdbd68008031491515e84441e505163918819994b28f295f762c"}, + {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f400bc18a70bfdb073532c3054ecd78a0e64f96ff7b6140adde5b122580ec2b"}, + {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:aacff5656fb3e15cede7d02903da2634d376aa928d7a81ec8df19b0724d7972a"}, + {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8a2ae42a14cbf766d4478d7101da6359b0648dd813e60eb3486ac56ad2f5add3"}, + {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:616698edb547d10f0b960cb9f2e8629c55a420dd4c2b1ab46706f49a1815621d"}, + {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f277c50ba184929dfeed39b6cf9468e3446093521b0aeb52bd54a21ca08f5473"}, + {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:661237739b385c90d8837d5e96b06de093cc6e610236977e198f88f5a979686e"}, + {file = "bitarray-2.9.3-cp313-cp313-win32.whl", hash = "sha256:68acec6c19d798051f178a1197b76f891985f683f95a4b12811b68e58b080f5a"}, + {file = "bitarray-2.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:3055720afdcfd7e8f630fa16db7bed7e55c9d0a1f4756195e3b250e203f3b436"}, + {file = "bitarray-2.9.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:72bf17d0e7d8a4f645655a07999d23e42472cbf2100b8dad7ce26586075241d7"}, + {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cfd332b5f1ad8c4dc3cc79ecef33c19b42d8d8e6a39fd5c9ecb5855be0b9723"}, + {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5b466ef1e48f25621c9d27e95deb5e33b8656827ed8aa530b972de73870bd1f"}, + {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:938cf26fdaf4d0adfac82d830c025523c5d36ddead0470b735286028231c1784"}, + {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0f766669e768ef9a2b23ecfa710b38b6a48da3f91755113c79320b207ae255d"}, + {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6337c0c64044f35ddfb241143244aac707a68f34ae31a71dad115f773ccc8b"}, + {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:731b59540167f8b2b20f69f487ecee2339fc4657059906a16cb51acac17f89c3"}, + {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:4feed0539a9d6432361fc4d3820eea3a81fa631d542f166cf8430aad81a971da"}, + {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:eb65c96a42e73f35175ec738d67992ffdf054c20abee3933cfcfa2343fa1187d"}, + {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:4f40ceac94d182de6135759d81289683ff3e4cf0da709bc5826a7fe00d754114"}, + {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:5b29f7844080a281635a231a37e99f0bd6f567af6cf19f4f6d212137f99a9cdf"}, + {file = "bitarray-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:947cf522a3b339b73114d12417fd848fa01303dbaa7883ced4c87688dba5637c"}, + {file = "bitarray-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:ea794ea60d514d68777a87a74106110db7a4bbc2c46720e67010e3071afefb95"}, + {file = "bitarray-2.9.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c7bc7cb79dcac8bdce23b305e671c06eaeffb012fa065b8c33bc51df7e1733f0"}, + {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6380ad0f929ad9220abadd1c9b7234271c4b6ea9c753a88611d489e93a8f2e"}, + {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05f4e2451e2ad450b41ede8440e52c1fd798e81027e1dc2256292ec0787d3bf1"}, + {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7267885c98138f3707c710d5b08eedef150a3e5112c760cfe1200f3366fd7064"}, + {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:976957423cb41df8fe0eb811dbb53d8c5ab1ca3beec7a3ca7ff679be44a72714"}, + {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0ec5141a69f73ed6ff17ea7344d5cc166e087095bfe3661dbb42b519e76aa16"}, + {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:218a1b7c0652a3c1020f903ded0f9768c3719fb6d43a6e9d346e985292992d35"}, + {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:cf0c9ebf2df280794244e1e12ed626357506ddaa2f0d6f69efe493ae7bbf4bf7"}, + {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:c450a04a7e091b57d4c0bd1531648522cd0ef26913ad0e5dea0432ea29b0e5c1"}, + {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:a212eb89a50e32ef4969387e44a7410447dc59587615e3966d090edc338a1b85"}, + {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:4269232026212ee6b73379b88a578107a6b36a6182307a49d5509686c7495261"}, + {file = "bitarray-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:8a0fb358e6a43f216c3fb0871e2ac14c16563aec363c23bc2fbbb18f6201285d"}, + {file = "bitarray-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:a8368774cdc737eec8fce6f28d0abc095fbc0edccf8fab8d29fddc264b68def9"}, + {file = "bitarray-2.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7d0724a4fef6ded914075a3385ea2d05afdeed567902f83490ed4e7e7e75d9bf"}, + {file = "bitarray-2.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0e11b37c6dff6f41ebc49914628824ceb8c8d6ebd0fda2ebe3c0fe0c63e8621e"}, + {file = "bitarray-2.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:085f4081d72c7468f82f722a9f113e03a1f7a4c132ef4c2a4e680c5d78b7db00"}, + {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b530b5fbed2900634fbc43f546e384abd72ad9c49795ff5bd6a93cac1aa9c4d8"}, + {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09ff88e4385967571146fb0d270442de39393d44198f4d108f3350cfd6486f0b"}, + {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344bb212ddf87db4976a6711d274660a5d887da4fd3faafcdaa092152f85a6d"}, + {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc569c96b990f92fd5946d5b50501fee48b01a116a286d1de7961ebd9c6f06f3"}, + {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2fbbe7938ef8a7abe3e8519fa0578b51d2787f7171d3144e7d373551b5851fd"}, + {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0b5912fab904507b47217509b01aa903d7f98b6e725e490a7f01661f4d9a4fa7"}, + {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:0c836ccfca9cf60927256738ef234dfe500565492eff269610cdd1bca56801d0"}, + {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:af0e4441ebf51c18fc450962f1e201c96f444d63b17cc8dcf7c0b05111bd4486"}, + {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:9e9b57175fb6fe76d7ddd0647e06a25f6e23f4b54b5febf337c5a840ab37dc3b"}, + {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:7f7de81721ae9492926bd067007ac974692182bb83fc8f0ba330a67f37a018bd"}, + {file = "bitarray-2.9.3-cp38-cp38-win32.whl", hash = "sha256:4beafb6b6e344385480df6611fdebfcb3579bbb40636ce1ddf5e72fb744e095f"}, + {file = "bitarray-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:d8eaeca98900bd6f06a29cdef57999813a67d314f661d14901d71e04f4cf9f00"}, + {file = "bitarray-2.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:413965d9d384aef90e58b959f4a39f1d5060b145c26080297b7b4cf23cf38faa"}, + {file = "bitarray-2.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2fbb56f2bb89c3a15304a6c0ea56013dc340a98337d9bbd7fc5c21451dc05f8c"}, + {file = "bitarray-2.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b8a84f39f7885627711473872d8fc58fc7a0a1e4ecd9ddf42daf9a3643432742"}, + {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45147a9c8580e857c1344d15bd49d2b4387777bd582a2ede11be2ba740653f28"}, + {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed255423dc60c6b2d5c0d90c13dea2962a31929767fdf1c525ab3210269e75c5"}, + {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f5bd02671ea5c4ad52bbfe0e8e8197b6e8fa85dec1e93a4a05448c19354cc65"}, + {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1c99c58f044549c93fb6d4cda22678deccaed19845eaa2e6917b5b7ca058f2d"}, + {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:921ee87681e32e17d1849e11c96eb6a8a7edaa1269dd26831013daf8546bde05"}, + {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2ed97d8ec40c4658d9f9aa8f26cb473f44fa1dbccba3fa3fbe4a102e38c6a8d7"}, + {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9d7f7db37edb9c50c9aad6a18f2e87dd7dc5ff2a33406821804a03263fedb2ca"}, + {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:292f726cdb9efc744ed0a1d7453c44151526648148a28d9a2495cc7c7b2c62a8"}, + {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2cc94784238782a9376f307b1aa9a85ce77b6eded9f82d2fe062db7fdb02c645"}, + {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5051436b1d318f6ce0df3b2f8a60bfa66a54c1d9e8719d6cb6b448140e7061f2"}, + {file = "bitarray-2.9.3-cp39-cp39-win32.whl", hash = "sha256:a3d436c686ce59fd0b93438ed2c0e1d3e1716e56bce64b874d05b9f49f1ca5d1"}, + {file = "bitarray-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:f168fc45664266a560f2cb28a327041b7f69d4a7faad8ab89e0a1dd7c270a70d"}, + {file = "bitarray-2.9.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ae36787299cff41f212aee33cfe1defee13979a41552665a412b6ca3fa8f7eb8"}, + {file = "bitarray-2.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42afe48abb8eeb386d93e7f1165ace1dd027f136a8a31edd2b20bc57a0c071d7"}, + {file = "bitarray-2.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451ceecdb86bb95ae101b0d65c8c4524d692ae3666662fef8c89877ce17748c5"}, + {file = "bitarray-2.9.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4d67d3e3de2aede737b12cd75a84963700c941b77b579c14bd05517e05d7a9f"}, + {file = "bitarray-2.9.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2406d13ded84049b4238815a5821e44d6f58ba00fbb6b705b6ef8ccd88be8f03"}, + {file = "bitarray-2.9.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0db944fc2a048020fc940841ef46c0295b045d45a5a582cba69f78962a49a384"}, + {file = "bitarray-2.9.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25c603f141171a7d108773d5136d14e572c473e4cdb3fb464c39c8a138522eb2"}, + {file = "bitarray-2.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86c06b02705305cab0914d209caa24effda81316e2f2555a71a9aa399b75c5a5"}, + {file = "bitarray-2.9.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ddda45b24a802eaaca8f794e6267ff2b62de5fe7b900b76d6f662d95192bebf"}, + {file = "bitarray-2.9.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:81490623950d04870c6dd4d7e6df2eb68dd04eca8bec327895ebee8bbe0cc3c7"}, + {file = "bitarray-2.9.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a9e69ac6a514cc574891c24a50847022dac2fef8c3f4df530f92820a07337755"}, + {file = "bitarray-2.9.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:545c695ee69d26b41351ced4c76244d8b6225669fc0af3652ff8ed5a6b28325d"}, + {file = "bitarray-2.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbb2e6daabd2a64d091ac7460b0c5c5f9268199ae9a8ce32737cf5273987f1fa"}, + {file = "bitarray-2.9.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a969e5cf63144b944ee8d0a0739f53ef1ae54725b5e01258d690a8995d880526"}, + {file = "bitarray-2.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:73bbb9301ac9000f869c51db2cc5fcc6541985d3fcdcfe6e02f90c9e672a00be"}, + {file = "bitarray-2.9.3-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c07e346926488a85a48542d898f4168f3587ec42379fef0d18be301e08a3f27"}, + {file = "bitarray-2.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a26d8a14cd8ee496306f2afac34833502dd1ae826355af309333b6f252b23fe"}, + {file = "bitarray-2.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cef148ed37c892395ca182d6a235524165a9f765f4283d0a1ced891e7c43c67a"}, + {file = "bitarray-2.9.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94f35a8f0c8a50ee98a8bef9a070d0b68ecf623f20a2148cc039aba5557346a6"}, + {file = "bitarray-2.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b03207460daae828e2743874c84264e8d96a8c6156490279092b624cd5d2de08"}, + {file = "bitarray-2.9.3.tar.gz", hash = "sha256:9eff55cf189b0c37ba97156a00d640eb7392db58a8049be6f26ff2712b93fa89"}, ] [[package]] @@ -415,78 +428,78 @@ files = [ [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -494,101 +507,116 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -709,83 +737,73 @@ requests = "*" [[package]] name = "coverage" -version = "7.6.1" +version = "7.6.7" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, - {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, - {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, - {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, - {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, - {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, - {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, - {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, - {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, - {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, - {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, - {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, - {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, - {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, - {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, - {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, - {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, - {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, + {file = "coverage-7.6.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:108bb458827765d538abcbf8288599fee07d2743357bdd9b9dad456c287e121e"}, + {file = "coverage-7.6.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c973b2fe4dc445cb865ab369df7521df9c27bf40715c837a113edaa2aa9faf45"}, + {file = "coverage-7.6.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c6b24007c4bcd0b19fac25763a7cac5035c735ae017e9a349b927cfc88f31c1"}, + {file = "coverage-7.6.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acbb8af78f8f91b3b51f58f288c0994ba63c646bc1a8a22ad072e4e7e0a49f1c"}, + {file = "coverage-7.6.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad32a981bcdedb8d2ace03b05e4fd8dace8901eec64a532b00b15217d3677dd2"}, + {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:34d23e28ccb26236718a3a78ba72744212aa383141961dd6825f6595005c8b06"}, + {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e25bacb53a8c7325e34d45dddd2f2fbae0dbc230d0e2642e264a64e17322a777"}, + {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af05bbba896c4472a29408455fe31b3797b4d8648ed0a2ccac03e074a77e2314"}, + {file = "coverage-7.6.7-cp310-cp310-win32.whl", hash = "sha256:796c9b107d11d2d69e1849b2dfe41730134b526a49d3acb98ca02f4985eeff7a"}, + {file = "coverage-7.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:987a8e3da7da4eed10a20491cf790589a8e5e07656b6dc22d3814c4d88faf163"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e61b0e77ff4dddebb35a0e8bb5a68bf0f8b872407d8d9f0c726b65dfabe2469"}, + {file = "coverage-7.6.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a5407a75ca4abc20d6252efeb238377a71ce7bda849c26c7a9bece8680a5d99"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df002e59f2d29e889c37abd0b9ee0d0e6e38c24f5f55d71ff0e09e3412a340ec"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673184b3156cba06154825f25af33baa2671ddae6343f23175764e65a8c4c30b"}, + {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69ad502f1a2243f739f5bd60565d14a278be58be4c137d90799f2c263e7049a"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60dcf7605c50ea72a14490d0756daffef77a5be15ed1b9fea468b1c7bda1bc3b"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9c2eb378bebb2c8f65befcb5147877fc1c9fbc640fc0aad3add759b5df79d55d"}, + {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c0317288f032221d35fa4cbc35d9f4923ff0dfd176c79c9b356e8ef8ef2dff4"}, + {file = "coverage-7.6.7-cp311-cp311-win32.whl", hash = "sha256:951aade8297358f3618a6e0660dc74f6b52233c42089d28525749fc8267dccd2"}, + {file = "coverage-7.6.7-cp311-cp311-win_amd64.whl", hash = "sha256:5e444b8e88339a2a67ce07d41faabb1d60d1004820cee5a2c2b54e2d8e429a0f"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f07ff574986bc3edb80e2c36391678a271d555f91fd1d332a1e0f4b5ea4b6ea9"}, + {file = "coverage-7.6.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:49ed5ee4109258973630c1f9d099c7e72c5c36605029f3a91fe9982c6076c82b"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3b925300484a3294d1c70f6b2b810d6526f2929de954e5b6be2bf8caa1f12c1"}, + {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c42ec2c522e3ddd683dec5cdce8e62817afb648caedad9da725001fa530d354"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e5f2a0f161d126ccc7038f1f3029184dbdf8f018230af17ef6fd6a707a5b881f"}, + {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c132b5a22821f9b143f87446805e13580b67c670a548b96da945a8f6b4f2efbb"}, + {file = "coverage-7.6.7-cp312-cp312-win32.whl", hash = "sha256:7c07de0d2a110f02af30883cd7dddbe704887617d5c27cf373362667445a4c76"}, + {file = "coverage-7.6.7-cp312-cp312-win_amd64.whl", hash = "sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46f21663e358beae6b368429ffadf14ed0a329996248a847a4322fb2e35d64d3"}, + {file = "coverage-7.6.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40cca284c7c310d622a1677f105e8507441d1bb7c226f41978ba7c86979609ab"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77256ad2345c29fe59ae861aa11cfc74579c88d4e8dbf121cbe46b8e32aec808"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87ea64b9fa52bf395272e54020537990a28078478167ade6c61da7ac04dc14bc"}, + {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d608a7808793e3615e54e9267519351c3ae204a6d85764d8337bd95993581a8"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdd94501d65adc5c24f8a1a0eda110452ba62b3f4aeaba01e021c1ed9cb8f34a"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82c809a62e953867cf57e0548c2b8464207f5f3a6ff0e1e961683e79b89f2c55"}, + {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb684694e99d0b791a43e9fc0fa58efc15ec357ac48d25b619f207c41f2fd384"}, + {file = "coverage-7.6.7-cp313-cp313-win32.whl", hash = "sha256:963e4a08cbb0af6623e61492c0ec4c0ec5c5cf74db5f6564f98248d27ee57d30"}, + {file = "coverage-7.6.7-cp313-cp313-win_amd64.whl", hash = "sha256:14045b8bfd5909196a90da145a37f9d335a5d988a83db34e80f41e965fb7cb42"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f2c7a045eef561e9544359a0bf5784b44e55cefc7261a20e730baa9220c83413"}, + {file = "coverage-7.6.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dd4e4a49d9c72a38d18d641135d2fb0bdf7b726ca60a103836b3d00a1182acd"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c95e0fa3d1547cb6f021ab72f5c23402da2358beec0a8e6d19a368bd7b0fb37"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b"}, + {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead9b9605c54d15be228687552916c89c9683c215370c4a44f1f217d2adcc34d"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e2c8e3384c12dfa19fa9a52f23eb091a8fad93b5b81a41b14c17c78e23dd1d8b"}, + {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:70a56a2ec1869e6e9fa69ef6b76b1a8a7ef709972b9cc473f9ce9d26b5997ce3"}, + {file = "coverage-7.6.7-cp313-cp313t-win32.whl", hash = "sha256:dbba8210f5067398b2c4d96b4e64d8fb943644d5eb70be0d989067c8ca40c0f8"}, + {file = "coverage-7.6.7-cp313-cp313t-win_amd64.whl", hash = "sha256:dfd14bcae0c94004baba5184d1c935ae0d1231b8409eb6c103a5fd75e8ecdc56"}, + {file = "coverage-7.6.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37a15573f988b67f7348916077c6d8ad43adb75e478d0910957394df397d2874"}, + {file = "coverage-7.6.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b6cce5c76985f81da3769c52203ee94722cd5d5889731cd70d31fee939b74bf0"}, + {file = "coverage-7.6.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ab9763d291a17b527ac6fd11d1a9a9c358280adb320e9c2672a97af346ac2c"}, + {file = "coverage-7.6.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6cf96ceaa275f071f1bea3067f8fd43bec184a25a962c754024c973af871e1b7"}, + {file = "coverage-7.6.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aee9cf6b0134d6f932d219ce253ef0e624f4fa588ee64830fcba193269e4daa3"}, + {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2bc3e45c16564cc72de09e37413262b9f99167803e5e48c6156bccdfb22c8327"}, + {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:623e6965dcf4e28a3debaa6fcf4b99ee06d27218f46d43befe4db1c70841551c"}, + {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850cfd2d6fc26f8346f422920ac204e1d28814e32e3a58c19c91980fa74d8289"}, + {file = "coverage-7.6.7-cp39-cp39-win32.whl", hash = "sha256:c296263093f099da4f51b3dff1eff5d4959b527d4f2f419e16508c5da9e15e8c"}, + {file = "coverage-7.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:90746521206c88bdb305a4bf3342b1b7316ab80f804d40c536fc7d329301ee13"}, + {file = "coverage-7.6.7-pp39.pp310-none-any.whl", hash = "sha256:0ddcb70b3a3a57581b450571b31cb774f23eb9519c2aaa6176d3a84c9fc57671"}, + {file = "coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24"}, ] [package.extras] @@ -793,38 +811,38 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "43.0.1" +version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"}, - {file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"}, - {file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"}, - {file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"}, - {file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"}, - {file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"}, - {file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"}, - {file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"}, - {file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"}, - {file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"}, - {file = "cryptography-43.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172"}, - {file = "cryptography-43.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2"}, - {file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"}, + {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, + {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, + {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, + {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, + {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, + {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, + {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, + {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, + {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, + {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, + {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa"}, + {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, + {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, ] [package.dependencies] @@ -837,7 +855,7 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -959,15 +977,33 @@ toolz = ">=0.8.0" [package.extras] cython = ["cython"] +[[package]] +name = "deepdiff" +version = "8.0.1" +description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +optional = false +python-versions = ">=3.8" +files = [ + {file = "deepdiff-8.0.1-py3-none-any.whl", hash = "sha256:42e99004ce603f9a53934c634a57b04ad5900e0d8ed0abb15e635767489cbc05"}, + {file = "deepdiff-8.0.1.tar.gz", hash = "sha256:245599a4586ab59bb599ca3517a9c42f3318ff600ded5e80a3432693c8ec3c4b"}, +] + +[package.dependencies] +orderly-set = "5.2.2" + +[package.extras] +cli = ["click (==8.1.7)", "pyyaml (==6.0.1)"] +optimize = ["orjson"] + [[package]] name = "distlib" -version = "0.3.8" +version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" files = [ - {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, - {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, ] [[package]] @@ -1258,19 +1294,19 @@ all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)" [[package]] name = "filelock" -version = "3.15.4" +version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, - {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] -typing = ["typing-extensions (>=4.8)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "flask" @@ -1382,13 +1418,13 @@ files = [ [[package]] name = "googleapis-common-protos" -version = "1.65.0" +version = "1.66.0" description = "Common protobufs used in Google APIs" optional = false python-versions = ">=3.7" files = [ - {file = "googleapis_common_protos-1.65.0-py2.py3-none-any.whl", hash = "sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63"}, - {file = "googleapis_common_protos-1.65.0.tar.gz", hash = "sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0"}, + {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, + {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, ] [package.dependencies] @@ -1427,72 +1463,84 @@ websockets = ["websockets (>=10,<12)"] [[package]] name = "graphql-core" -version = "3.2.3" +version = "3.2.5" description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." optional = false -python-versions = ">=3.6,<4" +python-versions = "<4,>=3.6" files = [ - {file = "graphql-core-3.2.3.tar.gz", hash = "sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676"}, - {file = "graphql_core-3.2.3-py3-none-any.whl", hash = "sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3"}, + {file = "graphql_core-3.2.5-py3-none-any.whl", hash = "sha256:2f150d5096448aa4f8ab26268567bbfeef823769893b39c1a2e1409590939c8a"}, + {file = "graphql_core-3.2.5.tar.gz", hash = "sha256:e671b90ed653c808715645e3998b7ab67d382d55467b7e2978549111bbabf8d5"}, ] +[package.dependencies] +typing-extensions = {version = ">=4,<5", markers = "python_version < \"3.10\""} + [[package]] name = "grpcio" -version = "1.66.1" +version = "1.68.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.66.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:4877ba180591acdf127afe21ec1c7ff8a5ecf0fe2600f0d3c50e8c4a1cbc6492"}, - {file = "grpcio-1.66.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:3750c5a00bd644c75f4507f77a804d0189d97a107eb1481945a0cf3af3e7a5ac"}, - {file = "grpcio-1.66.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:a013c5fbb12bfb5f927444b477a26f1080755a931d5d362e6a9a720ca7dbae60"}, - {file = "grpcio-1.66.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1b24c23d51a1e8790b25514157d43f0a4dce1ac12b3f0b8e9f66a5e2c4c132f"}, - {file = "grpcio-1.66.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7ffb8ea674d68de4cac6f57d2498fef477cef582f1fa849e9f844863af50083"}, - {file = "grpcio-1.66.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:307b1d538140f19ccbd3aed7a93d8f71103c5d525f3c96f8616111614b14bf2a"}, - {file = "grpcio-1.66.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1c17ebcec157cfb8dd445890a03e20caf6209a5bd4ac5b040ae9dbc59eef091d"}, - {file = "grpcio-1.66.1-cp310-cp310-win32.whl", hash = "sha256:ef82d361ed5849d34cf09105d00b94b6728d289d6b9235513cb2fcc79f7c432c"}, - {file = "grpcio-1.66.1-cp310-cp310-win_amd64.whl", hash = "sha256:292a846b92cdcd40ecca46e694997dd6b9be6c4c01a94a0dfb3fcb75d20da858"}, - {file = "grpcio-1.66.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:c30aeceeaff11cd5ddbc348f37c58bcb96da8d5aa93fed78ab329de5f37a0d7a"}, - {file = "grpcio-1.66.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8a1e224ce6f740dbb6b24c58f885422deebd7eb724aff0671a847f8951857c26"}, - {file = "grpcio-1.66.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a66fe4dc35d2330c185cfbb42959f57ad36f257e0cc4557d11d9f0a3f14311df"}, - {file = "grpcio-1.66.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3ba04659e4fce609de2658fe4dbf7d6ed21987a94460f5f92df7579fd5d0e22"}, - {file = "grpcio-1.66.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4573608e23f7e091acfbe3e84ac2045680b69751d8d67685ffa193a4429fedb1"}, - {file = "grpcio-1.66.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7e06aa1f764ec8265b19d8f00140b8c4b6ca179a6dc67aa9413867c47e1fb04e"}, - {file = "grpcio-1.66.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3885f037eb11f1cacc41f207b705f38a44b69478086f40608959bf5ad85826dd"}, - {file = "grpcio-1.66.1-cp311-cp311-win32.whl", hash = "sha256:97ae7edd3f3f91480e48ede5d3e7d431ad6005bfdbd65c1b56913799ec79e791"}, - {file = "grpcio-1.66.1-cp311-cp311-win_amd64.whl", hash = "sha256:cfd349de4158d797db2bd82d2020554a121674e98fbe6b15328456b3bf2495bb"}, - {file = "grpcio-1.66.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:a92c4f58c01c77205df6ff999faa008540475c39b835277fb8883b11cada127a"}, - {file = "grpcio-1.66.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fdb14bad0835914f325349ed34a51940bc2ad965142eb3090081593c6e347be9"}, - {file = "grpcio-1.66.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f03a5884c56256e08fd9e262e11b5cfacf1af96e2ce78dc095d2c41ccae2c80d"}, - {file = "grpcio-1.66.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ca2559692d8e7e245d456877a85ee41525f3ed425aa97eb7a70fc9a79df91a0"}, - {file = "grpcio-1.66.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ca1be089fb4446490dd1135828bd42a7c7f8421e74fa581611f7afdf7ab761"}, - {file = "grpcio-1.66.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d639c939ad7c440c7b2819a28d559179a4508783f7e5b991166f8d7a34b52815"}, - {file = "grpcio-1.66.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b9feb4e5ec8dc2d15709f4d5fc367794d69277f5d680baf1910fc9915c633524"}, - {file = "grpcio-1.66.1-cp312-cp312-win32.whl", hash = "sha256:7101db1bd4cd9b880294dec41a93fcdce465bdbb602cd8dc5bd2d6362b618759"}, - {file = "grpcio-1.66.1-cp312-cp312-win_amd64.whl", hash = "sha256:b0aa03d240b5539648d996cc60438f128c7f46050989e35b25f5c18286c86734"}, - {file = "grpcio-1.66.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:ecfe735e7a59e5a98208447293ff8580e9db1e890e232b8b292dc8bd15afc0d2"}, - {file = "grpcio-1.66.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4825a3aa5648010842e1c9d35a082187746aa0cdbf1b7a2a930595a94fb10fce"}, - {file = "grpcio-1.66.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:f517fd7259fe823ef3bd21e508b653d5492e706e9f0ef82c16ce3347a8a5620c"}, - {file = "grpcio-1.66.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1fe60d0772831d96d263b53d83fb9a3d050a94b0e94b6d004a5ad111faa5b5b"}, - {file = "grpcio-1.66.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31a049daa428f928f21090403e5d18ea02670e3d5d172581670be006100db9ef"}, - {file = "grpcio-1.66.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6f914386e52cbdeb5d2a7ce3bf1fdfacbe9d818dd81b6099a05b741aaf3848bb"}, - {file = "grpcio-1.66.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bff2096bdba686019fb32d2dde45b95981f0d1490e054400f70fc9a8af34b49d"}, - {file = "grpcio-1.66.1-cp38-cp38-win32.whl", hash = "sha256:aa8ba945c96e73de29d25331b26f3e416e0c0f621e984a3ebdb2d0d0b596a3b3"}, - {file = "grpcio-1.66.1-cp38-cp38-win_amd64.whl", hash = "sha256:161d5c535c2bdf61b95080e7f0f017a1dfcb812bf54093e71e5562b16225b4ce"}, - {file = "grpcio-1.66.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:d0cd7050397b3609ea51727b1811e663ffda8bda39c6a5bb69525ef12414b503"}, - {file = "grpcio-1.66.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0e6c9b42ded5d02b6b1fea3a25f036a2236eeb75d0579bfd43c0018c88bf0a3e"}, - {file = "grpcio-1.66.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:c9f80f9fad93a8cf71c7f161778ba47fd730d13a343a46258065c4deb4b550c0"}, - {file = "grpcio-1.66.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dd67ed9da78e5121efc5c510f0122a972216808d6de70953a740560c572eb44"}, - {file = "grpcio-1.66.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48b0d92d45ce3be2084b92fb5bae2f64c208fea8ceed7fccf6a7b524d3c4942e"}, - {file = "grpcio-1.66.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4d813316d1a752be6f5c4360c49f55b06d4fe212d7df03253dfdae90c8a402bb"}, - {file = "grpcio-1.66.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9c9bebc6627873ec27a70fc800f6083a13c70b23a5564788754b9ee52c5aef6c"}, - {file = "grpcio-1.66.1-cp39-cp39-win32.whl", hash = "sha256:30a1c2cf9390c894c90bbc70147f2372130ad189cffef161f0432d0157973f45"}, - {file = "grpcio-1.66.1-cp39-cp39-win_amd64.whl", hash = "sha256:17663598aadbedc3cacd7bbde432f541c8e07d2496564e22b214b22c7523dac8"}, - {file = "grpcio-1.66.1.tar.gz", hash = "sha256:35334f9c9745add3e357e3372756fd32d925bd52c41da97f4dfdafbde0bf0ee2"}, + {file = "grpcio-1.68.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:619b5d0f29f4f5351440e9343224c3e19912c21aeda44e0c49d0d147a8d01544"}, + {file = "grpcio-1.68.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:a59f5822f9459bed098ffbceb2713abbf7c6fd13f2b9243461da5c338d0cd6c3"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:c03d89df516128febc5a7e760d675b478ba25802447624edf7aa13b1e7b11e2a"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44bcbebb24363d587472089b89e2ea0ab2e2b4df0e4856ba4c0b087c82412121"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79f81b7fbfb136247b70465bd836fa1733043fdee539cd6031cb499e9608a110"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:88fb2925789cfe6daa20900260ef0a1d0a61283dfb2d2fffe6194396a354c618"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:99f06232b5c9138593ae6f2e355054318717d32a9c09cdc5a2885540835067a1"}, + {file = "grpcio-1.68.0-cp310-cp310-win32.whl", hash = "sha256:a6213d2f7a22c3c30a479fb5e249b6b7e648e17f364598ff64d08a5136fe488b"}, + {file = "grpcio-1.68.0-cp310-cp310-win_amd64.whl", hash = "sha256:15327ab81131ef9b94cb9f45b5bd98803a179c7c61205c8c0ac9aff9d6c4e82a"}, + {file = "grpcio-1.68.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3b2b559beb2d433129441783e5f42e3be40a9e1a89ec906efabf26591c5cd415"}, + {file = "grpcio-1.68.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e46541de8425a4d6829ac6c5d9b16c03c292105fe9ebf78cb1c31e8d242f9155"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:c1245651f3c9ea92a2db4f95d37b7597db6b246d5892bca6ee8c0e90d76fb73c"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f1931c7aa85be0fa6cea6af388e576f3bf6baee9e5d481c586980c774debcb4"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ff09c81e3aded7a183bc6473639b46b6caa9c1901d6f5e2cba24b95e59e30"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8c73f9fbbaee1a132487e31585aa83987ddf626426d703ebcb9a528cf231c9b1"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6b2f98165ea2790ea159393a2246b56f580d24d7da0d0342c18a085299c40a75"}, + {file = "grpcio-1.68.0-cp311-cp311-win32.whl", hash = "sha256:e1e7ed311afb351ff0d0e583a66fcb39675be112d61e7cfd6c8269884a98afbc"}, + {file = "grpcio-1.68.0-cp311-cp311-win_amd64.whl", hash = "sha256:e0d2f68eaa0a755edd9a47d40e50dba6df2bceda66960dee1218da81a2834d27"}, + {file = "grpcio-1.68.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8af6137cc4ae8e421690d276e7627cfc726d4293f6607acf9ea7260bd8fc3d7d"}, + {file = "grpcio-1.68.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4028b8e9a3bff6f377698587d642e24bd221810c06579a18420a17688e421af7"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f60fa2adf281fd73ae3a50677572521edca34ba373a45b457b5ebe87c2d01e1d"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e18589e747c1e70b60fab6767ff99b2d0c359ea1db8a2cb524477f93cdbedf5b"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d30f3fee9372796f54d3100b31ee70972eaadcc87314be369360248a3dcffe"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7e0a3e72c0e9a1acab77bef14a73a416630b7fd2cbd893c0a873edc47c42c8cd"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a831dcc343440969aaa812004685ed322cdb526cd197112d0db303b0da1e8659"}, + {file = "grpcio-1.68.0-cp312-cp312-win32.whl", hash = "sha256:5a180328e92b9a0050958ced34dddcb86fec5a8b332f5a229e353dafc16cd332"}, + {file = "grpcio-1.68.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bddd04a790b69f7a7385f6a112f46ea0b34c4746f361ebafe9ca0be567c78e9"}, + {file = "grpcio-1.68.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:fc05759ffbd7875e0ff2bd877be1438dfe97c9312bbc558c8284a9afa1d0f40e"}, + {file = "grpcio-1.68.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15fa1fe25d365a13bc6d52fcac0e3ee1f9baebdde2c9b3b2425f8a4979fccea1"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:32a9cb4686eb2e89d97022ecb9e1606d132f85c444354c17a7dbde4a455e4a3b"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dba037ff8d284c8e7ea9a510c8ae0f5b016004f13c3648f72411c464b67ff2fb"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0efbbd849867e0e569af09e165363ade75cf84f5229b2698d53cf22c7a4f9e21"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:4e300e6978df0b65cc2d100c54e097c10dfc7018b9bd890bbbf08022d47f766d"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:6f9c7ad1a23e1047f827385f4713b5b8c6c7d325705be1dd3e31fb00dcb2f665"}, + {file = "grpcio-1.68.0-cp313-cp313-win32.whl", hash = "sha256:3ac7f10850fd0487fcce169c3c55509101c3bde2a3b454869639df2176b60a03"}, + {file = "grpcio-1.68.0-cp313-cp313-win_amd64.whl", hash = "sha256:afbf45a62ba85a720491bfe9b2642f8761ff348006f5ef67e4622621f116b04a"}, + {file = "grpcio-1.68.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:f8f695d9576ce836eab27ba7401c60acaf9ef6cf2f70dfe5462055ba3df02cc3"}, + {file = "grpcio-1.68.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9fe1b141cda52f2ca73e17d2d3c6a9f3f3a0c255c216b50ce616e9dca7e3441d"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:4df81d78fd1646bf94ced4fb4cd0a7fe2e91608089c522ef17bc7db26e64effd"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46a2d74d4dd8993151c6cd585594c082abe74112c8e4175ddda4106f2ceb022f"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a17278d977746472698460c63abf333e1d806bd41f2224f90dbe9460101c9796"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:15377bce516b1c861c35e18eaa1c280692bf563264836cece693c0f169b48829"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cc5f0a4f5904b8c25729a0498886b797feb817d1fd3812554ffa39551112c161"}, + {file = "grpcio-1.68.0-cp38-cp38-win32.whl", hash = "sha256:def1a60a111d24376e4b753db39705adbe9483ef4ca4761f825639d884d5da78"}, + {file = "grpcio-1.68.0-cp38-cp38-win_amd64.whl", hash = "sha256:55d3b52fd41ec5772a953612db4e70ae741a6d6ed640c4c89a64f017a1ac02b5"}, + {file = "grpcio-1.68.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0d230852ba97654453d290e98d6aa61cb48fa5fafb474fb4c4298d8721809354"}, + {file = "grpcio-1.68.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:50992f214264e207e07222703c17d9cfdcc2c46ed5a1ea86843d440148ebbe10"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:14331e5c27ed3545360464a139ed279aa09db088f6e9502e95ad4bfa852bb116"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f84890b205692ea813653ece4ac9afa2139eae136e419231b0eec7c39fdbe4c2"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0cf343c6f4f6aa44863e13ec9ddfe299e0be68f87d68e777328bff785897b05"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fd2c2d47969daa0e27eadaf15c13b5e92605c5e5953d23c06d0b5239a2f176d3"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:18668e36e7f4045820f069997834e94e8275910b1f03e078a6020bd464cb2363"}, + {file = "grpcio-1.68.0-cp39-cp39-win32.whl", hash = "sha256:2af76ab7c427aaa26aa9187c3e3c42f38d3771f91a20f99657d992afada2294a"}, + {file = "grpcio-1.68.0-cp39-cp39-win_amd64.whl", hash = "sha256:e694b5928b7b33ca2d3b4d5f9bf8b5888906f181daff6b406f4938f3a997a490"}, + {file = "grpcio-1.68.0.tar.gz", hash = "sha256:7e7483d39b4a4fddb9906671e9ea21aaad4f031cdfc349fec76bdfa1e404543a"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.66.1)"] +protobuf = ["grpcio-tools (>=1.68.0)"] [[package]] name = "h11" @@ -1524,33 +1572,40 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "idna" -version = "3.8" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" files = [ - {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, - {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "importlib-metadata" -version = "8.4.0" +version = "8.5.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, - {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, + {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, + {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, ] [package.dependencies] -zipp = ">=0.5" +zipp = ">=3.20" [package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["pytest-mypy"] [[package]] name = "iniconfig" @@ -1734,71 +1789,72 @@ altgraph = ">=0.17" [[package]] name = "markupsafe" -version = "2.1.5" +version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, ] [[package]] @@ -1943,18 +1999,18 @@ nicer-shell = ["ipython"] [[package]] name = "open-aea" -version = "1.53.0" +version = "1.57.0" description = "Open Autonomous Economic Agent framework (without vendor lock-in)" optional = false python-versions = ">=3.8" files = [ - {file = "open_aea-1.53.0-py3-none-any.whl", hash = "sha256:1244855875effe09e2c965750ac401a973a1ae56cdc880045eea70f19ed90dcb"}, - {file = "open_aea-1.53.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:d0a848e33798599953dc764d37083fc37642140a91624e06a56b8d2f95ae6cb9"}, - {file = "open_aea-1.53.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:48f5715f13a0389799b9461bc776e9638e6ae38173d0f2bf6d28bad637232914"}, - {file = "open_aea-1.53.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:87e4ae903ec9a7268eba0ead449f9693cb5bedb6dfc5846c90f94f2354bd35ab"}, - {file = "open_aea-1.53.0-py3-none-win32.whl", hash = "sha256:182e9f8a77fe8efcc768360ac7308a0951ec16bcb12e2ad4f55886b12258d702"}, - {file = "open_aea-1.53.0-py3-none-win_amd64.whl", hash = "sha256:cef9d4d177ea7d959ebacab962fbd1d03d7243c0b72d10a3ee7850df8d922e06"}, - {file = "open_aea-1.53.0.tar.gz", hash = "sha256:6fcb82ceed0b6841c0f41d116b207308556e3d18807fe140e9ef1a898c7a8a0b"}, + {file = "open_aea-1.57.0-py3-none-any.whl", hash = "sha256:19714577414fa7ce7c9a43e4dd9d7849189b77b158a3d60e75cb43a7ea0eecd5"}, + {file = "open_aea-1.57.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:a56d0b6dfa5bcdcf24d0edd167bf0e90c205bb6f20b59bcee0975a8dbd1811fe"}, + {file = "open_aea-1.57.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:a03df0c0e8354a8a0d940969252dbdf633f9b5698ce499e1cd30f694f7635151"}, + {file = "open_aea-1.57.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:1fb3c78c7877bcd41d33b3bd5ee51f2cfe62efa2a07f193838133c771fff5237"}, + {file = "open_aea-1.57.0-py3-none-win32.whl", hash = "sha256:a068d8710d3e235499ae866d167825bca1b56314f255b05591b2e362c1f9b3a6"}, + {file = "open_aea-1.57.0-py3-none-win_amd64.whl", hash = "sha256:eb2ef61a7e7d74f4b99fc27fdbad7350320c18528f85678fe1a6503736ef2de5"}, + {file = "open_aea-1.57.0.tar.gz", hash = "sha256:7cef260f56a4214752ea6242d43cf20a7488815f7e2de53ff2836b57a650a385"}, ] [package.dependencies] @@ -1971,10 +2027,7 @@ py-multicodec = ">=0.2.0" pymultihash = "0.8.2" pytest = {version = ">=7.0.0,<7.3.0", optional = true, markers = "extra == \"all\""} python-dotenv = ">=0.14.0,<1.0.1" -pyyaml = [ - {version = ">=6.0.1,<7"}, - {version = ">=6.0.1,<9", optional = true, markers = "extra == \"all\""}, -] +pyyaml = {version = ">=6.0.1,<7", optional = true, markers = "extra == \"all\""} requests = ">=2.28.1,<3" semver = ">=2.9.1,<3.0.0" @@ -1985,13 +2038,13 @@ test-tools = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "jsonschema (>= [[package]] name = "open-aea-cli-ipfs" -version = "1.53.0" +version = "1.57.0" description = "CLI extension for open AEA framework wrapping IPFS functionality." optional = false python-versions = "*" files = [ - {file = "open_aea_cli_ipfs-1.53.0-py3-none-any.whl", hash = "sha256:335a02473d1c6820bb63a31e2931749ba644f586a7acbc650da9efc4c7168efa"}, - {file = "open_aea_cli_ipfs-1.53.0.tar.gz", hash = "sha256:499a66a45925064e6946ec72f482182390263cc7726409832f1317fe831b6289"}, + {file = "open_aea_cli_ipfs-1.57.0-py3-none-any.whl", hash = "sha256:6cbefd42a682f1f0c116e527f728998f61a9bc930995acdd754b5335e54ad97d"}, + {file = "open_aea_cli_ipfs-1.57.0.tar.gz", hash = "sha256:8254a1ecef4e7e3dbc9ba990243413963a0d5055b336c1ce6f2e0ae4ddaa25ce"}, ] [package.dependencies] @@ -2016,13 +2069,13 @@ web3 = ">=6.0.0,<7" [[package]] name = "open-aea-ledger-cosmos" -version = "1.53.0" +version = "1.57.0" description = "Python package wrapping the public and private key cryptography and ledger api of Cosmos." optional = false python-versions = "*" files = [ - {file = "open_aea_ledger_cosmos-1.53.0-py3-none-any.whl", hash = "sha256:79b2eafc8723593634b72973da39e3e3c01bceae04b330b51a5059eb1200262b"}, - {file = "open_aea_ledger_cosmos-1.53.0.tar.gz", hash = "sha256:14a032918d7f0659fedbe21a53fa668b24505bb9e97358340b20325943f9fa26"}, + {file = "open_aea_ledger_cosmos-1.57.0-py3-none-any.whl", hash = "sha256:dfedc58ae4cebd938b51834f3eca5e2c8ffce95661a84212c3c4b6341e8952d4"}, + {file = "open_aea_ledger_cosmos-1.57.0.tar.gz", hash = "sha256:35ae99e188a256bfcb06d510d161643922d6ed1e639eed92b3b5f7ee3576d5bf"}, ] [package.dependencies] @@ -2034,13 +2087,13 @@ pycryptodome = ">=3.10.1,<4.0.0" [[package]] name = "open-aea-ledger-ethereum" -version = "1.53.0" +version = "1.57.0" description = "Python package wrapping the public and private key cryptography and ledger api of Ethereum." optional = false python-versions = "*" files = [ - {file = "open_aea_ledger_ethereum-1.53.0-py3-none-any.whl", hash = "sha256:501eb9e9e228552bf9f6f8811d780f33dbbf477ddb33b63d335caaeb24840274"}, - {file = "open_aea_ledger_ethereum-1.53.0.tar.gz", hash = "sha256:734f335061c33a171b945ab1bcea5d47be9b9532457ed361b3aab727e85bca0d"}, + {file = "open_aea_ledger_ethereum-1.57.0-py3-none-any.whl", hash = "sha256:8ad775344baa77fc6b8e5a92edfa6d7e32f3361a885113379733e7ce4e4d6405"}, + {file = "open_aea_ledger_ethereum-1.57.0.tar.gz", hash = "sha256:7c16858ad751db3906ec72046c821ad5b057c5e47edbc951da99c52714fb8c5e"}, ] [package.dependencies] @@ -2051,28 +2104,28 @@ web3 = ">=6.0.0,<7" [[package]] name = "open-aea-ledger-ethereum-flashbots" -version = "1.53.0" +version = "1.57.0" description = "Python package extending the default open-aea ethereum ledger plugin to add support for flashbots." optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "open_aea_ledger_ethereum_flashbots-1.53.0-py3-none-any.whl", hash = "sha256:04e1d04b68159f092dbe8c94d419221ad45bac17497c8feed9cbe92270a675b3"}, - {file = "open_aea_ledger_ethereum_flashbots-1.53.0.tar.gz", hash = "sha256:683e0c73c04413a0098f4903e3afa8c1570f8c51591ad6cef66fd38cfad463d8"}, + {file = "open_aea_ledger_ethereum_flashbots-1.57.0-py3-none-any.whl", hash = "sha256:cab2988933fb0196e04b4efe665fb8cb07cd10866a2a37969fac1bad51094cff"}, + {file = "open_aea_ledger_ethereum_flashbots-1.57.0.tar.gz", hash = "sha256:1ce8d8028383a62c0a759936c20af6cc58e594b1bb9dd8a93add2905dafd6511"}, ] [package.dependencies] open-aea-flashbots = "1.4.0" -open-aea-ledger-ethereum = ">=1.53.0,<1.54.0" +open-aea-ledger-ethereum = ">=1.57.0,<1.58.0" [[package]] name = "open-autonomy" -version = "0.14.14.post2" +version = "0.16.1" description = "A framework for the creation of autonomous agent services." optional = false python-versions = ">=3.8" files = [ - {file = "open_autonomy-0.14.14.post2-py3-none-any.whl", hash = "sha256:76efc0ce814c748eb02176477eef5b5ca4c6a84d77230e01a40c3df5ad2254b8"}, - {file = "open_autonomy-0.14.14.post2.tar.gz", hash = "sha256:0e1e7f3207fde38b8778a260c43153737a3b9fefe6d7abf373710a1aae9e267b"}, + {file = "open_autonomy-0.16.1-py3-none-any.whl", hash = "sha256:fec8611e0730d24debf53ed1f6a238a178eb8afc6ada422fbbb027b628e5ef72"}, + {file = "open_autonomy-0.16.1.tar.gz", hash = "sha256:bc670251a5d5859a807f9a7f5a1437c073a0a4b4060378f713a63d6fcb6930e7"}, ] [package.dependencies] @@ -2084,8 +2137,8 @@ Flask = ">=2.0.2,<3.0.0" gql = "3.5.0" hexbytes = "*" jsonschema = ">=4.3.0,<4.4.0" -open-aea = {version = "1.53.0", extras = ["all"]} -open-aea-cli-ipfs = "1.53.0" +open-aea = {version = "1.57.0", extras = ["all"]} +open-aea-cli-ipfs = "1.57.0" protobuf = ">=4.21.6,<4.25.0" pytest = "7.2.1" python-dotenv = ">=0.14.5,<0.22.0" @@ -2098,8 +2151,19 @@ watchdog = ">=2.1.6" werkzeug = "2.0.3" [package.extras] -all = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "open-aea-cli-ipfs (==1.53.0)", "pytest (>=7.0.0,<7.3.0)", "python-dotenv (>=0.14.5,<0.22.0)", "texttable (==1.6.7)"] -cli = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "open-aea-cli-ipfs (==1.53.0)", "pytest (>=7.0.0,<7.3.0)", "python-dotenv (>=0.14.5,<0.22.0)", "texttable (==1.6.7)"] +all = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "open-aea-cli-ipfs (==1.57.0)", "pytest (>=7.0.0,<7.3.0)", "python-dotenv (>=0.14.5,<0.22.0)", "texttable (==1.6.7)"] +cli = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "open-aea-cli-ipfs (==1.57.0)", "pytest (>=7.0.0,<7.3.0)", "python-dotenv (>=0.14.5,<0.22.0)", "texttable (==1.6.7)"] + +[[package]] +name = "orderly-set" +version = "5.2.2" +description = "Orderly set" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orderly_set-5.2.2-py3-none-any.whl", hash = "sha256:f7a37c95a38c01cdfe41c3ffb62925a318a2286ea0a41790c057fc802aec54da"}, + {file = "orderly_set-5.2.2.tar.gz", hash = "sha256:52a18b86aaf3f5d5a498bbdb27bf3253a4e5c57ab38e5b7a56fa00115cd28448"}, +] [[package]] name = "packaging" @@ -2114,13 +2178,13 @@ files = [ [[package]] name = "paramiko" -version = "3.4.1" +version = "3.5.0" description = "SSH2 protocol library" optional = false python-versions = ">=3.6" files = [ - {file = "paramiko-3.4.1-py3-none-any.whl", hash = "sha256:8e49fd2f82f84acf7ffd57c64311aa2b30e575370dc23bdb375b10262f7eac32"}, - {file = "paramiko-3.4.1.tar.gz", hash = "sha256:8b15302870af7f6652f2e038975c1d2973f06046cb5d7d65355668b3ecbece0c"}, + {file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"}, + {file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"}, ] [package.dependencies] @@ -2149,30 +2213,30 @@ regex = ">=2022.3.15" [[package]] name = "pefile" -version = "2024.8.26" +version = "2023.2.7" description = "Python PE parsing module" optional = false python-versions = ">=3.6.0" files = [ - {file = "pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f"}, - {file = "pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632"}, + {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, + {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, ] [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "pluggy" @@ -2189,6 +2253,113 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "propcache" +version = "0.2.0" +description = "Accelerated property cache" +optional = false +python-versions = ">=3.8" +files = [ + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, + {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, + {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, + {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, + {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, + {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, + {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, + {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, + {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, + {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, + {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, + {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, + {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, + {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, + {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, +] + [[package]] name = "protobuf" version = "4.24.4" @@ -2295,160 +2466,172 @@ files = [ [[package]] name = "pycryptodome" -version = "3.20.0" +version = "3.21.0" description = "Cryptographic library for Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818"}, - {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"}, - {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4"}, - {file = "pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72"}, - {file = "pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9"}, - {file = "pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a"}, - {file = "pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e"}, - {file = "pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7"}, +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pycryptodome-3.21.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:dad9bf36eda068e89059d1f07408e397856be9511d7113ea4b586642a429a4fd"}, + {file = "pycryptodome-3.21.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:a1752eca64c60852f38bb29e2c86fca30d7672c024128ef5d70cc15868fa10f4"}, + {file = "pycryptodome-3.21.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ba4cc304eac4d4d458f508d4955a88ba25026890e8abff9b60404f76a62c55e"}, + {file = "pycryptodome-3.21.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cb087b8612c8a1a14cf37dd754685be9a8d9869bed2ffaaceb04850a8aeef7e"}, + {file = "pycryptodome-3.21.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:26412b21df30b2861424a6c6d5b1d8ca8107612a4cfa4d0183e71c5d200fb34a"}, + {file = "pycryptodome-3.21.0-cp27-cp27m-win32.whl", hash = "sha256:cc2269ab4bce40b027b49663d61d816903a4bd90ad88cb99ed561aadb3888dd3"}, + {file = "pycryptodome-3.21.0-cp27-cp27m-win_amd64.whl", hash = "sha256:0fa0a05a6a697ccbf2a12cec3d6d2650b50881899b845fac6e87416f8cb7e87d"}, + {file = "pycryptodome-3.21.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6cce52e196a5f1d6797ff7946cdff2038d3b5f0aba4a43cb6bf46b575fd1b5bb"}, + {file = "pycryptodome-3.21.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:a915597ffccabe902e7090e199a7bf7a381c5506a747d5e9d27ba55197a2c568"}, + {file = "pycryptodome-3.21.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4e74c522d630766b03a836c15bff77cb657c5fdf098abf8b1ada2aebc7d0819"}, + {file = "pycryptodome-3.21.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:a3804675283f4764a02db05f5191eb8fec2bb6ca34d466167fc78a5f05bbe6b3"}, + {file = "pycryptodome-3.21.0-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:2480ec2c72438430da9f601ebc12c518c093c13111a5c1644c82cdfc2e50b1e4"}, + {file = "pycryptodome-3.21.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:de18954104667f565e2fbb4783b56667f30fb49c4d79b346f52a29cb198d5b6b"}, + {file = "pycryptodome-3.21.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de4b7263a33947ff440412339cb72b28a5a4c769b5c1ca19e33dd6cd1dcec6e"}, + {file = "pycryptodome-3.21.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0714206d467fc911042d01ea3a1847c847bc10884cf674c82e12915cfe1649f8"}, + {file = "pycryptodome-3.21.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d85c1b613121ed3dbaa5a97369b3b757909531a959d229406a75b912dd51dd1"}, + {file = "pycryptodome-3.21.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8898a66425a57bcf15e25fc19c12490b87bd939800f39a03ea2de2aea5e3611a"}, + {file = "pycryptodome-3.21.0-cp36-abi3-musllinux_1_2_i686.whl", hash = "sha256:932c905b71a56474bff8a9c014030bc3c882cee696b448af920399f730a650c2"}, + {file = "pycryptodome-3.21.0-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:18caa8cfbc676eaaf28613637a89980ad2fd96e00c564135bf90bc3f0b34dd93"}, + {file = "pycryptodome-3.21.0-cp36-abi3-win32.whl", hash = "sha256:280b67d20e33bb63171d55b1067f61fbd932e0b1ad976b3a184303a3dad22764"}, + {file = "pycryptodome-3.21.0-cp36-abi3-win_amd64.whl", hash = "sha256:b7aa25fc0baa5b1d95b7633af4f5f1838467f1815442b22487426f94e0d66c53"}, + {file = "pycryptodome-3.21.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:2cb635b67011bc147c257e61ce864879ffe6d03342dc74b6045059dfbdedafca"}, + {file = "pycryptodome-3.21.0-pp27-pypy_73-win32.whl", hash = "sha256:4c26a2f0dc15f81ea3afa3b0c87b87e501f235d332b7f27e2225ecb80c0b1cdd"}, + {file = "pycryptodome-3.21.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d5ebe0763c982f069d3877832254f64974139f4f9655058452603ff559c482e8"}, + {file = "pycryptodome-3.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee86cbde706be13f2dec5a42b52b1c1d1cbb90c8e405c68d0755134735c8dc6"}, + {file = "pycryptodome-3.21.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fd54003ec3ce4e0f16c484a10bc5d8b9bd77fa662a12b85779a2d2d85d67ee0"}, + {file = "pycryptodome-3.21.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5dfafca172933506773482b0e18f0cd766fd3920bd03ec85a283df90d8a17bc6"}, + {file = "pycryptodome-3.21.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:590ef0898a4b0a15485b05210b4a1c9de8806d3ad3d47f74ab1dc07c67a6827f"}, + {file = "pycryptodome-3.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f35e442630bc4bc2e1878482d6f59ea22e280d7121d7adeaedba58c23ab6386b"}, + {file = "pycryptodome-3.21.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff99f952db3db2fbe98a0b355175f93ec334ba3d01bbde25ad3a5a33abc02b58"}, + {file = "pycryptodome-3.21.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8acd7d34af70ee63f9a849f957558e49a98f8f1634f86a59d2be62bb8e93f71c"}, + {file = "pycryptodome-3.21.0.tar.gz", hash = "sha256:f7787e0d469bdae763b876174cf2e6c0f7be79808af26b1da96f1a64bcf47297"}, ] [[package]] name = "pydantic" -version = "2.8.2" +version = "2.10.0" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, + {file = "pydantic-2.10.0-py3-none-any.whl", hash = "sha256:5e7807ba9201bdf61b1b58aa6eb690916c40a47acfb114b1b4fef3e7fd5b30fc"}, + {file = "pydantic-2.10.0.tar.gz", hash = "sha256:0aca0f045ff6e2f097f1fe89521115335f15049eeb8a7bef3dafe4b19a74e289"}, ] [package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" -typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} +annotated-types = ">=0.6.0" +pydantic-core = "2.27.0" +typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.20.1" +version = "2.27.0" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, + {file = "pydantic_core-2.27.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:cd2ac6b919f7fed71b17fe0b4603c092a4c9b5bae414817c9c81d3c22d1e1bcc"}, + {file = "pydantic_core-2.27.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e015833384ca3e1a0565a79f5d953b0629d9138021c27ad37c92a9fa1af7623c"}, + {file = "pydantic_core-2.27.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db72e40628967f6dc572020d04b5f800d71264e0531c6da35097e73bdf38b003"}, + {file = "pydantic_core-2.27.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df45c4073bed486ea2f18757057953afed8dd77add7276ff01bccb79982cf46c"}, + {file = "pydantic_core-2.27.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:836a4bfe0cc6d36dc9a9cc1a7b391265bf6ce9d1eb1eac62ac5139f5d8d9a6fa"}, + {file = "pydantic_core-2.27.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4bf1340ae507f6da6360b24179c2083857c8ca7644aab65807023cf35404ea8d"}, + {file = "pydantic_core-2.27.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ab325fc86fbc077284c8d7f996d904d30e97904a87d6fb303dce6b3de7ebba9"}, + {file = "pydantic_core-2.27.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1da0c98a85a6c6ed702d5556db3b09c91f9b0b78de37b7593e2de8d03238807a"}, + {file = "pydantic_core-2.27.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7b0202ebf2268954090209a84f9897345719e46a57c5f2c9b7b250ca0a9d3e63"}, + {file = "pydantic_core-2.27.0-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:35380671c3c921fe8adf31ad349dc6f7588b7e928dbe44e1093789734f607399"}, + {file = "pydantic_core-2.27.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b4c19525c3538fbc0bbda6229f9682fb8199ce9ac37395880e6952798e00373"}, + {file = "pydantic_core-2.27.0-cp310-none-win32.whl", hash = "sha256:333c840a1303d1474f491e7be0b718226c730a39ead0f7dab2c7e6a2f3855555"}, + {file = "pydantic_core-2.27.0-cp310-none-win_amd64.whl", hash = "sha256:99b2863c1365f43f74199c980a3d40f18a218fbe683dd64e470199db426c4d6a"}, + {file = "pydantic_core-2.27.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4523c4009c3f39d948e01962223c9f5538602e7087a628479b723c939fab262d"}, + {file = "pydantic_core-2.27.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84af1cf7bfdcbc6fcf5a5f70cc9896205e0350306e4dd73d54b6a18894f79386"}, + {file = "pydantic_core-2.27.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e65466b31be1070b4a5b7dbfbd14b247884cb8e8b79c64fb0f36b472912dbaea"}, + {file = "pydantic_core-2.27.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a5c022bb0d453192426221605efc865373dde43b17822a264671c53b068ac20c"}, + {file = "pydantic_core-2.27.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bb69bf3b6500f195c3deb69c1205ba8fc3cb21d1915f1f158a10d6b1ef29b6a"}, + {file = "pydantic_core-2.27.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0aa4d1b2eba9a325897308b3124014a142cdccb9f3e016f31d3ebee6b5ea5e75"}, + {file = "pydantic_core-2.27.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e96ca781e0c01e32115912ebdf7b3fb0780ce748b80d7d28a0802fa9fbaf44e"}, + {file = "pydantic_core-2.27.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b872c86d8d71827235c7077461c502feb2db3f87d9d6d5a9daa64287d75e4fa0"}, + {file = "pydantic_core-2.27.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:82e1ad4ca170e8af4c928b67cff731b6296e6a0a0981b97b2eb7c275cc4e15bd"}, + {file = "pydantic_core-2.27.0-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:eb40f828bc2f73f777d1eb8fee2e86cd9692a4518b63b6b5aa8af915dfd3207b"}, + {file = "pydantic_core-2.27.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9a8fbf506fde1529a1e3698198fe64bfbe2e0c09557bc6a7dcf872e7c01fec40"}, + {file = "pydantic_core-2.27.0-cp311-none-win32.whl", hash = "sha256:24f984fc7762ed5f806d9e8c4c77ea69fdb2afd987b4fd319ef06c87595a8c55"}, + {file = "pydantic_core-2.27.0-cp311-none-win_amd64.whl", hash = "sha256:68950bc08f9735306322bfc16a18391fcaac99ded2509e1cc41d03ccb6013cfe"}, + {file = "pydantic_core-2.27.0-cp311-none-win_arm64.whl", hash = "sha256:3eb8849445c26b41c5a474061032c53e14fe92a11a5db969f722a2716cd12206"}, + {file = "pydantic_core-2.27.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8117839a9bdbba86e7f9df57018fe3b96cec934c3940b591b0fd3fbfb485864a"}, + {file = "pydantic_core-2.27.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a291d0b4243a259c8ea7e2b84eb9ccb76370e569298875a7c5e3e71baf49057a"}, + {file = "pydantic_core-2.27.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84e35afd9e10b2698e6f2f32256678cb23ca6c1568d02628033a837638b3ed12"}, + {file = "pydantic_core-2.27.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:58ab0d979c969983cdb97374698d847a4acffb217d543e172838864636ef10d9"}, + {file = "pydantic_core-2.27.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d06b667e53320332be2bf6f9461f4a9b78092a079b8ce8634c9afaa7e10cd9f"}, + {file = "pydantic_core-2.27.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78f841523729e43e3928a364ec46e2e3f80e6625a4f62aca5c345f3f626c6e8a"}, + {file = "pydantic_core-2.27.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:400bf470e4327e920883b51e255617dfe4496d4e80c3fea0b5a5d0bf2c404dd4"}, + {file = "pydantic_core-2.27.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:951e71da6c89d354572098bada5ba5b5dc3a9390c933af8a614e37755d3d1840"}, + {file = "pydantic_core-2.27.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2a51ce96224eadd1845150b204389623c8e129fde5a67a84b972bd83a85c6c40"}, + {file = "pydantic_core-2.27.0-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:483c2213a609e7db2c592bbc015da58b6c75af7360ca3c981f178110d9787bcf"}, + {file = "pydantic_core-2.27.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:359e7951f04ad35111b5ddce184db3391442345d0ab073aa63a95eb8af25a5ef"}, + {file = "pydantic_core-2.27.0-cp312-none-win32.whl", hash = "sha256:ee7d9d5537daf6d5c74a83b38a638cc001b648096c1cae8ef695b0c919d9d379"}, + {file = "pydantic_core-2.27.0-cp312-none-win_amd64.whl", hash = "sha256:2be0ad541bb9f059954ccf8877a49ed73877f862529575ff3d54bf4223e4dd61"}, + {file = "pydantic_core-2.27.0-cp312-none-win_arm64.whl", hash = "sha256:6e19401742ed7b69e51d8e4df3c03ad5ec65a83b36244479fd70edde2828a5d9"}, + {file = "pydantic_core-2.27.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5f2b19b8d6fca432cb3acf48cf5243a7bf512988029b6e6fd27e9e8c0a204d85"}, + {file = "pydantic_core-2.27.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c86679f443e7085ea55a7376462553996c688395d18ef3f0d3dbad7838f857a2"}, + {file = "pydantic_core-2.27.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:510b11e9c3b1a852876d1ccd8d5903684336d635214148637ceb27366c75a467"}, + {file = "pydantic_core-2.27.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb704155e73b833801c247f39d562229c0303f54770ca14fb1c053acb376cf10"}, + {file = "pydantic_core-2.27.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ce048deb1e033e7a865ca384770bccc11d44179cf09e5193a535c4c2f497bdc"}, + {file = "pydantic_core-2.27.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58560828ee0951bb125c6f2862fbc37f039996d19ceb6d8ff1905abf7da0bf3d"}, + {file = "pydantic_core-2.27.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abb4785894936d7682635726613c44578c420a096729f1978cd061a7e72d5275"}, + {file = "pydantic_core-2.27.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2883b260f7a93235488699d39cbbd94fa7b175d3a8063fbfddd3e81ad9988cb2"}, + {file = "pydantic_core-2.27.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c6fcb3fa3855d583aa57b94cf146f7781d5d5bc06cb95cb3afece33d31aac39b"}, + {file = "pydantic_core-2.27.0-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:e851a051f7260e6d688267eb039c81f05f23a19431bd7dfa4bf5e3cb34c108cd"}, + {file = "pydantic_core-2.27.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:edb1bfd45227dec8d50bc7c7d86463cd8728bcc574f9b07de7369880de4626a3"}, + {file = "pydantic_core-2.27.0-cp313-none-win32.whl", hash = "sha256:678f66462058dd978702db17eb6a3633d634f7aa0deaea61e0a674152766d3fc"}, + {file = "pydantic_core-2.27.0-cp313-none-win_amd64.whl", hash = "sha256:d28ca7066d6cdd347a50d8b725dc10d9a1d6a1cce09836cf071ea6a2d4908be0"}, + {file = "pydantic_core-2.27.0-cp313-none-win_arm64.whl", hash = "sha256:6f4a53af9e81d757756508b57cae1cf28293f0f31b9fa2bfcb416cc7fb230f9d"}, + {file = "pydantic_core-2.27.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:e9f9feee7f334b72ceae46313333d002b56f325b5f04271b4ae2aadd9e993ae4"}, + {file = "pydantic_core-2.27.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:225bfff5d425c34e1fd562cef52d673579d59b967d9de06178850c4802af9039"}, + {file = "pydantic_core-2.27.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921ad596ff1a82f9c692b0758c944355abc9f0de97a4c13ca60ffc6d8dc15d4"}, + {file = "pydantic_core-2.27.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6354e18a9be37bfa124d6b288a87fb30c673745806c92956f1a25e3ae6e76b96"}, + {file = "pydantic_core-2.27.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ee4c2a75af9fe21269a4a0898c5425afb01af1f5d276063f57e2ae1bc64e191"}, + {file = "pydantic_core-2.27.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c91e3c04f5191fd3fb68764bddeaf02025492d5d9f23343b283870f6ace69708"}, + {file = "pydantic_core-2.27.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a6ebfac28fd51890a61df36ef202adbd77d00ee5aca4a3dadb3d9ed49cfb929"}, + {file = "pydantic_core-2.27.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36aa167f69d8807ba7e341d67ea93e50fcaaf6bc433bb04939430fa3dab06f31"}, + {file = "pydantic_core-2.27.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e8d89c276234579cd3d095d5fa2a44eb10db9a218664a17b56363cddf226ff3"}, + {file = "pydantic_core-2.27.0-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:5cc822ab90a70ea3a91e6aed3afac570b276b1278c6909b1d384f745bd09c714"}, + {file = "pydantic_core-2.27.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e15315691fe2253eb447503153acef4d7223dfe7e7702f9ed66539fcd0c43801"}, + {file = "pydantic_core-2.27.0-cp38-none-win32.whl", hash = "sha256:dfa5f5c0a4c8fced1422dc2ca7eefd872d5d13eb33cf324361dbf1dbfba0a9fe"}, + {file = "pydantic_core-2.27.0-cp38-none-win_amd64.whl", hash = "sha256:513cb14c0cc31a4dfd849a4674b20c46d87b364f997bbcb02282306f5e187abf"}, + {file = "pydantic_core-2.27.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:4148dc9184ab79e356dc00a4199dc0ee8647973332cb385fc29a7cced49b9f9c"}, + {file = "pydantic_core-2.27.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5fc72fbfebbf42c0856a824b8b0dc2b5cd2e4a896050281a21cfa6fed8879cb1"}, + {file = "pydantic_core-2.27.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:185ef205256cd8b38431205698531026979db89a79587725c1e55c59101d64e9"}, + {file = "pydantic_core-2.27.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:395e3e1148fa7809016231f8065f30bb0dc285a97b4dc4360cd86e17bab58af7"}, + {file = "pydantic_core-2.27.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33d14369739c5d07e2e7102cdb0081a1fa46ed03215e07f097b34e020b83b1ae"}, + {file = "pydantic_core-2.27.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7820bb0d65e3ce1e3e70b6708c2f66143f55912fa02f4b618d0f08b61575f12"}, + {file = "pydantic_core-2.27.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43b61989068de9ce62296cde02beffabcadb65672207fc51e7af76dca75e6636"}, + {file = "pydantic_core-2.27.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15e350efb67b855cd014c218716feea4986a149ed1f42a539edd271ee074a196"}, + {file = "pydantic_core-2.27.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:433689845288f9a1ee5714444e65957be26d30915f7745091ede4a83cfb2d7bb"}, + {file = "pydantic_core-2.27.0-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:3fd8bc2690e7c39eecdf9071b6a889ce7b22b72073863940edc2a0a23750ca90"}, + {file = "pydantic_core-2.27.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:884f1806609c2c66564082540cffc96868c5571c7c3cf3a783f63f2fb49bd3cd"}, + {file = "pydantic_core-2.27.0-cp39-none-win32.whl", hash = "sha256:bf37b72834e7239cf84d4a0b2c050e7f9e48bced97bad9bdf98d26b8eb72e846"}, + {file = "pydantic_core-2.27.0-cp39-none-win_amd64.whl", hash = "sha256:31a2cae5f059329f9cfe3d8d266d3da1543b60b60130d186d9b6a3c20a346361"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4fb49cfdb53af5041aba909be00cccfb2c0d0a2e09281bf542371c5fd36ad04c"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:49633583eb7dc5cba61aaf7cdb2e9e662323ad394e543ee77af265736bcd3eaa"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:153017e3d6cd3ce979de06d84343ca424bb6092727375eba1968c8b4693c6ecb"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff63a92f6e249514ef35bc795de10745be0226eaea06eb48b4bbeaa0c8850a4a"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5982048129f40b082c2654de10c0f37c67a14f5ff9d37cf35be028ae982f26df"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:91bc66f878557313c2a6bcf396e7befcffe5ab4354cfe4427318968af31143c3"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:68ef5377eb582fa4343c9d0b57a5b094046d447b4c73dd9fbd9ffb216f829e7d"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:c5726eec789ee38f2c53b10b1821457b82274f81f4f746bb1e666d8741fcfadb"}, + {file = "pydantic_core-2.27.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0c431e4be5c1a0c6654e0c31c661cd89e0ca956ef65305c3c3fd96f4e72ca39"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:8e21d927469d04b39386255bf00d0feedead16f6253dcc85e9e10ddebc334084"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4b51f964fcbb02949fc546022e56cdb16cda457af485e9a3e8b78ac2ecf5d77e"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a7fd4de38f7ff99a37e18fa0098c3140286451bc823d1746ba80cec5b433a1"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fda87808429c520a002a85d6e7cdadbf58231d60e96260976c5b8f9a12a8e13"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8a150392102c402c538190730fda06f3bce654fc498865579a9f2c1d2b425833"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c9ed88b398ba7e3bad7bd64d66cc01dcde9cfcb7ec629a6fd78a82fa0b559d78"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:9fe94d9d2a2b4edd7a4b22adcd45814b1b59b03feb00e56deb2e89747aec7bfe"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d8b5ee4ae9170e2775d495b81f414cc20268041c42571530513496ba61e94ba3"}, + {file = "pydantic_core-2.27.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d29e235ce13c91902ef3efc3d883a677655b3908b1cbc73dee816e5e1f8f7739"}, + {file = "pydantic_core-2.27.0.tar.gz", hash = "sha256:f57783fbaf648205ac50ae7d646f27582fc706be3977e87c3c124e7a92407b10"}, ] [package.dependencies] @@ -2456,23 +2639,23 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pyinstaller" -version = "6.10.0" +version = "6.11.1" description = "PyInstaller bundles a Python application and all its dependencies into a single package." optional = false python-versions = "<3.14,>=3.8" files = [ - {file = "pyinstaller-6.10.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:d60fb22859e11483af735aec115fdde09467cdbb29edd9844839f2c920b748c0"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:46d75359668993ddd98630a3669dc5249f3c446e35239b43bc7f4155bc574748"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_i686.whl", hash = "sha256:3398a98fa17d47ccb31f8779ecbdacec025f7adb2f22757a54b706ac8b4fe906"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e9989f354ae4ed8a3bec7bdb37ae0d170751d6520e500f049c7cd0632d31d5c3"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:b7c90c91921b3749083115b28f30f40abf2bb481ceff196d2b2ce0eaa2b3d429"}, - {file = "pyinstaller-6.10.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6cf876d7d93b8b4f28d1ad57fa24645cf43119c79e985dd5e5f7a801245e6f53"}, - {file = "pyinstaller-6.10.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:db05e3f2f10f9f78c56f1fb163d9cb453433429fe4281218ebaf1ebfd39ba942"}, - {file = "pyinstaller-6.10.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:28eca3817f176fdc19747e1afcf434f13bb9f17a644f611be2c5a61b1f498ed7"}, - {file = "pyinstaller-6.10.0-py3-none-win32.whl", hash = "sha256:703e041718987e46ba0568a2c71ecf2459fddef57cf9edf3efeed4a53e3dae3f"}, - {file = "pyinstaller-6.10.0-py3-none-win_amd64.whl", hash = "sha256:95b55966e563e8b8f31a43882aea10169e9a11fdf38e626d86a2907b640c0701"}, - {file = "pyinstaller-6.10.0-py3-none-win_arm64.whl", hash = "sha256:308e0a8670c9c9ac0cebbf1bbb492e71b6675606f2ec78bc4adfc830d209e087"}, - {file = "pyinstaller-6.10.0.tar.gz", hash = "sha256:143840f8056ff7b910bf8f16f6cd92cc10a6c2680bb76d0a25d558d543d21270"}, + {file = "pyinstaller-6.11.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:44e36172de326af6d4e7663b12f71dbd34e2e3e02233e181e457394423daaf03"}, + {file = "pyinstaller-6.11.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:6d12c45a29add78039066a53fb05967afaa09a672426072b13816fe7676abfc4"}, + {file = "pyinstaller-6.11.1-py3-none-manylinux2014_i686.whl", hash = "sha256:ddc0fddd75f07f7e423da1f0822e389a42af011f9589e0269b87e0d89aa48c1f"}, + {file = "pyinstaller-6.11.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:0d6475559c4939f0735122989611d7f739ed3bf02f666ce31022928f7a7e4fda"}, + {file = "pyinstaller-6.11.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:e21c7806e34f40181e7606926a14579f848bfb1dc52cbca7eea66eccccbfe977"}, + {file = "pyinstaller-6.11.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:32c742a24fe65d0702958fadf4040f76de85859c26bec0008766e5dbabc5b68f"}, + {file = "pyinstaller-6.11.1-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:208c0ef6dab0837a0a273ea32d1a3619a208e3d1fe3fec3785eea71a77fd00ce"}, + {file = "pyinstaller-6.11.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:ad84abf465bcda363c1d54eafa76745d77b6a8a713778348377dc98d12a452f7"}, + {file = "pyinstaller-6.11.1-py3-none-win32.whl", hash = "sha256:2e8365276c5131c9bef98e358fbc305e4022db8bedc9df479629d6414021956a"}, + {file = "pyinstaller-6.11.1-py3-none-win_amd64.whl", hash = "sha256:7ac83c0dc0e04357dab98c487e74ad2adb30e7eb186b58157a8faf46f1fa796f"}, + {file = "pyinstaller-6.11.1-py3-none-win_arm64.whl", hash = "sha256:35e6b8077d240600bb309ed68bb0b1453fd2b7ab740b66d000db7abae6244423"}, + {file = "pyinstaller-6.11.1.tar.gz", hash = "sha256:491dfb4d9d5d1d9650d9507daec1ff6829527a254d8e396badd60a0affcb72ef"}, ] [package.dependencies] @@ -2480,8 +2663,8 @@ altgraph = "*" importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} packaging = ">=22.0" -pefile = {version = ">=2022.5.30", markers = "sys_platform == \"win32\""} -pyinstaller-hooks-contrib = ">=2024.8" +pefile = {version = ">=2022.5.30,<2024.8.26 || >2024.8.26", markers = "sys_platform == \"win32\""} +pyinstaller-hooks-contrib = ">=2024.9" pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} setuptools = ">=42.0.0" @@ -2491,13 +2674,13 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2024.8" +version = "2024.10" description = "Community maintained hooks for PyInstaller" optional = false python-versions = ">=3.8" files = [ - {file = "pyinstaller_hooks_contrib-2024.8-py3-none-any.whl", hash = "sha256:0057fe9a5c398d3f580e73e58793a1d4a8315ca91c3df01efea1c14ed557825a"}, - {file = "pyinstaller_hooks_contrib-2024.8.tar.gz", hash = "sha256:29b68d878ab739e967055b56a93eb9b58e529d5b054fbab7a2f2bacf80cef3e2"}, + {file = "pyinstaller_hooks_contrib-2024.10-py3-none-any.whl", hash = "sha256:ad47db0e153683b4151e10d231cb91f2d93c85079e78d76d9e0f57ac6c8a5e10"}, + {file = "pyinstaller_hooks_contrib-2024.10.tar.gz", hash = "sha256:8a46655e5c5b0186b5e527399118a9b342f10513eb1425c483fa4f6d02e8800c"}, ] [package.dependencies] @@ -2650,25 +2833,29 @@ cli = ["click (>=5.0)"] [[package]] name = "pywin32" -version = "306" +version = "308" description = "Python for Window Extensions" optional = false python-versions = "*" files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, + {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, + {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, + {file = "pywin32-308-cp310-cp310-win_arm64.whl", hash = "sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c"}, + {file = "pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a"}, + {file = "pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b"}, + {file = "pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6"}, + {file = "pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897"}, + {file = "pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47"}, + {file = "pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091"}, + {file = "pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed"}, + {file = "pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4"}, + {file = "pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd"}, + {file = "pywin32-308-cp37-cp37m-win32.whl", hash = "sha256:1f696ab352a2ddd63bd07430080dd598e6369152ea13a25ebcdd2f503a38f1ff"}, + {file = "pywin32-308-cp37-cp37m-win_amd64.whl", hash = "sha256:13dcb914ed4347019fbec6697a01a0aec61019c1046c2b905410d197856326a6"}, + {file = "pywin32-308-cp38-cp38-win32.whl", hash = "sha256:5794e764ebcabf4ff08c555b31bd348c9025929371763b2183172ff4708152f0"}, + {file = "pywin32-308-cp38-cp38-win_amd64.whl", hash = "sha256:3b92622e29d651c6b783e368ba7d6722b1634b8e70bd376fd7610fe1992e19de"}, + {file = "pywin32-308-cp39-cp39-win32.whl", hash = "sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341"}, + {file = "pywin32-308-cp39-cp39-win_amd64.whl", hash = "sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920"}, ] [[package]] @@ -2744,90 +2931,105 @@ files = [ [[package]] name = "regex" -version = "2024.7.24" +version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" files = [ - {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce"}, - {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024"}, - {file = "regex-2024.7.24-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa"}, - {file = "regex-2024.7.24-cp310-cp310-win32.whl", hash = "sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66"}, - {file = "regex-2024.7.24-cp310-cp310-win_amd64.whl", hash = "sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e"}, - {file = "regex-2024.7.24-cp311-cp311-win32.whl", hash = "sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c"}, - {file = "regex-2024.7.24-cp311-cp311-win_amd64.whl", hash = "sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38"}, - {file = "regex-2024.7.24-cp312-cp312-win32.whl", hash = "sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc"}, - {file = "regex-2024.7.24-cp312-cp312-win_amd64.whl", hash = "sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8"}, - {file = "regex-2024.7.24-cp38-cp38-win32.whl", hash = "sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96"}, - {file = "regex-2024.7.24-cp38-cp38-win_amd64.whl", hash = "sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9"}, - {file = "regex-2024.7.24-cp39-cp39-win32.whl", hash = "sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1"}, - {file = "regex-2024.7.24-cp39-cp39-win_amd64.whl", hash = "sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9"}, - {file = "regex-2024.7.24.tar.gz", hash = "sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, + {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, + {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, + {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, + {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, + {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, + {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, + {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, + {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, + {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, + {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, + {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, + {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, + {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, ] [[package]] @@ -2899,23 +3101,23 @@ files = [ [[package]] name = "setuptools" -version = "74.1.1" +version = "75.6.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "setuptools-74.1.1-py3-none-any.whl", hash = "sha256:fc91b5f89e392ef5b77fe143b17e32f65d3024744fba66dc3afe07201684d766"}, - {file = "setuptools-74.1.1.tar.gz", hash = "sha256:2353af060c06388be1cecbf5953dcdb1f38362f87a2356c480b6b4d5fcfc8847"}, + {file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"}, + {file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"] +core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"] [[package]] name = "six" @@ -2970,13 +3172,13 @@ files = [ [[package]] name = "tomli" -version = "2.0.1" +version = "2.1.0" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"}, + {file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"}, ] [[package]] @@ -3013,13 +3215,13 @@ vulture = ["vulture (==2.7)"] [[package]] name = "toolz" -version = "0.12.1" +version = "1.0.0" description = "List processing tools and functional utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "toolz-0.12.1-py3-none-any.whl", hash = "sha256:d22731364c07d72eea0a0ad45bafb2c2937ab6fd38a3507bf55eae8744aa7d85"}, - {file = "toolz-0.12.1.tar.gz", hash = "sha256:ecca342664893f177a13dac0e6b41cbd8ac25a358e5f215316d43e2100224f4d"}, + {file = "toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236"}, + {file = "toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02"}, ] [[package]] @@ -3060,13 +3262,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.2" +version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.extras] @@ -3134,13 +3336,13 @@ files = [ [[package]] name = "virtualenv" -version = "20.26.3" +version = "20.27.1" description = "Virtual Python Environment builder" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, - {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, + {file = "virtualenv-20.27.1-py3-none-any.whl", hash = "sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4"}, + {file = "virtualenv-20.27.1.tar.gz", hash = "sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba"}, ] [package.dependencies] @@ -3154,41 +3356,41 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "watchdog" -version = "5.0.2" +version = "6.0.0" description = "Filesystem events monitoring" optional = false python-versions = ">=3.9" files = [ - {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d961f4123bb3c447d9fcdcb67e1530c366f10ab3a0c7d1c0c9943050936d4877"}, - {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72990192cb63872c47d5e5fefe230a401b87fd59d257ee577d61c9e5564c62e5"}, - {file = "watchdog-5.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bec703ad90b35a848e05e1b40bf0050da7ca28ead7ac4be724ae5ac2653a1a0"}, - {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dae7a1879918f6544201d33666909b040a46421054a50e0f773e0d870ed7438d"}, - {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4a440f725f3b99133de610bfec93d570b13826f89616377715b9cd60424db6e"}, - {file = "watchdog-5.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8b2918c19e0d48f5f20df458c84692e2a054f02d9df25e6c3c930063eca64c1"}, - {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aa9cd6e24126d4afb3752a3e70fce39f92d0e1a58a236ddf6ee823ff7dba28ee"}, - {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f627c5bf5759fdd90195b0c0431f99cff4867d212a67b384442c51136a098ed7"}, - {file = "watchdog-5.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d7594a6d32cda2b49df3fd9abf9b37c8d2f3eab5df45c24056b4a671ac661619"}, - {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba32efcccfe2c58f4d01115440d1672b4eb26cdd6fc5b5818f1fb41f7c3e1889"}, - {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:963f7c4c91e3f51c998eeff1b3fb24a52a8a34da4f956e470f4b068bb47b78ee"}, - {file = "watchdog-5.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8c47150aa12f775e22efff1eee9f0f6beee542a7aa1a985c271b1997d340184f"}, - {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:14dd4ed023d79d1f670aa659f449bcd2733c33a35c8ffd88689d9d243885198b"}, - {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b84bff0391ad4abe25c2740c7aec0e3de316fdf7764007f41e248422a7760a7f"}, - {file = "watchdog-5.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e8d5ff39f0a9968952cce548e8e08f849141a4fcc1290b1c17c032ba697b9d7"}, - {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fb223456db6e5f7bd9bbd5cd969f05aae82ae21acc00643b60d81c770abd402b"}, - {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9814adb768c23727a27792c77812cf4e2fd9853cd280eafa2bcfa62a99e8bd6e"}, - {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:901ee48c23f70193d1a7bc2d9ee297df66081dd5f46f0ca011be4f70dec80dab"}, - {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:638bcca3d5b1885c6ec47be67bf712b00a9ab3d4b22ec0881f4889ad870bc7e8"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:5597c051587f8757798216f2485e85eac583c3b343e9aa09127a3a6f82c65ee8"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:53ed1bf71fcb8475dd0ef4912ab139c294c87b903724b6f4a8bd98e026862e6d"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:29e4a2607bd407d9552c502d38b45a05ec26a8e40cc7e94db9bb48f861fa5abc"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:b6dc8f1d770a8280997e4beae7b9a75a33b268c59e033e72c8a10990097e5fde"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:d2ab34adc9bf1489452965cdb16a924e97d4452fcf88a50b21859068b50b5c3b"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:7d1aa7e4bb0f0c65a1a91ba37c10e19dabf7eaaa282c5787e51371f090748f4b"}, - {file = "watchdog-5.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:726eef8f8c634ac6584f86c9c53353a010d9f311f6c15a034f3800a7a891d941"}, - {file = "watchdog-5.0.2-py3-none-win32.whl", hash = "sha256:bda40c57115684d0216556671875e008279dea2dc00fcd3dde126ac8e0d7a2fb"}, - {file = "watchdog-5.0.2-py3-none-win_amd64.whl", hash = "sha256:d010be060c996db725fbce7e3ef14687cdcc76f4ca0e4339a68cc4532c382a73"}, - {file = "watchdog-5.0.2-py3-none-win_ia64.whl", hash = "sha256:3960136b2b619510569b90f0cd96408591d6c251a75c97690f4553ca88889769"}, - {file = "watchdog-5.0.2.tar.gz", hash = "sha256:dcebf7e475001d2cdeb020be630dc5b687e9acdd60d16fea6bb4508e7b94cf76"}, + {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, + {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, + {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, + {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, + {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, + {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, + {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, + {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, + {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, + {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, + {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, ] [package.extras] @@ -3243,97 +3445,80 @@ six = "*" [[package]] name = "websockets" -version = "13.0.1" +version = "14.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "websockets-13.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1841c9082a3ba4a05ea824cf6d99570a6a2d8849ef0db16e9c826acb28089e8f"}, - {file = "websockets-13.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c5870b4a11b77e4caa3937142b650fbbc0914a3e07a0cf3131f35c0587489c1c"}, - {file = "websockets-13.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f1d3d1f2eb79fe7b0fb02e599b2bf76a7619c79300fc55f0b5e2d382881d4f7f"}, - {file = "websockets-13.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15c7d62ee071fa94a2fc52c2b472fed4af258d43f9030479d9c4a2de885fd543"}, - {file = "websockets-13.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6724b554b70d6195ba19650fef5759ef11346f946c07dbbe390e039bcaa7cc3d"}, - {file = "websockets-13.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a952fa2ae57a42ba7951e6b2605e08a24801a4931b5644dfc68939e041bc7f"}, - {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:17118647c0ea14796364299e942c330d72acc4b248e07e639d34b75067b3cdd8"}, - {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64a11aae1de4c178fa653b07d90f2fb1a2ed31919a5ea2361a38760192e1858b"}, - {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0617fd0b1d14309c7eab6ba5deae8a7179959861846cbc5cb528a7531c249448"}, - {file = "websockets-13.0.1-cp310-cp310-win32.whl", hash = "sha256:11f9976ecbc530248cf162e359a92f37b7b282de88d1d194f2167b5e7ad80ce3"}, - {file = "websockets-13.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c3c493d0e5141ec055a7d6809a28ac2b88d5b878bb22df8c621ebe79a61123d0"}, - {file = "websockets-13.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:699ba9dd6a926f82a277063603fc8d586b89f4cb128efc353b749b641fcddda7"}, - {file = "websockets-13.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf2fae6d85e5dc384bf846f8243ddaa9197f3a1a70044f59399af001fd1f51d4"}, - {file = "websockets-13.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:52aed6ef21a0f1a2a5e310fb5c42d7555e9c5855476bbd7173c3aa3d8a0302f2"}, - {file = "websockets-13.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8eb2b9a318542153674c6e377eb8cb9ca0fc011c04475110d3477862f15d29f0"}, - {file = "websockets-13.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5df891c86fe68b2c38da55b7aea7095beca105933c697d719f3f45f4220a5e0e"}, - {file = "websockets-13.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac2d146ff30d9dd2fcf917e5d147db037a5c573f0446c564f16f1f94cf87462"}, - {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b8ac5b46fd798bbbf2ac6620e0437c36a202b08e1f827832c4bf050da081b501"}, - {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:46af561eba6f9b0848b2c9d2427086cabadf14e0abdd9fde9d72d447df268418"}, - {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b5a06d7f60bc2fc378a333978470dfc4e1415ee52f5f0fce4f7853eb10c1e9df"}, - {file = "websockets-13.0.1-cp311-cp311-win32.whl", hash = "sha256:556e70e4f69be1082e6ef26dcb70efcd08d1850f5d6c5f4f2bcb4e397e68f01f"}, - {file = "websockets-13.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:67494e95d6565bf395476e9d040037ff69c8b3fa356a886b21d8422ad86ae075"}, - {file = "websockets-13.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f9c9e258e3d5efe199ec23903f5da0eeaad58cf6fccb3547b74fd4750e5ac47a"}, - {file = "websockets-13.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6b41a1b3b561f1cba8321fb32987552a024a8f67f0d05f06fcf29f0090a1b956"}, - {file = "websockets-13.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f73e676a46b0fe9426612ce8caeca54c9073191a77c3e9d5c94697aef99296af"}, - {file = "websockets-13.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f613289f4a94142f914aafad6c6c87903de78eae1e140fa769a7385fb232fdf"}, - {file = "websockets-13.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f52504023b1480d458adf496dc1c9e9811df4ba4752f0bc1f89ae92f4f07d0c"}, - {file = "websockets-13.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:139add0f98206cb74109faf3611b7783ceafc928529c62b389917a037d4cfdf4"}, - {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:47236c13be337ef36546004ce8c5580f4b1150d9538b27bf8a5ad8edf23ccfab"}, - {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c44ca9ade59b2e376612df34e837013e2b273e6c92d7ed6636d0556b6f4db93d"}, - {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9bbc525f4be3e51b89b2a700f5746c2a6907d2e2ef4513a8daafc98198b92237"}, - {file = "websockets-13.0.1-cp312-cp312-win32.whl", hash = "sha256:3624fd8664f2577cf8de996db3250662e259bfbc870dd8ebdcf5d7c6ac0b5185"}, - {file = "websockets-13.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0513c727fb8adffa6d9bf4a4463b2bade0186cbd8c3604ae5540fae18a90cb99"}, - {file = "websockets-13.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1ee4cc030a4bdab482a37462dbf3ffb7e09334d01dd37d1063be1136a0d825fa"}, - {file = "websockets-13.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dbb0b697cc0655719522406c059eae233abaa3243821cfdfab1215d02ac10231"}, - {file = "websockets-13.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:acbebec8cb3d4df6e2488fbf34702cbc37fc39ac7abf9449392cefb3305562e9"}, - {file = "websockets-13.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63848cdb6fcc0bf09d4a155464c46c64ffdb5807ede4fb251da2c2692559ce75"}, - {file = "websockets-13.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:872afa52a9f4c414d6955c365b6588bc4401272c629ff8321a55f44e3f62b553"}, - {file = "websockets-13.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05e70fec7c54aad4d71eae8e8cab50525e899791fc389ec6f77b95312e4e9920"}, - {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e82db3756ccb66266504f5a3de05ac6b32f287faacff72462612120074103329"}, - {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4e85f46ce287f5c52438bb3703d86162263afccf034a5ef13dbe4318e98d86e7"}, - {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f3fea72e4e6edb983908f0db373ae0732b275628901d909c382aae3b592589f2"}, - {file = "websockets-13.0.1-cp313-cp313-win32.whl", hash = "sha256:254ecf35572fca01a9f789a1d0f543898e222f7b69ecd7d5381d8d8047627bdb"}, - {file = "websockets-13.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:ca48914cdd9f2ccd94deab5bcb5ac98025a5ddce98881e5cce762854a5de330b"}, - {file = "websockets-13.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b74593e9acf18ea5469c3edaa6b27fa7ecf97b30e9dabd5a94c4c940637ab96e"}, - {file = "websockets-13.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:132511bfd42e77d152c919147078460c88a795af16b50e42a0bd14f0ad71ddd2"}, - {file = "websockets-13.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:165bedf13556f985a2aa064309baa01462aa79bf6112fbd068ae38993a0e1f1b"}, - {file = "websockets-13.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e801ca2f448850685417d723ec70298feff3ce4ff687c6f20922c7474b4746ae"}, - {file = "websockets-13.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30d3a1f041360f029765d8704eae606781e673e8918e6b2c792e0775de51352f"}, - {file = "websockets-13.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67648f5e50231b5a7f6d83b32f9c525e319f0ddc841be0de64f24928cd75a603"}, - {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4f0426d51c8f0926a4879390f53c7f5a855e42d68df95fff6032c82c888b5f36"}, - {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ef48e4137e8799998a343706531e656fdec6797b80efd029117edacb74b0a10a"}, - {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:249aab278810bee585cd0d4de2f08cfd67eed4fc75bde623be163798ed4db2eb"}, - {file = "websockets-13.0.1-cp38-cp38-win32.whl", hash = "sha256:06c0a667e466fcb56a0886d924b5f29a7f0886199102f0a0e1c60a02a3751cb4"}, - {file = "websockets-13.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1f3cf6d6ec1142412d4535adabc6bd72a63f5f148c43fe559f06298bc21953c9"}, - {file = "websockets-13.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1fa082ea38d5de51dd409434edc27c0dcbd5fed2b09b9be982deb6f0508d25bc"}, - {file = "websockets-13.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a365bcb7be554e6e1f9f3ed64016e67e2fa03d7b027a33e436aecf194febb63"}, - {file = "websockets-13.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:10a0dc7242215d794fb1918f69c6bb235f1f627aaf19e77f05336d147fce7c37"}, - {file = "websockets-13.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59197afd478545b1f73367620407b0083303569c5f2d043afe5363676f2697c9"}, - {file = "websockets-13.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d20516990d8ad557b5abeb48127b8b779b0b7e6771a265fa3e91767596d7d97"}, - {file = "websockets-13.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1a2e272d067030048e1fe41aa1ec8cfbbaabce733b3d634304fa2b19e5c897f"}, - {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ad327ac80ba7ee61da85383ca8822ff808ab5ada0e4a030d66703cc025b021c4"}, - {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:518f90e6dd089d34eaade01101fd8a990921c3ba18ebbe9b0165b46ebff947f0"}, - {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:68264802399aed6fe9652e89761031acc734fc4c653137a5911c2bfa995d6d6d"}, - {file = "websockets-13.0.1-cp39-cp39-win32.whl", hash = "sha256:a5dc0c42ded1557cc7c3f0240b24129aefbad88af4f09346164349391dea8e58"}, - {file = "websockets-13.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b448a0690ef43db5ef31b3a0d9aea79043882b4632cfc3eaab20105edecf6097"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:faef9ec6354fe4f9a2c0bbb52fb1ff852effc897e2a4501e25eb3a47cb0a4f89"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:03d3f9ba172e0a53e37fa4e636b86cc60c3ab2cfee4935e66ed1d7acaa4625ad"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d450f5a7a35662a9b91a64aefa852f0c0308ee256122f5218a42f1d13577d71e"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f55b36d17ac50aa8a171b771e15fbe1561217510c8768af3d546f56c7576cdc"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14b9c006cac63772b31abbcd3e3abb6228233eec966bf062e89e7fa7ae0b7333"}, - {file = "websockets-13.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b79915a1179a91f6c5f04ece1e592e2e8a6bd245a0e45d12fd56b2b59e559a32"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f40de079779acbcdbb6ed4c65af9f018f8b77c5ec4e17a4b737c05c2db554491"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80e4ba642fc87fa532bac07e5ed7e19d56940b6af6a8c61d4429be48718a380f"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a02b0161c43cc9e0232711eff846569fad6ec836a7acab16b3cf97b2344c060"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6aa74a45d4cdc028561a7d6ab3272c8b3018e23723100b12e58be9dfa5a24491"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00fd961943b6c10ee6f0b1130753e50ac5dcd906130dcd77b0003c3ab797d026"}, - {file = "websockets-13.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d93572720d781331fb10d3da9ca1067817d84ad1e7c31466e9f5e59965618096"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:71e6e5a3a3728886caee9ab8752e8113670936a193284be9d6ad2176a137f376"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c4a6343e3b0714e80da0b0893543bf9a5b5fa71b846ae640e56e9abc6fbc4c83"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a678532018e435396e37422a95e3ab87f75028ac79570ad11f5bf23cd2a7d8c"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6716c087e4aa0b9260c4e579bb82e068f84faddb9bfba9906cb87726fa2e870"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e33505534f3f673270dd67f81e73550b11de5b538c56fe04435d63c02c3f26b5"}, - {file = "websockets-13.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acab3539a027a85d568c2573291e864333ec9d912675107d6efceb7e2be5d980"}, - {file = "websockets-13.0.1-py3-none-any.whl", hash = "sha256:b80f0c51681c517604152eb6a572f5a9378f877763231fddb883ba2f968e8817"}, - {file = "websockets-13.0.1.tar.gz", hash = "sha256:4d6ece65099411cfd9a48d13701d7438d9c34f479046b34c50ff60bb8834e43e"}, + {file = "websockets-14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a0adf84bc2e7c86e8a202537b4fd50e6f7f0e4a6b6bf64d7ccb96c4cd3330b29"}, + {file = "websockets-14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90b5d9dfbb6d07a84ed3e696012610b6da074d97453bd01e0e30744b472c8179"}, + {file = "websockets-14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2177ee3901075167f01c5e335a6685e71b162a54a89a56001f1c3e9e3d2ad250"}, + {file = "websockets-14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f14a96a0034a27f9d47fd9788913924c89612225878f8078bb9d55f859272b0"}, + {file = "websockets-14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f874ba705deea77bcf64a9da42c1f5fc2466d8f14daf410bc7d4ceae0a9fcb0"}, + {file = "websockets-14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9607b9a442392e690a57909c362811184ea429585a71061cd5d3c2b98065c199"}, + {file = "websockets-14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bea45f19b7ca000380fbd4e02552be86343080120d074b87f25593ce1700ad58"}, + {file = "websockets-14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:219c8187b3ceeadbf2afcf0f25a4918d02da7b944d703b97d12fb01510869078"}, + {file = "websockets-14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ad2ab2547761d79926effe63de21479dfaf29834c50f98c4bf5b5480b5838434"}, + {file = "websockets-14.1-cp310-cp310-win32.whl", hash = "sha256:1288369a6a84e81b90da5dbed48610cd7e5d60af62df9851ed1d1d23a9069f10"}, + {file = "websockets-14.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0744623852f1497d825a49a99bfbec9bea4f3f946df6eb9d8a2f0c37a2fec2e"}, + {file = "websockets-14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:449d77d636f8d9c17952628cc7e3b8faf6e92a17ec581ec0c0256300717e1512"}, + {file = "websockets-14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a35f704be14768cea9790d921c2c1cc4fc52700410b1c10948511039be824aac"}, + {file = "websockets-14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b1f3628a0510bd58968c0f60447e7a692933589b791a6b572fcef374053ca280"}, + {file = "websockets-14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c3deac3748ec73ef24fc7be0b68220d14d47d6647d2f85b2771cb35ea847aa1"}, + {file = "websockets-14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7048eb4415d46368ef29d32133134c513f507fff7d953c18c91104738a68c3b3"}, + {file = "websockets-14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cf0ad281c979306a6a34242b371e90e891bce504509fb6bb5246bbbf31e7b6"}, + {file = "websockets-14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc1fc87428c1d18b643479caa7b15db7d544652e5bf610513d4a3478dbe823d0"}, + {file = "websockets-14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f95ba34d71e2fa0c5d225bde3b3bdb152e957150100e75c86bc7f3964c450d89"}, + {file = "websockets-14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9481a6de29105d73cf4515f2bef8eb71e17ac184c19d0b9918a3701c6c9c4f23"}, + {file = "websockets-14.1-cp311-cp311-win32.whl", hash = "sha256:368a05465f49c5949e27afd6fbe0a77ce53082185bbb2ac096a3a8afaf4de52e"}, + {file = "websockets-14.1-cp311-cp311-win_amd64.whl", hash = "sha256:6d24fc337fc055c9e83414c94e1ee0dee902a486d19d2a7f0929e49d7d604b09"}, + {file = "websockets-14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed"}, + {file = "websockets-14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d"}, + {file = "websockets-14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707"}, + {file = "websockets-14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a"}, + {file = "websockets-14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45"}, + {file = "websockets-14.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58"}, + {file = "websockets-14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058"}, + {file = "websockets-14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4"}, + {file = "websockets-14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05"}, + {file = "websockets-14.1-cp312-cp312-win32.whl", hash = "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0"}, + {file = "websockets-14.1-cp312-cp312-win_amd64.whl", hash = "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f"}, + {file = "websockets-14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9"}, + {file = "websockets-14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b"}, + {file = "websockets-14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3"}, + {file = "websockets-14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59"}, + {file = "websockets-14.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2"}, + {file = "websockets-14.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77569d19a13015e840b81550922056acabc25e3f52782625bc6843cfa034e1da"}, + {file = "websockets-14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9"}, + {file = "websockets-14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7"}, + {file = "websockets-14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a"}, + {file = "websockets-14.1-cp313-cp313-win32.whl", hash = "sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6"}, + {file = "websockets-14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0"}, + {file = "websockets-14.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:01bb2d4f0a6d04538d3c5dfd27c0643269656c28045a53439cbf1c004f90897a"}, + {file = "websockets-14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:414ffe86f4d6f434a8c3b7913655a1a5383b617f9bf38720e7c0799fac3ab1c6"}, + {file = "websockets-14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fda642151d5affdee8a430bd85496f2e2517be3a2b9d2484d633d5712b15c56"}, + {file = "websockets-14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd7c11968bc3860d5c78577f0dbc535257ccec41750675d58d8dc66aa47fe52c"}, + {file = "websockets-14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a032855dc7db987dff813583d04f4950d14326665d7e714d584560b140ae6b8b"}, + {file = "websockets-14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7e7ea2f782408c32d86b87a0d2c1fd8871b0399dd762364c731d86c86069a78"}, + {file = "websockets-14.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:39450e6215f7d9f6f7bc2a6da21d79374729f5d052333da4d5825af8a97e6735"}, + {file = "websockets-14.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ceada5be22fa5a5a4cdeec74e761c2ee7db287208f54c718f2df4b7e200b8d4a"}, + {file = "websockets-14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3fc753451d471cff90b8f467a1fc0ae64031cf2d81b7b34e1811b7e2691bc4bc"}, + {file = "websockets-14.1-cp39-cp39-win32.whl", hash = "sha256:14839f54786987ccd9d03ed7f334baec0f02272e7ec4f6e9d427ff584aeea8b4"}, + {file = "websockets-14.1-cp39-cp39-win_amd64.whl", hash = "sha256:d9fd19ecc3a4d5ae82ddbfb30962cf6d874ff943e56e0c81f5169be2fda62979"}, + {file = "websockets-14.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e5dc25a9dbd1a7f61eca4b7cb04e74ae4b963d658f9e4f9aad9cd00b688692c8"}, + {file = "websockets-14.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:04a97aca96ca2acedf0d1f332c861c5a4486fdcba7bcef35873820f940c4231e"}, + {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df174ece723b228d3e8734a6f2a6febbd413ddec39b3dc592f5a4aa0aff28098"}, + {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:034feb9f4286476f273b9a245fb15f02c34d9586a5bc936aff108c3ba1b21beb"}, + {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c308dabd2b380807ab64b62985eaccf923a78ebc572bd485375b9ca2b7dc7"}, + {file = "websockets-14.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a42d3ecbb2db5080fc578314439b1d79eef71d323dc661aa616fb492436af5d"}, + {file = "websockets-14.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddaa4a390af911da6f680be8be4ff5aaf31c4c834c1a9147bc21cbcbca2d4370"}, + {file = "websockets-14.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4c805c6034206143fbabd2d259ec5e757f8b29d0a2f0bf3d2fe5d1f60147a4a"}, + {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:205f672a6c2c671a86d33f6d47c9b35781a998728d2c7c2a3e1cf3333fcb62b7"}, + {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef440054124728cc49b01c33469de06755e5a7a4e83ef61934ad95fc327fbb0"}, + {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7591d6f440af7f73c4bd9404f3772bfee064e639d2b6cc8c94076e71b2471c1"}, + {file = "websockets-14.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:25225cc79cfebc95ba1d24cd3ab86aaa35bcd315d12fa4358939bd55e9bd74a5"}, + {file = "websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e"}, + {file = "websockets-14.1.tar.gz", hash = "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8"}, ] [[package]] @@ -3352,118 +3537,109 @@ watchdog = ["watchdog"] [[package]] name = "yarl" -version = "1.9.8" +version = "1.17.2" description = "Yet another URL library" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "yarl-1.9.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:08359dbc3540fafa8972db45d3ef2d61370b4c24b8a028a4301bc5d076eee0e2"}, - {file = "yarl-1.9.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7a716aae4fcecadfe4648268d3c194315152715391f4af6fad50d502be122e9"}, - {file = "yarl-1.9.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:62223670042a219b8e6fbd2c7f35c456278dcd346d3aba3f2c01c9bdec28f37e"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18097a9e50ea31c61fece83bac8f63263f0c0c16c439bf82ac729c23f3b170e3"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5809f8a48c8dab91f708947d358271ef1890c3012d6c45719f49d04af2112057"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71ff7a22355241f89e850afbc8858fb671ba7e2763af32ebbea158d23a84902a"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d54e9880e781a490483200a74f6314fb6cf692a8197ccde93adf32bec95626b"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ad8ea6ab27e27821739dfb94fab63284e3a52055e268f04529dc082fd0d59a2"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b79e031524259b51cdd1ea41f5053491ad3565b9cecd76389c9f705752d14283"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:bd91ccded75d080f13ed01a5f5796887916d2e8c0999cd68bcb58f89f9b1c29c"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:583f48ab25b3906e3716479e8f700c4cc487e44d52766a4ea52b01cb7ea772d6"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2f3e89838acdaf5bbd69383c408d9e119b4e9efbe8a38fa40045b5c966f918e3"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a44c0b83d1871e1e1859167a1804143f590f86ac4708380852dca4d8299d8594"}, - {file = "yarl-1.9.8-cp310-cp310-win32.whl", hash = "sha256:5d39ae58a67b64b470021d18a13529d0c58efc5bf057936ec4b29092d4061030"}, - {file = "yarl-1.9.8-cp310-cp310-win_amd64.whl", hash = "sha256:f89ade31926b9931bbe29f5c62d4174057e532fb0c72e2e6abdd129fda6a60f3"}, - {file = "yarl-1.9.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:986296e65b0312c1da168de4ec1bb054b4a7b0ec26e3f9e8dafc06bbb1385030"}, - {file = "yarl-1.9.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b4c7c015dc813aa5fe15379f3540d178e3743c0f1cf9e4a4a8bff94bd2832a4d"}, - {file = "yarl-1.9.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:22b2db22f72e1cb8a552ae12dfb748167153c7cbf353c62781915b5328bf2561"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a567416bfb2a2b093aa64685aa7b6dfb593888784ef91b16fa6b985cceb951"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:178f4ab054f3a5dc84c8091bd7395b6713aac83af893b62259d5eb3f5359ce7f"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:02fe9809b29a7dc4a27b769a43c556288d949205db54338871a122b64751e0f4"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c885a81f6c89b0d45fc0dd88e005c77dd8ba1dac421466d0dbb9192ce6d34e1e"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99f78f45c8b4c9824e1a37eb0a3ae63ad2dff66434d9620265a4256088be9cda"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:30929a10be9a13026fd68377aba3223d633370abb93dadd3932754f3dcf4734a"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ee7c00a1979b3f23c8094dce6d9875453b3cb91b1153d9efaefa6773cf80cdb0"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e89d76b2aa11287f038a37577528c5f62d9385020b795a011f60dfd1b217cf9f"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:81fde88456d2cbe005e16aca78ef744f322b3b15184dfe41b5b04f97b46aa5be"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b3dca0a4e192207f8bb4057725ff95e9a14d53a04728742f2b03692fc91b0a43"}, - {file = "yarl-1.9.8-cp311-cp311-win32.whl", hash = "sha256:9ea3a8532ea9fc2eeb6fc3def0c341aaeab7625545844f9c0a15350c17f9f479"}, - {file = "yarl-1.9.8-cp311-cp311-win_amd64.whl", hash = "sha256:c810606719683f4ab92127712efe283674d6ed29a627374411c762852913c2dd"}, - {file = "yarl-1.9.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b3d373373908e687aa4c8b0666870b0cf65605254ba0819ed8d5af2fc0780496"}, - {file = "yarl-1.9.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e3d1be58e28825a14fb9561733de62fbe95c892febe7d7a9ebcde916c531d603"}, - {file = "yarl-1.9.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7318736a8ee9de8217d590866dd716fa3c0895e684e2ec6152d945a4ab758043"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db3dd602cbf6613dc1e4a6fbde7a1bee86948e5940086090bb505c2ab959bbdf"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5950226b128a1610f57c1f756fc611fdbdcb1e6b4497ccb05fce76a38915b07"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b341a995673180ed81a1040228a59e0b47ee687e367b1a03d829fa3c0eb4607e"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f912153a34698994f32cf683d966014b0dd99c73481302d6159bcb3a8303e84"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ceab2b16043ae1953863ec240eb918ba1ac40d2aad55225141aac288c606442"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c0d2bc2646ae2380bb91b9ddc2eb1e1fa6baef128499e817134d1d50c8b6c56"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ebd98e16ff9948e4d31514c937275017a122b765cb89961dd5d44ecd2cc18140"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:83273ca458c85d7b026c770a86df6e36349e85100bd2cefe6d0ad7167a8f12a6"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4511dd73b6aeda0cc39111839923f1545726d621813c9d13355824fba328dbcf"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ffb9f1cad56c547aa127e2c315e666ee9838156c8a3b14f37ba545b0167aa5e"}, - {file = "yarl-1.9.8-cp312-cp312-win32.whl", hash = "sha256:5796358c3d6c72b108b570e20ab951463237ec473b6d204da21050feaaaf7dca"}, - {file = "yarl-1.9.8-cp312-cp312-win_amd64.whl", hash = "sha256:c2dc6e941bf53160b44858d1b24767a056cd83166b69fbdd3b2e401856d8932e"}, - {file = "yarl-1.9.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cb3d488f049db9522e3a0de50e07bac0c53565acd88a07bc9cf7182fd6890307"}, - {file = "yarl-1.9.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:50cbf73b6a4b62c3ad633e8920f2791adf485356ef37c9edbd5a1e7de8da2ddc"}, - {file = "yarl-1.9.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1e0649ee7ac354a3e40ee849707140b14a2cd0cd2dc2062fe620458dfe465c8"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2501b230e89cad2361719860648f780197812d3be91c7ca6658a097a7e22fc4"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be441a73f9f49427906274008bd98384d8ca4655981735281c314fc7c145d256"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7de1968a1c2690b86e32e91acf8ed2043c346293f9bbe1704b9f6a481b73bd11"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce892a75a2209cf4f7007de21c6f6d607f4b9406ac613a59ad02340f6e933e4"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:405e75bb94b87cc4167eef0e08d6a539f60633229f7043edc2e65c82ef80e874"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5811c1906b38f2a203df1266c6dd11680ca85d610d6ee3701dde262a305520"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:51476f19fe1296d3efe3770179548f5f4822e5c4ead9f5160ba156a6a9f5272c"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2af144a81883db914636bec646da4dcccfe9db05c2899e7afe90a3d817ffce"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:8c91b71b0af1fb5454709e34b39e38c975faaa89c0cc8bb744d60300ca710fcd"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a562055b5ec6371c307320e8460d16675244e810b20f343371fc52797d23615"}, - {file = "yarl-1.9.8-cp313-cp313-win32.whl", hash = "sha256:f7442a9342aa04ea60b760a8f0d210e269f881eb0660a2000fa1f8cb89820931"}, - {file = "yarl-1.9.8-cp313-cp313-win_amd64.whl", hash = "sha256:21ef75d8a18fa47725b50fcb7ae6d23a51c71a7426cdf7097e52f9e12a995eb6"}, - {file = "yarl-1.9.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd9affa8c18198dfa5a19c63b29ef2a2f35b8efacaf0bdd3e58f974c0ab0108d"}, - {file = "yarl-1.9.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f79e65f16413a95d9f7633802a2ee34730b3ba1dd0af82811b377057883c4fb7"}, - {file = "yarl-1.9.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3f8c454cf7e4d3762515ed2b5a40cf2feaeb8a8ed1d121f131a6178e16015319"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f972fc63a1d6165d1cff650a16a498b0087334f7f9cd7385860c086d009cd49"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ac4aa2f2d8253b9a5455d5f0ed45687ea9715b78a563490ddf7954337974cb7"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b001379047de5e03224dc0592f1b0e60738857a9b992d9b636b5050500ecce23"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39deb5a67b591682e54d1b09b36e79cd608ca27bea1fefed3bcaaa0b05d2b25e"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffd9dd7eac5d36f53fccdf11e98730b7a628561c77f6c2a9e0909d2a304f34d1"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:497d5fd7dce44b5dcac648c830c99a673d30bc6cd9905b3e255c92c6dc01f537"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d99011d564f2b5cb4cf1012f9058e08d8d79674332474f7e940131f5952015df"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:600f734296cb99db1af7e34c0dcf8ec9477072f72c4621677637fdc2273af120"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6703deac7bb0dd8b3f0bc3cb6844dab4e74c85c70783ae89bd0b52286ebdc102"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3346e2f641fcf31cf32c5a394d625e0676aba6fadccc06d35435e475753ed05d"}, - {file = "yarl-1.9.8-cp38-cp38-win32.whl", hash = "sha256:a54f7a63e48156a77a7c0333cefed29ceb004ab683d685a1192b341ac445cb73"}, - {file = "yarl-1.9.8-cp38-cp38-win_amd64.whl", hash = "sha256:45992ff8d941a1901c35f2ed90a60cb5fee8705ffadff395db4a5fd164473542"}, - {file = "yarl-1.9.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:590437f092af08e71521cc302940ef897e969152434c825bb3fb8f308b63a8bb"}, - {file = "yarl-1.9.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:551c26789acd38c7b90a89a1f262291d9f9a6a677185a83b5781e2a2c4258aec"}, - {file = "yarl-1.9.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:121bf7d647b3f6481ce1030350c1cc4c43e18758010732a449c71a1784ae793d"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9db466370e8bc3459912850494ad3401f3664ff3a56842f0d4514166f54c9f"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff56e21379824f3e3c39a37083d5ab905168b9483b1c0c563dd92eb2db18b251"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cce910a1510d60c7eff4bb263b28b9afdcc5f6b85c555e492cfe7548a09e2476"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ba7c4b50cc0bb4caaa54554613ca13db47a24878a4fc1063e6303494fc67567"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b345de5e725b82e9458dc1381d7e28fe7d7ef93491370461dc98283b9dda51e2"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:49dd58b79b0fd04e880c90bc570fde68407cc516c58812f0321f5e74c131107c"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:15fb127bcc19065fd912391a43bc80114635f0062e0465765633ab5d0c7fc3a1"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:6f4f87a7c97ba77fdc764b893ae4083c74e5857904962a70025ade0cd42bdbaf"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d336601d9ff3dc3b12263739ab1add25bdd2345d675f59ad49f72d9a6ccbc865"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3574834e4aaf24e24d12fa4fd53d0b0fd1d70b24a67bed81c44b284377e81d45"}, - {file = "yarl-1.9.8-cp39-cp39-win32.whl", hash = "sha256:db9305328486539bb7182c15f1ad1ea95dae52245e93a049f2b1d6f04e63674d"}, - {file = "yarl-1.9.8-cp39-cp39-win_amd64.whl", hash = "sha256:588d62a57c7a43b230557728ec9f252b3f81ad073cb5c0ef48d87cd3f8b6ace2"}, - {file = "yarl-1.9.8-py3-none-any.whl", hash = "sha256:d1612ce50f23b94897b9ef5eb65b72398a9a83ea990b42825272590f3484dae3"}, - {file = "yarl-1.9.8.tar.gz", hash = "sha256:3089553548d9ab23152cecb5a71131caaa9e9b16d7fc8196057c374fdc53cc4b"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b"}, + {file = "yarl-1.17.2-cp310-cp310-win32.whl", hash = "sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673"}, + {file = "yarl-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0"}, + {file = "yarl-1.17.2-cp311-cp311-win32.whl", hash = "sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628"}, + {file = "yarl-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20"}, + {file = "yarl-1.17.2-cp312-cp312-win32.whl", hash = "sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b"}, + {file = "yarl-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2"}, + {file = "yarl-1.17.2-cp313-cp313-win32.whl", hash = "sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28"}, + {file = "yarl-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8"}, + {file = "yarl-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130"}, + {file = "yarl-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed"}, + {file = "yarl-1.17.2-py3-none-any.whl", hash = "sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b"}, + {file = "yarl-1.17.2.tar.gz", hash = "sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178"}, ] [package.dependencies] idna = ">=2.0" multidict = ">=4.0" +propcache = ">=0.2.0" [[package]] name = "zipp" -version = "3.20.1" +version = "3.21.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"}, - {file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"}, + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, ] [package.extras] @@ -3477,4 +3653,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "<3.12,>=3.9" -content-hash = "85568473089af1d5ba1b5a8ada225c96b7ff03067a2edabdaacd7ff61e4d0a06" +content-hash = "b75277aad08d587ce11fa395aea10930ac7abac3fe7f3ad48e10dc0af70ffc05" diff --git a/pyproject.toml b/pyproject.toml index 0a48a9d4c..b70d60020 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "olas-operate-middleware" -version = "0.1.0-rc184" +version = "0.2.0-rc9" description = "" authors = ["David Vilela ", "Viraj Patel "] readme = "README.md" @@ -10,8 +10,8 @@ packages = [ include = [ "operate/data/acn/*", "operate/data/contracts/*", - "operate/data/contracts/service_staking_token/*", - "operate/data/contracts/service_staking_token/build/*", + "operate/data/contracts/staking_token/*", + "operate/data/contracts/staking_token/build/*", ] [tool.poetry.scripts] @@ -19,11 +19,11 @@ operate = "operate.cli:main" [tool.poetry.dependencies] python = "<3.12,>=3.9" -open-autonomy = "==0.14.14.post2" -open-aea-ledger-cosmos = "==1.53.0" -open-aea-ledger-ethereum = "==1.53.0" -open-aea-ledger-ethereum-flashbots = "==1.53.0" -open-aea-cli-ipfs = "==1.53.0" +open-autonomy = "==0.16.1" +open-aea-ledger-cosmos = "==1.57.0" +open-aea-ledger-ethereum = "==1.57.0" +open-aea-ledger-ethereum-flashbots = "==1.57.0" +open-aea-cli-ipfs = "==1.57.0" clea = "==0.1.0rc4" cytoolz = "==0.12.3" docker = "6.1.2" @@ -48,6 +48,7 @@ web3 = "==6.1.0" psutil = "^5.9.8" pyinstaller = "^6.8.0" aiohttp = "3.9.5" +deepdiff = "^8.0.1" [tool.poetry.group.development.dependencies] tomte = {version = "0.2.17", extras = ["cli"]} diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..f5276a231 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +log_cli = 1 +log_cli_level = INFO +log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s) +log_cli_date_format=%Y-%m-%d %H:%M:%S diff --git a/scripts/js/tenderly-optimus-fund-eoa-onboarding.js b/scripts/js/tenderly-optimus-fund-eoa-onboarding.js index 0a58942c1..9f551c801 100644 --- a/scripts/js/tenderly-optimus-fund-eoa-onboarding.js +++ b/scripts/js/tenderly-optimus-fund-eoa-onboarding.js @@ -25,17 +25,17 @@ const setBalance = async (masterEoa, rpc) => fetch(rpc, { }), }).then(() => console.log(`Successfully set balance for ${masterEoa} on ${rpc}`)) -const main = async () => { +const main = async () => { const rpcs = { - gnosis: process.env.GNOSIS_DEV_RPC, - optimus: process.env.OPTIMISM_DEV_RPC, - base: process.env.BASE_DEV_RPC, - ethereum: process.env.ETHEREUM_DEV_RPC + gnosis: process.env.GNOSIS_RPC, + optimus: process.env.OPTIMISM_RPC, + base: process.env.BASE_RPC, + ethereum: process.env.ETHEREUM_RPC }; console.log(rpcs) - await Promise.all(Object.values(rpcs).map(rpc => setBalance(masterEoa, rpc))); + await Promise.all(Object.values(rpcs).map(rpc => setBalance(masterEoa, rpc))); } main() \ No newline at end of file diff --git a/scripts/js/tenderly-optimus-fund-master-safes.js b/scripts/js/tenderly-optimus-fund-master-safes.js index b17215026..695b480c0 100644 --- a/scripts/js/tenderly-optimus-fund-master-safes.js +++ b/scripts/js/tenderly-optimus-fund-master-safes.js @@ -10,66 +10,101 @@ require('dotenv').config(); const fs = require('fs'); -const operateEthereumJson = fs.readFileSync('.operate/wallets/ethereum.json'); +const operateEthereumJson = fs.readFileSync('./.operate/wallets/ethereum.json'); const operateEthereum = JSON.parse(operateEthereumJson); -console.log(operateEthereum) +const masterSafeAddress = Object.values(operateEthereum.safes)[0]; // assuming all safe addresses are the same -const masterSafeAddress = operateEthereum.safes['4']; // assuming all safe addresses are the same - -const setBalance = async (masterSafeAddress, rpc) => fetch(rpc, { +const setBalance = async (address, rpc) => fetch(rpc, { method: 'POST', body: JSON.stringify({ jsonrpc: '2.0', method: 'tenderly_setBalance', params: [ - masterSafeAddress, + address, "0x3635C9ADC5DEA00000" ] }), -}).then(() => console.log(`Successfully set balance for ${masterSafeAddress} on ${rpc}`)) +}).then(() => console.log(`Successfully set balance for ${address} on ${rpc}`)) -const setErc20Balance = async (erc20Address, masterSafeAddress, rpc) => fetch(rpc, { +const setErc20Balance = async (erc20Address, address, rpc) => fetch(rpc, { method: 'POST', body: JSON.stringify({ jsonrpc: '2.0', - method: 'tenderly_setERC20Balance', + method: 'tenderly_setErc20Balance', params: [ erc20Address, - masterSafeAddress, - "0x3635C9ADC5DEA00000" - ] + address, + "0x56BC75E2D63100000" + ], + id: "3640" }), -}).then(() => console.log(`Successfully set ERC20 balance for ${masterSafeAddress} on ${rpc}`)) +}).then((e) => console.log(`Successfully set ERC20 balance for ${address} on ${rpc}\n ${JSON.stringify(e)}`)) -const main = async () => { +const main = async () => { const rpcs = { - gnosis: process.env.GNOSIS_DEV_RPC, - optimism: process.env.OPTIMISM_DEV_RPC, - base: process.env.BASE_DEV_RPC, - ethereum: process.env.ETHEREUM_DEV_RPC + gnosis: process.env.GNOSIS_RPC, + optimism: process.env.OPTIMISM_RPC, + base: process.env.BASE_RPC, + ethereum: process.env.ETHEREUM_RPC }; const erc20Addresses = { olas: { - gnosis: "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f", + gnosis: "0xce11e14225575945b8e6dc0d4f2dd4c570f79d9f", optimism: "0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527", - ethereum: - "0x0001A500A6B18995B03f44bb040A5fFc28E45CB0", + ethereum: + "0x0001a500a6b18995b03f44bb040a5ffc28e45cb0", base: - "0x4B1a99467a284CC690e3237bc69105956816F762" + "0x54330d28ca3357F294334BDC454a032e7f353416" }, usdc: { ethereum: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" } } + // ETH on all - await Promise.all(Object.values(rpcs).map(rpc => setBalance(masterSafeAddress, rpc))); + await Promise.all(Object.values(rpcs).map(rpc => setBalance(masterSafeAddress, rpc))); + + // check eth on all + await Promise.all(Object.entries(rpcs).map(([chain, rpc]) => + fetch(rpc, { + method: 'POST', + body: JSON.stringify({ + jsonrpc: '2.0', + method: 'eth_getBalance', + params: [ + masterSafeAddress, + 'latest' + ], + id: 1 + }), + }).then(async (res) => JSON.stringify(({... await res.json(), chain}), null, 0)).then(console.log) + )); // ERC20s - await setErc20Balance(erc20Addresses.usdc.ethereum, masterSafeAddress, rpcs.ethereum) - await setErc20Balance(erc20Addresses.olas.optimism, masterSafeAddress, rpcs.optimism) + // await Promise.all(Object.entries(erc20Addresses.olas).map(([chain, address]) => (chain==="gnosis") && setErc20Balance(address, masterSafeAddress, rpcs[chain]))); + await setErc20Balance(erc20Addresses.olas.gnosis, masterSafeAddress, rpcs.gnosis); + + // check erc20s + await Promise.all(Object.entries(erc20Addresses.olas).map(([chain, address]) => + fetch(rpcs[chain], { + method: 'POST', + body: JSON.stringify({ + jsonrpc: '2.0', + method: 'eth_call', + params: [ + { + to: address, + data: `0x70a082310000000000000000${masterSafeAddress.slice(2)}` + }, + 'latest' + ], + id: 1 + }), + }).then(async (res) => JSON.stringify(({... await res.json(), chain}), null, 0)).then(console.log) + )); } main() \ No newline at end of file diff --git a/scripts/setup_wallet.py b/scripts/setup_wallet.py index 5d5a47f70..99279ae16 100644 --- a/scripts/setup_wallet.py +++ b/scripts/setup_wallet.py @@ -21,7 +21,7 @@ import requests -from operate.operate_types import ChainType +from operate.operate_types import Chain from scripts.fund import fund @@ -48,7 +48,7 @@ wallet = requests.post( "http://localhost:8000/api/wallet", json={ - "chain_type": ChainType.GNOSIS, + "chain": Chain.GNOSIS, }, ).json() print("Setting up wallet") @@ -61,7 +61,7 @@ requests.post( "http://localhost:8000/api/wallet/safe", json={ - "chain_type": ChainType.GNOSIS, + "chain": Chain.GNOSIS, "owner": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", # Backup owner }, ).json() diff --git a/templates/optimus.yaml b/templates/optimus.yaml index 331c61eb3..4076c9bb5 100644 --- a/templates/optimus.yaml +++ b/templates/optimus.yaml @@ -3,9 +3,9 @@ hash: bafybeibiiuhqronhgkxjo7x5xve24lkbqom5rqcjxg7vrl6jwavfyypmhu description: Optimus image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 service_version: v0.2.9 -home_chain_id: 10 +home_chain: "optimistic" configurations: - 1: + ethereum: staking_program_id: optimus_alpha nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq agent_id: 14 @@ -17,7 +17,7 @@ configurations: fund_requirements: agent: 1000 safe: 1000 - 10: + optimistic: staking_program_id: optimus_alpha nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq agent_id: 14 @@ -29,7 +29,7 @@ configurations: fund_requirements: agent: 1000 safe: 1000 - 8453: + base: staking_program_id: optimus_alpha nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq agent_id: 14 diff --git a/templates/trader.yaml b/templates/trader.yaml index a65c73664..643d0658d 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -1,66 +1,60 @@ -# name: "Trader Agent" -# description: "A single-agent service (sovereign agent) placing bets on Omen" -# hash: bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u -# image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 -# service_version: v0.18.4 -# home_chain_id: 100 -# configurations: -# 100: -# staking_program_id: pearl_beta -# nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq -# rpc: http://localhost:8545 # User provided -# threshold: 1 # TODO: Move to service component -# use_staking: false # User provided -# use_mech_marketplace: false # User provided -# cost_of_bond: 10000000000000000 -# monthly_gas_estimate: 10000000000000000000 # TODO: Where is this used -# fund_requirements: -# agent: 100000000000000000 -# safe: 5000000000000000000 - -name: "Optimus" -description: "Optimus" -hash: bafybeibzujtdlgsft3hnjmboa5yfni7vqc2iocjlyti5nadc55jxj3kxbu +name: "Trader Agent" +description: "A single-agent service (sovereign agent) placing bets on Omen" +hash: bafybeicts6zhavxzz2rxahz3wzs2pzamoq64n64wp4q4cdanfuz7id6c2q image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 -service_version: v0.2.9 -home_chain_id: 10 +service_version: v0.18.4 +home_chain: "gnosis" configurations: - 10: - staking_program_id: optimus_alpha + gnosis: + staking_program_id: pearl_beta nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq rpc: http://localhost:8545 # User provided - agent_id: 14 - threshold: 1 - use_staking: true - use_mech_marketplace: false - cost_of_bond: 1000 - monthly_gas_estimate: 1000 + threshold: 1 # TODO: Move to service component + use_staking: false # User provided + use_mech_marketplace: false # User provided + cost_of_bond: 10000000000000000 + monthly_gas_estimate: 10000000000000000000 # TODO: Where is this used fund_requirements: - agent: 1000 - safe: 1000 - 1: - staking_program_id: optimus_alpha - nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq - rpc: http://localhost:8545 # User provided - agent_id: 14 - threshold: 1 - use_staking: false - use_mech_marketplace: false - cost_of_bond: 1 - monthly_gas_estimate: 1000 - fund_requirements: - agent: 1000 - safe: 1000 - 8453: - staking_program_id: optimus_alpha - nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq - rpc: http://localhost:8545 # User provided - agent_id: 14 - threshold: 1 - use_staking: false - use_mech_marketplace: false - cost_of_bond: 1 - monthly_gas_estimate: 1000 - fund_requirements: - agent: 1000 - safe: 1000 + agent: 100000000000000000 + safe: 5000000000000000000 +env_variables: + GNOSIS_LEDGER_RPC: + name: "Gnosis ledger RPC" + description: "" + value: "" + provision_type: "computed" + STAKING_CONTRACT_ADDRESS: + name: "Staking contract address" + description: "" + value: "" + provision_type: "computed" + MECH_ACTIVITY_CHECKER_CONTRACT: + name: "Mech activity checker contract" + description: "" + value: "" + provision_type: "computed" + MECH_CONTRACT_ADDRESS: + name: "Mech contract address" + description: "" + value: "" + provision_type: "computed" + MECH_REQUEST_PRICE: + name: "Mech request price" + description: "" + value: "" + provision_type: "computed" + USE_MECH_MARKETPLACE: + name: "Use Mech marketplace" + description: "" + value: "" + provision_type: "computed" + REQUESTER_STAKING_INSTANCE_ADDRESS: + name: "Requester staking instance address" + description: "" + value: "" + provision_type: "computed" + PRIORITY_MECH_ADDRESS: + name: "Priority Mech address" + description: "" + value: "" + provision_type: "computed" diff --git a/tests/test_services_service.py b/tests/test_services_service.py new file mode 100644 index 000000000..f040a890e --- /dev/null +++ b/tests/test_services_service.py @@ -0,0 +1,304 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2024 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""Tests for services.service module.""" + +import json +import typing as t +from pathlib import Path + +import pytest +from deepdiff import DeepDiff + +from operate.services.service import ( + SERVICE_CONFIG_PREFIX, + SERVICE_CONFIG_VERSION, + Service, +) + + +DEFAULT_CONFIG_KWARGS = { + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "use_staking": True, + "use_mech_marketplace": False, + "rpc": "https://rpc.com", + "service_config_id": "sc-00000000-0000-0000-0000-000000000000", + "hash_timestamp": 1704063600, + "token": 42, + "staked": True, + "on_chain_state": 4, + "staking_program_id": "staking_program_1", + "threshold": 1, + "agent_id": 14, + "cost_of_bond": 10000000000000000, + "fund_requirements_agent": 100000000000000000, + "fund_requirements_safe": 5000000000000000000, + "nft": "bafybeinft", + "name": "Trader Service", + "description": "Service description", + "keys_address_0": "0x0000000000000000000000000000000000000001", + "keys_private_key_0": "0x0000000000000000000000000000000000000000000000000000000000000001", + "instance_0": "0x0000000000000000000000000000000000000001", + "multisig": "0x0000000000000000000000000000000000000020", +} + + +def get_config_json_data_v0(**kwargs: t.Any) -> t.Dict[str, t.Any]: + """get_config_json_data_v0""" + + return { + "hash": kwargs.get("hash"), + "keys": [ + { + "ledger": 0, + "address": kwargs.get("keys_address_0"), + "private_key": kwargs.get("keys_private_key_0"), + } + ], + "ledger_config": {"rpc": kwargs.get("rpc"), "type": 0, "chain": 2}, + "chain_data": { + "instances": [kwargs.get("instance_0")], + "token": kwargs.get("token"), + "multisig": kwargs.get("multisig"), + "staked": True, + "on_chain_state": kwargs.get("on_chain_state"), + "user_params": { + "nft": kwargs.get("nft"), + "agent_id": kwargs.get("agent_id"), + "threshold": kwargs.get("threshold"), + "use_staking": kwargs.get("use_staking"), + "cost_of_bond": kwargs.get("cost_of_bond"), + "olas_cost_of_bond": 10000000000000000000, + "olas_required_to_stake": 10000000000000000000, + "fund_requirements": { + "agent": kwargs.get("fund_requirements_agent"), + "safe": kwargs.get("fund_requirements_safe"), + }, + }, + }, + "service_path": f"/home/user/.operate/services/{kwargs.get('hash')}/trader_pearl", + "name": kwargs.get("name"), + } + + +def get_config_json_data_v2(**kwargs: t.Any) -> t.Dict[str, t.Any]: + """get_config_json_data_v2""" + + return { + "version": 2, + "hash": kwargs.get("hash"), + "keys": [ + { + "ledger": 0, + "address": kwargs.get("keys_address_0"), + "private_key": kwargs.get("keys_private_key_0"), + } + ], + "home_chain_id": "100", + "chain_configs": { + "100": { + "ledger_config": {"rpc": kwargs.get("rpc"), "type": 0, "chain": 2}, + "chain_data": { + "instances": [kwargs.get("instance_0")], + "token": kwargs.get("token"), + "multisig": kwargs.get("multisig"), + "staked": True, + "on_chain_state": kwargs.get("on_chain_state"), + "user_params": { + "staking_program_id": kwargs.get("staking_program_id"), + "nft": kwargs.get("nft"), + "threshold": kwargs.get("threshold"), + "use_staking": kwargs.get("use_staking"), + "cost_of_bond": kwargs.get("cost_of_bond"), + "fund_requirements": { + "agent": kwargs.get("fund_requirements_agent"), + "safe": kwargs.get("fund_requirements_safe"), + }, + }, + }, + } + }, + "service_path": f"/home/user/.operate/services/{kwargs.get('hash')}/trader_pearl", + "name": kwargs.get("name"), + } + + +def get_config_json_data_v3(**kwargs: t.Any) -> t.Dict[str, t.Any]: + """get_config_json_data_v3""" + + return { + "version": 3, + "hash": kwargs.get("hash"), + "keys": [ + { + "ledger": 0, + "address": kwargs.get("keys_address_0"), + "private_key": kwargs.get("keys_private_key_0"), + } + ], + "home_chain_id": "100", + "chain_configs": { + "100": { + "ledger_config": {"rpc": kwargs.get("rpc"), "type": 0, "chain": 2}, + "chain_data": { + "instances": [kwargs.get("instance_0")], + "token": kwargs.get("token"), + "multisig": kwargs.get("multisig"), + "staked": True, + "on_chain_state": kwargs.get("on_chain_state"), + "user_params": { + "staking_program_id": kwargs.get("staking_program_id"), + "nft": kwargs.get("nft"), + "threshold": kwargs.get("threshold"), + "use_staking": kwargs.get("use_staking"), + "use_mech_marketplace": kwargs.get("use_mech_marketplace"), + "cost_of_bond": kwargs.get("cost_of_bond"), + "fund_requirements": { + "agent": kwargs.get("fund_requirements_agent"), + "safe": kwargs.get("fund_requirements_safe"), + }, + }, + }, + } + }, + "service_path": f"/home/user/.operate/services/{kwargs.get('hash')}/trader_pearl", + "name": kwargs.get("name"), + } + + +def get_config_json_data_v4(**kwargs: t.Any) -> t.Dict[str, t.Any]: + """get_config_json_data_v4""" + + return { + "version": kwargs.get("version"), + "service_config_id": kwargs.get("service_config_id"), + "hash": kwargs.get("hash"), + "hash_history": {kwargs.get("hash_timestamp"): kwargs.get("hash")}, + "keys": [ + { + "ledger": "ethereum", + "address": kwargs.get("keys_address_0"), + "private_key": kwargs.get("keys_private_key_0"), + } + ], + "home_chain": "gnosis", + "chain_configs": { + "gnosis": { + "ledger_config": {"rpc": kwargs.get("rpc"), "chain": "gnosis"}, + "chain_data": { + "instances": [kwargs.get("instance_0")], + "token": kwargs.get("token"), + "multisig": kwargs.get("multisig"), + "staked": kwargs.get("staked"), + "on_chain_state": kwargs.get("on_chain_state"), + "user_params": { + "staking_program_id": kwargs.get("staking_program_id"), + "nft": kwargs.get("nft"), + "threshold": kwargs.get("threshold"), + "agent_id": kwargs.get("agent_id"), + "use_staking": kwargs.get("use_staking"), + "use_mech_marketplace": kwargs.get("use_mech_marketplace"), + "cost_of_bond": kwargs.get("cost_of_bond"), + "fund_requirements": { + "agent": kwargs.get("fund_requirements_agent"), + "safe": kwargs.get("fund_requirements_safe"), + }, + }, + }, + } + }, + "description": kwargs.get("description"), + "env_variables": {}, + "service_path": kwargs.get("service_path"), + "name": kwargs.get("name"), + } + + +get_expected_data = get_config_json_data_v4 + + +class TestService: + """Tests for services.service.Service class.""" + + @pytest.mark.parametrize( + "staking_program_id", ["staking_program_1", "staking_program_2"] + ) + @pytest.mark.parametrize("use_mech_marketplace", [True, False]) + @pytest.mark.parametrize("use_staking", [True, False]) + @pytest.mark.parametrize( + "get_config_json_data", + [get_config_json_data_v0, get_config_json_data_v2, get_config_json_data_v3], + ) + def test_service_migrate_format( + self, + get_config_json_data: t.Callable[..., t.Dict[str, t.Any]], + use_staking: bool, + use_mech_marketplace: bool, + staking_program_id: str, + tmp_path: Path, + ) -> None: + """Test services.service.Service.migrate_format()""" + + config_kwargs = DEFAULT_CONFIG_KWARGS.copy() + config_kwargs["use_staking"] = use_staking + config_kwargs["use_mech_marketplace"] = use_mech_marketplace + config_kwargs["staking_program"] = staking_program_id + old_config_json_data = get_config_json_data(**config_kwargs) + + # Emulate an existing service directory contents + service_config_dir = tmp_path / old_config_json_data.get( + "service_config_id", old_config_json_data.get("hash") + ) + service_config_dir.mkdir(parents=True, exist_ok=True) + + config_json_path = service_config_dir / "config.json" + with open(config_json_path, "w", encoding="utf-8") as file: + json.dump(old_config_json_data, file, indent=4) + + # Migrate the service using Service.migrate_format and read the resulting + # migrated data + Service.migrate_format(service_config_dir) + + migrated_config_dir = next(tmp_path.glob(f"{SERVICE_CONFIG_PREFIX}*/")) + new_config_json_path = migrated_config_dir / "config.json" + with open(new_config_json_path, "r", encoding="utf-8") as file: + migrated_data = json.load(file) + + # Construct the expected data + if old_config_json_data.get("version", 0) < 2: + config_kwargs["staking_program_id"] = "pearl_alpha" + + if old_config_json_data.get("version", 0) < 3: + config_kwargs["use_mech_marketplace"] = False + + if old_config_json_data.get("version", 0) < 4: + config_kwargs["description"] = config_kwargs["name"] + + config_kwargs["service_config_id"] = migrated_config_dir.name + config_kwargs["version"] = SERVICE_CONFIG_VERSION + config_kwargs["hash_timestamp"] = list(migrated_data["hash_history"].keys())[0] + config_kwargs["service_path"] = str(migrated_config_dir / "trader_pearl") + + expected_data = get_expected_data(**config_kwargs) + + diff = DeepDiff(migrated_data, expected_data) + if diff: + print(diff) + + assert not diff, "Migrated data does not match expected data." diff --git a/tests/test_wallet_master.py b/tests/test_wallet_master.py new file mode 100644 index 000000000..53b7a4b7b --- /dev/null +++ b/tests/test_wallet_master.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2024 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""Test for wallet.master module.""" diff --git a/tox.ini b/tox.ini index 88426bd93..e59dbb791 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,7 @@ skip_install = True deps = tomte[black]==0.2.15 commands = - black operate scripts tests + black operate scripts tests --exclude operate/data [testenv:black-check] skipsdist = True @@ -27,7 +27,7 @@ skip_install = True deps = tomte[black]==0.2.15 commands = - black --check operate scripts tests + black --check operate scripts tests --exclude operate/data [testenv:isort] skipsdist = True @@ -35,7 +35,7 @@ skip_install = True deps = tomte[isort]==0.2.15 commands = - isort operate/ scripts/ tests/ + isort operate/ scripts/ tests/ --skip operate/data [testenv:isort-check] skipsdist = True @@ -43,7 +43,7 @@ skip_install = True deps = tomte[isort]==0.2.15 commands = - isort --check-only --gitignore operate/ scripts/ tests/ + isort --check-only --gitignore operate/ scripts/ tests/ --skip operate/data [testenv:flake8] skipsdist = True @@ -136,6 +136,7 @@ exclude=.md, packages/valory/protocols/contract_api, packages/valory/protocols/http, packages/valory/protocols/ledger_api + operate/data/ max-line-length = 88 select = B,C,D,E,F,I,W, ignore = E203,E501,W503,D202,B014,D400,D401,DAR,B028,B017 @@ -161,6 +162,10 @@ sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER [mypy] strict_optional = True +exclude = ^(operate/operate_types\.py|scripts/setup_wallet\.py|operate/ledger/profiles\.py|operate/ledger/__init__\.py|operate/wallet/master\.py|operate/services/protocol\.py|operate/services/manage\.py|operate/cli\.py)$ + +[mypy-operate.*] +follow_imports = skip [mypy-typing_extentions.*] ignore_missing_imports = True @@ -218,3 +223,15 @@ ignore_missing_imports = True [mypy-eth_utils.*] ignore_missing_imports = True + +[mypy-pytest.*] +ignore_missing_imports = True + +[mypy-deepdiff.*] +ignore_missing_imports = True + +[testenv:unit-tests] +deps = + pytest==7.2.1 +commands = + pytest tests/ \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b8e7bcff5..684a3fb4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -124,10 +124,10 @@ ajv "^6.12.0" ajv-keywords "^3.4.1" -"@electron/asar@^3.2.1": - version "3.2.10" - resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.10.tgz#615cf346b734b23cafa4e0603551010bd0e50aa8" - integrity sha512-mvBSwIBUeiRscrCeJE1LwctAriBj65eUDm0Pc11iE5gRwzkmsdbS7FnZ1XUWjpSeQWL1L5g12Fc/SchPM9DUOw== +"@electron/asar@^3.2.7": + version "3.2.17" + resolved "https://registry.npmjs.org/@electron/asar/-/asar-3.2.17.tgz#91d28087aad80d1a1c8cc4e667c6476edf50f949" + integrity sha512-OcWImUI686w8LkghQj9R2ynZ2ME693Ek6L1SiaAgqGKzBaTIZw3fHDqN82Rcl+EU1Gm9EgkJ5KLIY/q5DCRbbA== dependencies: commander "^5.0.0" glob "^7.1.6" @@ -148,28 +148,19 @@ optionalDependencies: global-agent "^3.0.0" -"@electron/notarize@2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-2.2.1.tgz#d0aa6bc43cba830c41bfd840b85dbe0e273f59fe" - integrity sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg== - dependencies: - debug "^4.1.1" - fs-extra "^9.0.1" - promise-retry "^2.0.1" - -"@electron/notarize@^2.3.0": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-2.3.2.tgz#20a52a961747be8542a35003380988a0d3fe15e6" - integrity sha512-zfayxCe19euNwRycCty1C7lF7snk9YwfRpB5M8GLr1a4ICH63znxaPNAubrMvj0yDvVozqfgsdYpXVUnpWBDpg== +"@electron/notarize@2.5.0", "@electron/notarize@^2.5.0": + version "2.5.0" + resolved "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz#d4d25356adfa29df4a76bd64a8bd347237cd251e" + integrity sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A== dependencies: debug "^4.1.1" fs-extra "^9.0.1" promise-retry "^2.0.1" -"@electron/osx-sign@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@electron/osx-sign/-/osx-sign-1.0.5.tgz#0af7149f2fce44d1a8215660fd25a9fb610454d8" - integrity sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww== +"@electron/osx-sign@1.3.1": + version "1.3.1" + resolved "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz#faf7eeca7ca004a6be541dc4cf7a1bd59ec59b1c" + integrity sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw== dependencies: compare-version "^0.1.2" debug "^4.3.4" @@ -178,18 +169,38 @@ minimist "^1.2.6" plist "^3.0.5" -"@electron/universal@1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-1.5.1.tgz#f338bc5bcefef88573cf0ab1d5920fac10d06ee5" - integrity sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw== +"@electron/rebuild@3.6.1": + version "3.6.1" + resolved "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.6.1.tgz#59e8e36c3f6e6b94a699425dfb61f0394c3dd4df" + integrity sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w== dependencies: - "@electron/asar" "^3.2.1" - "@malept/cross-spawn-promise" "^1.1.0" + "@malept/cross-spawn-promise" "^2.0.0" + chalk "^4.0.0" + debug "^4.1.1" + detect-libc "^2.0.1" + fs-extra "^10.0.0" + got "^11.7.0" + node-abi "^3.45.0" + node-api-version "^0.2.0" + node-gyp "^9.0.0" + ora "^5.1.0" + read-binary-file-arch "^1.0.6" + semver "^7.3.5" + tar "^6.0.5" + yargs "^17.0.1" + +"@electron/universal@2.0.1": + version "2.0.1" + resolved "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz#7b070ab355e02957388f3dbd68e2c3cd08c448ae" + integrity sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA== + dependencies: + "@electron/asar" "^3.2.7" + "@malept/cross-spawn-promise" "^2.0.0" debug "^4.3.1" - dir-compare "^3.0.0" - fs-extra "^9.0.1" - minimatch "^3.0.4" - plist "^3.0.4" + dir-compare "^4.2.0" + fs-extra "^11.1.1" + minimatch "^9.0.3" + plist "^3.1.0" "@emotion/hash@^0.8.0": version "0.8.0" @@ -602,6 +613,11 @@ resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-5.0.19.tgz#680a71be6311e60df77c78fcdd941753886a59e4" integrity sha512-tVU77yjKnsoUotrXGYbbYxmL9nbm/MSo3deZietmf8V2FEDlbi9fvkJHMrYbo7ZsOqR1AYBBqRYmemz4pSE5Mg== +"@gar/promisify@^1.1.3": + version "1.1.3" + resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== + "@graphql-typed-document-node/core@^3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" @@ -638,10 +654,10 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@malept/cross-spawn-promise@^1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d" - integrity sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ== +"@malept/cross-spawn-promise@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz#d0772de1aa680a0bfb9ba2f32b4c828c7857cb9d" + integrity sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg== dependencies: cross-spawn "^7.0.1" @@ -929,6 +945,22 @@ "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" +"@npmcli/fs@^2.1.0": + version "2.1.2" + resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865" + integrity sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ== + dependencies: + "@gar/promisify" "^1.1.3" + semver "^7.3.5" + +"@npmcli/move-file@^2.0.0": + version "2.0.1" + resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz#26f6bdc379d87f75e55739bab89db525b06100e4" + integrity sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -1289,6 +1321,11 @@ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== +abbrev@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3, abstract-level@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.4.tgz#3ad8d684c51cc9cbc9cf9612a7100b716c414b57" @@ -1327,13 +1364,27 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -agent-base@6: +agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.1" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + +agentkeepalive@^4.2.1: + version "4.5.0" + resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1487,44 +1538,62 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -app-builder-bin@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-4.0.0.tgz#1df8e654bd1395e4a319d82545c98667d7eed2f0" - integrity sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA== +app-builder-bin@5.0.0-alpha.10: + version "5.0.0-alpha.10" + resolved "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz#cf12e593b6b847fb9d04027fa755c6c6610d778b" + integrity sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw== -app-builder-lib@24.13.3: - version "24.13.3" - resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-24.13.3.tgz#36e47b65fecb8780bb73bff0fee4e0480c28274b" - integrity sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig== +app-builder-lib@25.1.8: + version "25.1.8" + resolved "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-25.1.8.tgz#ae376039c5f269c7d562af494a087e5bc6310f1b" + integrity sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg== dependencies: "@develar/schema-utils" "~2.6.5" - "@electron/notarize" "2.2.1" - "@electron/osx-sign" "1.0.5" - "@electron/universal" "1.5.1" + "@electron/notarize" "2.5.0" + "@electron/osx-sign" "1.3.1" + "@electron/rebuild" "3.6.1" + "@electron/universal" "2.0.1" "@malept/flatpak-bundler" "^0.4.0" "@types/fs-extra" "9.0.13" async-exit-hook "^2.0.1" bluebird-lst "^1.0.9" - builder-util "24.13.1" - builder-util-runtime "9.2.4" + builder-util "25.1.7" + builder-util-runtime "9.2.10" chromium-pickle-js "^0.2.0" + config-file-ts "0.2.8-rc1" debug "^4.3.4" + dotenv "^16.4.5" + dotenv-expand "^11.0.6" ejs "^3.1.8" - electron-publish "24.13.1" + electron-publish "25.1.7" form-data "^4.0.0" fs-extra "^10.1.0" hosted-git-info "^4.1.0" is-ci "^3.0.0" isbinaryfile "^5.0.0" js-yaml "^4.1.0" + json5 "^2.2.3" lazy-val "^1.0.5" - minimatch "^5.1.1" - read-config-file "6.3.2" + minimatch "^10.0.0" + resedit "^1.7.0" sanitize-filename "^1.6.3" semver "^7.3.8" tar "^6.1.12" temp-file "^3.4.0" +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -1570,10 +1639,10 @@ atomically@^1.7.0: resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe" integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w== -axios@^1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" - integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== +axios@^1.7.7: + version "1.7.7" + resolved "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -1611,6 +1680,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + blakejs@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" @@ -1718,11 +1796,6 @@ buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== -buffer-equal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.1.tgz#2f7651be5b1b3f057fcd6e7ee16cf34767077d90" - integrity sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg== - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -1733,7 +1806,7 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer@^5.1.0: +buffer@^5.1.0, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -1749,6 +1822,14 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +builder-util-runtime@9.2.10: + version "9.2.10" + resolved "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz#a0f7d9e214158402e78b74a745c8d9f870c604bc" + integrity sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw== + dependencies: + debug "^4.3.4" + sax "^1.2.4" + builder-util-runtime@9.2.4: version "9.2.4" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz#13cd1763da621e53458739a1e63f7fcba673c42a" @@ -1757,22 +1838,22 @@ builder-util-runtime@9.2.4: debug "^4.3.4" sax "^1.2.4" -builder-util@24.13.1: - version "24.13.1" - resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-24.13.1.tgz#4a4c4f9466b016b85c6990a0ea15aa14edec6816" - integrity sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA== +builder-util@25.1.7: + version "25.1.7" + resolved "https://registry.npmjs.org/builder-util/-/builder-util-25.1.7.tgz#a07b404f0cb1a635aa165902be65297d58932ff8" + integrity sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww== dependencies: "7zip-bin" "~5.2.0" "@types/debug" "^4.1.6" - app-builder-bin "4.0.0" + app-builder-bin "5.0.0-alpha.10" bluebird-lst "^1.0.9" - builder-util-runtime "9.2.4" + builder-util-runtime "9.2.10" chalk "^4.1.2" cross-spawn "^7.0.3" debug "^4.3.4" fs-extra "^10.1.0" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.1" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" is-ci "^3.0.0" js-yaml "^4.1.0" source-map-support "^0.5.19" @@ -1791,6 +1872,30 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cacache@^16.1.0: + version "16.1.3" + resolved "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e" + integrity sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ== + dependencies: + "@npmcli/fs" "^2.1.0" + "@npmcli/move-file" "^2.0.0" + chownr "^2.0.0" + fs-minipass "^2.1.0" + glob "^8.0.1" + infer-owner "^1.0.4" + lru-cache "^7.7.1" + minipass "^3.1.6" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + mkdirp "^1.0.4" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^9.0.0" + tar "^6.1.11" + unique-filename "^2.0.0" + cacheable-lookup@^5.0.3: version "5.0.4" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" @@ -1925,6 +2030,18 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.2" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" @@ -1963,6 +2080,11 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -1995,6 +2117,11 @@ color-string@^1.6.0: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + color@^3.1.3: version "3.2.1" resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" @@ -2064,13 +2191,18 @@ conf@^10.2.0: pkg-up "^3.1.0" semver "^7.3.5" -config-file-ts@^0.2.4: - version "0.2.6" - resolved "https://registry.yarnpkg.com/config-file-ts/-/config-file-ts-0.2.6.tgz#b424ff74612fb37f626d6528f08f92ddf5d22027" - integrity sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w== +config-file-ts@0.2.8-rc1: + version "0.2.8-rc1" + resolved "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz#fb7fc6ccb2e313f69dbeb78f1db0b00038049de0" + integrity sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg== dependencies: - glob "^10.3.10" - typescript "^5.3.3" + glob "^10.3.12" + typescript "^5.4.3" + +console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== cookie@^0.4.1: version "0.4.2" @@ -2202,6 +2334,13 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + defer-to-connect@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" @@ -2230,11 +2369,21 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +detect-libc@^2.0.1: + version "2.0.3" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + detect-node@^2.0.4: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" @@ -2245,22 +2394,22 @@ diff@^5.2.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== -dir-compare@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-3.3.0.tgz#2c749f973b5c4b5d087f11edaae730db31788416" - integrity sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg== +dir-compare@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz#d1d4999c14fbf55281071fdae4293b3b9ce86f19" + integrity sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ== dependencies: - buffer-equal "^1.0.0" - minimatch "^3.0.4" + minimatch "^3.0.5" + p-limit "^3.1.0 " -dmg-builder@24.13.3: - version "24.13.3" - resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-24.13.3.tgz#95d5b99c587c592f90d168a616d7ec55907c7e55" - integrity sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ== +dmg-builder@25.1.8: + version "25.1.8" + resolved "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.1.8.tgz#41f3b725edd896156e891016a44129e1bd580430" + integrity sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ== dependencies: - app-builder-lib "24.13.3" - builder-util "24.13.1" - builder-util-runtime "9.2.4" + app-builder-lib "25.1.8" + builder-util "25.1.7" + builder-util-runtime "9.2.10" fs-extra "^10.1.0" iconv-lite "^0.6.2" js-yaml "^4.1.0" @@ -2310,21 +2459,18 @@ dotenv-expand@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== -dotenv-expand@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" - integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== +dotenv-expand@^11.0.6: + version "11.0.6" + resolved "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz#f2c840fd924d7c77a94eff98f153331d876882d3" + integrity sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g== + dependencies: + dotenv "^16.4.4" -dotenv@^16.3.0, dotenv@^16.4.5: +dotenv@^16.3.0, dotenv@^16.4.4, dotenv@^16.4.5: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== -dotenv@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05" - integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg== - duplexer@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -2342,20 +2488,19 @@ ejs@^3.1.8: dependencies: jake "^10.8.5" -electron-builder@^24.12.0: - version "24.13.3" - resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-24.13.3.tgz#c506dfebd36d9a50a83ee8aa32d803d83dbe4616" - integrity sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg== +electron-builder@^25.1.8: + version "25.1.8" + resolved "https://registry.npmjs.org/electron-builder/-/electron-builder-25.1.8.tgz#b0e310f1600787610bb84c3f39bc7aadb2548486" + integrity sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig== dependencies: - app-builder-lib "24.13.3" - builder-util "24.13.1" - builder-util-runtime "9.2.4" + app-builder-lib "25.1.8" + builder-util "25.1.7" + builder-util-runtime "9.2.10" chalk "^4.1.2" - dmg-builder "24.13.3" + dmg-builder "25.1.8" fs-extra "^10.1.0" is-ci "^3.0.0" lazy-val "^1.0.5" - read-config-file "6.3.2" simple-update-notifier "2.0.0" yargs "^17.6.2" @@ -2364,14 +2509,14 @@ electron-log@^5.1.4: resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-5.1.5.tgz#70d5051fc5ab7669b2592f53f72034867269c96e" integrity sha512-vuq10faUAxRbILgQx7yHoMObKZDEfj7hMSZrJPsVrDNeCpV/HN11dU7QuY4UDUe055pzBxhSCB3m0+6D3Aktjw== -electron-publish@24.13.1: - version "24.13.1" - resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-24.13.1.tgz#57289b2f7af18737dc2ad134668cdd4a1b574a0c" - integrity sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A== +electron-publish@25.1.7: + version "25.1.7" + resolved "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz#14e50c2a3fafdc1c454eadbbc47ead89a48bb554" + integrity sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg== dependencies: "@types/fs-extra" "^9.0.11" - builder-util "24.13.1" - builder-util-runtime "9.2.4" + builder-util "25.1.7" + builder-util-runtime "9.2.10" chalk "^4.1.2" fs-extra "^10.1.0" lazy-val "^1.0.5" @@ -2399,10 +2544,10 @@ electron-updater@^6.1.8: semver "^7.3.8" tiny-typed-emitter "^2.1.0" -electron@30.0.6: - version "30.0.6" - resolved "https://registry.yarnpkg.com/electron/-/electron-30.0.6.tgz#9ddea5f68396ecca88ad7c2c466a30fc9c16144b" - integrity sha512-PkhEPFdpYcTzjAO3gMHZ+map7g2+xCrMDedo/L1i0ir2BRXvAB93IkTJX497U6Srb/09r2cFt+k20VPNVCdw3Q== +electron@^33.2.0: + version "33.2.0" + resolved "https://registry.npmjs.org/electron/-/electron-33.2.0.tgz#2a7098653eaf1a53c7311a01d5636783019f2354" + integrity sha512-PVw1ICAQDPsnnsmpNFX/b1i/49h67pbSPxuIENd9K9WpGO1tsRaQt+K2bmXqTuoMJsbzIc75Ce8zqtuwBPqawA== dependencies: "@electron/get" "^2.0.0" "@types/node" "^20.9.0" @@ -2449,6 +2594,13 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== +encoding@^0.1.13: + version "0.1.13" + resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -2733,6 +2885,11 @@ evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" @@ -2917,6 +3074,15 @@ fs-extra@^10.0.0, fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^11.1.1: + version "11.2.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -2945,7 +3111,7 @@ fs-extra@^9.0.0, fs-extra@^9.0.1: jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^2.0.0: +fs-minipass@^2.0.0, fs-minipass@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== @@ -2972,6 +3138,20 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -3021,10 +3201,10 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^10.3.10: - version "10.4.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.3.tgz#e0ba2253dd21b3d0acdfb5d507c59a29f513fc7a" - integrity sha512-Q38SGlYRpVtDBPSWEylRyctn7uDeTp4NQERTLiCT1FqA9JXPYWqAVmQU6qh4r/zMM5ehxTcbaO8EjhWnvEhmyg== +glob@^10.3.12: + version "10.4.5" + resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: foreground-child "^3.1.0" jackspeak "^3.1.2" @@ -3033,7 +3213,7 @@ glob@^10.3.10: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" -glob@^7.1.3, glob@^7.1.6: +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3045,7 +3225,7 @@ glob@^7.1.3, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.1.0: +glob@^8.0.1, glob@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -3090,7 +3270,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -got@^11.8.5: +got@^11.7.0, got@^11.8.5: version "11.8.6" resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== @@ -3107,7 +3287,7 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.11: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3211,6 +3391,11 @@ has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + hash-base@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" @@ -3256,7 +3441,7 @@ hosted-git-info@^4.1.0: dependencies: lru-cache "^6.0.0" -http-cache-semantics@^4.0.0: +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -3281,6 +3466,14 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" +http-proxy-agent@^7.0.0: + version "7.0.2" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + http2-wrapper@^1.0.0-beta.5.2: version "1.0.3" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" @@ -3289,7 +3482,7 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" -https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: +https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== @@ -3297,6 +3490,21 @@ https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: agent-base "6" debug "4" +https-proxy-agent@^7.0.0: + version "7.0.5" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + iconv-corefoundation@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz#31065e6ab2c9272154c8b0821151e2c88f1b002a" @@ -3352,6 +3560,11 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== +infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3372,6 +3585,14 @@ io-ts@1.10.4: dependencies: fp-ts "^1.0.0" +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" + is-arrayish@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" @@ -3418,6 +3639,16 @@ is-hex-prefixed@1.0.0: resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-lambda@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -3504,6 +3735,11 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -3541,9 +3777,9 @@ json2mq@^0.2.0: dependencies: string-convert "^0.2.0" -json5@^2.2.0: +json5@^2.2.3: version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^2.1.0: @@ -3597,7 +3833,7 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== -lazy-val@^1.0.4, lazy-val@^1.0.5: +lazy-val@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d" integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q== @@ -3731,11 +3967,38 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@^7.7.1: + version "7.18.3" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== + lru_map@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== +make-fetch-happen@^10.0.3: + version "10.2.1" + resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164" + integrity sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w== + dependencies: + agentkeepalive "^4.2.1" + cacache "^16.1.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^7.7.1" + minipass "^3.1.6" + minipass-collect "^1.0.2" + minipass-fetch "^2.0.3" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + socks-proxy-agent "^7.0.0" + ssri "^9.0.0" + map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" @@ -3823,6 +4086,13 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== +minimatch@^10.0.0: + version "10.0.1" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -3830,14 +4100,14 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1, minimatch@^5.1.1, minimatch@^5.1.6: +minimatch@^5.0.1, minimatch@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.4: +minimatch@^9.0.3, minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== @@ -3849,7 +4119,46 @@ minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -minipass@^3.0.0: +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-fetch@^2.0.3: + version "2.1.2" + resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz#95560b50c472d81a3bc76f20ede80eaed76d8add" + integrity sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA== + dependencies: + minipass "^3.1.6" + minipass-sized "^1.0.3" + minizlib "^2.1.2" + optionalDependencies: + encoding "^0.1.13" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass-sized@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" + integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: version "3.3.6" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== @@ -3866,7 +4175,7 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== -minizlib@^2.1.1: +minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -3874,7 +4183,7 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mkdirp@^1.0.3: +mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -3922,7 +4231,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1, ms@^2.1.3: +ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -3942,6 +4251,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +negotiator@^0.6.3: + version "0.6.4" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + net@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/net/-/net-1.0.2.tgz#d1757ec9a7fb2371d83cf4755ce3e27e10829388" @@ -3970,6 +4284,13 @@ next@^14.2.3: "@next/swc-win32-ia32-msvc" "14.2.4" "@next/swc-win32-x64-msvc" "14.2.4" +node-abi@^3.45.0: + version "3.71.0" + resolved "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz#52d84bbcd8575efb71468fbaa1f9a49b2c242038" + integrity sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw== + dependencies: + semver "^7.3.5" + node-addon-api@^1.6.3: version "1.7.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" @@ -3980,6 +4301,13 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +node-api-version@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz#5177441da2b1046a4d4547ab9e0972eed7b1ac1d" + integrity sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg== + dependencies: + semver "^7.3.5" + node-fetch@^2.6.12: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -3992,6 +4320,30 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz#976d3ad905e71b76086f4f0b0d3637fe79b6cda5" integrity sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw== +node-gyp@^9.0.0: + version "9.4.1" + resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz#8a1023e0d6766ecb52764cc3a734b36ff275e185" + integrity sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ== + dependencies: + env-paths "^2.2.0" + exponential-backoff "^3.1.1" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^10.0.3" + nopt "^6.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + +nopt@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d" + integrity sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g== + dependencies: + abbrev "^1.0.0" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -4002,6 +4354,16 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== +npmlog@^6.0.0: + version "6.0.2" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -4026,7 +4388,7 @@ one-time@^1.0.0: dependencies: fn.name "1.x.x" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -4045,6 +4407,21 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +ora@^5.1.0: + version "5.4.1" + resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -4069,7 +4446,7 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.2, "p-limit@^3.1.0 ": version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -4177,6 +4554,11 @@ pbkdf2@^3.0.17: safe-buffer "^5.0.1" sha.js "^2.4.8" +pe-library@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz#e269be0340dcb13aa6949d743da7d658c3e2fbea" + integrity sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw== + pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -4199,7 +4581,7 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -plist@^3.0.4, plist@^3.0.5: +plist@^3.0.4, plist@^3.0.5, plist@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9" integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== @@ -4253,6 +4635,11 @@ progress@^2.0.3: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + promise-retry@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" @@ -4684,17 +5071,12 @@ react@^18.3.1: dependencies: loose-envify "^1.1.0" -read-config-file@6.3.2: - version "6.3.2" - resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-6.3.2.tgz#556891aa6ffabced916ed57457cb192e61880411" - integrity sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q== +read-binary-file-arch@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz#959c4637daa932280a9b911b1a6766a7e44288fc" + integrity sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg== dependencies: - config-file-ts "^0.2.4" - dotenv "^9.0.2" - dotenv-expand "^5.1.0" - js-yaml "^4.1.0" - json5 "^2.2.0" - lazy-val "^1.0.4" + debug "^4.3.4" readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" @@ -4727,6 +5109,13 @@ require-from-string@^2.0.0, require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +resedit@^1.7.0: + version "1.7.2" + resolved "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz#b1041170b99811710c13f949c7d225871de4cc78" + integrity sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA== + dependencies: + pe-library "^0.4.1" + resize-observer-polyfill@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" @@ -4756,6 +5145,14 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -4934,6 +5331,11 @@ serialize-javascript@^6.0.2: dependencies: randombytes "^2.1.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -4969,6 +5371,11 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +signal-exit@^3.0.2, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -4997,11 +5404,28 @@ slice-ansi@^3.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -smart-buffer@^4.0.2: +smart-buffer@^4.0.2, smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== +socks-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6" + integrity sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww== + dependencies: + agent-base "^6.0.2" + debug "^4.3.3" + socks "^2.6.2" + +socks@^2.6.2: + version "2.8.3" + resolved "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz#1ebd0f09c52ba95a09750afe3f3f9f724a800cb5" + integrity sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw== + dependencies: + ip-address "^9.0.5" + smart-buffer "^4.2.0" + solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -5042,11 +5466,18 @@ split@0.3: dependencies: through "2" -sprintf-js@^1.1.2: +sprintf-js@^1.1.2, sprintf-js@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== +ssri@^9.0.0: + version "9.0.1" + resolved "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057" + integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q== + dependencies: + minipass "^3.1.1" + stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -5086,7 +5517,16 @@ string-convert@^0.2.0: resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5111,7 +5551,14 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5205,7 +5652,7 @@ synckit@^0.8.6: "@pkgr/core" "^0.1.0" tslib "^2.6.2" -tar@^6.1.12: +tar@^6.0.5, tar@^6.1.11, tar@^6.1.12, tar@^6.1.2: version "6.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== @@ -5365,10 +5812,15 @@ type-fest@^2.17.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== -typescript@^5.3.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa" - integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ== +typescript@5.3.x: + version "5.3.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + +typescript@^5.4.3: + version "5.6.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== undici-types@~5.26.4: version "5.26.5" @@ -5382,6 +5834,20 @@ undici@^5.14.0: dependencies: "@fastify/busboy" "^2.0.0" +unique-filename@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz#e785f8675a9a7589e0ac77e0b5c34d2eaeac6da2" + integrity sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A== + dependencies: + unique-slug "^3.0.0" + +unique-slug@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz#6d347cf57c8a7a7a6044aabd0e2d74e4d76dc7c9" + integrity sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w== + dependencies: + imurmurhash "^0.1.4" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -5435,6 +5901,13 @@ verror@^1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -5448,13 +5921,20 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which@^2.0.1: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" +wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + winston-transport@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.0.tgz#e302e6889e6ccb7f383b926df6936a5b781bd1f0" @@ -5491,7 +5971,16 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -5577,7 +6066,7 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.6.2: +yargs@^17.0.1, yargs@^17.6.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==