From 6e33a9ac32244ad6ce86f111d5547995d68369d3 Mon Sep 17 00:00:00 2001 From: Mohan Date: Thu, 12 Sep 2024 17:20:59 +0530 Subject: [PATCH] feat: staging to main (#335) * initial win support * win: process kill fixes * win: tendermint installation automated * helthchecker env vars to switch it off. small refactoring * service hash id updated * use bundled in tendermint.exe, not download it * lint fixes * feat: add staking deployment vars * feat: added pearl beta 2 address & section * chore: add pearl beta 2 address * chore: init * chore: comment env example * fix: isNil check for low balance * fix: serviceFundRequirements coalesce * refactor: order and map staking contracts * fix: required olas when both staked and not staked * feat: update StakingContractSection to support multi-contract * feat: updated STAKING_PROGRAM_META with deprecated and supported migration targets * fix: isAddress checks to protect against 0xm * feat: added pearl_beta_2 to StakingContractInfo record * feat: add pearl_beta_2 Beta2 enum * chore: comment availableRewards until it's used * feat: extend serviceStakingMechUsageContracts with pearl_beta_2, protect against -1 serviceId * fix: protect against -1 serviceId related errors * feat: add pearl_beta_2 requirement * bump: rc124 for test release * add staking contract update button in homepage * update contract UI * update * win release updates * add loading state * workflow cleanup * fix: default contract fallback, instead of "not staked" * fix: broken import (kebabCase import) * bump: rc125 * win build poetry version bump * fix: added minimum staking duration to migration condition * fix for windows tendermint bundle in * fix: disable hash update * fix: migration countdown, and minimum duration fix from staging * fix: typos * refactor: popover copy * fix: typo * fix for tendermint PATH env vars * feat: Disable the staking contract button if the balance is low. (#317) * feat: disable staking contract button if low balance * feat: update staking contract button popover message * feat: add useNeedsFunds hook * feat: integrate useNeedsFunds hook for disable staking contract * update logic * refactor: remove OLAS requirement from notification * fix: commented link to broken site * feat: Staking info per contract (#325) * refractor: tiny format document * feat: add InfoBreakdown component * feat: replace OlasBalanceSection with BalanceBreakdown * refactor: Update InfoBreakdown component and add InfoBreakdownList * feat: add more contract methods for staking info * move from different function inside the main one (Autonolas.ts) * feat: add types * refactor: Update StakingContractSection component and add StakingContractInfo * other changes * feat: minor * feat: address Josh review changes * feat: Add balance polling pause functionality to StakingContractSection (#330) * bump: rc126 * hotfix: undefined fixes in useStakingContractInfo hook for build 126 * refactor: simplify logic, remove New tag * chore: remove redundant "New" objects * fix: remove commented mistakenly commented code * feat: Update backup wallet alert copy (#341) * feat: Add backup wallet warning message * update text * refactor: cleanup staking program parse from contract * chore: update minimum staking duration comment * feat: add loader to staking contract info provider * refactor: return loader from hook, rework comments, add service staked check * refactor: match active staking program type meta with active staking program type * refactor: rewrite staking contract section to consolidate, clean-up business logic * chore: delete huge comment block (cantMigrateReason) * fix: migrate button display logic * fix: Release 0.1.0-rc126 issues (#342) * Refactor SetupWelcome component to handle account setup state correctly * feat: trigger IPC call on app load (with commented code) * feat: remove all comments from main.js * Update frontend/components/ManageStakingPage/StakingContractSection/index.tsx * Update frontend/components/ManageStakingPage/StakingContractSection/index.tsx * Update frontend/components/ManageStakingPage/StakingContractSection/index.tsx Co-authored-by: Mohan * Update frontend/components/ManageStakingPage/StakingContractSection/index.tsx * chore: prettier fix * refactor: seperate CountdownUntilMigration * hotfix: update actions/upload-artifact to v4 * hotfix: update checkout and download-artifact actions to v4 * fix: add version prefix * bump: rc127 * refactor: numerous changes * chore: fix leftover `stakingProgram` references * chore: comment purpose * fix: migration and funding button validation * fix: migrate & funding button condition fixes * refactor: can't migrate reason copy * chore: leftover `stakingProgramId` refactor * fix: experienced bug where alpha showed during migration * fix: use Text component instead of span * fix: Badge "Active" status to be displayed only on active staking contract (#345) * fix StakingContractTag * fix * fix: reinstate #345 changes after overwrite due to merge conflicts * chore: better comment * Update frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx Co-authored-by: Mohan * Update frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx --------- Co-authored-by: Yuri (solarw) Turchenkov Co-authored-by: jmoreira-valory Co-authored-by: truemiller Co-authored-by: Josh Miller <31908788+truemiller@users.noreply.github.com> --- .env.example | 4 +- .github/workflows/backend.yml | 2 +- .github/workflows/common_checks.yml | 2 +- .github/workflows/release.yml | 8 +- .github/workflows/release_win.yml | 55 + Makefile | 58 ++ build-win-tenderly.js | 38 + build-win.js | 49 + electron/install.js | 79 +- electron/main.js | 26 +- electron/preload.js | 2 + electron/processes.js | 36 +- frontend/client/types.ts | 6 +- frontend/components/InfoBreakdown.tsx | 63 ++ .../MainPage/header/AgentButton.tsx | 26 +- frontend/components/MainPage/index.tsx | 8 +- .../MainPage/modals/MigrationModal.tsx | 6 +- .../MainPage/sections/GasBalanceSection.tsx | 5 + .../MainPage/sections/NeedsFundsSection.tsx | 80 +- .../MainPage/sections/OlasBalanceSection.tsx | 51 +- .../sections/StakingContractUpdate.tsx | 83 ++ .../CantMigrateAlert.tsx | 111 ++ .../CountdownUntilMigration.tsx | 69 ++ .../StakingContractSection/MigrateButton.tsx | 90 ++ .../StakingContractDetails.tsx | 58 ++ .../StakingContractFundingButton.tsx | 21 + .../StakingContractTag.tsx | 8 +- .../StakingContractSection/alerts.tsx | 69 -- .../StakingContractSection/index.tsx | 357 ++----- .../StakingContractSection/useMigrate.tsx | 165 +++ .../components/ManageStakingPage/index.tsx | 61 +- .../SettingsPage/DebugInfoSection.tsx | 6 +- .../SettingsStakingContractSection.tsx | 58 -- frontend/components/SettingsPage/index.tsx | 10 +- .../components/SetupPage/SetupWelcome.tsx | 20 +- frontend/constants/colors.ts | 1 + frontend/constants/contractAddresses.ts | 10 +- frontend/constants/serviceTemplates.ts | 6 +- frontend/constants/stakingProgramMeta.ts | 26 +- frontend/context/BalanceProvider.tsx | 12 +- frontend/context/ElectronApiProvider.tsx | 3 + frontend/context/RewardProvider.tsx | 10 +- .../context/StakingContractInfoProvider.tsx | 58 +- frontend/context/StakingProgramContext.tsx | 34 +- frontend/enums/StakingProgram.ts | 3 +- frontend/enums/StakingProgramStatus.ts | 1 - frontend/hooks/useNeedsFunds.ts | 71 ++ frontend/hooks/useStakingContractInfo.ts | 38 +- frontend/hooks/useStakingProgram.ts | 43 +- frontend/package.json | 2 +- frontend/pages/index.tsx | 4 + frontend/service/Autonolas.ts | 152 ++- frontend/service/Services.ts | 8 +- frontend/types/Autonolas.ts | 8 +- frontend/utils/service.ts | 27 +- operate/cli.py | 13 +- operate/ledger/__init__.py | 1 + operate/ledger/profiles.py | 1 + operate/services/deployment_runner.py | 57 +- operate/services/health_checker.py | 58 +- operate/services/manage.py | 33 +- operate/services/protocol.py | 24 + operate/services/service.py | 14 +- package.json | 2 +- poetry.lock | 950 ++++++++++-------- pyproject.toml | 2 +- templates/trader.yaml | 2 +- 67 files changed, 2181 insertions(+), 1283 deletions(-) create mode 100644 .github/workflows/release_win.yml create mode 100644 Makefile create mode 100644 build-win-tenderly.js create mode 100644 build-win.js create mode 100644 frontend/components/InfoBreakdown.tsx create mode 100644 frontend/components/MainPage/sections/StakingContractUpdate.tsx create mode 100644 frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx create mode 100644 frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx create mode 100644 frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx create mode 100644 frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx create mode 100644 frontend/components/ManageStakingPage/StakingContractSection/StakingContractFundingButton.tsx delete mode 100644 frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx create mode 100644 frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx delete mode 100644 frontend/components/SettingsPage/SettingsStakingContractSection.tsx create mode 100644 frontend/hooks/useNeedsFunds.ts diff --git a/.env.example b/.env.example index f6a88375f..cec7b1d2f 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,7 @@ -FORK_URL= NODE_ENV= +FORK_URL= DEV_RPC= + +# TODO: determine if these are needed STAKING_TEST_KEYS_PATH= IS_STAGING= diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index 24a790c4a..f2655da3c 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Node.js (for package scripts) - uses: actions/setup-node@v4 diff --git a/.github/workflows/common_checks.yml b/.github/workflows/common_checks.yml index f4258a3d2..df38258ba 100644 --- a/.github/workflows/common_checks.yml +++ b/.github/workflows/common_checks.yml @@ -15,7 +15,7 @@ jobs: python-version: ["3.10.9"] timeout-minutes: 30 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-python@master with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a07e5fe40..9ba0fd8c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,7 +54,7 @@ jobs: 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@v2 + uses: actions/upload-artifact@v4 with: name: pearl_${{ env.OS_ARCH }} path: dist/pearl_${{ env.OS_ARCH }} @@ -64,7 +64,7 @@ jobs: needs: - "build-macos-pyinstaller" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: "3.10" @@ -72,12 +72,12 @@ jobs: with: node-version: lts/* - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: pearl_x64 path: electron/bins/ - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: pearl_arm64 path: electron/bins/ diff --git a/.github/workflows/release_win.yml b/.github/workflows/release_win.yml new file mode 100644 index 000000000..4a3d3efeb --- /dev/null +++ b/.github/workflows/release_win.yml @@ -0,0 +1,55 @@ +name: Release for Windows + +on: + push: + tags: + - 'v*.*.*' + +jobs: + build-windows: + runs-on: windows-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - uses: actions/setup-node@v4 + with: + node-version: lts/* + + - name: Install and configure Poetry + uses: snok/install-poetry@v1 + with: + version: '1.8.3' + virtualenvs-create: true + virtualenvs-in-project: false + virtualenvs-path: ~/my-custom-path + installer-parallel: true + - name: Install dependencies + run: poetry install + + - name: install node deps + run: yarn install-deps + + - name: set env vars to prod.env + env: + NODE_ENV: production + DEV_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + IS_STAGING: ${{ github.ref != 'refs/heads/main' && 'true' || 'false' }} + FORK_URL: https://rpc-gate.autonolas.tech/gnosis-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 + cat prod.env + echo GH_TOKEN=$GH_TOKEN >> prod.env + - run: rm -rf /dist + - name: "Build, notarize, publish" + run: make build diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..5a766bb51 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ + +define setup_env + $(eval ENV_FILE := $(1).env) + @echo " - setup env $(ENV_FILE)" + $(eval include $(1).env) + $(eval export) +endef + + +./trader/: + pwd + git clone https://github.com/valory-xyz/trader.git + +./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 + cp -f trader/dist/trader_win.exe ./dist/aea_win.exe + pwd + + +./dist/tendermint_win.exe: ./operate/ + pwd + poetry install && poetry run pyinstaller operate/services/utils/tendermint.py --onefile --name tendermint_win + + +./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 + + +./electron/bins/: + mkdir -p ./electron/bins/ + +./electron/bins/tendermint.exe: ./electron/bins/ + curl -L https://github.com/tendermint/tendermint/releases/download/v0.34.19/tendermint_0.34.19_windows_amd64.tar.gz -o tendermint.tar.gz + tar -xvf tendermint.tar.gz tendermint.exe + cp ./tendermint.exe ./electron/bins/tendermint.exe + +.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 + + + + +.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 + GH_TOKEN=${GH_TOKEN} node build-win-tenderly.js \ No newline at end of file diff --git a/build-win-tenderly.js b/build-win-tenderly.js new file mode 100644 index 000000000..68fbdbbf4 --- /dev/null +++ b/build-win-tenderly.js @@ -0,0 +1,38 @@ +/** + * This script is used to build the electron app **with notarization**. It is used for the final build and release process. + */ +require('dotenv').config(); +const build = require('electron-builder').build; + +const { publishOptions } = require('./electron/constants'); + +const main = async () => { + console.log('Building...'); + + /** @type import {CliOptions} from "electron-builder" */ + await build({ + publish: 'onTag', + config: { + appId: 'xyz.valory.olas-operate-app', + artifactName: '${productName}-${version}-${platform}-${arch}-tenderly.${ext}', + productName: 'Pearl', + files: ['electron/**/*', 'package.json'], + directories: { + output: 'dist', + }, + nsis: { + oneClick: false, + }, + extraResources: [ + { + from: 'electron/bins', + to: 'bins', + filter: ['**/*'], + }, + ], + + }, + }); +}; + +main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); diff --git a/build-win.js b/build-win.js new file mode 100644 index 000000000..9427337c1 --- /dev/null +++ b/build-win.js @@ -0,0 +1,49 @@ +/** + * This script is used to build the electron app **with notarization**. It is used for the final build and release process. + */ +require('dotenv').config(); +const build = require('electron-builder').build; + +const { publishOptions } = require('./electron/constants'); + + +function artifactName() { + const env = process.env.NODE_ENV; + const prefix = env === 'production' ? '' : 'dev-'; + return prefix + '${productName}-${version}-${platform}-${arch}.${ext}'; +} + +const main = async () => { + console.log('Building...'); + + /** @type import {CliOptions} from "electron-builder" */ + await build({ + publish: 'onTag', + config: { + appId: 'xyz.valory.olas-operate-app', + artifactName: artifactName(), + productName: 'Pearl', + files: ['electron/**/*', 'package.json'], + directories: { + output: 'dist', + }, + nsis: { + oneClick: false, + }, + win: { + publish: publishOptions, + icon: 'electron/assets/icons/splash-robot-head-dock.png', + }, + extraResources: [ + { + from: 'electron/bins', + to: 'bins', + filter: ['**/*'], + }, + ], + + }, + }); +}; + +main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); diff --git a/electron/install.js b/electron/install.js index 861bf44ed..a117a78b3 100644 --- a/electron/install.js +++ b/electron/install.js @@ -6,15 +6,15 @@ const process = require('process'); const axios = require('axios'); const { spawnSync } = require('child_process'); const { logger } = require('./logger'); - +const { execSync} = require('child_process'); const { paths } = require('./constants'); - +const homedir = os.homedir(); /** * current version of the pearl release * - use "" (nothing as a suffix) for latest release candidate, for example "0.1.0rc26" * - use "alpha" for alpha release, for example "0.1.0rc26-alpha" */ -const OlasMiddlewareVersion = '0.1.0rc120'; +const OlasMiddlewareVersion = '0.1.0rc127'; const path = require('path'); const { app } = require('electron'); @@ -55,6 +55,21 @@ const TendermintUrls = { }, }; + +function execSyncExitCode(cmd) { + try { + execSync(cmd); + return 0; + } + 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()`. + return error.status; + } +} + function getBinPath(command) { return spawnSync('/usr/bin/which', [command], { env: Env }) .stdout?.toString() @@ -79,6 +94,7 @@ function runCmdUnix(command, options) { logger.electron(`===== stderr ===== \n${output.stderr}`); } + function runSudoUnix(command, options) { let bin = getBinPath(command); if (!bin) { @@ -113,6 +129,12 @@ function isTendermintInstalledUnix() { return Boolean(getBinPath('tendermint')); } +function isTendermintInstalledWindows() { + return true; + //always installed cause bundled in + return execSyncExitCode('tendermint --help') === 0; +} + async function downloadFile(url, dest) { const writer = fs.createWriteStream(dest); try { @@ -132,6 +154,41 @@ async function downloadFile(url, dest) { } } +async function installTendermintWindows() { + 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( + `Downloading ${url} to ${paths.tempDir}. This might take a while...`, + ); + await downloadFile(url, `${paths.tempDir}/tendermint.tar.gz`); + + 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() { logger.electron(`Installing tendermint for ${os.platform()}-${process.arch}`); const cwd = process.cwd(); @@ -202,8 +259,24 @@ async function setupUbuntu(ipcChannel) { } } + + +async function setupWindows(ipcChannel) { + logger.electron('Creating required directories'); + await createDirectory(`${paths.dotOperateDirectory}`); + await createDirectory(`${paths.tempDir}`); + + logger.electron('Checking tendermint installation: ' + isTendermintInstalledWindows()); + if (!isTendermintInstalledWindows()) { + ipcChannel.send('response', 'Installing tendermint'); + logger.electron('Installing tendermint'); + await installTendermintWindows(); + } +} + module.exports = { setupDarwin, setupUbuntu, + setupWindows, Env, }; diff --git a/electron/main.js b/electron/main.js index e60d56fd1..5216987e2 100644 --- a/electron/main.js +++ b/electron/main.js @@ -17,7 +17,7 @@ const http = require('http'); const AdmZip = require('adm-zip'); const { TRAY_ICONS, TRAY_ICONS_PATHS } = require('./icons'); -const { setupDarwin, setupUbuntu, Env } = require('./install'); +const { setupDarwin, setupUbuntu, setupWindows, Env } = require('./install'); const { paths } = require('./constants'); const { killProcesses } = require('./processes'); @@ -39,6 +39,9 @@ const binaryPaths = { arm64: 'bins/pearl_arm64', x64: 'bins/pearl_x64', }, + win32: { + x64: 'bins/pearl_win.exe', + }, }; let appConfig = { @@ -54,8 +57,12 @@ let appConfig = { }, }; +/** + * @type {BrowserWindow} + */ +let mainWindow; + let tray, - mainWindow, splashWindow, operateDaemon, operateDaemonPid, @@ -240,6 +247,14 @@ const createMainWindow = async () => { showNotification(title, description || undefined); }); + // if app (ie. mainWindow) is loaded, destroy splash window. + ipcMain.on('is-app-loaded', (_event, isLoaded) => { + if (isLoaded && splashWindow) { + splashWindow.destroy(); + splashWindow = null; + } + }); + mainWindow.webContents.on('did-fail-load', () => { mainWindow.webContents.reloadIgnoringCache(); }); @@ -258,7 +273,7 @@ const createMainWindow = async () => { event.preventDefault(); mainWindow.hide(); }); - + try { logger.electron('Setting up store IPC'); await setupStoreIpc(ipcMain, mainWindow); @@ -398,6 +413,7 @@ async function launchNextAppDev() { 'yarn', ['dev:frontend', '--port', appConfig.ports.dev.next], { + shell: true, env: { ...process.env, NEXT_PUBLIC_BACKEND_PORT: appConfig.ports.dev.operate, @@ -441,7 +457,7 @@ ipcMain.on('check', async function (event, _argument) { if (platform === 'darwin') { await setupDarwin(event.sender); } else if (platform === 'win32') { - // TODO + await setupWindows(event.sender); } else { await setupUbuntu(event.sender); } @@ -498,7 +514,6 @@ ipcMain.on('check', async function (event, _argument) { event.sender.send('response', 'Launching App'); await createMainWindow(); createTray(); - splashWindow.destroy(); } catch (e) { logger.electron(e); new Notification({ @@ -517,6 +532,7 @@ app.on('ready', async () => { path.join(__dirname, 'assets/icons/splash-robot-head-dock.png'), ); } + createSplashWindow(); }); diff --git a/electron/preload.js b/electron/preload.js index 2878e232e..562f49c72 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -1,6 +1,8 @@ const { contextBridge, ipcRenderer } = require('electron/renderer'); contextBridge.exposeInMainWorld('electronAPI', { + setIsAppLoaded: (isAppLoaded) => + ipcRenderer.send('is-app-loaded', isAppLoaded), closeApp: () => ipcRenderer.send('close-app'), minimizeApp: () => ipcRenderer.send('minimize-app'), setTrayIcon: (status) => ipcRenderer.send('tray', status), diff --git a/electron/processes.js b/electron/processes.js index e67dcaac5..faaa9266f 100644 --- a/electron/processes.js +++ b/electron/processes.js @@ -3,7 +3,7 @@ const { exec } = require('child_process'); const unixKillCommand = 'kill -9'; const windowsKillCommand = 'taskkill /F /PID'; - +const { logger } = require('./logger'); const isWindows = process.platform === 'win32'; function killProcesses(pid) { @@ -16,23 +16,29 @@ function killProcesses(pid) { // Array of PIDs to kill, starting with the children const pidsToKill = children.map((p) => p.PID); - pidsToKill.push(pid); // Also kill the main process + logger.info("Pids to kill " + JSON.stringify(pidsToKill)); const killCommand = isWindows ? windowsKillCommand : unixKillCommand; - const joinedCommand = pidsToKill - .map((pid) => `${killCommand} ${pid}`) - .join('; '); // Separate commands with a semicolon, so they run in sequence even if one fails. Also works on Windows. - - exec(joinedCommand, (err) => { - if ( - err?.message?.includes(isWindows ? 'not found' : 'No such process') - ) { - return; // Ignore errors for processes that are already dead - } - reject(err); - }); - resolve(); + let errors = []; + for (const ppid of pidsToKill) { + logger.info("kill: " + ppid); + exec(`${killCommand} ${ppid}`, (err) => { + logger.error("Pids to kill error:" + err); + if ( + err?.message?.includes(isWindows ? 'not found' : 'No such process') + ) { + return; // Ignore errors for processes that are already dead + } + errors.push(err); + }); + } + + if (errors.length === 0) { + reject(errors); + + + } else resolve(); }); }); } diff --git a/frontend/client/types.ts b/frontend/client/types.ts index fc5d7fe72..9b3c25ca7 100644 --- a/frontend/client/types.ts +++ b/frontend/client/types.ts @@ -1,4 +1,4 @@ -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; import { Chain, DeploymentStatus, Ledger } from './enums'; @@ -30,7 +30,7 @@ export type ChainData = { safe: number; }; nft: string; - staking_program_id: StakingProgram; + staking_program_id: StakingProgramId; threshold: number; use_staking: true; }; @@ -62,7 +62,7 @@ export type ServiceTemplate = { export type ConfigurationTemplate = { rpc?: string; // added on deployment - staking_program_id?: StakingProgram; // added on deployment + staking_program_id?: StakingProgramId; // added on deployment nft: string; agent_id: number; threshold: number; diff --git a/frontend/components/InfoBreakdown.tsx b/frontend/components/InfoBreakdown.tsx new file mode 100644 index 000000000..6fff80bc0 --- /dev/null +++ b/frontend/components/InfoBreakdown.tsx @@ -0,0 +1,63 @@ +import { CSSProperties, ReactNode } from 'react'; +import styled from 'styled-components'; + +import { COLOR } from '@/constants/colors'; + +type Size = 'small' | 'default' | 'large'; +type Color = 'default' | 'primary'; + +const Breakdown = styled.div` + display: flex; + flex-direction: column; +`; + +const BreakdownLine = styled.div<{ size?: Size }>` + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + font-size: ${({ size }: { size?: Size }) => { + switch (size) { + case 'small': + return '14px'; + case 'large': + return '16px'; + default: + return 'inherit'; + } + }}; + color: ${COLOR.TEXT}; + width: 100%; + gap: 12px; +`; + +const Line = styled.span<{ color?: Color }>` + flex: 1; + border-top: ${({ color }: { color?: Color }) => + `1px solid ${color === 'primary' ? COLOR.PURPLE_LIGHT : COLOR.BORDER_GRAY}`}; +`; + +type Info = { id?: number | string; left: ReactNode; right: ReactNode }; +type InfoBreakdownListProps = { + list: Info[]; + parentStyle?: CSSProperties; + size?: Size; + color?: Color; +}; + +export const InfoBreakdownList = ({ + list, + parentStyle, + size, + color, +}: InfoBreakdownListProps) => ( + + {list.map((item, index) => ( + + {item.left} + + {item.right} + + ))} + +); diff --git a/frontend/components/MainPage/header/AgentButton.tsx b/frontend/components/MainPage/header/AgentButton.tsx index 6fcdbdea0..06fd81b34 100644 --- a/frontend/components/MainPage/header/AgentButton.tsx +++ b/frontend/components/MainPage/header/AgentButton.tsx @@ -4,7 +4,6 @@ import { useCallback, useMemo } from 'react'; import { Chain, DeploymentStatus } from '@/client'; import { COLOR } from '@/constants/colors'; -import { StakingProgram } from '@/enums/StakingProgram'; import { useBalance } from '@/hooks/useBalance'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useServices } from '@/hooks/useServices'; @@ -108,7 +107,8 @@ const AgentNotRunningButton = () => { } = useBalance(); const { storeState } = useStore(); const { isEligibleForStaking, isAgentEvicted } = useStakingContractInfo(); - const { activeStakingProgram, defaultStakingProgram } = useStakingProgram(); + const { activeStakingProgramId, defaultStakingProgramId } = + useStakingProgram(); // const minStakingDeposit = // stakingContractInfoRecord?.[activeStakingProgram ?? defaultStakingProgram] @@ -116,7 +116,7 @@ const AgentNotRunningButton = () => { const requiredOlas = getMinimumStakedAmountRequired( serviceTemplate, - activeStakingProgram ?? defaultStakingProgram, + activeStakingProgramId ?? defaultStakingProgramId, ); const safeOlasBalance = safeBalance?.OLAS; @@ -155,7 +155,7 @@ const AgentNotRunningButton = () => { // Then create / deploy the service try { await ServicesService.createService({ - stakingProgram: activeStakingProgram ?? defaultStakingProgram, // overwrite with StakingProgram.Alpha to test migration + stakingProgramId: activeStakingProgramId ?? defaultStakingProgramId, // overwrite with StakingProgram.Alpha to test migration serviceTemplate, deploy: true, }); @@ -170,18 +170,7 @@ const AgentNotRunningButton = () => { // Show success notification based on whether there was a service prior to starting try { - if (!service) { - showNotification?.('Your agent is now running!'); - } else { - const minimumStakedAmountRequired = getMinimumStakedAmountRequired( - serviceTemplate, - StakingProgram.Beta, // users should always deploy on Beta if they are yet to start their agent - ); - - showNotification?.( - `Your agent is running and you've staked ${minimumStakedAmountRequired} OLAS!`, - ); - } + showNotification?.(`Your agent is running!`); } catch (error) { console.error(error); showNotification?.('Error while showing "running" notification'); @@ -199,10 +188,9 @@ const AgentNotRunningButton = () => { setServiceStatus, masterSafeAddress, showNotification, - activeStakingProgram, - defaultStakingProgram, + activeStakingProgramId, + defaultStakingProgramId, serviceTemplate, - service, ]); const isDeployable = useMemo(() => { diff --git a/frontend/components/MainPage/index.tsx b/frontend/components/MainPage/index.tsx index f97acf159..9fb839e36 100644 --- a/frontend/components/MainPage/index.tsx +++ b/frontend/components/MainPage/index.tsx @@ -3,7 +3,7 @@ import { Button, Card, Flex } from 'antd'; import { useEffect } from 'react'; import { Pages } from '@/enums/PageState'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { useBalance } from '@/hooks/useBalance'; import { usePageState } from '@/hooks/usePageState'; import { useServices } from '@/hooks/useServices'; @@ -17,12 +17,13 @@ import { MainNeedsFunds } from './sections/NeedsFundsSection'; import { NewStakingProgramAlertSection } from './sections/NewStakingProgramAlertSection'; import { MainOlasBalance } from './sections/OlasBalanceSection'; import { MainRewards } from './sections/RewardsSection'; +import { StakingContractUpdate } from './sections/StakingContractUpdate'; export const Main = () => { const { goto } = usePageState(); const { updateServicesState } = useServices(); const { updateBalances, isLoaded, setIsLoaded } = useBalance(); - const { activeStakingProgram: currentStakingProgram } = useStakingProgram(); + const { activeStakingProgramId: currentStakingProgram } = useStakingProgram(); useEffect(() => { if (!isLoaded) { @@ -53,12 +54,13 @@ export const Main = () => { style={{ borderTopColor: 'transparent' }} > - {currentStakingProgram === StakingProgram.Alpha && ( + {currentStakingProgram === StakingProgramId.Alpha && ( )} + diff --git a/frontend/components/MainPage/modals/MigrationModal.tsx b/frontend/components/MainPage/modals/MigrationModal.tsx index 30b3b2e08..026cbd203 100644 --- a/frontend/components/MainPage/modals/MigrationModal.tsx +++ b/frontend/components/MainPage/modals/MigrationModal.tsx @@ -12,15 +12,15 @@ export const MigrationSuccessModal = ({ open: boolean; onClose: () => void; }) => { - const { activeStakingProgram } = useStakingProgram(); + const { activeStakingProgramId } = useStakingProgram(); // Close modal if no active staking program, migration doesn't apply to non-stakers - if (!activeStakingProgram) { + if (!activeStakingProgramId) { onClose(); return null; } - const activeStakingProgramMeta = STAKING_PROGRAM_META[activeStakingProgram]; + const activeStakingProgramMeta = STAKING_PROGRAM_META[activeStakingProgramId]; return ( { ]); const status = useMemo(() => { + if (isNil(isLowBalance)) { + return { statusName: 'Loading...', StatusComponent: EmptyDot }; + } + if (isLowBalance) { return { statusName: 'Too low', StatusComponent: EmptyDot }; } diff --git a/frontend/components/MainPage/sections/NeedsFundsSection.tsx b/frontend/components/MainPage/sections/NeedsFundsSection.tsx index 08ae82696..71d0604fe 100644 --- a/frontend/components/MainPage/sections/NeedsFundsSection.tsx +++ b/frontend/components/MainPage/sections/NeedsFundsSection.tsx @@ -1,16 +1,11 @@ import { Flex, Typography } from 'antd'; -import { formatUnits } from 'ethers/lib/utils'; import { ReactNode, useEffect, useMemo } from 'react'; import styled from 'styled-components'; import { CustomAlert } from '@/components/Alert'; -import { CHAINS } from '@/constants/chains'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { useBalance } from '@/hooks/useBalance'; import { useElectronApi } from '@/hooks/useElectronApi'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; -import { useStore } from '@/hooks/useStore'; -import { getMinimumStakedAmountRequired } from '@/utils/service'; +import { useNeedsFunds } from '@/hooks/useNeedsFunds'; import { CardSection } from '../../styled/CardSection'; @@ -24,86 +19,17 @@ const FundingValue = styled.div` letter-spacing: -0.72px; `; -const useNeedsFunds = () => { - const { getServiceTemplates } = useServiceTemplates(); - - const serviceTemplate = useMemo( - () => getServiceTemplates()[0], - [getServiceTemplates], - ); - - const { storeState } = useStore(); - const { safeBalance, totalOlasStakedBalance } = useBalance(); - - const isInitialFunded = storeState?.isInitialFunded; - - const serviceFundRequirements = useMemo(() => { - const monthlyGasEstimate = Number( - formatUnits( - `${serviceTemplate.configurations[CHAINS.GNOSIS.chainId].monthly_gas_estimate}`, - 18, - ), - ); - - const minimumStakedAmountRequired = - getMinimumStakedAmountRequired(serviceTemplate); - - return { - eth: monthlyGasEstimate, - olas: minimumStakedAmountRequired, - }; - }, [serviceTemplate]); - - const hasEnoughEthForInitialFunding = useMemo( - () => (safeBalance?.ETH || 0) >= (serviceFundRequirements?.eth || 0), - [serviceFundRequirements?.eth, safeBalance], - ); - - const hasEnoughOlasForInitialFunding = useMemo(() => { - const olasInSafe = safeBalance?.OLAS || 0; - const olasStakedBySafe = totalOlasStakedBalance || 0; - - const olasInSafeAndStaked = olasInSafe + olasStakedBySafe; - - return olasInSafeAndStaked >= serviceFundRequirements.olas; - }, [ - safeBalance?.OLAS, - totalOlasStakedBalance, - serviceFundRequirements?.olas, - ]); - - return { - hasEnoughEthForInitialFunding, - hasEnoughOlasForInitialFunding, - serviceFundRequirements, - isInitialFunded, - }; -}; - export const MainNeedsFunds = () => { - const { isBalanceLoaded } = useBalance(); const { hasEnoughEthForInitialFunding, hasEnoughOlasForInitialFunding, serviceFundRequirements, isInitialFunded, + needsInitialFunding, } = useNeedsFunds(); const electronApi = useElectronApi(); - const isVisible: boolean = useMemo(() => { - if (isInitialFunded) return false; - if (!isBalanceLoaded) return false; - if (hasEnoughEthForInitialFunding && hasEnoughOlasForInitialFunding) - return false; - return true; - }, [ - hasEnoughEthForInitialFunding, - hasEnoughOlasForInitialFunding, - isBalanceLoaded, - isInitialFunded, - ]); - const message: ReactNode = useMemo( () => ( @@ -152,7 +78,7 @@ export const MainNeedsFunds = () => { isInitialFunded, ]); - if (!isVisible) return null; + if (!needsInitialFunding) return null; return ( diff --git a/frontend/components/MainPage/sections/OlasBalanceSection.tsx b/frontend/components/MainPage/sections/OlasBalanceSection.tsx index 0c5571da1..8b8dfd9ae 100644 --- a/frontend/components/MainPage/sections/OlasBalanceSection.tsx +++ b/frontend/components/MainPage/sections/OlasBalanceSection.tsx @@ -4,7 +4,7 @@ import { useMemo } from 'react'; import styled from 'styled-components'; import { CustomAlert } from '@/components/Alert'; -import { COLOR } from '@/constants/colors'; +import { InfoBreakdownList } from '@/components/InfoBreakdown'; import { UNICODE_SYMBOLS } from '@/constants/symbols'; import { LOW_MASTER_SAFE_BALANCE } from '@/constants/thresholds'; import { useBalance } from '@/hooks/useBalance'; @@ -20,40 +20,7 @@ const Balance = styled.span` letter-spacing: -2px; margin-right: 4px; `; -const BalanceBreakdown = styled.div` - padding: 4px; -`; -const BalanceBreakdownLine = styled.div` - position: relative; - display: flex; - align-items: center; - justify-content: space-between; - font-size: 14px; - color: ${COLOR.TEXT}; - - > span { - background: ${COLOR.WHITE}; - z-index: 1; - &:first-child { - padding-right: 6px; - } - &:last-child { - padding-left: 6px; - } - } - &:before { - content: ''; - position: absolute; - bottom: 6px; - width: 100%; - border-bottom: 2px dotted ${COLOR.BORDER_GRAY}; - } - - &:not(:last-child) { - margin-bottom: 8px; - } -`; const OVERLAY_STYLE = { maxWidth: '300px', width: '300px' }; const CurrentBalance = () => { @@ -91,14 +58,14 @@ const CurrentBalance = () => { placement="bottom" overlayStyle={OVERLAY_STYLE} title={ - - {balances.map((item, index) => ( - - {item.title} - {item.value} OLAS - - ))} - + ({ + left: item.title, + right: `${item.value} OLAS`, + }))} + size="small" + parentStyle={{ padding: 4, gap: 8 }} + /> } > diff --git a/frontend/components/MainPage/sections/StakingContractUpdate.tsx b/frontend/components/MainPage/sections/StakingContractUpdate.tsx new file mode 100644 index 000000000..b769c4702 --- /dev/null +++ b/frontend/components/MainPage/sections/StakingContractUpdate.tsx @@ -0,0 +1,83 @@ +import { RightOutlined } from '@ant-design/icons'; +import { Button, Flex, Popover, Skeleton, Typography } from 'antd'; +import { useMemo } from 'react'; + +import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; +import { Pages } from '@/enums/PageState'; +import { useBalance } from '@/hooks/useBalance'; +import { useNeedsFunds } from '@/hooks/useNeedsFunds'; +import { usePageState } from '@/hooks/usePageState'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; + +import { CardSection } from '../../styled/CardSection'; + +const { Text } = Typography; + +export const StakingContractUpdate = () => { + const { goto } = usePageState(); + const { isBalanceLoaded, isLowBalance } = useBalance(); + const { needsInitialFunding } = useNeedsFunds(); + const { + activeStakingProgramMeta, + isActiveStakingProgramLoaded, + defaultStakingProgramId, + } = useStakingProgram(); + + const stakingContractName = useMemo(() => { + if (activeStakingProgramMeta) return activeStakingProgramMeta.name; + return STAKING_PROGRAM_META[defaultStakingProgramId].name; + }, [activeStakingProgramMeta, defaultStakingProgramId]); + + const canUpdateStakingContract = useMemo(() => { + if (!isBalanceLoaded) return false; + if (isLowBalance) return false; + if (needsInitialFunding) return false; + return true; + }, [isBalanceLoaded, isLowBalance, needsInitialFunding]); + + const stakingButton = useMemo(() => { + if (!isActiveStakingProgramLoaded) return ; + return ( + + ); + }, [ + goto, + isActiveStakingProgramLoaded, + stakingContractName, + canUpdateStakingContract, + ]); + + return ( + + + Staking contract + + {canUpdateStakingContract ? ( + stakingButton + ) : ( + Fund your agent to manage staking contracts} + > + {stakingButton} + + )} + + + ); +}; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx b/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx new file mode 100644 index 000000000..52b23737c --- /dev/null +++ b/frontend/components/ManageStakingPage/StakingContractSection/CantMigrateAlert.tsx @@ -0,0 +1,111 @@ +import { Flex, Typography } from 'antd'; +import { isNil } from 'lodash'; + +import { CustomAlert } from '@/components/Alert'; +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 { CantMigrateReason } from './useMigrate'; + +const { Text } = Typography; + +type CantMigrateAlertProps = { stakingProgramId: StakingProgramId }; + +const AlertInsufficientMigrationFunds = ({ + stakingProgramId, +}: CantMigrateAlertProps) => { + const { serviceTemplate } = useServiceTemplates(); + const { isServiceStaked } = useStakingContractInfo(); + const { safeBalance, totalOlasStakedBalance } = useBalance(); + + const totalOlasRequiredForStaking = getMinimumStakedAmountRequired( + serviceTemplate, + stakingProgramId, + ); + + if (isNil(totalOlasRequiredForStaking)) return null; + if (isNil(safeBalance?.OLAS)) return null; + if (isNil(totalOlasStakedBalance)) return null; + + const requiredOlasDeposit = isServiceStaked + ? totalOlasRequiredForStaking - (totalOlasStakedBalance + safeBalance.OLAS) // when staked + : totalOlasRequiredForStaking - safeBalance.OLAS; // when not staked + + return ( + + + An additional {requiredOlasDeposit} OLAS is required to switch + + + Add {requiredOlasDeposit} OLAS to your account to + meet the contract requirements and switch. + + + } + /> + ); +}; + +const AlertNoSlots = () => ( + No slots currently available - try again later.} + /> +); + +// TODO: uncomment when required +// +// const AlertUpdateToMigrate = () => ( +// +// App update required + +// {/* +// TODO: Define version requirement in some JSON store? +// How do we access this date on a previous version? +// */} +// +// Update Pearl to the latest version to switch to the staking contract. +// +// {/* TODO: trigger update through IPC */} +// +// Update Pearl to the latest version {UNICODE_SYMBOLS.EXTERNAL_LINK} +// +// +// } +// /> +// ); + +/** + * Displays alerts for specific non-migration reasons + */ +export const CantMigrateAlert = ({ + stakingProgramId, + cantMigrateReason, +}: { + stakingProgramId: StakingProgramId; + cantMigrateReason: CantMigrateReason; +}) => { + if (cantMigrateReason === CantMigrateReason.NoAvailableStakingSlots) { + return ; + } + + if (cantMigrateReason === CantMigrateReason.InsufficientOlasToMigrate) { + return ( + + ); + } + + return null; +}; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx b/frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx new file mode 100644 index 000000000..d8f71c07a --- /dev/null +++ b/frontend/components/ManageStakingPage/StakingContractSection/CountdownUntilMigration.tsx @@ -0,0 +1,69 @@ +import { Flex, Typography } from 'antd'; +import { isNil } from 'lodash'; +import { useState } from 'react'; +import { useInterval } from 'usehooks-ts'; + +import { StakingContractInfo } from '@/types/Autonolas'; + +const { Text } = Typography; + +export const CountdownUntilMigration = ({ + activeStakingContractInfo, +}: { + activeStakingContractInfo: Partial; +}) => { + const [secondsUntilReady, setSecondsUntilMigration] = useState(); + + useInterval(() => { + if (!activeStakingContractInfo) return; + + const { serviceStakingStartTime, minimumStakingDuration } = + activeStakingContractInfo; + + if (isNil(minimumStakingDuration)) return; + if (isNil(serviceStakingStartTime)) return; + + const now = Math.round(Date.now() / 1000); + const timeSinceLastStaked = now - serviceStakingStartTime; + + const timeUntilMigration = minimumStakingDuration - timeSinceLastStaked; + + if (timeUntilMigration < 0) { + setSecondsUntilMigration(0); + return; + } + + setSecondsUntilMigration(timeUntilMigration); + }, 1000); + + const countdownDisplay = isNil(secondsUntilReady) + ? 'Loading...' + : 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 + {countdownDisplay} + + ); +}; + +const countdownDisplayFormat = (totalSeconds: number) => { + const days = Math.floor(totalSeconds / (24 * 3600)); + totalSeconds %= 24 * 3600; + + const hours = Math.floor(totalSeconds / 3600); + totalSeconds %= 3600; + + const minutes = Math.floor(totalSeconds / 60); + const seconds = totalSeconds % 60; + + // Ensure double digits for hours, minutes, and seconds + const formattedHours = String(hours).padStart(2, '0'); + const formattedMinutes = String(minutes).padStart(2, '0'); + const formattedSeconds = String(seconds).padStart(2, '0'); + // TODO: update this support plural and singular text + return `${days} days ${formattedHours} hours ${formattedMinutes} minutes ${formattedSeconds} seconds`; +}; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx new file mode 100644 index 000000000..5d1c33473 --- /dev/null +++ b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx @@ -0,0 +1,90 @@ +import { Button, Popover } from 'antd'; +import { isNil } from 'lodash'; +import { useMemo } from 'react'; + +import { DeploymentStatus } from '@/client'; +import { Pages } from '@/enums/PageState'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { useBalance } from '@/hooks/useBalance'; +import { useModals } from '@/hooks/useModals'; +import { usePageState } from '@/hooks/usePageState'; +import { useServices } from '@/hooks/useServices'; +import { useServiceTemplates } from '@/hooks/useServiceTemplates'; +import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; +import { ServicesService } from '@/service/Services'; + +import { CountdownUntilMigration } from './CountdownUntilMigration'; +import { CantMigrateReason, useMigrate } from './useMigrate'; + +type MigrateButtonProps = { + stakingProgramId: StakingProgramId; +}; +export const MigrateButton = ({ stakingProgramId }: MigrateButtonProps) => { + const { goto } = usePageState(); + const { serviceTemplate } = useServiceTemplates(); + const { setIsServicePollingPaused, setServiceStatus, updateServiceStatus } = + useServices(); + const { setIsPaused: setIsBalancePollingPaused } = useBalance(); + const { updateActiveStakingProgramId: updateStakingProgram } = + useStakingProgram(); + const { activeStakingContractInfo } = useStakingContractInfo(); + const { setMigrationModalOpen } = useModals(); + + const { migrateValidation } = useMigrate(stakingProgramId); + + const popoverContent = useMemo(() => { + if (migrateValidation.canMigrate) return null; + + if ( + migrateValidation.reason === + CantMigrateReason.NotStakedForMinimumDuration && + !isNil(activeStakingContractInfo) + ) { + return ( + + ); + } + + return migrateValidation.reason; + }, [activeStakingContractInfo, migrateValidation]); + + return ( + + + + ); +}; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx new file mode 100644 index 000000000..6ff75f3ab --- /dev/null +++ b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractDetails.tsx @@ -0,0 +1,58 @@ +import { Alert, Skeleton } from 'antd'; +import { useMemo } from 'react'; + +import { InfoBreakdownList } from '@/components/InfoBreakdown'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; + +export const StakingContractDetails = ({ + stakingProgramId, +}: { + stakingProgramId: StakingProgramId; +}) => { + const { stakingContractInfoRecord } = useStakingContractInfo(); + + const balances = useMemo(() => { + if (!stakingContractInfoRecord) return null; + if (!stakingProgramId) return null; + if (!stakingContractInfoRecord?.[stakingProgramId]) return null; + + const details = stakingContractInfoRecord[stakingProgramId]; + return [ + { + left: 'Rewards per work period', + right: `~ ${details.rewardsPerWorkPeriod?.toFixed(2)} OLAS`, + }, + { + left: 'Annual percentage Yield (APY)', + right: `${details.apy}%`, + }, + { + left: 'Required OLAS for staking', + right: `${details.olasStakeRequired} OLAS`, + }, + ]; + }, [stakingContractInfoRecord, stakingProgramId]); + + if (!stakingContractInfoRecord) { + return ; + } + + if (!balances) { + return ( + + ); + } + + return ( + + ); +}; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractFundingButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractFundingButton.tsx new file mode 100644 index 000000000..4a4837a46 --- /dev/null +++ b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractFundingButton.tsx @@ -0,0 +1,21 @@ +import { Button } from 'antd'; +import { useState } from 'react'; + +import { OpenAddFundsSection } from '@/components/MainPage/sections/AddFundsSection'; + +export const StakingContractFundingButton = () => { + const [isFundingSectionOpen, setIsFundingSectionOpen] = useState(false); + + return ( + <> + + {isFundingSectionOpen && } + + ); +}; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractTag.tsx b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractTag.tsx index b09c11a05..cd9e525df 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/StakingContractTag.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/StakingContractTag.tsx @@ -5,12 +5,10 @@ import { StakingProgramStatus } from '@/enums/StakingProgramStatus'; export const StakingContractTag = ({ status, }: { - status?: StakingProgramStatus; + status: StakingProgramStatus | null; }) => { - if (status === StakingProgramStatus.New) { - return New; - } else if (status === StakingProgramStatus.Selected) { - return Selected; + if (status === StakingProgramStatus.Selected) { + return Active; } return null; }; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx b/frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx deleted file mode 100644 index 7df340884..000000000 --- a/frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { Flex, Typography } from 'antd'; - -import { CustomAlert } from '@/components/Alert'; -import { UNICODE_SYMBOLS } from '@/constants/symbols'; - -const { Text } = Typography; - -export const AlertInsufficientMigrationFunds = ({ - masterSafeOlasBalance, - stakedOlasBalance, - totalOlasRequiredForStaking, -}: { - masterSafeOlasBalance: number; - stakedOlasBalance: number; - totalOlasRequiredForStaking: number; -}) => { - const requiredOlasDeposit = - totalOlasRequiredForStaking - (stakedOlasBalance + masterSafeOlasBalance); - - return ( - - - An additional {requiredOlasDeposit} OLAS is required to switch - - - Add {requiredOlasDeposit} OLAS to your account to - meet the contract requirements and switch. - - - } - /> - ); -}; - -export const AlertNoSlots = () => ( - No slots currently available - try again later.} - /> -); - -export const AlertUpdateToMigrate = () => ( - - App update required - - {/* - TODO: Define version requirement in some JSON store? - How do we access this date on a previous version? - */} - - Update Pearl to the latest version to switch to the staking contract. - - {/* TODO: trigger update through IPC */} - - Update Pearl to the latest version {UNICODE_SYMBOLS.EXTERNAL_LINK} - - - } - /> -); diff --git a/frontend/components/ManageStakingPage/StakingContractSection/index.tsx b/frontend/components/ManageStakingPage/StakingContractSection/index.tsx index 1971f8cc8..c0e7aa048 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/index.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/index.tsx @@ -1,341 +1,108 @@ -import { Button, Flex, Popover, theme, Typography } from 'antd'; -import { useMemo, useState } from 'react'; +import { Flex, theme, Typography } from 'antd'; +import { useMemo } from 'react'; -import { Chain, DeploymentStatus } from '@/client'; -import { OpenAddFundsSection } from '@/components/MainPage/sections/AddFundsSection'; +import { Chain } 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 { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { Pages } from '@/enums/PageState'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { StakingProgramStatus } from '@/enums/StakingProgramStatus'; -import { useBalance } from '@/hooks/useBalance'; -import { useModals } from '@/hooks/useModals'; -import { usePageState } from '@/hooks/usePageState'; -import { useServices } from '@/hooks/useServices'; -import { useServiceTemplates } from '@/hooks/useServiceTemplates'; -import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; import { useStakingProgram } from '@/hooks/useStakingProgram'; -import { ServicesService } from '@/service/Services'; -import { getMinimumStakedAmountRequired } from '@/utils/service'; -import { - AlertInsufficientMigrationFunds, - AlertNoSlots, - AlertUpdateToMigrate, -} from './alerts'; +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 { Text } = Typography; - +const { Title } = Typography; const { useToken } = theme; -// const CustomDivider = styled(Divider)` -// flex: auto; -// width: max-content; -// min-width: 0; -// margin: 0; -// `; - -// const ContractParameter = ({ -// label, -// value, -// }: { -// label: string; -// value: string; -// }) => ( -// -// {label} -// -// {value} -// -// ); - +type StakingContractSectionProps = { stakingProgramId: StakingProgramId }; export const StakingContractSection = ({ - stakingProgram, -}: { - stakingProgram: StakingProgram; -}) => { - const { goto } = usePageState(); - const { - setServiceStatus, - serviceStatus, - setIsServicePollingPaused, - updateServiceStatus, - } = useServices(); - const { serviceTemplate } = useServiceTemplates(); - const { setMigrationModalOpen } = useModals(); - const { activeStakingProgram, defaultStakingProgram, updateStakingProgram } = + stakingProgramId, +}: StakingContractSectionProps) => { + const { activeStakingProgramId, defaultStakingProgramId } = useStakingProgram(); + const { token } = useToken(); - const { safeBalance, totalOlasStakedBalance, isBalanceLoaded } = useBalance(); - const { isServiceStakedForMinimumDuration, stakingContractInfoRecord } = - useStakingContractInfo(); - const [isFundingSectionOpen, setIsFundingSectionOpen] = useState(false); + + const { migrateValidation } = useMigrate(stakingProgramId); const stakingContractAddress = SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS][ - stakingProgram + stakingProgramId ]; - const stakingContractInfoForStakingProgram = - stakingContractInfoRecord?.[stakingProgram]; - - const activeStakingProgramMeta = STAKING_PROGRAM_META[stakingProgram]; - - const isSelected = - activeStakingProgram && activeStakingProgram === stakingProgram; - - const hasEnoughRewards = true; - //(stakingContractInfoForStakingProgram?.availableRewards ?? 0) > 0; - - const minimumOlasRequiredToMigrate = useMemo( - () => getMinimumStakedAmountRequired(serviceTemplate, StakingProgram.Beta), - [serviceTemplate], - ); - - const hasEnoughOlasToMigrate = useMemo(() => { - if (safeBalance?.OLAS === undefined || totalOlasStakedBalance === undefined) - return false; - - const balanceForMigration = safeBalance.OLAS + totalOlasStakedBalance; - - if (minimumOlasRequiredToMigrate === undefined) return false; - - return balanceForMigration >= minimumOlasRequiredToMigrate; - }, [minimumOlasRequiredToMigrate, safeBalance?.OLAS, totalOlasStakedBalance]); - - const hasEnoughSlots = - stakingContractInfoForStakingProgram?.maxNumServices && - stakingContractInfoForStakingProgram?.serviceIds && - stakingContractInfoForStakingProgram?.maxNumServices > - stakingContractInfoForStakingProgram?.serviceIds?.length; - - // TODO: compatibility needs to be implemented - const isAppVersionCompatible = true; // contract.appVersion === 'rc105'; - - const isMigratable = - !isSelected && - activeStakingProgram === StakingProgram.Alpha && // TODO: make more elegant - isBalanceLoaded && - hasEnoughSlots && - hasEnoughRewards && - hasEnoughOlasToMigrate && - isAppVersionCompatible && - serviceStatus !== DeploymentStatus.DEPLOYED && - serviceStatus !== DeploymentStatus.DEPLOYING && - serviceStatus !== DeploymentStatus.STOPPING && - isServiceStakedForMinimumDuration; - - const cantMigrateReason = useMemo(() => { - if (isSelected) { - return 'Contract is already selected'; - } - - if (!hasEnoughRewards) { - return 'No available rewards'; - } - - if (activeStakingProgram !== StakingProgram.Alpha) { - return 'Can only migrate from Alpha to Beta'; - } + const stakingProgramMeta = STAKING_PROGRAM_META[stakingProgramId]; - if (!isBalanceLoaded) { - return 'Loading balance...'; - } - - if (!hasEnoughSlots) { - return 'No available staking slots'; - } - - if (!hasEnoughOlasToMigrate) { - return `Insufficient OLAS to migrate, ${minimumOlasRequiredToMigrate} OLAS required in total.`; - } - - if (!isAppVersionCompatible) { - return 'Pearl update required to migrate'; - } - - if (serviceStatus === DeploymentStatus.DEPLOYED) { - return 'Service is currently running'; - } - - if (serviceStatus === DeploymentStatus.DEPLOYING) { - return 'Service is currently deploying'; - } - - if (serviceStatus === DeploymentStatus.STOPPING) { - return 'Service is currently stopping'; - } - - if (!isServiceStakedForMinimumDuration) { - return 'Service has not been staked for the minimum duration'; - } - }, [ - activeStakingProgram, - hasEnoughOlasToMigrate, - hasEnoughRewards, - hasEnoughSlots, - isAppVersionCompatible, - isBalanceLoaded, - isSelected, - isServiceStakedForMinimumDuration, - minimumOlasRequiredToMigrate, - serviceStatus, - ]); - - const cantMigrateAlert = useMemo(() => { - if (isSelected || !isBalanceLoaded) { - return null; - } - - if (!hasEnoughSlots) { - return ; - } - - if ( - !hasEnoughOlasToMigrate && - safeBalance?.OLAS !== undefined && - totalOlasStakedBalance !== undefined - ) { - return ( - - ); - } - - if (!isAppVersionCompatible) { - return ; - } - }, [ - isSelected, - isBalanceLoaded, - hasEnoughSlots, - hasEnoughOlasToMigrate, - isAppVersionCompatible, - safeBalance?.OLAS, - totalOlasStakedBalance, - minimumOlasRequiredToMigrate, - ]); + /** + * 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 (activeStakingProgram === stakingProgram) + if (activeStakingProgramId === stakingProgramId) return StakingProgramStatus.Selected; - // Pearl is not staked, set as Selected if default (Beta) - if (!activeStakingProgram && stakingProgram === defaultStakingProgram) + // Pearl is not staked, set as Selected if default + if (!activeStakingProgramId && stakingProgramId === defaultStakingProgramId) return StakingProgramStatus.Selected; - // Otherwise, highlight Beta as New - if (stakingProgram === StakingProgram.Beta) return StakingProgramStatus.New; - // Otherwise, no tag - return; - }, [activeStakingProgram, defaultStakingProgram, stakingProgram]); + return null; + }, [activeStakingProgramId, defaultStakingProgramId, stakingProgramId]); + + const showMigrateButton = !isActiveStakingProgram; + const showFundingButton = useMemo(() => { + if (migrateValidation.canMigrate) return false; + return ( + migrateValidation.reason === CantMigrateReason.InsufficientOlasToMigrate + ); + }, [migrateValidation]); return ( <> - {/* Title */} - {`${activeStakingProgramMeta.name} contract`} + + {`${stakingProgramMeta?.name} contract`} + - {!isSelected && ( - // here instead of isSelected we should check that the contract is not the old staking contract - // but the one from staking factory (if we want to open govern) - - Contract details {UNICODE_SYMBOLS.EXTERNAL_LINK} - - )} - {/* TODO: redisplay once bugs resolved */} - - {/* Contract details - {stakingContractInfo?.availableRewards && ( - - )} - - {stakingContractInfo?.minStakingDeposit && ( - - )} */} - - {cantMigrateAlert} - {/* Switch to program button */} - {stakingProgram !== StakingProgram.Alpha && ( - - - + + + View contract details {UNICODE_SYMBOLS.EXTERNAL_LINK} + + + {!migrateValidation.canMigrate && ( + )} - {stakingProgram === StakingProgram.Beta && ( - + + {showMigrateButton && ( + )} + {showFundingButton && } - {stakingProgram === StakingProgram.Beta && isFundingSectionOpen && ( - - )} ); }; diff --git a/frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx b/frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx new file mode 100644 index 000000000..1a1ed4aba --- /dev/null +++ b/frontend/components/ManageStakingPage/StakingContractSection/useMigrate.tsx @@ -0,0 +1,165 @@ +import { isNil } from 'lodash'; +import { useMemo } from 'react'; + +import { DeploymentStatus } from '@/client'; +import { StakingProgramId } from '@/enums/StakingProgram'; +import { useBalance } from '@/hooks/useBalance'; +import { useServices } from '@/hooks/useServices'; +import { useServiceTemplates } from '@/hooks/useServiceTemplates'; +import { useStakingContractInfo } from '@/hooks/useStakingContractInfo'; +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', + MigrationNotSupported = 'Switching to this program is not currently supported', + NoAvailableRewards = 'This program has no rewards available', + NoAvailableStakingSlots = 'The program has no more avaiable slots', + NotStakedForMinimumDuration = 'Pearl has not been staked for the required minimum duration', + PearlCurrentlyRunning = 'Unable to switch while Pearl is running', +} + +type MigrateValidation = + | { + canMigrate: true; + } + | { + canMigrate: false; + reason: CantMigrateReason; + }; + +export const useMigrate = (stakingProgramId: StakingProgramId) => { + const { serviceStatus } = useServices(); + const { serviceTemplate } = useServiceTemplates(); + const { isBalanceLoaded, safeBalance, totalOlasStakedBalance } = useBalance(); + const { activeStakingProgramId, activeStakingProgramMeta } = + useStakingProgram(); + const { + activeStakingContractInfo, + isServiceStaked, + isServiceStakedForMinimumDuration, + isStakingContractInfoLoaded, + isRewardsAvailable, + hasEnoughServiceSlots, + } = useStakingContractInfo(); + + const minimumOlasRequiredToMigrate = useMemo( + () => getMinimumStakedAmountRequired(serviceTemplate, stakingProgramId), + [serviceTemplate, stakingProgramId], + ); + + const hasEnoughOlasToMigrate = useMemo(() => { + if (!isBalanceLoaded) return false; + if (isNil(safeBalance?.OLAS)) return false; + if (isNil(totalOlasStakedBalance)) return false; + if (isNil(minimumOlasRequiredToMigrate)) return false; + + const balanceForMigration = safeBalance.OLAS + totalOlasStakedBalance; + + return balanceForMigration >= minimumOlasRequiredToMigrate; + }, [ + isBalanceLoaded, + minimumOlasRequiredToMigrate, + safeBalance, + totalOlasStakedBalance, + ]); + + const migrateValidation = useMemo(() => { + // loading requirements + if (!isBalanceLoaded) { + return { canMigrate: false, reason: CantMigrateReason.LoadingBalance }; + } + + if (!isStakingContractInfoLoaded) { + return { + canMigrate: false, + reason: CantMigrateReason.LoadingStakingContractInfo, + }; + } + + // general requirements + if (activeStakingProgramId === stakingProgramId) { + return { + canMigrate: false, + reason: CantMigrateReason.ContractAlreadySelected, + }; + } + + if (!isRewardsAvailable) { + return { + canMigrate: false, + reason: CantMigrateReason.NoAvailableRewards, + }; + } + + if (!hasEnoughServiceSlots) { + return { + canMigrate: false, + reason: CantMigrateReason.NoAvailableStakingSlots, + }; + } + + if (!hasEnoughOlasToMigrate) { + return { + canMigrate: false, + reason: CantMigrateReason.InsufficientOlasToMigrate, + }; + } + + // 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 + + if (!activeStakingProgramMeta?.canMigrateTo.includes(stakingProgramId)) { + return { + canMigrate: false, + reason: CantMigrateReason.MigrationNotSupported, + }; + } + + if (activeStakingContractInfo && !isServiceStakedForMinimumDuration) { + return { + canMigrate: false, + reason: CantMigrateReason.NotStakedForMinimumDuration, + }; + } + + return { canMigrate: true }; + }, [ + isBalanceLoaded, + isStakingContractInfoLoaded, + activeStakingProgramId, + stakingProgramId, + isRewardsAvailable, + hasEnoughServiceSlots, + hasEnoughOlasToMigrate, + isServiceStaked, + activeStakingProgramMeta?.canMigrateTo, + activeStakingContractInfo, + isServiceStakedForMinimumDuration, + serviceStatus, + ]); + + return { + migrateValidation, + }; +}; diff --git a/frontend/components/ManageStakingPage/index.tsx b/frontend/components/ManageStakingPage/index.tsx index 82938256f..f58d07467 100644 --- a/frontend/components/ManageStakingPage/index.tsx +++ b/frontend/components/ManageStakingPage/index.tsx @@ -1,16 +1,56 @@ import { CloseOutlined } from '@ant-design/icons'; import { Button, Card } from 'antd'; +import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; import { Pages } from '@/enums/PageState'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { usePageState } from '@/hooks/usePageState'; +import { useStakingProgram } from '@/hooks/useStakingProgram'; import { CardTitle } from '../Card/CardTitle'; +import { CardSection } from '../styled/CardSection'; import { StakingContractSection } from './StakingContractSection'; import { WhatAreStakingContractsSection } from './WhatAreStakingContracts'; export const ManageStakingPage = () => { const { goto } = usePageState(); + const { activeStakingProgramId, defaultStakingProgramId } = + 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 === defaultStakingProgramId + ) + 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 otherStakingProgramIds = orderedStakingProgramIds.filter( + (stakingProgramId) => { + const info = STAKING_PROGRAM_META[stakingProgramId]; + if (!info) return false; + if (activeStakingProgramId === stakingProgramId) return false; + if (info.deprecated) return false; + return true; + }, + ); + return ( } @@ -24,8 +64,23 @@ export const ManageStakingPage = () => { } > - - + + {activeStakingProgramId && ( + + )} + + + {`Browse ${otherStakingProgramIds.length} staking contract${otherStakingProgramIds.length > 1 ? 's' : ''}.`} + + + {otherStakingProgramIds.map((stakingProgramId) => ( + + ))} ); }; diff --git a/frontend/components/SettingsPage/DebugInfoSection.tsx b/frontend/components/SettingsPage/DebugInfoSection.tsx index 4fa00aebf..0bb775e76 100644 --- a/frontend/components/SettingsPage/DebugInfoSection.tsx +++ b/frontend/components/SettingsPage/DebugInfoSection.tsx @@ -175,7 +175,7 @@ export const DebugInfoSection = () => { ?.instances?.[0]; if (instanceAddress) { result.push({ - title: 'Agent instance', + title: 'Agent Instance EOA', ...getItemData(walletBalances, instanceAddress!), }); } @@ -186,10 +186,6 @@ export const DebugInfoSection = () => { result.push({ title: 'Agent Safe', ...getItemData(walletBalances, multisigAddress), - link: { - title: 'See agent activity on Pandora', - href: `https://pandora.computer/predict/${multisigAddress}`, - }, }); } diff --git a/frontend/components/SettingsPage/SettingsStakingContractSection.tsx b/frontend/components/SettingsPage/SettingsStakingContractSection.tsx deleted file mode 100644 index 121b36476..000000000 --- a/frontend/components/SettingsPage/SettingsStakingContractSection.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Button, Flex, Skeleton, Typography } from 'antd'; - -import { Chain } from '@/client'; -import { SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES } from '@/constants/contractAddresses'; -import { UNICODE_SYMBOLS } from '@/constants/symbols'; -import { Pages } from '@/enums/PageState'; -import { usePageState } from '@/hooks/usePageState'; -import { useStakingProgram } from '@/hooks/useStakingProgram'; - -import { CardSection } from '../styled/CardSection'; - -const { Text } = Typography; - -export const SettingsStakingContractSection = () => { - const { goto } = usePageState(); - const { - activeStakingProgram, - activeStakingProgramMeta, - defaultStakingProgram, - isLoadedActiveStakingProgram, - } = useStakingProgram(); - - const stakingContractAddress = - SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS][ - activeStakingProgram ?? defaultStakingProgram - ]; - - if (!isLoadedActiveStakingProgram) { - return ; - } - - return ( - - Staking contract - - - {activeStakingProgramMeta - ? activeStakingProgramMeta.name - : 'Not staked'} - - - Contract details {UNICODE_SYMBOLS.EXTERNAL_LINK} - - - - - ); -}; diff --git a/frontend/components/SettingsPage/index.tsx b/frontend/components/SettingsPage/index.tsx index 3170d1e54..76f5b01c7 100644 --- a/frontend/components/SettingsPage/index.tsx +++ b/frontend/components/SettingsPage/index.tsx @@ -16,7 +16,6 @@ import { CardTitle } from '../Card/CardTitle'; import { CardSection } from '../styled/CardSection'; import { AddBackupWalletPage } from './AddBackupWalletPage'; import { DebugInfoSection } from './DebugInfoSection'; -import { SettingsStakingContractSection } from './SettingsStakingContractSection'; const { Text, Paragraph } = Typography; @@ -76,6 +75,7 @@ const SettingsMain = () => { ******** + {/* Wallet backup */} Backup wallet @@ -91,8 +91,7 @@ const SettingsMain = () => { )} - {/* Staking contract section */} - + {/* Debug info */} @@ -114,7 +113,10 @@ const NoBackupWallet = () => { <> Your funds are at risk! - You will lose any assets you send on other chains. + + Add a backup wallet to allow you to retrieve funds if you lose + your password and seed phrase. + } diff --git a/frontend/components/SetupPage/SetupWelcome.tsx b/frontend/components/SetupPage/SetupWelcome.tsx index b12c2ebfa..9d3c3b3d8 100644 --- a/frontend/components/SetupPage/SetupWelcome.tsx +++ b/frontend/components/SetupPage/SetupWelcome.tsx @@ -39,12 +39,13 @@ export const SetupWelcome = () => { case true: setIsSetup(AccountIsSetup.True); break; - case false: + case false: { // Reset persistent state // if creating new account electronApi.store?.clear?.(); setIsSetup(AccountIsSetup.False); break; + } default: setIsSetup(AccountIsSetup.Error); break; @@ -64,18 +65,27 @@ export const SetupWelcome = () => { return ; case AccountIsSetup.Loading: return ( - + ); - default: + case AccountIsSetup.Error: return ( - + - Error determining account setup state. + Unable to determine the account setup status, please try again. ); + default: + return null; } }, [isSetup]); diff --git a/frontend/constants/colors.ts b/frontend/constants/colors.ts index 7625d03ee..69678c0ed 100644 --- a/frontend/constants/colors.ts +++ b/frontend/constants/colors.ts @@ -3,6 +3,7 @@ export const COLOR = { GREEN_2: '#00F422', PURPLE: '#722ed1', PURPLE_DARK: '#36075F', + PURPLE_LIGHT: '#EFCFFF', BLUE: '#1677FF', ORANGE: '#FAAD14', WHITE: '#ffffff', diff --git a/frontend/constants/contractAddresses.ts b/frontend/constants/contractAddresses.ts index bf76ee672..f22eebd2b 100644 --- a/frontend/constants/contractAddresses.ts +++ b/frontend/constants/contractAddresses.ts @@ -1,5 +1,5 @@ import { Chain } from '@/client'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; export const MULTICALL_CONTRACT_ADDRESS: Address = @@ -18,12 +18,12 @@ export const SERVICE_REGISTRY_TOKEN_UTILITY_CONTRACT_ADDRESS: Record< export const SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES: Record< number, - Record + Record > = { [Chain.GNOSIS]: { - // Maintain order, as it is used in the UI - [StakingProgram.Beta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', - [StakingProgram.Alpha]: '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', + [StakingProgramId.Beta2]: '0x1c2F82413666d2a3fD8bC337b0268e62dDF67434', + [StakingProgramId.Beta]: '0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d', + [StakingProgramId.Alpha]: '0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A', }, }; diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts index 19948f76a..6a4b2ebe1 100644 --- a/frontend/constants/serviceTemplates.ts +++ b/frontend/constants/serviceTemplates.ts @@ -1,10 +1,10 @@ import { ServiceTemplate } from '@/client'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; export const SERVICE_TEMPLATES: ServiceTemplate[] = [ { name: 'Trader Agent', - hash: 'bafybeicrstlxew36hlxl7pzi73nmd44aibnhwxzkchzlec6t6yhvs7gvhy', + hash: 'bafybeidu3e3hdx5qt3bclheo7opr4adiil6zs2cger6m733qvhttnlo6na', // hash: 'bafybeibbloa4w33vj4bvdkso7pzk6tr3duvxjpecbx4mur4ix6ehnwb5uu', // temporary description: 'Trader agent for omen prediction markets', image: @@ -13,7 +13,7 @@ export const SERVICE_TEMPLATES: ServiceTemplate[] = [ home_chain_id: '100', configurations: { 100: { - staking_program_id: StakingProgram.Beta, // default, may be overwritten + staking_program_id: StakingProgramId.Beta, // default, may be overwritten nft: 'bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq', agent_id: 14, threshold: 1, diff --git a/frontend/constants/stakingProgramMeta.ts b/frontend/constants/stakingProgramMeta.ts index f060c3ab2..4fabb4c6d 100644 --- a/frontend/constants/stakingProgramMeta.ts +++ b/frontend/constants/stakingProgramMeta.ts @@ -1,15 +1,27 @@ -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; +export type StakingProgramMeta = { + name: string; + canMigrateTo: StakingProgramId[]; + deprecated: boolean; +}; export const STAKING_PROGRAM_META: Record< - StakingProgram, - { - name: string; - } + StakingProgramId, + StakingProgramMeta > = { - [StakingProgram.Alpha]: { + [StakingProgramId.Alpha]: { name: 'Pearl Alpha', + canMigrateTo: [StakingProgramId.Beta, StakingProgramId.Beta2], + deprecated: true, }, - [StakingProgram.Beta]: { + [StakingProgramId.Beta]: { name: 'Pearl Beta', + canMigrateTo: [StakingProgramId.Beta2], + deprecated: false, + }, + [StakingProgramId.Beta2]: { + name: 'Pearl Beta 2', + canMigrateTo: [StakingProgramId.Beta], + deprecated: false, }, }; diff --git a/frontend/context/BalanceProvider.tsx b/frontend/context/BalanceProvider.tsx index 2bee8e074..d9cbae01f 100644 --- a/frontend/context/BalanceProvider.tsx +++ b/frontend/context/BalanceProvider.tsx @@ -132,9 +132,11 @@ export const BalanceProvider = ({ children }: PropsWithChildren) => { try { const walletAddresses: Address[] = []; - if (masterEoaAddress) walletAddresses.push(masterEoaAddress); - if (masterSafeAddress) walletAddresses.push(masterSafeAddress); - if (serviceAddresses) walletAddresses.push(...serviceAddresses); + if (isAddress(masterEoaAddress)) walletAddresses.push(masterEoaAddress); + if (isAddress(`${masterSafeAddress}`)) + walletAddresses.push(masterSafeAddress as Address); + if (serviceAddresses) + walletAddresses.push(...serviceAddresses.filter(isAddress)); const walletBalances = await getWalletBalances(walletAddresses); if (!walletBalances) return; @@ -150,10 +152,10 @@ export const BalanceProvider = ({ children }: PropsWithChildren) => { return; } - if (masterSafeAddress && serviceId) { + if (isAddress(`${masterSafeAddress}`) && serviceId > 0) { const { depositValue, bondValue, serviceState } = await AutonolasService.getServiceRegistryInfo( - masterSafeAddress, + masterSafeAddress as Address, serviceId, ); diff --git a/frontend/context/ElectronApiProvider.tsx b/frontend/context/ElectronApiProvider.tsx index 01f85bdf9..7927bf7d4 100644 --- a/frontend/context/ElectronApiProvider.tsx +++ b/frontend/context/ElectronApiProvider.tsx @@ -4,6 +4,7 @@ import { createContext, PropsWithChildren } from 'react'; import { ElectronStore, ElectronTrayIconStatus } from '@/types/ElectronApi'; type ElectronApiContextProps = { + setIsAppLoaded?: (isLoaded: boolean) => void; closeApp?: () => void; minimizeApp?: () => void; setTrayIcon?: (status: ElectronTrayIconStatus) => void; @@ -33,6 +34,7 @@ type ElectronApiContextProps = { }; export const ElectronApiContext = createContext({ + setIsAppLoaded: () => false, closeApp: () => {}, minimizeApp: () => {}, setTrayIcon: () => {}, @@ -70,6 +72,7 @@ export const ElectronApiProvider = ({ children }: PropsWithChildren) => { return ( { const service = useMemo(() => services?.[0], [services]); const { storeState } = useStore(); const electronApi = useElectronApi(); - const { activeStakingProgram, defaultStakingProgram } = useContext( + const { activeStakingProgramId, defaultStakingProgramId } = useContext( StakingProgramContext, ); @@ -76,7 +76,7 @@ export const RewardProvider = ({ children }: PropsWithChildren) => { // only check for rewards if there's a currentStakingProgram active if ( - activeStakingProgram && + activeStakingProgramId && service?.chain_configs[CHAINS.GNOSIS.chainId].chain_data?.multisig && service?.chain_configs[CHAINS.GNOSIS.chainId].chain_data?.token ) { @@ -85,13 +85,13 @@ export const RewardProvider = ({ children }: PropsWithChildren) => { service.chain_configs[CHAINS.GNOSIS.chainId].chain_data.multisig!, serviceId: service.chain_configs[CHAINS.GNOSIS.chainId].chain_data.token!, - stakingProgram: activeStakingProgram, + stakingProgram: activeStakingProgramId, }); } // can fallback to default staking program if no current staking program is active const epochRewardsPromise = AutonolasService.getAvailableRewardsForEpoch( - activeStakingProgram ?? defaultStakingProgram, + activeStakingProgramId ?? defaultStakingProgramId, ); const [stakingRewardsInfo, rewards] = await Promise.all([ @@ -104,7 +104,7 @@ export const RewardProvider = ({ children }: PropsWithChildren) => { stakingRewardsInfo?.accruedServiceStakingRewards, ); setAvailableRewardsForEpoch(rewards); - }, [activeStakingProgram, defaultStakingProgram, service]); + }, [activeStakingProgramId, defaultStakingProgramId, service]); useEffect(() => { if (isEligibleForRewards && !storeState?.firstStakingRewardAchieved) { diff --git a/frontend/context/StakingContractInfoProvider.tsx b/frontend/context/StakingContractInfoProvider.tsx index 6bf19408a..71910cb2d 100644 --- a/frontend/context/StakingContractInfoProvider.tsx +++ b/frontend/context/StakingContractInfoProvider.tsx @@ -11,7 +11,7 @@ import { useInterval } from 'usehooks-ts'; import { CHAINS } from '@/constants/chains'; import { FIVE_SECONDS_INTERVAL } from '@/constants/intervals'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { AutonolasService } from '@/service/Autonolas'; import { StakingContractInfo } from '@/types/Autonolas'; @@ -19,32 +19,37 @@ import { ServicesContext } from './ServicesProvider'; import { StakingProgramContext } from './StakingProgramContext'; type StakingContractInfoContextProps = { - updateActiveStakingContractInfo: () => Promise; - activeStakingContractInfo?: StakingContractInfo; + activeStakingContractInfo?: Partial; + isStakingContractInfoLoaded: boolean; stakingContractInfoRecord?: Record< - StakingProgram, + StakingProgramId, Partial >; + updateActiveStakingContractInfo: () => Promise; }; export const StakingContractInfoContext = createContext({ - updateActiveStakingContractInfo: async () => {}, activeStakingContractInfo: undefined, + isStakingContractInfoLoaded: false, stakingContractInfoRecord: undefined, + updateActiveStakingContractInfo: async () => {}, }); export const StakingContractInfoProvider = ({ children, }: PropsWithChildren) => { const { services } = useContext(ServicesContext); - const { activeStakingProgram } = useContext(StakingProgramContext); + const { activeStakingProgramId } = useContext(StakingProgramContext); + + const [isStakingContractInfoLoaded, setIsStakingContractInfoLoaded] = + useState(false); const [activeStakingContractInfo, setActiveStakingContractInfo] = - useState(); + useState>(); const [stakingContractInfoRecord, setStakingContractInfoRecord] = - useState>>(); + useState>>(); const serviceId = useMemo( () => services?.[0]?.chain_configs[CHAINS.GNOSIS.chainId].chain_data?.token, @@ -55,33 +60,45 @@ export const StakingContractInfoProvider = ({ // it requires serviceId and activeStakingProgram const updateActiveStakingContractInfo = useCallback(async () => { if (!serviceId) return; - if (!activeStakingProgram) return; + if (!activeStakingProgramId) return; AutonolasService.getStakingContractInfoByServiceIdStakingProgram( serviceId, - activeStakingProgram, + activeStakingProgramId, ).then(setActiveStakingContractInfo); - }, [activeStakingProgram, serviceId]); + }, [activeStakingProgramId, serviceId]); useInterval(updateActiveStakingContractInfo, FIVE_SECONDS_INTERVAL); // Record of staking contract info for each staking program // not user/service specific - const updateStakingContractInfoRecord = () => { + const updateStakingContractInfoRecord = async () => { const alpha = AutonolasService.getStakingContractInfoByStakingProgram( - StakingProgram.Alpha, + StakingProgramId.Alpha, ); const beta = AutonolasService.getStakingContractInfoByStakingProgram( - StakingProgram.Beta, + StakingProgramId.Beta, ); - Promise.all([alpha, beta]).then((values) => { - const [alphaInfo, betaInfo] = values; + const beta_2 = AutonolasService.getStakingContractInfoByStakingProgram( + StakingProgramId.Beta2, + ); + + try { + const [alphaInfo, betaInfo, beta2Info] = await Promise.all([ + alpha, + beta, + beta_2, + ]); setStakingContractInfoRecord({ - [StakingProgram.Alpha]: alphaInfo, - [StakingProgram.Beta]: betaInfo, + [StakingProgramId.Alpha]: alphaInfo, + [StakingProgramId.Beta]: betaInfo, + [StakingProgramId.Beta2]: beta2Info, }); - }); + setIsStakingContractInfoLoaded(true); + } catch (e) { + setIsStakingContractInfoLoaded(false); + } }; useEffect(() => { @@ -92,9 +109,10 @@ export const StakingContractInfoProvider = ({ return ( {children} diff --git a/frontend/context/StakingProgramContext.tsx b/frontend/context/StakingProgramContext.tsx index fecdf645c..39e6ba2ab 100644 --- a/frontend/context/StakingProgramContext.tsx +++ b/frontend/context/StakingProgramContext.tsx @@ -2,55 +2,55 @@ import { createContext, PropsWithChildren, useCallback, useState } from 'react'; import { useInterval } from 'usehooks-ts'; import { CHAINS } from '@/constants/chains'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; import { useServices } from '@/hooks/useServices'; import { AutonolasService } from '@/service/Autonolas'; export const StakingProgramContext = createContext<{ - activeStakingProgram?: StakingProgram | null; - defaultStakingProgram: StakingProgram; - updateActiveStakingProgram: () => Promise; + activeStakingProgramId?: StakingProgramId | null; + defaultStakingProgramId: StakingProgramId; + updateActiveStakingProgramId: () => Promise; }>({ - activeStakingProgram: undefined, - defaultStakingProgram: StakingProgram.Beta, - updateActiveStakingProgram: async () => {}, + activeStakingProgramId: undefined, + defaultStakingProgramId: StakingProgramId.Beta, + updateActiveStakingProgramId: async () => {}, }); /** Determines the current active staking program, if any */ export const StakingProgramProvider = ({ children }: PropsWithChildren) => { const { service } = useServices(); - const [activeStakingProgram, setActiveStakingProgram] = - useState(); + const [activeStakingProgramId, setActiveStakingProgramId] = + useState(); - const updateActiveStakingProgram = useCallback(async () => { + const updateActiveStakingProgramId = useCallback(async () => { // if no service nft, not staked const serviceId = service?.chain_configs[CHAINS.GNOSIS.chainId].chain_data?.token; if (!service?.chain_configs[CHAINS.GNOSIS.chainId].chain_data?.token) { - setActiveStakingProgram(null); + setActiveStakingProgramId(null); return; } if (serviceId) { // if service exists, we need to check if it is staked AutonolasService.getCurrentStakingProgramByServiceId(serviceId).then( - (stakingProgram) => { - setActiveStakingProgram(stakingProgram); + (stakingProgramId) => { + setActiveStakingProgramId(stakingProgramId); }, ); } }, [service]); - useInterval(updateActiveStakingProgram, 5000); + useInterval(updateActiveStakingProgramId, 5000); return ( {children} diff --git a/frontend/enums/StakingProgram.ts b/frontend/enums/StakingProgram.ts index c3d98cd42..dc5a16da9 100644 --- a/frontend/enums/StakingProgram.ts +++ b/frontend/enums/StakingProgram.ts @@ -1,4 +1,5 @@ -export enum StakingProgram { +export enum StakingProgramId { Alpha = 'pearl_alpha', Beta = 'pearl_beta', + Beta2 = 'pearl_beta_2', } diff --git a/frontend/enums/StakingProgramStatus.ts b/frontend/enums/StakingProgramStatus.ts index d2789f1ef..d161434b7 100644 --- a/frontend/enums/StakingProgramStatus.ts +++ b/frontend/enums/StakingProgramStatus.ts @@ -1,4 +1,3 @@ export enum StakingProgramStatus { - New = 'new', Selected = 'current', } diff --git a/frontend/hooks/useNeedsFunds.ts b/frontend/hooks/useNeedsFunds.ts new file mode 100644 index 000000000..f99e909a9 --- /dev/null +++ b/frontend/hooks/useNeedsFunds.ts @@ -0,0 +1,71 @@ +import { formatUnits } from 'ethers/lib/utils'; +import { useMemo } from 'react'; + +import { CHAINS } from '@/constants/chains'; +import { getMinimumStakedAmountRequired } from '@/utils/service'; + +import { useBalance } from './useBalance'; +import { useServiceTemplates } from './useServiceTemplates'; +import { useStore } from './useStore'; + +export const useNeedsFunds = () => { + const { getServiceTemplates } = useServiceTemplates(); + + const serviceTemplate = useMemo( + () => getServiceTemplates()[0], + [getServiceTemplates], + ); + + const { storeState } = useStore(); + const { isBalanceLoaded, safeBalance, totalOlasStakedBalance } = useBalance(); + + const serviceFundRequirements = useMemo(() => { + const gasEstimate = + serviceTemplate.configurations[CHAINS.GNOSIS.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 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, + ]); + + const isInitialFunded = storeState?.isInitialFunded; + const needsInitialFunding: boolean = useMemo(() => { + if (isInitialFunded) return false; + if (!isBalanceLoaded) return false; + if (hasEnoughEthForInitialFunding && hasEnoughOlasForInitialFunding) + return false; + return true; + }, [ + hasEnoughEthForInitialFunding, + hasEnoughOlasForInitialFunding, + isBalanceLoaded, + isInitialFunded, + ]); + + return { + hasEnoughEthForInitialFunding, + hasEnoughOlasForInitialFunding, + serviceFundRequirements, + isInitialFunded, + needsInitialFunding, + }; +}; diff --git a/frontend/hooks/useStakingContractInfo.ts b/frontend/hooks/useStakingContractInfo.ts index 460f74613..9cf911ffd 100644 --- a/frontend/hooks/useStakingContractInfo.ts +++ b/frontend/hooks/useStakingContractInfo.ts @@ -1,3 +1,4 @@ +import { isNil } from 'lodash'; import { useContext } from 'react'; import { StakingContractInfoContext } from '@/context/StakingContractInfoProvider'; @@ -5,9 +6,11 @@ import { StakingContractInfoContext } from '@/context/StakingContractInfoProvide import { useServices } from './useServices'; export const useStakingContractInfo = () => { - const { activeStakingContractInfo, stakingContractInfoRecord } = useContext( - StakingContractInfoContext, - ); + const { + activeStakingContractInfo, + stakingContractInfoRecord, + isStakingContractInfoLoaded, + } = useContext(StakingContractInfoContext); const { services } = useServices(); @@ -17,19 +20,28 @@ export const useStakingContractInfo = () => { const { serviceStakingState, serviceStakingStartTime, - availableRewards, + //availableRewards, // TODO: uncomment when availableRewards is available serviceIds, maxNumServices, minimumStakingDuration, } = activeStakingContractInfo; const isRewardsAvailable = true; // availableRewards > 0; - const hasEnoughServiceSlots = serviceIds.length < maxNumServices; + + 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 @@ -41,25 +53,31 @@ export const useStakingContractInfo = () => { * */ const isServiceStakedForMinimumDuration = + !isNil(serviceStakingStartTime) && + !isNil(minimumStakingDuration) && Math.round(Date.now() / 1000) - serviceStakingStartTime >= - minimumStakingDuration; + minimumStakingDuration; /** - * user can start the agent iff, + * User can only stake if: * - rewards are available * - service has enough slots - * - if agent is evicted, then service should be staked for minimum duration + * - agent is not evicted + * - if agent is evicted, then service should be staked for minimum duration */ const isEligibleForStaking = - hasEnoughRewardsAndSlots && + !isNil(hasEnoughRewardsAndSlots) && (isAgentEvicted ? isServiceStakedForMinimumDuration : true); return { + activeStakingContractInfo, hasEnoughServiceSlots, isEligibleForStaking, isRewardsAvailable, isAgentEvicted, - stakingContractInfoRecord, isServiceStakedForMinimumDuration, + isServiceStaked, + isStakingContractInfoLoaded, + stakingContractInfoRecord, }; }; diff --git a/frontend/hooks/useStakingProgram.ts b/frontend/hooks/useStakingProgram.ts index 8d07739be..560c8c811 100644 --- a/frontend/hooks/useStakingProgram.ts +++ b/frontend/hooks/useStakingProgram.ts @@ -1,33 +1,42 @@ -import { useContext } from 'react'; +import { useContext, useMemo } from 'react'; import { STAKING_PROGRAM_META } from '@/constants/stakingProgramMeta'; import { StakingProgramContext } from '@/context/StakingProgramContext'; /** - * Mock hook for staking program abstraction - * @returns {currentStakingProgram: IncentiveProgram} + * Hook to get the active staking program and its metadata, and the default staking program. + * @returns {Object} The active staking program and its metadata. */ export const useStakingProgram = () => { const { - activeStakingProgram, - defaultStakingProgram, - updateActiveStakingProgram: updateStakingProgram, + activeStakingProgramId, + defaultStakingProgramId, + updateActiveStakingProgramId, } = useContext(StakingProgramContext); - const isLoadedActiveStakingProgram = activeStakingProgram !== undefined; + const isActiveStakingProgramLoaded = activeStakingProgramId !== undefined; - const activeStakingProgramMeta = - activeStakingProgram === undefined - ? null - : activeStakingProgram === null - ? null - : STAKING_PROGRAM_META[activeStakingProgram]; + /** + * TODO: implement enums + * returns `StakingProgramMeta` if defined + * returns `undefined` if not loaded + * returns `null` if not actively staked + */ + const activeStakingProgramMeta = useMemo(() => { + if (activeStakingProgramId === undefined) return undefined; + if (activeStakingProgramId === null) return null; + return STAKING_PROGRAM_META[activeStakingProgramId]; + }, [activeStakingProgramId]); + + const defaultStakingProgramMeta = + STAKING_PROGRAM_META[defaultStakingProgramId]; return { - activeStakingProgram, + activeStakingProgramId, activeStakingProgramMeta, - defaultStakingProgram, - updateStakingProgram, - isLoadedActiveStakingProgram, + defaultStakingProgramId, + defaultStakingProgramMeta, + isActiveStakingProgramLoaded, + updateActiveStakingProgramId, }; }; diff --git a/frontend/package.json b/frontend/package.json index ec20ee33a..0289f79d7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -45,7 +45,7 @@ "private": true, "scripts": { "dev": "next dev", - "build": "NODE_ENV=production next build", + "build": "bash -c \"DEV_RPC=$DEV_RPC FORK_URL=$FORK_URL NODE_ENV=production next build\"", "lint": "next lint", "test": "jest", "start": "next start" diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index 0eca2b8db..074a78b4b 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -16,6 +16,10 @@ export default function Home() { const electronApi = useElectronApi(); useEffect(() => { + // Notify the main process that the app is loaded + electronApi?.setIsAppLoaded?.(true); + + // Set the app height to the body scroll height function updateAppHeight() { const bodyElement = document.querySelector('body'); if (bodyElement) { diff --git a/frontend/service/Autonolas.ts b/frontend/service/Autonolas.ts index b0e9e74d6..ad5b91809 100644 --- a/frontend/service/Autonolas.ts +++ b/frontend/service/Autonolas.ts @@ -1,4 +1,5 @@ import { BigNumber, ethers } from 'ethers'; +import { formatEther } from 'ethers/lib/utils'; import { Contract as MulticallContract } from 'ethers-multicall'; import { AGENT_MECH_ABI } from '@/abis/agentMech'; @@ -16,10 +17,11 @@ import { } from '@/constants/contractAddresses'; import { gnosisMulticallProvider } from '@/constants/providers'; import { ServiceRegistryL2ServiceState } from '@/enums/ServiceRegistryL2ServiceState'; -import { StakingProgram } from '@/enums/StakingProgram'; +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 agentMechContract = new MulticallContract( @@ -27,25 +29,31 @@ const agentMechContract = new MulticallContract( AGENT_MECH_ABI.filter((abi) => abi.type === 'function'), // weird bug in the package where their filter doesn't work.. ); +const ServiceStakingTokenAbi = SERVICE_STAKING_TOKEN_MECH_USAGE_ABI.filter( + (abi) => abi.type === 'function', +); + const serviceStakingTokenMechUsageContracts: Record< - StakingProgram, + StakingProgramId, MulticallContract > = { - [StakingProgram.Alpha]: new MulticallContract( + [StakingProgramId.Alpha]: new MulticallContract( + SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS][ + StakingProgramId.Alpha + ], + ServiceStakingTokenAbi, + ), + [StakingProgramId.Beta]: new MulticallContract( SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS][ - StakingProgram.Alpha + StakingProgramId.Beta ], - SERVICE_STAKING_TOKEN_MECH_USAGE_ABI.filter( - (abi) => abi.type === 'function', - ), // same as above + ServiceStakingTokenAbi, ), - [StakingProgram.Beta]: new MulticallContract( + [StakingProgramId.Beta2]: new MulticallContract( SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS][ - StakingProgram.Beta + StakingProgramId.Beta2 ], - SERVICE_STAKING_TOKEN_MECH_USAGE_ABI.filter( - (abi) => abi.type === 'function', - ), // same as above + ServiceStakingTokenAbi, ), }; @@ -71,7 +79,7 @@ const getAgentStakingRewardsInfo = async ({ }: { agentMultisigAddress: Address; serviceId: number; - stakingProgram: StakingProgram; + stakingProgram: StakingProgramId; }): Promise => { if (!agentMultisigAddress) return; if (!serviceId) return; @@ -161,20 +169,18 @@ const getAgentStakingRewardsInfo = async ({ }; const getAvailableRewardsForEpoch = async ( - stakingProgram: StakingProgram, + stakingProgramId: StakingProgramId, ): Promise => { const contractCalls = [ - serviceStakingTokenMechUsageContracts[stakingProgram].rewardsPerSecond(), - serviceStakingTokenMechUsageContracts[stakingProgram].livenessPeriod(), // epoch length - serviceStakingTokenMechUsageContracts[stakingProgram].tsCheckpoint(), // last checkpoint timestamp + serviceStakingTokenMechUsageContracts[stakingProgramId].rewardsPerSecond(), + serviceStakingTokenMechUsageContracts[stakingProgramId].livenessPeriod(), // epoch length + serviceStakingTokenMechUsageContracts[stakingProgramId].tsCheckpoint(), // last checkpoint timestamp ]; await gnosisMulticallProvider.init(); const multicallResponse = await gnosisMulticallProvider.all(contractCalls); - const [rewardsPerSecond, livenessPeriod, tsCheckpoint] = multicallResponse; - const nowInSeconds = Math.floor(Date.now() / 1000); return Math.max( @@ -185,22 +191,24 @@ const getAvailableRewardsForEpoch = async ( const getStakingContractInfoByServiceIdStakingProgram = async ( serviceId: number, - stakingProgram: StakingProgram, -): Promise => { + stakingProgramId: StakingProgramId, +): Promise | undefined> => { if (!serviceId) return; const contractCalls = [ - serviceStakingTokenMechUsageContracts[stakingProgram].availableRewards(), - serviceStakingTokenMechUsageContracts[stakingProgram].maxNumServices(), - serviceStakingTokenMechUsageContracts[stakingProgram].getServiceIds(), - serviceStakingTokenMechUsageContracts[stakingProgram].minStakingDuration(), - serviceStakingTokenMechUsageContracts[stakingProgram].getServiceInfo( + serviceStakingTokenMechUsageContracts[stakingProgramId].availableRewards(), + serviceStakingTokenMechUsageContracts[stakingProgramId].maxNumServices(), + serviceStakingTokenMechUsageContracts[stakingProgramId].getServiceIds(), + serviceStakingTokenMechUsageContracts[ + stakingProgramId + ].minStakingDuration(), + serviceStakingTokenMechUsageContracts[stakingProgramId].getServiceInfo( serviceId, ), - serviceStakingTokenMechUsageContracts[stakingProgram].getStakingState( + serviceStakingTokenMechUsageContracts[stakingProgramId].getStakingState( serviceId, ), - serviceStakingTokenMechUsageContracts[stakingProgram].minStakingDeposit(), + serviceStakingTokenMechUsageContracts[stakingProgramId].minStakingDeposit(), ]; await gnosisMulticallProvider.init(); @@ -233,15 +241,22 @@ const getStakingContractInfoByServiceIdStakingProgram = async ( }; }; +/** + * Get staking contract info by staking program name + * eg. Alpha, Beta, Beta2 + */ const getStakingContractInfoByStakingProgram = async ( - stakingProgram: StakingProgram, -) => { + 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(), ]; await gnosisMulticallProvider.init(); @@ -253,6 +268,9 @@ const getStakingContractInfoByStakingProgram = async ( getServiceIdsInBN, minStakingDurationInBN, minStakingDeposit, + rewardsPerSecond, + numAgentInstances, + livenessPeriod, ] = multicallResponse; const availableRewards = parseFloat( @@ -261,12 +279,32 @@ const getStakingContractInfoByStakingProgram = async ( const serviceIds = getServiceIdsInBN.map((id: BigNumber) => id.toNumber()); const maxNumServices = maxNumServicesInBN.toNumber(); + // APY + const rewardsPerYear = rewardsPerSecond.mul(ONE_YEAR); + const 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, }; }; @@ -308,30 +346,44 @@ const getServiceRegistryInfo = async ( }; }; +/** + * @param serviceId + * @returns StakingProgram | null (null when not staked) + */ const getCurrentStakingProgramByServiceId = async ( serviceId: number, -): Promise => { - const contractCalls = [ - serviceStakingTokenMechUsageContracts[StakingProgram.Alpha].getStakingState( - serviceId, - ), - serviceStakingTokenMechUsageContracts[StakingProgram.Beta].getStakingState( - serviceId, - ), - ]; - - await gnosisMulticallProvider.init(); +): Promise => { + if (serviceId <= -1) return null; + + const contractCalls = Object.values(StakingProgramId).reduce( + (acc, stakingProgramId: StakingProgramId) => ({ + ...acc, + [stakingProgramId]: + serviceStakingTokenMechUsageContracts[stakingProgramId].getStakingState( + serviceId, + ), + }), + {}, + ); try { - const [isAlphaStaked, isBetaStaked] = - await gnosisMulticallProvider.all(contractCalls); - - // Alpha should take precedence, as it must be migrated from - return isAlphaStaked - ? StakingProgram.Alpha - : isBetaStaked - ? StakingProgram.Beta - : null; + await gnosisMulticallProvider.init(); + const [isAlphaStaked, isBetaStaked, isBeta2Staked] = + await gnosisMulticallProvider.all(Object.values(contractCalls)); + + if (isAlphaStaked) { + return StakingProgramId.Alpha; + } + + if (isBetaStaked) { + return StakingProgramId.Beta; + } + + if (isBeta2Staked) { + return StakingProgramId.Beta2; + } + + return null; } catch (error) { console.error('Error while getting current staking program', error); return null; diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index 44730835c..be0a2c637 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -1,6 +1,6 @@ import { Deployment, Service, ServiceHash, ServiceTemplate } from '@/client'; import { BACKEND_URL } from '@/constants/urls'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; /** * Get a single service from the backend @@ -32,11 +32,11 @@ const getServices = async (): Promise => const createService = async ({ deploy, serviceTemplate, - stakingProgram, + stakingProgramId, }: { deploy: boolean; serviceTemplate: ServiceTemplate; - stakingProgram: StakingProgram; + stakingProgramId: StakingProgramId; }): Promise => new Promise((resolve, reject) => fetch(`${BACKEND_URL}/services`, { @@ -47,7 +47,7 @@ const createService = async ({ configurations: { 100: { ...serviceTemplate.configurations[100], - staking_program_id: stakingProgram, + staking_program_id: stakingProgramId, rpc: `${process.env.GNOSIS_RPC}`, }, }, diff --git a/frontend/types/Autonolas.ts b/frontend/types/Autonolas.ts index 3cd552d1c..187e13249 100644 --- a/frontend/types/Autonolas.ts +++ b/frontend/types/Autonolas.ts @@ -16,10 +16,16 @@ export type StakingContractInfo = { serviceIds: number[]; /** minimum staking duration (in seconds) */ minimumStakingDuration: number; - /** time when service was staked (in seconds) */ + /** 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; + /** annual percentage yield */ + apy: number; + /** amount of OLAS required to stake */ + olasStakeRequired: number; + /** rewards per work period */ + rewardsPerWorkPeriod: number; }; diff --git a/frontend/utils/service.ts b/frontend/utils/service.ts index 5a957ce93..e9720408f 100644 --- a/frontend/utils/service.ts +++ b/frontend/utils/service.ts @@ -1,21 +1,22 @@ import { ServiceTemplate } from '@/client'; -import { StakingProgram } from '@/enums/StakingProgram'; +import { StakingProgramId } from '@/enums/StakingProgram'; /** TODO: update from hardcoded, workaround for quick release */ export const getMinimumStakedAmountRequired = ( - serviceTemplate: ServiceTemplate, - stakingProgram: StakingProgram = StakingProgram.Beta, -) => { - // const olasCostOfBond = Number( - // formatUnits( - // `${serviceTemplate.configurations[CHAINS.GNOSIS.chainId].cost_of_bond}`, - // 18, - // ), - // ); - - if (stakingProgram === StakingProgram.Alpha) { + serviceTemplate?: ServiceTemplate, //TODO: remove, as unused + stakingProgramId: StakingProgramId = StakingProgramId.Beta, +): number | undefined => { + if (stakingProgramId === StakingProgramId.Alpha) { return 20; } - return 40; + if (stakingProgramId === StakingProgramId.Beta) { + return 40; + } + + if (stakingProgramId === StakingProgramId.Beta2) { + return 100; + } + + return; }; diff --git a/operate/cli.py b/operate/cli.py index 99cabe0f1..2c491ad3b 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -143,17 +143,22 @@ def create_app( # pylint: disable=too-many-locals, unused-argument, too-many-st home: t.Optional[Path] = None, ) -> FastAPI: """Create FastAPI object.""" + HEALTH_CHECKER_OFF = os.environ.get("HEALTH_CHECKER_OFF", "0") == "1" + number_of_fails = int(os.environ.get("HEALTH_CHECKER_TRIES", "5")) logger = setup_logger(name="operate") + if HEALTH_CHECKER_OFF: + logger.warning("healthchecker is off!!!") operate = OperateApp(home=home, logger=logger) funding_jobs: t.Dict[str, asyncio.Task] = {} - health_checker = HealthChecker(operate.service_manager()) + health_checker = HealthChecker( + operate.service_manager(), number_of_fails=number_of_fails + ) # Create shutdown endpoint shutdown_endpoint = uuid.uuid4().hex (operate._path / "operate.kill").write_text( # pylint: disable=protected-access shutdown_endpoint ) - thread_pool_executor = ThreadPoolExecutor() async def run_in_executor(fn: t.Callable, *args: t.Any) -> t.Any: @@ -188,7 +193,9 @@ def schedule_healthcheck_job( service: str, ) -> None: """Schedule a healthcheck job.""" - health_checker.start_for_service(service) + if not HEALTH_CHECKER_OFF: + # dont start health checker if it's switched off + health_checker.start_for_service(service) def cancel_funding_job(service: str) -> None: """Cancel funding job.""" diff --git a/operate/ledger/__init__.py b/operate/ledger/__init__.py index 078a93d1e..c54609833 100644 --- a/operate/ledger/__init__.py +++ b/operate/ledger/__init__.py @@ -38,6 +38,7 @@ GOERLI_RPC = os.environ.get("DEV_RPC", "https://ethereum-goerli.publicnode.com") SOLANA_RPC = os.environ.get("DEV_RPC", "https://api.mainnet-beta.solana.com") + PUBLIC_RPCS = { ChainType.ETHEREUM: ETHEREUM_PUBLIC_RPC, ChainType.GNOSIS: GNOSIS_PUBLIC_RPC, diff --git a/operate/ledger/profiles.py b/operate/ledger/profiles.py index bf7fa8433..523c1fdb9 100644 --- a/operate/ledger/profiles.py +++ b/operate/ledger/profiles.py @@ -39,6 +39,7 @@ ChainType.GNOSIS: { "pearl_alpha": "0xEE9F19b5DF06c7E8Bfc7B28745dcf944C504198A", "pearl_beta": "0xeF44Fb0842DDeF59D37f85D61A1eF492bbA6135d", + "pearl_beta_2": "0x1c2F82413666d2a3fD8bC337b0268e62dDF67434", } } diff --git a/operate/services/deployment_runner.py b/operate/services/deployment_runner.py index 1bf81904e..b53f9b12e 100644 --- a/operate/services/deployment_runner.py +++ b/operate/services/deployment_runner.py @@ -22,7 +22,6 @@ import os import platform import shutil # nosec -import signal # nosec import subprocess # nosec import sys # nosec import time @@ -55,7 +54,6 @@ def stop(self) -> None: def _kill_process(pid: int) -> None: """Kill process.""" - print(f"Trying to kill process: {pid}") while True: if not psutil.pid_exists(pid=pid): return @@ -66,14 +64,7 @@ def _kill_process(pid: int) -> None: ): return try: - os.kill( - pid, - ( - signal.CTRL_C_EVENT # type: ignore - if platform.platform() == "Windows" - else signal.SIGKILL - ), - ) + process.kill() except OSError: return time.sleep(1) @@ -236,14 +227,15 @@ def _start_agent(self) -> None: """Start agent process.""" working_dir = self._work_directory env = json.loads((working_dir / "agent.json").read_text(encoding="utf-8")) + env = {**os.environ, **env} process = subprocess.Popen( # pylint: disable=consider-using-with # nosec args=[self._aea_bin, "run"], cwd=working_dir / "agent", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, - env={**os.environ, **env}, + env=env, creationflags=( - 0x00000008 if platform.system() == "Windows" else 0 + 0x00000200 if platform.system() == "Windows" else 0 ), # Detach process from the main process ) (working_dir / "agent.pid").write_text( @@ -255,15 +247,24 @@ def _start_tendermint(self) -> None: """Start tendermint process.""" working_dir = self._work_directory env = json.loads((working_dir / "tendermint.json").read_text(encoding="utf-8")) + env = { + **os.environ, + **env, + } + + if platform.system() == "Windows": + # to look up for bundled in tendermint.exe + env["PATH"] = os.environ["PATH"] + ";" + os.path.dirname(sys.executable) + tendermint_com = self._tendermint_bin # type: ignore # pylint: disable=protected-access process = subprocess.Popen( # pylint: disable=consider-using-with # nosec args=[tendermint_com], cwd=working_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, - env={**os.environ, **env}, + env=env, creationflags=( - 0x00000008 if platform.system() == "Windows" else 0 + 0x00000200 if platform.system() == "Windows" else 0 ), # Detach process from the main process ) (working_dir / "tendermint.pid").write_text( @@ -272,6 +273,25 @@ def _start_tendermint(self) -> None: ) +class PyInstallerHostDeploymentRunnerMac(PyInstallerHostDeploymentRunner): + """Mac deployment runner.""" + + +class PyInstallerHostDeploymentRunnerWindows(PyInstallerHostDeploymentRunner): + """Windows deployment runner.""" + + @property + def _aea_bin(self) -> str: + """Return aea_bin path.""" + abin = str(Path(sys._MEIPASS) / "aea_win.exe") # type: ignore # pylint: disable=protected-access + return abin + + @property + def _tendermint_bin(self) -> str: + """Return tendermint path.""" + return str(Path(sys._MEIPASS) / "tendermint_win.exe") # type: ignore # pylint: disable=protected-access + + class HostPythonHostDeploymentRunner(BaseDeploymentRunner): """Deployment runner for host installed python.""" @@ -368,8 +388,15 @@ def _setup_agent(self) -> None: def _get_host_deployment_runner(build_dir: Path) -> BaseDeploymentRunner: """Return depoyment runner according to running env.""" deployment_runner: BaseDeploymentRunner + if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): - deployment_runner = PyInstallerHostDeploymentRunner(build_dir) + # pyinstaller inside! + if platform.system() == "Darwin": + deployment_runner = PyInstallerHostDeploymentRunner(build_dir) + elif platform.system() == "Windows": + deployment_runner = PyInstallerHostDeploymentRunnerWindows(build_dir) + else: + raise ValueError(f"Platform not supported {platform.system()}") else: deployment_runner = HostPythonHostDeploymentRunner(build_dir) return deployment_runner diff --git a/operate/services/health_checker.py b/operate/services/health_checker.py index e1979be13..7a9c27373 100644 --- a/operate/services/health_checker.py +++ b/operate/services/health_checker.py @@ -34,19 +34,28 @@ class HealthChecker: """Health checker manager.""" - SLEEP_PERIOD = 30 - PORT_UP_TIMEOUT = 120 # seconds + SLEEP_PERIOD_DEFAULT = 30 + PORT_UP_TIMEOUT_DEFAULT = 120 # seconds + NUMBER_OF_FAILS_DEFAULT = 5 - def __init__(self, service_manager: ServiceManager) -> None: + def __init__( + self, + service_manager: ServiceManager, + port_up_timeout: int | None = None, + sleep_period: int | None = None, + number_of_fails: int | None = None, + ) -> None: """Init the healtch checker.""" self._jobs: t.Dict[str, asyncio.Task] = {} self.logger = setup_logger(name="operate.health_checker") - self.logger.info("[HEALTCHECKER]: created") self._service_manager = service_manager + self.port_up_timeout = port_up_timeout or self.PORT_UP_TIMEOUT_DEFAULT + 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: """Start for a specific service.""" - self.logger.info(f"[HEALTCHECKER]: Starting healthcheck job for {service}") + self.logger.info(f"[HEALTH_CHECKER]: Starting healthcheck job for {service}") if service in self._jobs: self.stop_for_service(service=service) @@ -62,12 +71,12 @@ def stop_for_service(self, service: str) -> None: if service not in self._jobs: return self.logger.info( - f"[HEALTCHECKER]: Cancelling existing healthcheck_jobs job for {service}" + f"[HEALTH_CHECKER]: Cancelling existing healthcheck_jobs job for {service}" ) status = self._jobs[service].cancel() if not status: self.logger.info( - f"[HEALTCHECKER]: Healthcheck job cancellation for {service} failed" + f"[HEALTH_CHECKER]: Healthcheck job cancellation for {service} failed" ) @staticmethod @@ -90,22 +99,24 @@ async def healthcheck_job( try: self.logger.info( - f"[HEALTCHECKER] Start healthcheck job for service: {service}" + f"[HEALTH_CHECKER] Start healthcheck job for service: {service}" ) async def _wait_for_port(sleep_period: int = 15) -> None: - self.logger.info("[HEALTCHECKER]: wait port is up") + self.logger.info("[HEALTH_CHECKER]: wait port is up") while True: try: await self.check_service_health(service) - self.logger.info("[HEALTCHECKER]: port is UP") + self.logger.info("[HEALTH_CHECKER]: port is UP") return except aiohttp.ClientConnectionError: - self.logger.error("[HEALTCHECKER]: error connecting http port") + self.logger.error( + "[HEALTH_CHECKER]: error connecting http port" + ) await asyncio.sleep(sleep_period) async def _check_port_ready( - timeout: int = self.PORT_UP_TIMEOUT, sleep_period: int = 15 + timeout: int = self.port_up_timeout, sleep_period: int = 15 ) -> bool: try: await asyncio.wait_for( @@ -116,7 +127,7 @@ async def _check_port_ready( return False async def _check_health( - number_of_fails: int = 5, sleep_period: int = self.SLEEP_PERIOD + number_of_fails: int = 5, sleep_period: int = self.sleep_period ) -> None: fails = 0 while True: @@ -125,24 +136,24 @@ async def _check_health( healthy = await self.check_service_health(service) except aiohttp.ClientConnectionError: self.logger.info( - f"[HEALTCHECKER] {service} port read failed. restart" + f"[HEALTH_CHECKER] {service} port read failed. restart" ) return if not healthy: fails += 1 self.logger.info( - f"[HEALTCHECKER] {service} not healthy for {fails} time in a row" + f"[HEALTH_CHECKER] {service} not healthy for {fails} time in a row" ) else: - self.logger.info(f"[HEALTCHECKER] {service} is HEALTHY") + self.logger.info(f"[HEALTH_CHECKER] {service} is HEALTHY") # reset fails if comes healty fails = 0 if fails >= number_of_fails: # too much fails, exit self.logger.error( - f"[HEALTCHECKER] {service} failed {fails} times in a row. restart" + f"[HEALTH_CHECKER] {service} failed {fails} times in a row. restart" ) return await asyncio.sleep(sleep_period) @@ -162,17 +173,20 @@ def _do_restart() -> None: # upper cycle while True: - self.logger.info(f"[HEALTCHECKER] {service} wait for port ready") - if await _check_port_ready(timeout=self.PORT_UP_TIMEOUT): + self.logger.info(f"[HEALTH_CHECKER] {service} wait for port ready") + if await _check_port_ready(timeout=self.port_up_timeout): # blocking till restart needed self.logger.info( - f"[HEALTCHECKER] {service} port is ready, checking health every {self.SLEEP_PERIOD}" + f"[HEALTH_CHECKER] {service} port is ready, checking health every {self.sleep_period}" + ) + await _check_health( + number_of_fails=self.number_of_fails, + sleep_period=self.sleep_period, ) - await _check_health(sleep_period=self.SLEEP_PERIOD) else: self.logger.info( - "[HEALTCHECKER] port not ready within timeout. restart deployment" + "[HEALTH_CHECKER] port not ready within timeout. restart deployment" ) # perform restart diff --git a/operate/services/manage.py b/operate/services/manage.py index 076701949..83ccb84e0 100644 --- a/operate/services/manage.py +++ b/operate/services/manage.py @@ -476,9 +476,6 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to # TODO fix this os.environ["CUSTOM_CHAIN_RPC"] = ledger_config.rpc - os.environ[ - "OPEN_AUTONOMY_SUBGRAPH_URL" - ] = "https://subgraph.autonolas.tech/subgraphs/name/autonolas-staging" current_agent_id = None if chain_data.token > -1: @@ -497,16 +494,25 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to user_params.staking_program_id ], ) - else: # TODO fix this - using pearl beta params + else: staking_params = dict( # nosec + staking_contract=NULL_ADDRESS, agent_ids=[25], service_registry="0x9338b5153AE39BB89f50468E608eD9d764B755fD", # nosec - staking_token="0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f", # nosec + staking_token=NULL_ADDRESS, # nosec service_registry_token_utility="0xa45E64d13A30a51b91ae0eb182e88a40e9b18eD8", # nosec min_staking_deposit=20000000000000000000, - activity_checker="0x155547857680A6D51bebC5603397488988DEb1c8", # nosec + activity_checker=NULL_ADDRESS, # nosec + 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"] + if user_params.use_staking: self.logger.info("Checking staking compatibility") @@ -541,9 +547,10 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to ) on_chain_hash = self._get_on_chain_hash(chain_config=chain_config) - current_agent_bond = staking_params[ - "min_staking_deposit" - ] # TODO fixme, read from service registry token utility contract + current_agent_bond = sftxb.get_agent_bond( + service_id=chain_data.token, agent_id=staking_params["agent_ids"][0] + ) + is_first_mint = ( self._get_on_chain_state(service=service, chain_id=chain_id) == OnChainState.NON_EXISTENT @@ -552,8 +559,9 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to (not is_first_mint) and (on_chain_hash is not None) and ( - on_chain_hash != service.hash - or current_agent_id != staking_params["agent_ids"][0] + # TODO Discuss how to manage on-chain hash updates with staking programs. + # on_chain_hash != service.hash or # noqa + current_agent_id != staking_params["agent_ids"][0] or current_agent_bond != staking_params["min_staking_deposit"] ) ) @@ -561,12 +569,15 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to chain_data, ledger_config, sftxb ) + self.logger.info(f"{chain_data.token=}") self.logger.info(f"{current_staking_program=}") self.logger.info(f"{user_params.staking_program_id=}") self.logger.info(f"{on_chain_hash=}") self.logger.info(f"{service.hash=}") self.logger.info(f"{current_agent_id=}") self.logger.info(f"{staking_params['agent_ids'][0]=}") + self.logger.info(f"{current_agent_bond=}") + self.logger.info(f"{staking_params['min_staking_deposit']=}") self.logger.info(f"{is_first_mint=}") self.logger.info(f"{is_update=}") diff --git a/operate/services/protocol.py b/operate/services/protocol.py index 5b122bb7e..1d5b28536 100644 --- a/operate/services/protocol.py +++ b/operate/services/protocol.py @@ -48,6 +48,7 @@ get_delployment_payload, get_reuse_multisig_payload, get_service_info, + get_token_deposit_amount, ) from autonomy.chain.tx import TxSettler from autonomy.cli.helpers.chain import MintHelper as MintManager @@ -572,6 +573,24 @@ def info(self, token_id: int) -> t.Dict: instances=instances, ) + def get_agent_bond(self, service_id: int, agent_id: int) -> int: + """Get the agent bond for a given service""" + self._patch() + + if service_id <= 0 or agent_id <= 0: + return 0 + + ledger_api, _ = OnChainHelper.get_ledger_and_crypto_objects( + chain_type=self.chain_type + ) + bond = get_token_deposit_amount( + ledger_api=ledger_api, + chain_type=self.chain_type, + service_id=service_id, + agent_id=agent_id, + ) + return bond + def get_service_safe_owners(self, service_id: int) -> t.List[str]: """Get list of owners.""" ledger_api, _ = OnChainHelper.get_ledger_and_crypto_objects( @@ -749,13 +768,18 @@ def get_staking_params(self, staking_contract: str) -> t.Dict: staking_contract=staking_contract, ) + # TODO Read from activity checker contract + agent_mech = "0x77af31De935740567Cf4fF1986D04B2c964A786a" # nosec + return dict( + staking_contract=staking_contract, agent_ids=agent_ids, service_registry=service_registry, staking_token=staking_token, service_registry_token_utility=service_registry_token_utility, min_staking_deposit=min_staking_deposit, activity_checker=activity_checker, + agent_mech=agent_mech, ) diff --git a/operate/services/service.py b/operate/services/service.py index 7e115f5ff..ab2d26315 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -21,8 +21,10 @@ import json import os +import platform import shutil import subprocess # nosec +import sys import typing as t from copy import copy, deepcopy from dataclasses import dataclass @@ -272,11 +274,17 @@ class HostDeploymentGenerator(BaseDeploymentGenerator): def generate_config_tendermint(self) -> "HostDeploymentGenerator": """Generate tendermint configuration.""" tmhome = str(self.build_dir / "node") + tendermint_executable = str( + shutil.which("tendermint"), + ) + # TODO: move all platform related things to a dedicated file + if platform.system() == "Windows": + tendermint_executable = str( + Path(os.path.dirname(sys.executable)) / "tendermint.exe" + ) subprocess.run( # pylint: disable=subprocess-run-check # nosec args=[ - str( - shutil.which("tendermint"), - ), + tendermint_executable, "--home", tmhome, "init", diff --git a/package.json b/package.json index f940d09a7..923160d70 100644 --- a/package.json +++ b/package.json @@ -58,5 +58,5 @@ "download-binaries": "sh download_binaries.sh", "build:pearl": "sh build_pearl.sh" }, - "version": "0.1.0-rc120" + "version": "0.1.0-rc127" } \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index fd3b19a72..5fce400d8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -178,22 +178,22 @@ files = [ [[package]] name = "attrs" -version = "23.2.0" +version = "24.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "backoff" @@ -404,74 +404,89 @@ files = [ [[package]] name = "certifi" -version = "2024.7.4" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] name = "cffi" -version = "1.16.0" +version = "1.17.0" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, + {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"}, ] [package.dependencies] @@ -694,63 +709,83 @@ requests = "*" [[package]] name = "coverage" -version = "7.6.0" +version = "7.6.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, - {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, - {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, - {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, - {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, - {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, - {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, - {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, - {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, - {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, - {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, - {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, - {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, - {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, + {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"}, ] [package.extras] @@ -758,38 +793,38 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "43.0.0" +version = "43.0.1" 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.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:64c3f16e2a4fc51c0d06af28441881f98c5d91009b8caaff40cf3548089e9c74"}, - {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dcdedae5c7710b9f97ac6bba7e1052b95c7083c9d0e9df96e02a1932e777895"}, - {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d9a1eca329405219b605fac09ecfc09ac09e595d6def650a437523fcd08dd22"}, - {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ea9e57f8ea880eeea38ab5abf9fbe39f923544d7884228ec67d666abd60f5a47"}, - {file = "cryptography-43.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9a8d6802e0825767476f62aafed40532bd435e8a5f7d23bd8b4f5fd04cc80ecf"}, - {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:cc70b4b581f28d0a254d006f26949245e3657d40d8857066c2ae22a61222ef55"}, - {file = "cryptography-43.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4a997df8c1c2aae1e1e5ac49c2e4f610ad037fc5a3aadc7b64e39dea42249431"}, - {file = "cryptography-43.0.0-cp37-abi3-win32.whl", hash = "sha256:6e2b11c55d260d03a8cf29ac9b5e0608d35f08077d8c087be96287f43af3ccdc"}, - {file = "cryptography-43.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:31e44a986ceccec3d0498e16f3d27b2ee5fdf69ce2ab89b52eaad1d2f33d8778"}, - {file = "cryptography-43.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:7b3f5fe74a5ca32d4d0f302ffe6680fcc5c28f8ef0dc0ae8f40c0f3a1b4fca66"}, - {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac1955ce000cb29ab40def14fd1bbfa7af2017cca696ee696925615cafd0dce5"}, - {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:299d3da8e00b7e2b54bb02ef58d73cd5f55fb31f33ebbf33bd00d9aa6807df7e"}, - {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ee0c405832ade84d4de74b9029bedb7b31200600fa524d218fc29bfa371e97f5"}, - {file = "cryptography-43.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb013933d4c127349b3948aa8aaf2f12c0353ad0eccd715ca789c8a0f671646f"}, - {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fdcb265de28585de5b859ae13e3846a8e805268a823a12a4da2597f1f5afc9f0"}, - {file = "cryptography-43.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2905ccf93a8a2a416f3ec01b1a7911c3fe4073ef35640e7ee5296754e30b762b"}, - {file = "cryptography-43.0.0-cp39-abi3-win32.whl", hash = "sha256:47ca71115e545954e6c1d207dd13461ab81f4eccfcb1345eac874828b5e3eaaf"}, - {file = "cryptography-43.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:0663585d02f76929792470451a5ba64424acc3cd5227b03921dab0e2f27b1709"}, - {file = "cryptography-43.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c6d112bf61c5ef44042c253e4859b3cbbb50df2f78fa8fae6747a7814484a70"}, - {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:844b6d608374e7d08f4f6e6f9f7b951f9256db41421917dfb2d003dde4cd6b66"}, - {file = "cryptography-43.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:51956cf8730665e2bdf8ddb8da0056f699c1a5715648c1b0144670c1ba00b48f"}, - {file = "cryptography-43.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:aae4d918f6b180a8ab8bf6511a419473d107df4dbb4225c7b48c5c9602c38c7f"}, - {file = "cryptography-43.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:232ce02943a579095a339ac4b390fbbe97f5b5d5d107f8a08260ea2768be8cc2"}, - {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5bcb8a5620008a8034d39bce21dc3e23735dfdb6a33a06974739bfa04f853947"}, - {file = "cryptography-43.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:08a24a7070b2b6804c1940ff0f910ff728932a9d0e80e7814234269f9d46d069"}, - {file = "cryptography-43.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e9c5266c432a1e23738d178e51c2c7a5e2ddf790f248be939448c0ba2021f9d1"}, - {file = "cryptography-43.0.0.tar.gz", hash = "sha256:b88075ada2d51aa9f18283532c9f60e72170041bba88d7f37e49cbb10275299e"}, + {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"}, ] [package.dependencies] @@ -802,7 +837,7 @@ nox = ["nox"] pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.0)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "cryptography-vectors (==43.0.1)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] @@ -1347,13 +1382,13 @@ files = [ [[package]] name = "googleapis-common-protos" -version = "1.63.2" +version = "1.65.0" description = "Common protobufs used in Google APIs" optional = false python-versions = ">=3.7" files = [ - {file = "googleapis-common-protos-1.63.2.tar.gz", hash = "sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87"}, - {file = "googleapis_common_protos-1.63.2-py2.py3-none-any.whl", hash = "sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945"}, + {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"}, ] [package.dependencies] @@ -1403,61 +1438,61 @@ files = [ [[package]] name = "grpcio" -version = "1.65.1" +version = "1.66.1" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.65.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:3dc5f928815b8972fb83b78d8db5039559f39e004ec93ebac316403fe031a062"}, - {file = "grpcio-1.65.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8333ca46053c35484c9f2f7e8d8ec98c1383a8675a449163cea31a2076d93de8"}, - {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:7af64838b6e615fff0ec711960ed9b6ee83086edfa8c32670eafb736f169d719"}, - {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb64b4166362d9326f7efbf75b1c72106c1aa87f13a8c8b56a1224fac152f5c"}, - {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8422dc13ad93ec8caa2612b5032a2b9cd6421c13ed87f54db4a3a2c93afaf77"}, - {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4effc0562b6c65d4add6a873ca132e46ba5e5a46f07c93502c37a9ae7f043857"}, - {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a6c71575a2fedf259724981fd73a18906513d2f306169c46262a5bae956e6364"}, - {file = "grpcio-1.65.1-cp310-cp310-win32.whl", hash = "sha256:34966cf526ef0ea616e008d40d989463e3db157abb213b2f20c6ce0ae7928875"}, - {file = "grpcio-1.65.1-cp310-cp310-win_amd64.whl", hash = "sha256:ca931de5dd6d9eb94ff19a2c9434b23923bce6f767179fef04dfa991f282eaad"}, - {file = "grpcio-1.65.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:bbb46330cc643ecf10bd9bd4ca8e7419a14b6b9dedd05f671c90fb2c813c6037"}, - {file = "grpcio-1.65.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d827a6fb9215b961eb73459ad7977edb9e748b23e3407d21c845d1d8ef6597e5"}, - {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:6e71aed8835f8d9fbcb84babc93a9da95955d1685021cceb7089f4f1e717d719"}, - {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a1c84560b3b2d34695c9ba53ab0264e2802721c530678a8f0a227951f453462"}, - {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27adee2338d697e71143ed147fe286c05810965d5d30ec14dd09c22479bfe48a"}, - {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f62652ddcadc75d0e7aa629e96bb61658f85a993e748333715b4ab667192e4e8"}, - {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:71a05fd814700dd9cb7d9a507f2f6a1ef85866733ccaf557eedacec32d65e4c2"}, - {file = "grpcio-1.65.1-cp311-cp311-win32.whl", hash = "sha256:b590f1ad056294dfaeac0b7e1b71d3d5ace638d8dd1f1147ce4bd13458783ba8"}, - {file = "grpcio-1.65.1-cp311-cp311-win_amd64.whl", hash = "sha256:12e9bdf3b5fd48e5fbe5b3da382ad8f97c08b47969f3cca81dd9b36b86ed39e2"}, - {file = "grpcio-1.65.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:54cb822e177374b318b233e54b6856c692c24cdbd5a3ba5335f18a47396bac8f"}, - {file = "grpcio-1.65.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aaf3c54419a28d45bd1681372029f40e5bfb58e5265e3882eaf21e4a5f81a119"}, - {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:557de35bdfbe8bafea0a003dbd0f4da6d89223ac6c4c7549d78e20f92ead95d9"}, - {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bfd95ef3b097f0cc86ade54eafefa1c8ed623aa01a26fbbdcd1a3650494dd11"}, - {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6a8f3d6c41e6b642870afe6cafbaf7b61c57317f9ec66d0efdaf19db992b90"}, - {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1faaf7355ceed07ceaef0b9dcefa4c98daf1dd8840ed75c2de128c3f4a4d859d"}, - {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:60f1f38eed830488ad2a1b11579ef0f345ff16fffdad1d24d9fbc97ba31804ff"}, - {file = "grpcio-1.65.1-cp312-cp312-win32.whl", hash = "sha256:e75acfa52daf5ea0712e8aa82f0003bba964de7ae22c26d208cbd7bc08500177"}, - {file = "grpcio-1.65.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff5a84907e51924973aa05ed8759210d8cdae7ffcf9e44fd17646cf4a902df59"}, - {file = "grpcio-1.65.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:1fbd6331f18c3acd7e09d17fd840c096f56eaf0ef830fbd50af45ae9dc8dfd83"}, - {file = "grpcio-1.65.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:de5b6be29116e094c5ef9d9e4252e7eb143e3d5f6bd6d50a78075553ab4930b0"}, - {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:e4a3cdba62b2d6aeae6027ae65f350de6dc082b72e6215eccf82628e79efe9ba"}, - {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941c4869aa229d88706b78187d60d66aca77fe5c32518b79e3c3e03fc26109a2"}, - {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f40cebe5edb518d78b8131e87cb83b3ee688984de38a232024b9b44e74ee53d3"}, - {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2ca684ba331fb249d8a1ce88db5394e70dbcd96e58d8c4b7e0d7b141a453dce9"}, - {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8558f0083ddaf5de64a59c790bffd7568e353914c0c551eae2955f54ee4b857f"}, - {file = "grpcio-1.65.1-cp38-cp38-win32.whl", hash = "sha256:8d8143a3e3966f85dce6c5cc45387ec36552174ba5712c5dc6fcc0898fb324c0"}, - {file = "grpcio-1.65.1-cp38-cp38-win_amd64.whl", hash = "sha256:76e81a86424d6ca1ce7c16b15bdd6a964a42b40544bf796a48da241fdaf61153"}, - {file = "grpcio-1.65.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb5175f45c980ff418998723ea1b3869cce3766d2ab4e4916fbd3cedbc9d0ed3"}, - {file = "grpcio-1.65.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b12c1aa7b95abe73b3e04e052c8b362655b41c7798da69f1eaf8d186c7d204df"}, - {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:3019fb50128b21a5e018d89569ffaaaa361680e1346c2f261bb84a91082eb3d3"}, - {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ae15275ed98ea267f64ee9ddedf8ecd5306a5b5bb87972a48bfe24af24153e8"}, - {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f096ffb881f37e8d4f958b63c74bfc400c7cebd7a944b027357cd2fb8d91a57"}, - {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2f56b5a68fdcf17a0a1d524bf177218c3c69b3947cb239ea222c6f1867c3ab68"}, - {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:941596d419b9736ab548aa0feb5bbba922f98872668847bf0720b42d1d227b9e"}, - {file = "grpcio-1.65.1-cp39-cp39-win32.whl", hash = "sha256:5fd7337a823b890215f07d429f4f193d24b80d62a5485cf88ee06648591a0c57"}, - {file = "grpcio-1.65.1-cp39-cp39-win_amd64.whl", hash = "sha256:1bceeec568372cbebf554eae1b436b06c2ff24cfaf04afade729fb9035408c6c"}, - {file = "grpcio-1.65.1.tar.gz", hash = "sha256:3c492301988cd720cd145d84e17318d45af342e29ef93141228f9cd73222368b"}, + {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"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.65.1)"] +protobuf = ["grpcio-tools (>=1.66.1)"] [[package]] name = "h11" @@ -1489,24 +1524,24 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= [[package]] name = "idna" -version = "3.7" +version = "3.8" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] [[package]] name = "importlib-metadata" -version = "8.2.0" +version = "8.4.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"}, - {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"}, + {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, + {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, ] [package.dependencies] @@ -1936,7 +1971,10 @@ 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", optional = true, markers = "extra == \"all\""} +pyyaml = [ + {version = ">=6.0.1,<7"}, + {version = ">=6.0.1,<9", optional = true, markers = "extra == \"all\""}, +] requests = ">=2.28.1,<3" semver = ">=2.9.1,<3.0.0" @@ -2076,13 +2114,13 @@ files = [ [[package]] name = "paramiko" -version = "3.4.0" +version = "3.4.1" description = "SSH2 protocol library" optional = false python-versions = ">=3.6" files = [ - {file = "paramiko-3.4.0-py3-none-any.whl", hash = "sha256:43f0b51115a896f9c00f59618023484cb3a14b98bbceab43394a39c6739b7ee7"}, - {file = "paramiko-3.4.0.tar.gz", hash = "sha256:aac08f26a31dc4dffd92821527d1682d99d52f9ef6851968114a8728f3c274d3"}, + {file = "paramiko-3.4.1-py3-none-any.whl", hash = "sha256:8e49fd2f82f84acf7ffd57c64311aa2b30e575370dc23bdb375b10262f7eac32"}, + {file = "paramiko-3.4.1.tar.gz", hash = "sha256:8b15302870af7f6652f2e038975c1d2973f06046cb5d7d65355668b3ecbece0c"}, ] [package.dependencies] @@ -2111,13 +2149,13 @@ regex = ">=2022.3.15" [[package]] name = "pefile" -version = "2023.2.7" +version = "2024.8.26" description = "Python PE parsing module" optional = false python-versions = ">=3.6.0" files = [ - {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, - {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, + {file = "pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f"}, + {file = "pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632"}, ] [[package]] @@ -2418,23 +2456,23 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pyinstaller" -version = "6.9.0" +version = "6.10.0" description = "PyInstaller bundles a Python application and all its dependencies into a single package." optional = false -python-versions = "<3.13,>=3.8" +python-versions = "<3.14,>=3.8" files = [ - {file = "pyinstaller-6.9.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:5ced2e83acf222b936ea94abc5a5cc96588705654b39138af8fb321d9cf2b954"}, - {file = "pyinstaller-6.9.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:f18a3d551834ef8fb7830d48d4cc1527004d0e6b51ded7181e78374ad6111846"}, - {file = "pyinstaller-6.9.0-py3-none-manylinux2014_i686.whl", hash = "sha256:f2fc568de3d6d2a176716a3fc9f20da06d351e8bea5ddd10ecb5659fce3a05b0"}, - {file = "pyinstaller-6.9.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:a0f378f64ad0655d11ade9fde7877e7573fd3d5066231608ce7dfa9040faecdd"}, - {file = "pyinstaller-6.9.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:7bf0c13c5a8560c89540746ae742f4f4b82290e95a6b478374d9f34959fe25d6"}, - {file = "pyinstaller-6.9.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:da994aba14c5686db88796684de265a8665733b4df09b939f7ebdf097d18df72"}, - {file = "pyinstaller-6.9.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:4e3e50743c091a06e6d01c59bdd6d03967b453ee5384a9e790759be4129db4a4"}, - {file = "pyinstaller-6.9.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:b041be2fe78da47a269604d62c940d68c62f9a3913bdf64af4123f7689d47099"}, - {file = "pyinstaller-6.9.0-py3-none-win32.whl", hash = "sha256:2bf4de17a1c63c0b797b38e13bfb4d03b5ee7c0a68e28b915a7eaacf6b76087f"}, - {file = "pyinstaller-6.9.0-py3-none-win_amd64.whl", hash = "sha256:43709c70b1da8441a730327a8ed362bfcfdc3d42c1bf89f3e2b0a163cc4e7d33"}, - {file = "pyinstaller-6.9.0-py3-none-win_arm64.whl", hash = "sha256:f15c1ef11ed5ceb32447dfbdab687017d6adbef7fc32aa359d584369bfe56eda"}, - {file = "pyinstaller-6.9.0.tar.gz", hash = "sha256:f4a75c552facc2e2a370f1e422b971b5e5cdb4058ff38cea0235aa21fc0b378f"}, + {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"}, ] [package.dependencies] @@ -2443,7 +2481,7 @@ 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.7" +pyinstaller-hooks-contrib = ">=2024.8" pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} setuptools = ">=42.0.0" @@ -2453,13 +2491,13 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2024.7" +version = "2024.8" description = "Community maintained hooks for PyInstaller" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pyinstaller_hooks_contrib-2024.7-py2.py3-none-any.whl", hash = "sha256:8bf0775771fbaf96bcd2f4dfd6f7ae6c1dd1b1efe254c7e50477b3c08e7841d8"}, - {file = "pyinstaller_hooks_contrib-2024.7.tar.gz", hash = "sha256:fd5f37dcf99bece184e40642af88be16a9b89613ecb958a8bd1136634fc9fac5"}, + {file = "pyinstaller_hooks_contrib-2024.8-py3-none-any.whl", hash = "sha256:0057fe9a5c398d3f580e73e58793a1d4a8315ca91c3df01efea1c14ed557825a"}, + {file = "pyinstaller_hooks_contrib-2024.8.tar.gz", hash = "sha256:29b68d878ab739e967055b56a93eb9b58e529d5b054fbab7a2f2bacf80cef3e2"}, ] [package.dependencies] @@ -2635,13 +2673,13 @@ files = [ [[package]] name = "pywin32-ctypes" -version = "0.2.2" +version = "0.2.3" description = "A (partial) reimplementation of pywin32 using ctypes/cffi" optional = false python-versions = ">=3.6" files = [ - {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"}, - {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"}, + {file = "pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"}, + {file = "pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"}, ] [[package]] @@ -2861,19 +2899,23 @@ files = [ [[package]] name = "setuptools" -version = "71.1.0" +version = "74.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"}, - {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"}, + {file = "setuptools-74.1.1-py3-none-any.whl", hash = "sha256:fc91b5f89e392ef5b77fe143b17e32f65d3024744fba66dc3afe07201684d766"}, + {file = "setuptools-74.1.1.tar.gz", hash = "sha256:2353af060c06388be1cecbf5953dcdb1f38362f87a2356c480b6b4d5fcfc8847"}, ] [package.extras] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] -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"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +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)"] +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"] [[package]] name = "six" @@ -3112,43 +3154,41 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "watchdog" -version = "4.0.1" +version = "5.0.2" description = "Filesystem events monitoring" optional = false -python-versions = ">=3.8" -files = [ - {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"}, - {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"}, - {file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"}, - {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"}, - {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"}, - {file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"}, - {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"}, - {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"}, - {file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"}, - {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"}, - {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"}, - {file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"}, - {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"}, - {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"}, - {file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"}, - {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"}, - {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"}, - {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"}, - {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"}, - {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"}, - {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"}, - {file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"}, - {file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"}, - {file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"}, - {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"}, - {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"}, - {file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"}, - {file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"}, - {file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"}, - {file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"}, - {file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"}, - {file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"}, +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"}, ] [package.extras] @@ -3203,83 +3243,97 @@ six = "*" [[package]] name = "websockets" -version = "12.0" +version = "13.0.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false python-versions = ">=3.8" files = [ - {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, - {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, - {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, - {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, - {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, - {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, - {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, - {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, - {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, - {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, - {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, - {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, - {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, - {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, - {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, - {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, - {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, - {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, - {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, - {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, - {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, - {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, - {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, - {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, - {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, + {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"}, ] [[package]] @@ -3298,101 +3352,103 @@ watchdog = ["watchdog"] [[package]] name = "yarl" -version = "1.9.4" +version = "1.9.8" description = "Yet another URL library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, + {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"}, ] [package.dependencies] @@ -3401,18 +3457,22 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.19.2" +version = "3.20.1" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, - {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, + {file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"}, + {file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"}, ] [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"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] [metadata] lock-version = "2.0" diff --git a/pyproject.toml b/pyproject.toml index a02e08312..aa2516ec9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "olas-operate-middleware" -version = "0.1.0-rc120" +version = "0.1.0-rc127" description = "" authors = ["David Vilela ", "Viraj Patel "] readme = "README.md" diff --git a/templates/trader.yaml b/templates/trader.yaml index ed0b8679d..adabec45b 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -1,6 +1,6 @@ name: "Trader Agent" description: "A single-agent service (sovereign agent) placing bets on Omen" -hash: bafybeicrstlxew36hlxl7pzi73nmd44aibnhwxzkchzlec6t6yhvs7gvhy +hash: bafybeidu3e3hdx5qt3bclheo7opr4adiil6zs2cger6m733qvhttnlo6na image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 service_version: v0.18.1 home_chain_id: 100