diff --git a/.github/workflows/release_win.yml b/.github/workflows/release_win.yml
new file mode 100644
index 000000000..d08ac95a3
--- /dev/null
+++ b/.github/workflows/release_win.yml
@@ -0,0 +1,60 @@
+name: Release for Windows
+
+# This workflow is triggered on pushing a tag BE CAREFUL this application AUTO UPDATES !!!
+# git tag vX.Y.Z
+# git push origin tag vX.Y.Z
+
+on: [pull_request]
+
+jobs:
+ build-windows:
+ runs-on: windows-latest
+ #strategy:
+ # matrix:
+ # arch: [ x64, arm64 ]
+ 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.4.0'
+ virtualenvs-create: true
+ virtualenvs-in-project: false
+ virtualenvs-path: ~/my-custom-path
+ installer-parallel: true
+ #- name: Setup tmate session
+ # uses: mxschmitt/action-tmate@v3
+ - 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
+ - run: rm -rf /dist
+ - name: "Build, notarize, publish"
+ run: make build
diff --git a/.gitleaksignore b/.gitleaksignore
index 33c8c27cf..95964f4b2 100644
--- a/.gitleaksignore
+++ b/.gitleaksignore
@@ -29,4 +29,7 @@ d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-
99c0f139b037da2587708212fcf6d0e20786d0ba:operate/services/manage.py:generic-api-key:455
91ec07457f69e9a29f63693ac8ef887e4b5f49f0:operate/services/manage.py:generic-api-key:454
410bea2bd02ff54da69387fe8f3b58793e09f7b0:operate/services/manage.py:generic-api-key:421
-410bea2bd02ff54da69387fe8f3b58793e09f7b0:operate/services/manage.py:generic-api-key:422
\ No newline at end of file
+410bea2bd02ff54da69387fe8f3b58793e09f7b0:operate/services/manage.py:generic-api-key:422
+467e8e64f51fb3659e5af17ba53ab587ec24fc30:operate/services/manage.py:generic-api-key:290
+64afe2ea92daafa2515c054f0e09931622d99f31:operate/services/manage.py:generic-api-key:290
+64afe2ea92daafa2515c054f0e09931622d99f31:operate/services/manage.py:generic-api-key:289
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..1afb34116
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,52 @@
+
+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: ./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
+
+
+.PHONY: operate
+operate: ./dist/pearl_win.exe
+
+.PHONY: build
+build: ./dist/pearl_win.exe
+ $(call setup_env, prod)
+ echo ${DEV_RPC}
+ mkdir -p ./electron/bins
+ 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 build-win.js
+
+
+.PHONY: build-tenderly
+build-tenderly: ./dist/pearl_win.exe
+ $(call setup_env, dev-tenderly)
+ echo ${DEV_RPC}
+ cp -f dist/pearl_win.exe ./electron/bins/pearl_win.exe
+ echo ${NODE_ENV}
+ NODE_ENV=${NODE_ENV} DEV_RPC=${DEV_RPC} FORK_URL=${FORK_URL} yarn build:frontend
+ node build-win-tenderly.js
\ No newline at end of file
diff --git a/README.md b/README.md
index 8eb3551aa..76b4ede77 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,6 @@ Pearl is an application used to run autonomous agents powered by the OLAS Networ
- Javascript / TypeScript
- Python (3.10)
- Poetry (^1.7.1)
-- Docker Engine
## Getting Started
@@ -26,7 +25,7 @@ The following installation steps assume you have the following on each OS:
NodeJS
-NodeJS is best installed and managed through NVM. It allows you to install and select specific versions of NodeJS. Pearl has been built using version 20.11, LTS.
+NodeJS is best installed and managed through NVM. It allows you to install and select specific versions of NodeJS. Pearl has been built using version 20 LTS.
Linux
@@ -117,38 +116,6 @@ If promoted to run `pipx ensurepath`, run it.
-Docker
-
-Linux
-
-*Update the `ubuntu.22.04~jammy` version string to your current OS version before running the following command:*
-
-```bash
-VERSION_STRING=5:24.0.7-1~ubuntu.22.04~jammy
-sudo apt-get install docker-ce=$VERSION_STRING docker-ce-cli=$VERSION_STRING containerd.io docker-buildx-plugin docker-compose-plugin
-sudo usermod -aG docker $USER
-```
-
-If you are unsure about your current OS version/codename, you can find it by running:
-
-```bash
-lsb_release -a
-```
-
-MacOS
-
-You can [install Docker Desktop via the Docker website](https://www.docker.com/products/docker-desktop/). Be sure to select the correct version for your system's CPU architecture.
-
-If you are unsure about your system's CPU architecture, run the following command:
-
-```bash
-uname -p
-# x86 64 Intel chip
-# arm64 Apple chip
-```
-
-
-
Setting up your .env file
Create an `.env` file in the root directory, or rename `.env.example` to `.env`.
@@ -202,7 +169,7 @@ Provided your system dependencies are installed, environment variables are set,
You can start Pearl by running the following command in the root directory:
```bash
-yarn start
+yarn dev
```
This will run Electron, which launches the NextJS frontend and the Python backend as child processes.
@@ -254,9 +221,4 @@ poetry run python scripts/fund.py 0xYOURADDRESS
poetry run python scripts/transfer_olas.py PATH_TO_KEY_CONTAINING_OLAS ADDRESS_TO_TRANSFER AMOUNT
```
-
-
-Notes and Common Issues
-
-- If Pearl is running, it will kill any attempt to run another Pearl instance. This is to ensure there are no port conflicts.
-- Enivironment variables are cached in the terminal, if you change them while your terminal is open, you will need to restart the terminal.
\ No newline at end of file
+
\ 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..8575e448a
--- /dev/null
+++ b/build-win.js
@@ -0,0 +1,48 @@
+/**
+ * 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,
+ },
+ publish: publishOptions,
+ category: 'public.app-category.utilities',
+ 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 2c3de2faa..6e4cf4807 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.0rc115';
+const OlasMiddlewareVersion = '0.1.0rc120';
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..a1035a227 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 = {
@@ -334,6 +337,7 @@ async function launchDaemon() {
}
async function launchDaemonDev() {
+
const check = new Promise(function (resolve, _reject) {
operateDaemon = spawn('poetry', [
'run',
@@ -398,6 +402,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 +446,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);
}
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/components/MainPage/sections/AddFundsSection.tsx b/frontend/components/MainPage/sections/AddFundsSection.tsx
index 97bf85641..ad3e17053 100644
--- a/frontend/components/MainPage/sections/AddFundsSection.tsx
+++ b/frontend/components/MainPage/sections/AddFundsSection.tsx
@@ -18,7 +18,6 @@ import styled from 'styled-components';
import { UNICODE_SYMBOLS } from '@/constants/symbols';
import { COW_SWAP_GNOSIS_XDAI_OLAS_URL } from '@/constants/urls';
import { useWallet } from '@/hooks/useWallet';
-import { Address } from '@/types/Address';
import { copyToClipboard } from '@/utils/copyToClipboard';
import { truncateAddress } from '@/utils/truncate';
@@ -35,23 +34,6 @@ const CustomizedCardSection = styled(CardSection)<{ border?: boolean }>`
export const AddFundsSection = () => {
const [isAddFundsVisible, setIsAddFundsVisible] = useState(false);
- const { masterSafeAddress } = useWallet();
-
- const fundingAddress: Address | undefined = masterSafeAddress;
-
- const truncatedFundingAddress: string | undefined = useMemo(
- () => fundingAddress && truncateAddress(fundingAddress),
- [fundingAddress],
- );
-
- const handleCopyAddress = useCallback(
- () =>
- fundingAddress &&
- copyToClipboard(fundingAddress).then(() =>
- message.success('Copied successfully!'),
- ),
- [fundingAddress],
- );
return (
<>
@@ -75,17 +57,36 @@ export const AddFundsSection = () => {
- {isAddFundsVisible && (
- <>
-
-
-
- >
- )}
+ {isAddFundsVisible && }
+ >
+ );
+};
+
+export const OpenAddFundsSection = () => {
+ const { masterSafeAddress } = useWallet();
+
+ const truncatedFundingAddress: string | undefined = useMemo(
+ () => masterSafeAddress && truncateAddress(masterSafeAddress),
+ [masterSafeAddress],
+ );
+
+ const handleCopyAddress = useCallback(
+ () =>
+ masterSafeAddress &&
+ copyToClipboard(masterSafeAddress).then(() =>
+ message.success('Copied successfully!'),
+ ),
+ [masterSafeAddress],
+ );
+ return (
+ <>
+
+
+
>
);
};
diff --git a/frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx b/frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx
index f2c1cf6cd..7df340884 100644
--- a/frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx
+++ b/frontend/components/ManageStakingPage/StakingContractSection/alerts.tsx
@@ -6,28 +6,35 @@ import { UNICODE_SYMBOLS } from '@/constants/symbols';
const { Text } = Typography;
export const AlertInsufficientMigrationFunds = ({
- totalOlasBalance,
+ masterSafeOlasBalance,
+ stakedOlasBalance,
+ totalOlasRequiredForStaking,
}: {
- totalOlasBalance: number;
-}) => (
-
-
- Insufficient amount of funds to switch
-
+ masterSafeOlasBalance: number;
+ stakedOlasBalance: number;
+ totalOlasRequiredForStaking: number;
+}) => {
+ const requiredOlasDeposit =
+ totalOlasRequiredForStaking - (stakedOlasBalance + masterSafeOlasBalance);
- Add funds to your account to meet the program requirements.
-
- Your current OLAS balance:{' '}
- {totalOlasBalance} OLAS
-
-
- }
- />
-);
+ 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 = () => (
{
const { goto } = usePageState();
- const { setServiceStatus, serviceStatus, setIsServicePollingPaused } =
- useServices();
+ const {
+ setServiceStatus,
+ serviceStatus,
+ setIsServicePollingPaused,
+ updateServiceStatus,
+ } = useServices();
const { serviceTemplate } = useServiceTemplates();
const { setMigrationModalOpen } = useModals();
const { activeStakingProgram, defaultStakingProgram, updateStakingProgram } =
useStakingProgram();
- const { stakingContractInfoRecord } = useStakingContractInfo();
const { token } = useToken();
- const { totalOlasBalance, isBalanceLoaded } = useBalance();
- const { isServiceStakedForMinimumDuration } = useStakingContractInfo();
+ const { safeBalance, totalOlasStakedBalance, isBalanceLoaded } = useBalance();
+ const { isServiceStakedForMinimumDuration, stakingContractInfoRecord } =
+ useStakingContractInfo();
+ const [isFundingSectionOpen, setIsFundingSectionOpen] = useState(false);
+
+ const stakingContractAddress =
+ SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS][
+ stakingProgram
+ ];
const stakingContractInfoForStakingProgram =
stakingContractInfoRecord?.[stakingProgram];
@@ -87,10 +96,15 @@ export const StakingContractSection = ({
);
const hasEnoughOlasToMigrate = useMemo(() => {
- if (totalOlasBalance === undefined) return false;
- if (!minimumOlasRequiredToMigrate) return false;
- return totalOlasBalance >= minimumOlasRequiredToMigrate;
- }, [minimumOlasRequiredToMigrate, totalOlasBalance]);
+ 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 &&
@@ -167,6 +181,7 @@ export const StakingContractSection = ({
isBalanceLoaded,
isSelected,
isServiceStakedForMinimumDuration,
+ minimumOlasRequiredToMigrate,
serviceStatus,
]);
@@ -179,9 +194,17 @@ export const StakingContractSection = ({
return ;
}
- if (!hasEnoughOlasToMigrate) {
+ if (
+ !hasEnoughOlasToMigrate &&
+ safeBalance?.OLAS !== undefined &&
+ totalOlasStakedBalance !== undefined
+ ) {
return (
-
+
);
}
@@ -191,10 +214,12 @@ export const StakingContractSection = ({
}, [
isSelected,
isBalanceLoaded,
- totalOlasBalance,
hasEnoughSlots,
hasEnoughOlasToMigrate,
isAppVersionCompatible,
+ safeBalance?.OLAS,
+ totalOlasStakedBalance,
+ minimumOlasRequiredToMigrate,
]);
const contractTagStatus = useMemo(() => {
@@ -213,40 +238,41 @@ export const StakingContractSection = ({
}, [activeStakingProgram, defaultStakingProgram, stakingProgram]);
return (
-
- {/* Title */}
-
- {`${activeStakingProgramMeta.name} contract`}
- {/* TODO: pass `status` attribute */}
-
- {!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: fix */}
-
- {/* Contract details
+ <>
+
+ {/* Title */}
+
+ {`${activeStakingProgramMeta.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 && (
)} */}
- {cantMigrateAlert}
- {/* Switch to program button */}
- {!isSelected && (
-
+ {cantMigrateAlert}
+ {/* Switch to program button */}
+ {stakingProgram !== StakingProgram.Alpha && (
+
+ {
+ setIsServicePollingPaused(true);
+ try {
+ setServiceStatus(DeploymentStatus.DEPLOYING);
+ goto(Pages.Main);
+ // TODO: cleanup and call via hook
+
+ await ServicesService.createService({
+ stakingProgram,
+ serviceTemplate,
+ deploy: true,
+ });
+
+ await updateStakingProgram();
+
+ setMigrationModalOpen(true);
+ } catch (error) {
+ console.error(error);
+ } finally {
+ setIsServicePollingPaused(false);
+ updateServiceStatus();
+ }
+ }}
+ >
+ Switch to {activeStakingProgramMeta?.name} contract
+
+
+ )}
+ {stakingProgram === StakingProgram.Beta && (
{
- setIsServicePollingPaused(true);
- try {
- setServiceStatus(DeploymentStatus.DEPLOYING);
- goto(Pages.Main);
- // TODO: cleanup and call via hook
-
- await ServicesService.createService({
- stakingProgram,
- serviceTemplate,
- deploy: true,
- }).then(() => {
- updateStakingProgram().then(() =>
- setMigrationModalOpen(true),
- );
- });
- } catch (error) {
- console.error(error);
- } finally {
- setIsServicePollingPaused(false);
- }
- }}
+ onClick={() => setIsFundingSectionOpen((prev) => !prev)}
>
- Switch to {activeStakingProgramMeta?.name} contract
+ {isFundingSectionOpen ? 'Hide' : 'Show'} address to fund
-
+ )}
+
+ {stakingProgram === StakingProgram.Beta && isFundingSectionOpen && (
+
)}
-
+ >
);
};
diff --git a/frontend/components/ManageStakingPage/index.tsx b/frontend/components/ManageStakingPage/index.tsx
index 310d19eca..82938256f 100644
--- a/frontend/components/ManageStakingPage/index.tsx
+++ b/frontend/components/ManageStakingPage/index.tsx
@@ -1,8 +1,6 @@
import { CloseOutlined } from '@ant-design/icons';
import { Button, Card } from 'antd';
-import { Chain } from '@/client';
-import { SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES } from '@/constants/contractAddresses';
import { Pages } from '@/enums/PageState';
import { StakingProgram } from '@/enums/StakingProgram';
import { usePageState } from '@/hooks/usePageState';
@@ -26,15 +24,8 @@ export const ManageStakingPage = () => {
}
>
- {Object.entries(
- SERVICE_STAKING_TOKEN_MECH_USAGE_CONTRACT_ADDRESSES[Chain.GNOSIS],
- ).map(([stakingProgram, contractAddress]) => (
-
- ))}
+
+
);
};
diff --git a/frontend/constants/serviceTemplates.ts b/frontend/constants/serviceTemplates.ts
index 19948f76a..3002a9736 100644
--- a/frontend/constants/serviceTemplates.ts
+++ b/frontend/constants/serviceTemplates.ts
@@ -4,7 +4,7 @@ import { StakingProgram } from '@/enums/StakingProgram';
export const SERVICE_TEMPLATES: ServiceTemplate[] = [
{
name: 'Trader Agent',
- hash: 'bafybeicrstlxew36hlxl7pzi73nmd44aibnhwxzkchzlec6t6yhvs7gvhy',
+ hash: 'bafybeihqtqgohejyebrb4jvd2fgccuasmqk3gc456ylyfa7tcn6rucdrxm',
// hash: 'bafybeibbloa4w33vj4bvdkso7pzk6tr3duvxjpecbx4mur4ix6ehnwb5uu', // temporary
description: 'Trader agent for omen prediction markets',
image:
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/_app.tsx b/frontend/pages/_app.tsx
index 42657f818..9227cb596 100644
--- a/frontend/pages/_app.tsx
+++ b/frontend/pages/_app.tsx
@@ -28,19 +28,19 @@ export default function App({ Component, pageProps }: AppProps) {
}, []);
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
{isMounted ? (
@@ -50,18 +50,18 @@ export default function App({ Component, pageProps }: AppProps) {
) : null}
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/operate/cli.py b/operate/cli.py
index 7d5285d13..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."""
@@ -530,8 +537,8 @@ async def _create_services(request: Request) -> JSONResponse:
if template.get("deploy", False):
def _fn() -> None:
+ # deploy_service_onchain_from_safe includes stake_service_on_chain_from_safe
manager.deploy_service_onchain_from_safe(hash=service.hash)
- # manager.stake_service_on_chain_from_safe(hash=service.hash) # Done inside deploy_service_onchain
manager.fund_service(hash=service.hash)
manager.deploy_service_locally(hash=service.hash)
@@ -556,8 +563,9 @@ async def _update_services(request: Request) -> JSONResponse:
)
if template.get("deploy", False):
manager = operate.service_manager()
+
+ # deploy_service_onchain_from_safe includes stake_service_on_chain_from_safe
manager.deploy_service_onchain_from_safe(hash=service.hash)
- # manager.stake_service_on_chain_from_safe(hash=service.hash) # Done in deploy_service_onchain_from_safe
manager.fund_service(hash=service.hash)
manager.deploy_service_locally(hash=service.hash)
schedule_funding_job(service=service.hash)
@@ -675,7 +683,7 @@ async def _start_service_locally(request: Request) -> JSONResponse:
def _fn() -> None:
manager.deploy_service_onchain(hash=service)
- # manager.stake_service_on_chain(hash=service)
+ manager.stake_service_on_chain(hash=service)
manager.fund_service(hash=service)
manager.deploy_service_locally(hash=service, force=True)
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/services/deployment_runner.py b/operate/services/deployment_runner.py
index 1bf81904e..79c8940dc 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)
@@ -243,7 +234,7 @@ def _start_agent(self) -> None:
stderr=subprocess.DEVNULL,
env={**os.environ, **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(
@@ -261,9 +252,13 @@ def _start_tendermint(self) -> None:
cwd=working_dir,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
- env={**os.environ, **env},
+ env={
+ **os.environ,
+ **env,
+ "PATH": os.environ["PATH"] + ";" + os.path.dirname(sys.executable),
+ },
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 +267,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 +382,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 6acf0b462..076701949 100644
--- a/operate/services/manage.py
+++ b/operate/services/manage.py
@@ -23,6 +23,7 @@
import logging
import os
import shutil
+import time
import traceback
import typing as t
from collections import Counter
@@ -115,21 +116,26 @@ def json(self) -> t.List[t.Dict]:
self.logger.warning(
f"Failed to load service: {path.name}. Exception: {e}"
)
- # delete the invalid path
- shutil.rmtree(path)
- self.logger.info(f"Deleted invalid service: {path.name}")
+ # rename the invalid path
+ timestamp = int(time.time())
+ invalid_path = path.parent / f"invalid_{timestamp}_{path.name}"
+ os.rename(path, invalid_path)
+ self.logger.info(
+ f"Renamed invalid service: {path.name} to {invalid_path.name}"
+ )
+
return data
def exists(self, service: str) -> bool:
"""Check if service exists."""
return (self.path / service).exists()
- def get_on_chain_manager(self, service: Service) -> OnChainManager:
+ def get_on_chain_manager(self, ledger_config: LedgerConfig) -> OnChainManager:
"""Get OnChainManager instance."""
return OnChainManager(
- rpc=service.ledger_config.rpc,
- wallet=self.wallet_manager.load(service.ledger_config.type),
- contracts=CONTRACTS[service.ledger_config.chain],
+ rpc=ledger_config.rpc,
+ wallet=self.wallet_manager.load(ledger_config.type),
+ contracts=CONTRACTS[ledger_config.chain],
)
def get_eth_safe_tx_builder(self, ledger_config: LedgerConfig) -> EthSafeTxBuilder:
@@ -159,7 +165,9 @@ def load_or_create(
service = Service.load(path=path)
if service_template is not None:
- service.update_user_params_from_template(service_template=service_template)
+ service.update_user_params_from_template(
+ service_template=service_template
+ )
return service
@@ -184,22 +192,21 @@ def load_or_create(
return service
- def _get_on_chain_state(self, chain_config: ChainConfig) -> OnChainState:
+ def _get_on_chain_state(self, service: Service, chain_id: str) -> OnChainState:
+ chain_config = service.chain_configs[chain_id]
chain_data = chain_config.chain_data
ledger_config = chain_config.ledger_config
if chain_data.token == NON_EXISTENT_TOKEN:
service_state = OnChainState.NON_EXISTENT
chain_data.on_chain_state = service_state
- # TODO save service state
- # service.store()
+ service.store()
return service_state
sftxb = self.get_eth_safe_tx_builder(ledger_config=ledger_config)
info = sftxb.info(token_id=chain_data.token)
service_state = OnChainState(info["service_state"])
chain_data.on_chain_state = service_state
- # TODO save service state
- # service.store()
+ service.store()
return service_state
def _get_on_chain_hash(self, chain_config: ChainConfig) -> t.Optional[str]:
@@ -218,10 +225,28 @@ def _get_on_chain_hash(self, chain_config: ChainConfig) -> t.Optional[str]:
f"Something went wrong while trying to get the code uri from IPFS: {res}"
)
- def deploy_service_onchain( # pylint: disable=too-many-statements
+ def deploy_service_onchain( # pylint: disable=too-many-statements,too-many-locals
self,
hash: str,
- update: bool = False,
+ ) -> None:
+ """
+ Deploy as service on-chain
+
+ :param hash: Service hash
+ """
+ # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version.
+
+ service = self.load_or_create(hash=hash)
+ for chain_id in service.chain_configs.keys():
+ self._deploy_service_onchain(
+ hash=hash,
+ chain_id=chain_id,
+ )
+
+ def _deploy_service_onchain( # pylint: disable=too-many-statements,too-many-locals
+ self,
+ hash: str,
+ chain_id: str,
) -> None:
"""
Deploy as service on-chain
@@ -229,49 +254,73 @@ def deploy_service_onchain( # pylint: disable=too-many-statements
:param hash: Service hash
:param update: Update the existing deployment
"""
- self.logger.info("Loading service")
+ # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version.
+
+ self.logger.info(f"_deploy_service_onchain_from_safe {chain_id=}")
service = self.load_or_create(hash=hash)
- user_params = service.chain_data.user_params
+ chain_config = service.chain_configs[chain_id]
+ ledger_config = chain_config.ledger_config
+ chain_data = chain_config.chain_data
+ user_params = chain_config.chain_data.user_params
keys = service.keys
instances = [key.address for key in keys]
- ocm = self.get_on_chain_manager(service=service)
- if user_params.use_staking and not ocm.staking_slots_available(
- staking_contract=STAKING[service.ledger_config.chain]
- ):
- raise ValueError("No staking slots available")
+ ocm = self.get_on_chain_manager(ledger_config=ledger_config)
- if user_params.use_staking and not ocm.staking_rewards_available(
- staking_contract=STAKING[service.ledger_config.chain]
- ):
- raise ValueError("No staking rewards available")
+ # 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"
- if service.chain_data.token > -1:
+ current_agent_id = None
+ if chain_data.token > -1:
self.logger.info("Syncing service state")
- info = ocm.info(token_id=service.chain_data.token)
- service.chain_data.on_chain_state = OnChainState(info["service_state"])
- service.chain_data.instances = info["instances"]
- service.chain_data.multisig = info["multisig"]
+ info = ocm.info(token_id=chain_data.token)
+ chain_data.on_chain_state = OnChainState(info["service_state"])
+ chain_data.instances = info["instances"]
+ chain_data.multisig = info["multisig"]
service.store()
- self.logger.info(f"Service state: {service.chain_data.on_chain_state.name}")
+ self.logger.info(f"Service state: {chain_data.on_chain_state.name}")
+
+ if user_params.use_staking:
+ staking_params = ocm.get_staking_params(
+ staking_contract=STAKING[ledger_config.chain][
+ user_params.staking_program_id
+ ],
+ )
+ else: # TODO fix this - using pearl beta params
+ staking_params = dict( # nosec
+ agent_ids=[25],
+ service_registry="0x9338b5153AE39BB89f50468E608eD9d764B755fD", # nosec
+ staking_token="0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f", # nosec
+ service_registry_token_utility="0xa45E64d13A30a51b91ae0eb182e88a40e9b18eD8", # nosec
+ min_staking_deposit=20000000000000000000,
+ activity_checker="0x155547857680A6D51bebC5603397488988DEb1c8", # nosec
+ )
if user_params.use_staking:
self.logger.info("Checking staking compatibility")
- if service.chain_data.on_chain_state in (
+
+ # TODO: Missing check when the service is currently staked in a program, but needs to be staked
+ # in a different target program. The In this case, balance = currently staked balance + safe balance
+
+ if chain_data.on_chain_state in (
OnChainState.NON_EXISTENT,
OnChainState.PRE_REGISTRATION,
):
required_olas = (
- user_params.olas_cost_of_bond + user_params.olas_required_to_stake
+ staking_params["min_staking_deposit"]
+ + staking_params["min_staking_deposit"] # bond = staking
)
- elif service.chain_data.on_chain_state == OnChainState.ACTIVE_REGISTRATION:
- required_olas = user_params.olas_required_to_stake
+ elif chain_data.on_chain_state == OnChainState.ACTIVE_REGISTRATION:
+ required_olas = staking_params["min_staking_deposit"]
else:
required_olas = 0
balance = (
registry_contracts.erc20.get_instance(
ledger_api=ocm.ledger_api,
- contract_address=OLAS[service.ledger_config.chain],
+ contract_address=OLAS[ledger_config.chain],
)
.functions.balanceOf(ocm.crypto.address)
.call()
@@ -282,91 +331,108 @@ def deploy_service_onchain( # pylint: disable=too-many-statements
f"required olas: {required_olas}; your balance {balance}"
)
- if service.chain_data.on_chain_state == OnChainState.NON_EXISTENT:
+ 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
+ is_first_mint = (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.NON_EXISTENT
+ )
+ is_update = (
+ (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]
+ or current_agent_bond != staking_params["min_staking_deposit"]
+ )
+ )
+ current_staking_program = self._get_current_staking_program(
+ chain_data, ledger_config, ocm # type: ignore # FIXME
+ )
+
+ 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"{is_first_mint=}")
+ self.logger.info(f"{is_update=}")
+
+ if chain_data.on_chain_state == OnChainState.NON_EXISTENT:
self.logger.info("Minting service")
- service.chain_data.token = t.cast(
+ chain_data.token = t.cast(
int,
ocm.mint(
package_path=service.service_path,
- agent_id=user_params.agent_id,
+ agent_id=staking_params["agent_ids"][0],
number_of_slots=service.helper.config.number_of_agents,
cost_of_bond=(
- user_params.olas_cost_of_bond
+ staking_params["min_staking_deposit"]
if user_params.use_staking
else user_params.cost_of_bond
),
threshold=user_params.threshold,
nft=IPFSHash(user_params.nft),
- update_token=service.chain_data.token if update else None,
+ update_token=chain_data.token if is_update else None,
token=(
- OLAS[service.ledger_config.chain]
- if user_params.use_staking
- else None
+ OLAS[ledger_config.chain] if user_params.use_staking else None
),
).get("token"),
)
- service.chain_data.on_chain_state = OnChainState.PRE_REGISTRATION
+ chain_data.on_chain_state = OnChainState.PRE_REGISTRATION
service.store()
- info = ocm.info(token_id=service.chain_data.token)
- service.chain_data.on_chain_state = OnChainState(info["service_state"])
+ info = ocm.info(token_id=chain_data.token)
+ chain_data.on_chain_state = OnChainState(info["service_state"])
- if service.chain_data.on_chain_state == OnChainState.PRE_REGISTRATION:
+ if chain_data.on_chain_state == OnChainState.PRE_REGISTRATION:
self.logger.info("Activating service")
ocm.activate(
- service_id=service.chain_data.token,
- token=(
- OLAS[service.ledger_config.chain]
- if user_params.use_staking
- else None
- ),
+ service_id=chain_data.token,
+ token=(OLAS[ledger_config.chain] if user_params.use_staking else None),
)
- service.chain_data.on_chain_state = OnChainState.ACTIVE_REGISTRATION
+ chain_data.on_chain_state = OnChainState.ACTIVE_REGISTRATION
service.store()
- info = ocm.info(token_id=service.chain_data.token)
- service.chain_data.on_chain_state = OnChainState(info["service_state"])
+ info = ocm.info(token_id=chain_data.token)
+ chain_data.on_chain_state = OnChainState(info["service_state"])
- if service.chain_data.on_chain_state == OnChainState.ACTIVE_REGISTRATION:
+ if chain_data.on_chain_state == OnChainState.ACTIVE_REGISTRATION:
self.logger.info("Registering agent instances")
+ agent_id = staking_params["agent_ids"][0]
ocm.register(
- service_id=service.chain_data.token,
+ service_id=chain_data.token,
instances=instances,
- agents=[user_params.agent_id for _ in instances],
- token=(
- OLAS[service.ledger_config.chain]
- if user_params.use_staking
- else None
- ),
+ agents=[agent_id for _ in instances],
+ token=(OLAS[ledger_config.chain] if user_params.use_staking else None),
)
- service.chain_data.on_chain_state = OnChainState.FINISHED_REGISTRATION
+ chain_data.on_chain_state = OnChainState.FINISHED_REGISTRATION
service.store()
- info = ocm.info(token_id=service.chain_data.token)
- service.chain_data.on_chain_state = OnChainState(info["service_state"])
+ info = ocm.info(token_id=chain_data.token)
+ chain_data.on_chain_state = OnChainState(info["service_state"])
- if service.chain_data.on_chain_state == OnChainState.FINISHED_REGISTRATION:
+ if chain_data.on_chain_state == OnChainState.FINISHED_REGISTRATION:
self.logger.info("Deploying service")
ocm.deploy(
- service_id=service.chain_data.token,
- reuse_multisig=update,
- token=(
- OLAS[service.ledger_config.chain]
- if user_params.use_staking
- else None
- ),
+ service_id=chain_data.token,
+ reuse_multisig=is_update,
+ token=(OLAS[ledger_config.chain] if user_params.use_staking else None),
)
- service.chain_data.on_chain_state = OnChainState.DEPLOYED
+ chain_data.on_chain_state = OnChainState.DEPLOYED
service.store()
- info = ocm.info(token_id=service.chain_data.token)
- service.chain_data = OnChainData(
- token=service.chain_data.token,
+ info = ocm.info(token_id=chain_data.token)
+ chain_data = OnChainData(
+ token=chain_data.token,
instances=info["instances"],
multisig=info["multisig"],
staked=False,
- on_chain_state=service.chain_data.on_chain_state,
- user_params=service.chain_data.user_params,
+ on_chain_state=chain_data.on_chain_state,
+ user_params=chain_data.user_params,
)
service.store()
@@ -410,7 +476,9 @@ 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"
+ os.environ[
+ "OPEN_AUTONOMY_SUBGRAPH_URL"
+ ] = "https://subgraph.autonolas.tech/subgraphs/name/autonolas-staging"
current_agent_id = None
if chain_data.token > -1:
@@ -425,16 +493,18 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
if user_params.use_staking:
staking_params = sftxb.get_staking_params(
- staking_contract=STAKING[ledger_config.chain][user_params.staking_program_id],
+ staking_contract=STAKING[ledger_config.chain][
+ user_params.staking_program_id
+ ],
)
else: # TODO fix this - using pearl beta params
- staking_params = dict(
+ staking_params = dict( # nosec
agent_ids=[25],
service_registry="0x9338b5153AE39BB89f50468E608eD9d764B755fD", # nosec
staking_token="0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f", # nosec
service_registry_token_utility="0xa45E64d13A30a51b91ae0eb182e88a40e9b18eD8", # nosec
min_staking_deposit=20000000000000000000,
- activity_checker="0x155547857680A6D51bebC5603397488988DEb1c8" # nosec
+ activity_checker="0x155547857680A6D51bebC5603397488988DEb1c8", # nosec
)
if user_params.use_staking:
@@ -448,7 +518,8 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
OnChainState.PRE_REGISTRATION,
):
required_olas = (
- staking_params["min_staking_deposit"] + staking_params["min_staking_deposit"] # bond = staking
+ staking_params["min_staking_deposit"]
+ + staking_params["min_staking_deposit"] # bond = staking
)
elif chain_data.on_chain_state == OnChainState.ACTIVE_REGISTRATION:
required_olas = staking_params["min_staking_deposit"]
@@ -470,13 +541,25 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
)
on_chain_hash = self._get_on_chain_hash(chain_config=chain_config)
- is_first_mint = self._get_on_chain_state(chain_config=chain_config) == OnChainState.NON_EXISTENT
+ current_agent_bond = staking_params[
+ "min_staking_deposit"
+ ] # TODO fixme, read from service registry token utility contract
+ is_first_mint = (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.NON_EXISTENT
+ )
is_update = (
(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])
+ and (
+ on_chain_hash != service.hash
+ or current_agent_id != staking_params["agent_ids"][0]
+ or current_agent_bond != staking_params["min_staking_deposit"]
+ )
+ )
+ current_staking_program = self._get_current_staking_program(
+ chain_data, ledger_config, sftxb
)
- current_staking_program = self._get_current_staking_program(chain_data, ledger_config, sftxb)
self.logger.info(f"{current_staking_program=}")
self.logger.info(f"{user_params.staking_program_id=}")
@@ -488,13 +571,13 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
self.logger.info(f"{is_update=}")
if is_update:
- self._terminate_service_on_chain_from_safe(
- hash=hash,
- chain_id=chain_id
- )
+ self._terminate_service_on_chain_from_safe(hash=hash, chain_id=chain_id)
# Update service
- if self._get_on_chain_state(chain_config=chain_config) == OnChainState.PRE_REGISTRATION:
+ if (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.PRE_REGISTRATION
+ ):
self.logger.info("Updating service")
receipt = (
sftxb.new_tx()
@@ -533,10 +616,14 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
service.store()
# Mint service
- if self._get_on_chain_state(chain_config=chain_config) == OnChainState.NON_EXISTENT:
-
+ if (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.NON_EXISTENT
+ ):
if user_params.use_staking and not sftxb.staking_slots_available(
- staking_contract=STAKING[ledger_config.chain][user_params.staking_program_id]
+ staking_contract=STAKING[ledger_config.chain][
+ user_params.staking_program_id
+ ]
):
raise ValueError("No staking slots available")
@@ -578,7 +665,10 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
chain_data.on_chain_state = OnChainState.PRE_REGISTRATION
service.store()
- if self._get_on_chain_state(chain_config=chain_config) == OnChainState.PRE_REGISTRATION:
+ if (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.PRE_REGISTRATION
+ ):
cost_of_bond = staking_params["min_staking_deposit"]
if user_params.use_staking:
token_utility = staking_params["service_registry_token_utility"]
@@ -628,7 +718,10 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
chain_data.on_chain_state = OnChainState.ACTIVE_REGISTRATION
service.store()
- if self._get_on_chain_state(chain_config=chain_config) == OnChainState.ACTIVE_REGISTRATION:
+ if (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.ACTIVE_REGISTRATION
+ ):
cost_of_bond = user_params.cost_of_bond
if user_params.use_staking:
token_utility = staking_params["service_registry_token_utility"]
@@ -682,7 +775,10 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
chain_data.on_chain_state = OnChainState.FINISHED_REGISTRATION
service.store()
- if self._get_on_chain_state(chain_config=chain_config) == OnChainState.FINISHED_REGISTRATION:
+ if (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.FINISHED_REGISTRATION
+ ):
self.logger.info("Deploying service")
reuse_multisig = True
@@ -695,7 +791,7 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
messages = sftxb.get_deploy_data_from_safe(
service_id=chain_data.token,
reuse_multisig=reuse_multisig,
- master_safe=sftxb.wallet.safe,
+ master_safe=sftxb.wallet.safe, # type: ignore # TODO fix mypy
)
tx = sftxb.new_tx()
for message in messages:
@@ -713,34 +809,48 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to
service.store()
self.stake_service_on_chain_from_safe(hash=hash, chain_id=chain_id)
- def terminate_service_on_chain(self, hash: str) -> None:
+ def terminate_service_on_chain(
+ self, hash: str, chain_id: t.Optional[str] = None
+ ) -> None:
"""
Terminate service on-chain
:param hash: Service hash
"""
+ # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version.
+
+ self.logger.info("terminate_service_on_chain")
service = self.load_or_create(hash=hash)
- ocm = self.get_on_chain_manager(service=service)
- info = ocm.info(token_id=service.chain_data.token)
- service.chain_data.on_chain_state = OnChainState(info["service_state"])
- if service.chain_data.on_chain_state != OnChainState.DEPLOYED:
+ if chain_id is None:
+ chain_id = service.home_chain_id
+
+ chain_config = service.chain_configs[chain_id]
+ ledger_config = chain_config.ledger_config
+ chain_data = chain_config.chain_data
+ ocm = self.get_on_chain_manager(ledger_config=ledger_config)
+ info = ocm.info(token_id=chain_data.token)
+ chain_data.on_chain_state = OnChainState(info["service_state"])
+
+ if chain_data.on_chain_state != OnChainState.DEPLOYED:
self.logger.info("Cannot terminate service")
return
self.logger.info("Terminating service")
ocm.terminate(
- service_id=service.chain_data.token,
+ service_id=chain_data.token,
token=(
- OLAS[service.ledger_config.chain]
- if service.chain_data.user_params.use_staking
+ OLAS[ledger_config.chain]
+ if chain_data.user_params.use_staking
else None
),
)
- service.chain_data.on_chain_state = OnChainState.TERMINATED_BONDED
+ chain_data.on_chain_state = OnChainState.TERMINATED_BONDED
service.store()
- def _terminate_service_on_chain_from_safe(self, hash: str, chain_id: str) -> None:
+ def _terminate_service_on_chain_from_safe( # pylint: disable=too-many-locals
+ self, hash: str, chain_id: str
+ ) -> None:
"""
Terminate service on-chain
@@ -763,7 +873,9 @@ def _terminate_service_on_chain_from_safe(self, hash: str, chain_id: str) -> Non
chain_data.on_chain_state = OnChainState(info["service_state"])
# Determine if the service is staked in a known staking program
- current_staking_program = self._get_current_staking_program(chain_data, ledger_config, sftxb)
+ current_staking_program = self._get_current_staking_program(
+ chain_data, ledger_config, sftxb
+ )
is_staked = current_staking_program is not None
can_unstake = False
@@ -780,9 +892,11 @@ def _terminate_service_on_chain_from_safe(self, hash: str, chain_id: str) -> Non
# Unstake the service if applies
if is_staked and can_unstake:
- self.unstake_service_on_chain_from_safe(hash=hash, chain_id=chain_id, staking_program_id=current_staking_program)
+ self.unstake_service_on_chain_from_safe(
+ hash=hash, chain_id=chain_id, staking_program_id=current_staking_program
+ )
- if self._get_on_chain_state(chain_config) in (
+ if self._get_on_chain_state(service=service, chain_id=chain_id) in (
OnChainState.ACTIVE_REGISTRATION,
OnChainState.FINISHED_REGISTRATION,
OnChainState.DEPLOYED,
@@ -794,7 +908,10 @@ def _terminate_service_on_chain_from_safe(self, hash: str, chain_id: str) -> Non
)
).settle()
- if self._get_on_chain_state(chain_config) == OnChainState.TERMINATED_BONDED:
+ if (
+ self._get_on_chain_state(service=service, chain_id=chain_id)
+ == OnChainState.TERMINATED_BONDED
+ ):
self.logger.info("Unbonding service")
sftxb.new_tx().add(
sftxb.get_unbond_data(
@@ -808,17 +925,34 @@ def _terminate_service_on_chain_from_safe(self, hash: str, chain_id: str) -> Non
counter_instances = Counter(s.lower() for s in instances)
if counter_current_safe_owners == counter_instances:
+ self.logger.info("Service funded for safe swap")
+ self.fund_service(
+ hash=hash,
+ rpc=ledger_config.rpc,
+ agent_topup=chain_data.user_params.fund_requirements.agent,
+ agent_fund_threshold=chain_data.user_params.fund_requirements.agent,
+ safe_topup=0,
+ safe_fund_treshold=0,
+ )
+
self.logger.info("Swapping Safe owners")
sftxb.swap( # noqa: E800
service_id=chain_data.token, # noqa: E800
multisig=chain_data.multisig, # TODO this can be read from the registry
owner_key=str(
- self.keys_manager.get(key=current_safe_owners[0]).private_key # TODO allow multiple owners
+ self.keys_manager.get(
+ key=current_safe_owners[0]
+ ).private_key # TODO allow multiple owners
), # noqa: E800
- new_owner_address=wallet.safe if wallet.safe else wallet.crypto.address # TODO it should always be safe address
+ new_owner_address=wallet.safe
+ if wallet.safe
+ else wallet.crypto.address, # TODO it should always be safe address
) # noqa: E800
- def _get_current_staking_program(self, chain_data, ledger_config, sftxb) -> t.Optional[str]:
+ @staticmethod
+ def _get_current_staking_program(
+ chain_data: OnChainData, ledger_config: LedgerConfig, sftxb: EthSafeTxBuilder
+ ) -> t.Optional[str]:
if chain_data.token == NON_EXISTENT_TOKEN:
return None
@@ -832,34 +966,45 @@ def _get_current_staking_program(self, chain_data, ledger_config, sftxb) -> t.Op
current_staking_program = staking_program
return current_staking_program
- def unbond_service_on_chain(self, hash: str) -> None:
+ def unbond_service_on_chain(
+ self, hash: str, chain_id: t.Optional[str] = None
+ ) -> None:
"""
Unbond service on-chain
:param hash: Service hash
"""
+ # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version.
+
service = self.load_or_create(hash=hash)
- ocm = self.get_on_chain_manager(service=service)
- info = ocm.info(token_id=service.chain_data.token)
- service.chain_data.on_chain_state = OnChainState(info["service_state"])
- if service.chain_data.on_chain_state != OnChainState.TERMINATED_BONDED:
+ if chain_id is None:
+ chain_id = service.home_chain_id
+
+ chain_config = service.chain_configs[chain_id]
+ ledger_config = chain_config.ledger_config
+ chain_data = chain_config.chain_data
+ ocm = self.get_on_chain_manager(ledger_config=ledger_config)
+ info = ocm.info(token_id=chain_data.token)
+ chain_data.on_chain_state = OnChainState(info["service_state"])
+
+ if chain_data.on_chain_state != OnChainState.TERMINATED_BONDED:
self.logger.info("Cannot unbond service")
return
self.logger.info("Unbonding service")
ocm.unbond(
- service_id=service.chain_data.token,
+ service_id=chain_data.token,
token=(
- OLAS[service.ledger_config.chain]
- if service.chain_data.user_params.use_staking
+ OLAS[ledger_config.chain]
+ if chain_data.user_params.use_staking
else None
),
)
- service.chain_data.on_chain_state = OnChainState.UNBONDED
+ chain_data.on_chain_state = OnChainState.UNBONDED
service.store()
- def stake_service_on_chain(self, hash: str, chain_id: int, staking_program_id: str) -> None:
+ def stake_service_on_chain(self, hash: str) -> None:
"""
Stake service on-chain
@@ -867,7 +1012,9 @@ def stake_service_on_chain(self, hash: str, chain_id: int, staking_program_id: s
"""
raise NotImplementedError
- def stake_service_on_chain_from_safe(self, hash: str, chain_id: str) -> None:
+ def stake_service_on_chain_from_safe( # pylint: disable=too-many-statements,too-many-locals
+ self, hash: str, chain_id: str
+ ) -> None:
"""
Stake service on-chain
@@ -888,40 +1035,76 @@ def stake_service_on_chain_from_safe(self, hash: str, chain_id: str) -> None:
os.environ["CUSTOM_CHAIN_RPC"] = ledger_config.rpc
# Determine if the service is staked in a known staking program
- current_staking_program = self._get_current_staking_program(chain_data, ledger_config, sftxb)
+ current_staking_program = self._get_current_staking_program(
+ chain_data, ledger_config, sftxb
+ )
is_staked = current_staking_program is not None
- current_staking_contract = STAKING[ledger_config.chain][current_staking_program] if is_staked else None
+ current_staking_contract = (
+ STAKING[ledger_config.chain][current_staking_program]
+ if current_staking_program is not None
+ else None
+ )
# perform the unstaking flow if necessary
if is_staked:
- can_unstake = sftxb.can_unstake(chain_config.chain_data.token, current_staking_contract)
+ can_unstake = sftxb.can_unstake(
+ chain_config.chain_data.token, current_staking_contract # type: ignore # TODO fix mypy
+ )
if not chain_config.chain_data.user_params.use_staking and can_unstake:
- self.logger.info(f"Use staking is set to false, but service {chain_config.chain_data.token} is staked and can be unstaked. Unstaking...")
- self.unstake_service_on_chain_from_safe(hash=hash, chain_id=chain_id, staking_program_id=current_staking_program)
+ self.logger.info(
+ f"Use staking is set to false, but service {chain_config.chain_data.token} is staked and can be unstaked. Unstaking..."
+ )
+ self.unstake_service_on_chain_from_safe(
+ hash=hash,
+ chain_id=chain_id,
+ staking_program_id=current_staking_program,
+ )
info = sftxb.info(token_id=chain_config.chain_data.token)
chain_config.chain_data.on_chain_state = OnChainState(info["service_state"])
staking_state = sftxb.staking_status(
service_id=chain_data.token,
- staking_contract=current_staking_contract,
+ staking_contract=current_staking_contract, # type: ignore # TODO fix mypy
)
if staking_state == StakingState.EVICTED and can_unstake:
- self.logger.info(f"Service {chain_config.chain_data.token} has been evicted and can be unstaked. Unstaking...")
- self.unstake_service_on_chain_from_safe(hash=hash, chain_id=chain_id, staking_program_id=current_staking_program)
+ self.logger.info(
+ f"Service {chain_config.chain_data.token} has been evicted and can be unstaked. Unstaking..."
+ )
+ self.unstake_service_on_chain_from_safe(
+ hash=hash,
+ chain_id=chain_id,
+ staking_program_id=current_staking_program,
+ )
- if staking_state == StakingState.STAKED and can_unstake and not sftxb.staking_rewards_available(current_staking_contract):
+ if (
+ staking_state == StakingState.STAKED
+ and can_unstake
+ and not sftxb.staking_rewards_available(current_staking_contract) # type: ignore # TODO fix mypy
+ ):
self.logger.info(
f"There are no rewards available, service {chain_config.chain_data.token} "
f"is already staked and can be unstaked. Unstaking..."
)
- self.unstake_service_on_chain_from_safe(hash=hash, chain_id=chain_id, staking_program_id=current_staking_program)
+ self.unstake_service_on_chain_from_safe(
+ hash=hash,
+ chain_id=chain_id,
+ staking_program_id=current_staking_program,
+ )
- if staking_state == StakingState.STAKED and current_staking_program != target_staking_contract and can_unstake:
+ if (
+ staking_state == StakingState.STAKED
+ and current_staking_program != target_staking_contract
+ and can_unstake
+ ):
self.logger.info(
f"{chain_config.chain_data.token} is staked in a different staking program. Unstaking..."
)
- self.unstake_service_on_chain_from_safe(hash=hash, chain_id=chain_id, staking_program_id=current_staking_program)
+ self.unstake_service_on_chain_from_safe(
+ hash=hash,
+ chain_id=chain_id,
+ staking_program_id=current_staking_program,
+ )
staking_state = sftxb.staking_status(
service_id=chain_config.chain_data.token,
@@ -929,12 +1112,18 @@ def stake_service_on_chain_from_safe(self, hash: str, chain_id: str) -> None:
)
self.logger.info("Checking conditions to stake.")
- staking_rewards_available = sftxb.staking_rewards_available(target_staking_contract)
+ staking_rewards_available = sftxb.staking_rewards_available(
+ target_staking_contract
+ )
staking_slots_available = sftxb.staking_slots_available(target_staking_contract)
- on_chain_state = self._get_on_chain_state(chain_config=chain_config)
- current_staking_program = self._get_current_staking_program(chain_data, ledger_config, sftxb)
-
- self.logger.info(f"use_staking={chain_config.chain_data.user_params.use_staking}")
+ on_chain_state = self._get_on_chain_state(service=service, chain_id=chain_id)
+ current_staking_program = self._get_current_staking_program(
+ chain_data, ledger_config, sftxb
+ )
+
+ self.logger.info(
+ f"use_staking={chain_config.chain_data.user_params.use_staking}"
+ )
self.logger.info(f"{staking_state=}")
self.logger.info(f"{staking_rewards_available=}")
self.logger.info(f"{staking_slots_available=}")
@@ -943,19 +1132,17 @@ def stake_service_on_chain_from_safe(self, hash: str, chain_id: str) -> None:
self.logger.info(f"{target_staking_program=}")
if (
- chain_config.chain_data.user_params.use_staking
- and staking_state == StakingState.UNSTAKED
- and staking_rewards_available
- and staking_slots_available
- and on_chain_state == OnChainState.DEPLOYED
+ chain_config.chain_data.user_params.use_staking
+ and staking_state == StakingState.UNSTAKED
+ and staking_rewards_available
+ and staking_slots_available
+ and on_chain_state == OnChainState.DEPLOYED
):
self.logger.info(f"Approving staking: {chain_config.chain_data.token}")
sftxb.new_tx().add(
sftxb.get_staking_approval_data(
service_id=chain_config.chain_data.token,
- service_registry=CONTRACTS[ledger_config.chain][
- "service_registry"
- ],
+ service_registry=CONTRACTS[ledger_config.chain]["service_registry"],
staking_contract=target_staking_contract,
)
).settle()
@@ -970,44 +1157,57 @@ def stake_service_on_chain_from_safe(self, hash: str, chain_id: str) -> None:
chain_config.chain_data.staked = True
service.store()
- current_staking_program = self._get_current_staking_program(chain_data, ledger_config, sftxb)
+ current_staking_program = self._get_current_staking_program(
+ chain_data, ledger_config, sftxb
+ )
self.logger.info(f"{target_staking_program=}")
self.logger.info(f"{current_staking_program=}")
- def unstake_service_on_chain(self, hash: str) -> None:
+ def unstake_service_on_chain(
+ self, hash: str, chain_id: t.Optional[str] = None
+ ) -> None:
"""
Unbond service on-chain
:param hash: Service hash
"""
+ # TODO This method has not been thoroughly reviewed. Deprecated usage in favour of Safe version.
+
service = self.load_or_create(hash=hash)
- if not service.chain_data.user_params.use_staking:
+
+ if chain_id is None:
+ chain_id = service.home_chain_id
+
+ chain_config = service.chain_configs[chain_id]
+ ledger_config = chain_config.ledger_config
+ chain_data = chain_config.chain_data
+ ocm = self.get_on_chain_manager(ledger_config=ledger_config)
+ if not chain_data.user_params.use_staking:
self.logger.info("Cannot unstake service, `use_staking` is set to false")
return
- ocm = self.get_on_chain_manager(service=service)
state = ocm.staking_status(
- service_id=service.chain_data.token,
- staking_contract=STAKING[service.ledger_config.chain],
- )
- self.logger.info(
- f"Staking status for service {service.chain_data.token}: {state}"
+ service_id=chain_data.token,
+ staking_contract=STAKING[ledger_config.chain], # type: ignore # TODO fix mypy
)
+ self.logger.info(f"Staking status for service {chain_data.token}: {state}")
if state not in {StakingState.STAKED, StakingState.EVICTED}:
self.logger.info("Cannot unstake service, it's not staked")
- service.chain_data.staked = False
+ chain_data.staked = False
service.store()
return
- self.logger.info(f"Unstaking service: {service.chain_data.token}")
+ self.logger.info(f"Unstaking service: {chain_data.token}")
ocm.unstake(
- service_id=service.chain_data.token,
- staking_contract=STAKING[service.ledger_config.chain],
+ service_id=chain_data.token,
+ staking_contract=STAKING[ledger_config.chain], # type: ignore # TODO fix mypy
)
- service.chain_data.staked = False
+ chain_data.staked = False
service.store()
- def unstake_service_on_chain_from_safe(self, hash: str, chain_id: str, staking_program_id: str) -> None:
+ def unstake_service_on_chain_from_safe(
+ self, hash: str, chain_id: str, staking_program_id: t.Optional[str] = None
+ ) -> None:
"""
Unbond service on-chain
@@ -1020,6 +1220,12 @@ def unstake_service_on_chain_from_safe(self, hash: str, chain_id: str, staking_p
ledger_config = chain_config.ledger_config
chain_data = chain_config.chain_data
+ if staking_program_id is None:
+ self.logger.info(
+ "Cannot unstake service, `staking_program_id` is set to None"
+ )
+ return
+
if not chain_data.user_params.use_staking:
self.logger.info("Cannot unstake service, `use_staking` is set to false")
return
@@ -1029,9 +1235,7 @@ def unstake_service_on_chain_from_safe(self, hash: str, chain_id: str, staking_p
service_id=chain_data.token,
staking_contract=STAKING[ledger_config.chain][staking_program_id],
)
- self.logger.info(
- f"Staking status for service {chain_data.token}: {state}"
- )
+ self.logger.info(f"Staking status for service {chain_data.token}: {state}")
if state not in {StakingState.STAKED, StakingState.EVICTED}:
self.logger.info("Cannot unstake service, it's not staked")
chain_data.staked = False
@@ -1048,7 +1252,7 @@ def unstake_service_on_chain_from_safe(self, hash: str, chain_id: str, staking_p
chain_data.staked = False
service.store()
- def fund_service( # pylint: disable=too-many-arguments
+ def fund_service( # pylint: disable=too-many-arguments,too-many-locals
self,
hash: str,
rpc: t.Optional[str] = None,
@@ -1065,10 +1269,11 @@ def fund_service( # pylint: disable=too-many-arguments
ledger_config = chain_config.ledger_config
chain_data = chain_config.chain_data
wallet = self.wallet_manager.load(ledger_config.type)
- ledger_api = wallet.ledger_api(chain_type=ledger_config.chain, rpc=rpc if rpc else ledger_config.rpc)
+ ledger_api = wallet.ledger_api(
+ chain_type=ledger_config.chain, rpc=rpc if rpc else ledger_config.rpc
+ )
agent_fund_threshold = (
- agent_fund_threshold
- or chain_data.user_params.fund_requirements.agent
+ agent_fund_threshold or chain_data.user_params.fund_requirements.agent
)
for key in service.keys:
@@ -1078,8 +1283,7 @@ def fund_service( # pylint: disable=too-many-arguments
if agent_balance < agent_fund_threshold:
self.logger.info("Funding agents")
to_transfer = (
- agent_topup
- or chain_data.user_params.fund_requirements.agent
+ agent_topup or chain_data.user_params.fund_requirements.agent
)
self.logger.info(f"Transferring {to_transfer} units to {key.address}")
wallet.transfer(
@@ -1097,9 +1301,7 @@ def fund_service( # pylint: disable=too-many-arguments
self.logger.info(f"Required balance: {safe_fund_treshold}")
if safe_balance < safe_fund_treshold:
self.logger.info("Funding safe")
- to_transfer = (
- safe_topup or chain_data.user_params.fund_requirements.safe
- )
+ to_transfer = safe_topup or chain_data.user_params.fund_requirements.safe
self.logger.info(
f"Transferring {to_transfer} units to {chain_data.multisig}"
)
@@ -1177,25 +1379,28 @@ def update_service(
"""Update a service."""
self.logger.info("-----Entering update local service-----")
- old_service = self.load_or_create(
- hash=old_hash
- )
+ old_service = self.load_or_create(hash=old_hash)
new_service = self.load_or_create(
- hash=new_hash,
- service_template=service_template
+ hash=new_hash, service_template=service_template
)
new_service.keys = old_service.keys
- # new_Service.home_chain_id = old_service.home_chain_id
- # TODO - Ensure this works as expected - New service must copy all chain_data from old service,
- # but if service_template is not None, it must copy the user_params
- # passed in the service_template and copy the remaining attributes from old_service.
+ # TODO Ensure this is as intended.
+ new_service.home_chain_id = old_service.home_chain_id
+ # new_service must copy all chain_data from old_service.
+ # Additionally, if service_template is not None, it must overwrite
+ # the user_params on all chain_data by the values passed through the
+ # service_template.
new_service.chain_configs = {}
for chain_id, config in old_service.chain_configs.items():
- new_service.chain_configs[chain_id] = config
+ new_service.chain_configs[chain_id] = config
if service_template:
- new_service.chain_configs[chain_id].chain_data.user_params = OnChainUserParams.from_json(service_template["configurations"][chain_id])
+ new_service.chain_configs[
+ chain_id
+ ].chain_data.user_params = OnChainUserParams.from_json(
+ service_template["configurations"][chain_id] # type: ignore # TODO fix mypy
+ )
new_service.store()
diff --git a/operate/services/protocol.py b/operate/services/protocol.py
index 120355c94..5b122bb7e 100644
--- a/operate/services/protocol.py
+++ b/operate/services/protocol.py
@@ -242,8 +242,9 @@ def service_info(self, staking_contract: str, service_id: int) -> dict:
staking_contract,
service_id,
).get("data")
-
+
def agent_ids(self, staking_contract: str) -> t.List[int]:
+ """Get the agent IDs for the specified staking contract"""
instance = self.staking_ctr.get_instance(
ledger_api=self.ledger_api,
contract_address=staking_contract,
@@ -251,6 +252,7 @@ def agent_ids(self, staking_contract: str) -> t.List[int]:
return instance.functions.getAgentIds().call()
def service_registry(self, staking_contract: str) -> str:
+ """Get the service registry address for the specified staking contract"""
instance = self.staking_ctr.get_instance(
ledger_api=self.ledger_api,
contract_address=staking_contract,
@@ -258,6 +260,7 @@ def service_registry(self, staking_contract: str) -> str:
return instance.functions.serviceRegistry().call()
def staking_token(self, staking_contract: str) -> str:
+ """Get the staking token address for the specified staking contract"""
instance = self.staking_ctr.get_instance(
ledger_api=self.ledger_api,
contract_address=staking_contract,
@@ -265,6 +268,7 @@ def staking_token(self, staking_contract: str) -> str:
return instance.functions.stakingToken().call()
def service_registry_token_utility(self, staking_contract: str) -> str:
+ """Get the service registry token utility address for the specified staking contract"""
instance = self.staking_ctr.get_instance(
ledger_api=self.ledger_api,
contract_address=staking_contract,
@@ -272,6 +276,7 @@ def service_registry_token_utility(self, staking_contract: str) -> str:
return instance.functions.serviceRegistryTokenUtility().call()
def min_staking_deposit(self, staking_contract: str) -> str:
+ """Get the minimum staking deposit for the specified staking contract"""
instance = self.staking_ctr.get_instance(
ledger_api=self.ledger_api,
contract_address=staking_contract,
@@ -279,6 +284,7 @@ def min_staking_deposit(self, staking_contract: str) -> str:
return instance.functions.minStakingDeposit().call()
def activity_checker(self, staking_contract: str) -> str:
+ """Get the activity checker address for the specified staking contract"""
instance = self.staking_ctr.get_instance(
ledger_api=self.ledger_api,
contract_address=staking_contract,
@@ -529,14 +535,6 @@ def ledger_api(self) -> LedgerApi:
)
return ledger_api
- def owner_of(self, token_id: int) -> str:
- """Get owner of a service."""
- self._patch()
- ledger_api, _ = OnChainHelper.get_ledger_and_crypto_objects(
- chain_type=self.chain_type
- )
-
-
def info(self, token_id: int) -> t.Dict:
"""Get service info."""
self._patch()
@@ -574,7 +572,6 @@ def info(self, token_id: int) -> t.Dict:
instances=instances,
)
-
def get_service_safe_owners(self, service_id: int) -> t.List[str]:
"""Get list of owners."""
ledger_api, _ = OnChainHelper.get_ledger_and_crypto_objects(
@@ -599,13 +596,8 @@ def get_service_safe_owners(self, service_id: int) -> t.List[str]:
contract_address=multisig_address,
).get("owners", [])
-
def swap( # pylint: disable=too-many-arguments,too-many-locals
- self,
- service_id: int,
- multisig: str,
- owner_key: str,
- new_owner_address: str
+ self, service_id: int, multisig: str, owner_key: str, new_owner_address: str
) -> None:
"""Swap safe owner."""
logging.info(f"Swapping safe for service {service_id} [{multisig}]...")
@@ -634,9 +626,7 @@ def swap( # pylint: disable=too-many-arguments,too-many-locals
ledger_api=manager.ledger_api,
contract_address=multisig,
old_owner=manager.ledger_api.api.to_checksum_address(owner_to_swap),
- new_owner=manager.ledger_api.api.to_checksum_address(
- new_owner_address
- ),
+ new_owner=manager.ledger_api.api.to_checksum_address(new_owner_address),
).get("data")
multisend_txs.append(
{
@@ -720,6 +710,55 @@ def staking_rewards_available(self, staking_contract: str) -> bool:
)
return available_rewards > 0
+ def staking_status(self, service_id: int, staking_contract: str) -> StakingState:
+ """Stake the service"""
+ self._patch()
+ return StakingManager(
+ key=self.wallet.key_path,
+ password=self.wallet.password,
+ chain_type=self.chain_type,
+ ).status(
+ service_id=service_id,
+ staking_contract=staking_contract,
+ )
+
+ def get_staking_params(self, staking_contract: str) -> t.Dict:
+ """Get agent IDs for the staking contract"""
+ self._patch()
+ staking_manager = StakingManager(
+ key=self.wallet.key_path,
+ password=self.wallet.password,
+ chain_type=self.chain_type,
+ )
+ agent_ids = staking_manager.agent_ids(
+ staking_contract=staking_contract,
+ )
+ service_registry = staking_manager.service_registry(
+ staking_contract=staking_contract,
+ )
+ staking_token = staking_manager.staking_token(
+ staking_contract=staking_contract,
+ )
+ service_registry_token_utility = staking_manager.service_registry_token_utility(
+ staking_contract=staking_contract,
+ )
+ min_staking_deposit = staking_manager.min_staking_deposit(
+ staking_contract=staking_contract,
+ )
+ activity_checker = staking_manager.activity_checker(
+ staking_contract=staking_contract,
+ )
+
+ return dict(
+ 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,
+ )
+
+
class OnChainManager(_ChainUtil):
"""On chain service management."""
@@ -974,7 +1013,7 @@ def get_mint_tx_data( # pylint: disable=too-many-arguments
)
.load_metadata()
.verify_nft(nft=nft)
- #.verify_service_dependencies(agent_id=agent_id) # TODO add this check once subgraph production indexes agent 25
+ .verify_service_dependencies(agent_id=agent_id)
.publish_metadata()
)
instance = registry_contracts.service_manager.get_instance(
@@ -1003,9 +1042,9 @@ def get_mint_tx_data( # pylint: disable=too-many-arguments
[agent_id],
[[number_of_slots, cost_of_bond]],
threshold,
- update_token
+ update_token,
],
- )
+ )
return {
"to": self.contracts["service_manager"],
@@ -1139,7 +1178,11 @@ def get_deploy_data_from_safe(
)
approve_hash_message = None
if reuse_multisig:
- _deployment_payload, approve_hash_message, error = get_reuse_multisig_from_safe_payload(
+ (
+ _deployment_payload,
+ approve_hash_message,
+ error,
+ ) = get_reuse_multisig_from_safe_payload(
ledger_api=self.ledger_api,
chain_type=self.chain_type,
service_id=service_id,
@@ -1289,54 +1332,6 @@ def staking_slots_available(self, staking_contract: str) -> bool:
staking_contract=staking_contract,
)
- def staking_status(self, service_id: int, staking_contract: str) -> StakingState:
- """Stake the service"""
- self._patch()
- return StakingManager(
- key=self.wallet.key_path,
- password=self.wallet.password,
- chain_type=self.chain_type,
- ).status(
- service_id=service_id,
- staking_contract=staking_contract,
- )
-
- def get_staking_params(self, staking_contract: str) -> t.Dict:
- """Get agent IDs for the staking contract"""
- self._patch()
- staking_manager = StakingManager(
- key=self.wallet.key_path,
- password=self.wallet.password,
- chain_type=self.chain_type,
- )
- agent_ids = staking_manager.agent_ids(
- staking_contract=staking_contract,
- )
- service_registry = staking_manager.service_registry(
- staking_contract=staking_contract,
- )
- staking_token = staking_manager.staking_token(
- staking_contract=staking_contract,
- )
- service_registry_token_utility = staking_manager.service_registry_token_utility(
- staking_contract=staking_contract,
- )
- min_staking_deposit = staking_manager.min_staking_deposit(
- staking_contract=staking_contract,
- )
- activity_checker = staking_manager.activity_checker(
- staking_contract=staking_contract,
- )
-
- return dict(
- 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
- )
-
def can_unstake(self, service_id: int, staking_contract: str) -> bool:
"""Can unstake the service?"""
try:
@@ -1358,26 +1353,25 @@ def get_swap_data(self, service_id: int, multisig: str, owner_key: str) -> t.Dic
raise NotImplementedError()
-
def get_packed_signature_for_approved_hash(owners: t.Tuple[str]) -> bytes:
- """Get the packed signatures."""
- sorted_owners = sorted(owners, key=str.lower)
- signatures = b''
- for owner in sorted_owners:
- # Convert address to bytes and ensure it is 32 bytes long (left-padded with zeros)
- r_bytes = to_bytes(hexstr=owner[2:].rjust(64, '0'))
+ """Get the packed signatures."""
+ sorted_owners = sorted(owners, key=str.lower)
+ signatures = b""
+ for owner in sorted_owners:
+ # Convert address to bytes and ensure it is 32 bytes long (left-padded with zeros)
+ r_bytes = to_bytes(hexstr=owner[2:].rjust(64, "0"))
- # `s` as 32 zero bytes
- s_bytes = b'\x00' * 32
+ # `s` as 32 zero bytes
+ s_bytes = b"\x00" * 32
- # `v` as a single byte
- v_bytes = to_bytes(1)
+ # `v` as a single byte
+ v_bytes = to_bytes(1)
- # Concatenate r, s, and v to form the packed signature
- packed_signature = r_bytes + s_bytes + v_bytes
- signatures += packed_signature
+ # Concatenate r, s, and v to form the packed signature
+ packed_signature = r_bytes + s_bytes + v_bytes
+ signatures += packed_signature
- return signatures
+ return signatures
def get_reuse_multisig_from_safe_payload( # pylint: disable=too-many-locals
@@ -1477,7 +1471,7 @@ def get_reuse_multisig_from_safe_payload( # pylint: disable=too-many-locals
contract_address=multisend_address,
txs=txs,
)
- signature_bytes = get_packed_signature_for_approved_hash(owners=(master_safe, ))
+ signature_bytes = get_packed_signature_for_approved_hash(owners=(master_safe,))
safe_tx_hash = registry_contracts.gnosis_safe.get_raw_safe_transaction_hash(
ledger_api=ledger_api,
@@ -1517,4 +1511,3 @@ def get_reuse_multisig_from_safe_payload( # pylint: disable=too-many-locals
)
payload = multisig_address + safe_exec_data[2:]
return payload, approve_hash_message, None
-
diff --git a/operate/services/service.py b/operate/services/service.py
index ea6c563ca..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
@@ -82,12 +84,13 @@
)
+# pylint: disable=no-member,redefined-builtin,too-many-instance-attributes
+
SAFE_CONTRACT_ADDRESS = "safe_contract_address"
ALL_PARTICIPANTS = "all_participants"
CONSENSUS_THRESHOLD = "consensus_threshold"
DELETE_PREFIX = "delete_"
-
-# pylint: disable=no-member,redefined-builtin,too-many-instance-attributes
+SERVICE_CONFIG_VERSION = 2
DUMMY_MULTISIG = "0xm"
NON_EXISTENT_TOKEN = -1
@@ -238,7 +241,7 @@ def __init__(self, path: Path) -> None:
self.path = path
self.config = load_service_config(service_path=path)
- def ledger_configs(self) -> "LedgerConfigs":
+ def ledger_configs(self) -> LedgerConfigs:
"""Get ledger configs."""
ledger_configs = {}
for override in self.config.overrides:
@@ -271,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",
@@ -416,7 +425,10 @@ def _build_docker(
builder.deplopyment_type = DockerComposeGenerator.deployment_type
builder.try_update_abci_connection_params()
- home_chain_data = service.chain_configs[service.home_chain_id]
+ home_chain_data = service.chain_configs[service.home_chain_id].chain_data
+ home_chain_ledger_config = service.chain_configs[
+ service.home_chain_id
+ ].ledger_config
builder.try_update_runtime_params(
multisig_address=home_chain_data.multisig,
agent_instances=home_chain_data.instances,
@@ -425,8 +437,8 @@ def _build_docker(
)
# TODO: Support for multiledger
builder.try_update_ledger_params(
- chain=LedgerType(service.ledger_config.type).name.lower(),
- address=service.ledger_config.rpc,
+ chain=LedgerType(home_chain_ledger_config.type).name.lower(),
+ address=home_chain_ledger_config.rpc,
)
# build deployment
@@ -656,15 +668,19 @@ class Service(LocalResource):
@classmethod
def migrate_format(cls, path: Path) -> None:
"""Migrate the JSON file format if needed."""
- file_path = path / Service._file if Service._file is not None and path.name != Service._file else path
-
- with open(file_path, 'r', encoding='utf-8') as file:
+ file_path = (
+ path / Service._file
+ if Service._file is not None and path.name != Service._file
+ else path
+ )
+
+ with open(file_path, "r", encoding="utf-8") as file:
data = json.load(file)
-
- if 'version' in data:
+
+ if "version" in data:
# Data is already in the new format
return
-
+
# Migrate from old format to new format
new_data = {
"version": 2,
@@ -676,30 +692,42 @@ def migrate_format(cls, path: Path) -> None:
"ledger_config": {
"rpc": data.get("ledger_config", {}).get("rpc"),
"type": data.get("ledger_config", {}).get("type"),
- "chain": data.get("ledger_config", {}).get("chain")
+ "chain": data.get("ledger_config", {}).get("chain"),
},
"chain_data": {
"instances": data.get("chain_data", {}).get("instances", []),
"token": data.get("chain_data", {}).get("token"),
"multisig": data.get("chain_data", {}).get("multisig"),
"staked": data.get("chain_data", {}).get("staked", False),
- "on_chain_state": data.get("chain_data", {}).get("on_chain_state", 3),
+ "on_chain_state": data.get("chain_data", {}).get(
+ "on_chain_state", 3
+ ),
"user_params": {
"staking_program_id": "pearl_alpha",
- "nft": data.get("chain_data", {}).get("user_params", {}).get("nft"),
- "threshold": data.get("chain_data", {}).get("user_params", {}).get("threshold"),
- "use_staking": data.get("chain_data", {}).get("user_params", {}).get("use_staking"),
- "cost_of_bond": data.get("chain_data", {}).get("user_params", {}).get("cost_of_bond"),
- "fund_requirements": data.get("chain_data", {}).get("user_params", {}).get("fund_requirements", {})
- }
- }
+ "nft": data.get("chain_data", {})
+ .get("user_params", {})
+ .get("nft"),
+ "threshold": data.get("chain_data", {})
+ .get("user_params", {})
+ .get("threshold"),
+ "use_staking": data.get("chain_data", {})
+ .get("user_params", {})
+ .get("use_staking"),
+ "cost_of_bond": data.get("chain_data", {})
+ .get("user_params", {})
+ .get("cost_of_bond"),
+ "fund_requirements": data.get("chain_data", {})
+ .get("user_params", {})
+ .get("fund_requirements", {}),
+ },
+ },
}
},
"service_path": data.get("service_path", ""),
- "name": data.get("name", "")
+ "name": data.get("name", ""),
}
-
- with open(file_path, 'w', encoding='utf-8') as file:
+
+ with open(file_path, "w", encoding="utf-8") as file:
json.dump(new_data, file, indent=2)
@classmethod
@@ -725,7 +753,7 @@ def deployment(self) -> Deployment:
return t.cast(Deployment, self._deployment)
@staticmethod
- def new(
+ def new( # pylint: disable=too-many-locals
hash: str,
keys: Keys,
service_template: ServiceTemplate,
@@ -756,7 +784,7 @@ def new(
multisig=DUMMY_MULTISIG,
staked=False,
on_chain_state=OnChainState.NON_EXISTENT,
- user_params=OnChainUserParams.from_json(config),
+ user_params=OnChainUserParams.from_json(config), # type: ignore
)
chain_configs[chain] = ChainConfig(
@@ -765,7 +793,7 @@ def new(
)
service = Service(
- version=2, # TODO implement in appropriate place
+ version=SERVICE_CONFIG_VERSION,
name=service_yaml["author"] + "/" + service_yaml["name"],
hash=service_template["hash"],
keys=keys,
@@ -777,11 +805,16 @@ def new(
service.store()
return service
- def update_user_params_from_template(self, service_template: ServiceTemplate):
+ def update_user_params_from_template(
+ self, service_template: ServiceTemplate
+ ) -> None:
"""Update user params from template."""
for chain, config in service_template["configurations"].items():
- for chain, config in service_template["configurations"].items():
- self.chain_configs[chain].chain_data.user_params = OnChainUserParams.from_json(config)
+ self.chain_configs[
+ chain
+ ].chain_data.user_params = OnChainUserParams.from_json(
+ config # type: ignore
+ )
self.store()
diff --git a/package.json b/package.json
index c5afe288e..34d5ff1c1 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-rc115"
-}
\ No newline at end of file
+ "version": "0.1.0-rc120"
+}
diff --git a/poetry.lock b/poetry.lock
index fd3b19a72..ad092924b 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"
@@ -415,63 +415,78 @@ files = [
[[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]
@@ -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.0.0"
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.0.0-py3-none-any.whl", hash = "sha256:0274581a0037b638b9fc1c6883cc71c0210865aaa76073f7882376b641b84e8f"},
+ {file = "setuptools-74.0.0.tar.gz", hash = "sha256:a85e96b8be2b906f3e3e789adec6a9323abf79758ecfa3065bd740d81158b11e"},
]
[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.0"
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.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bf3216ec994eabb2212df9861f19056ca0d4cd3516d56cb95801933876519bfe"},
+ {file = "watchdog-5.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb59ad83a1700304fc1ac7bc53ae9e5cbe9d60a52ed9bba8e2e2d782a201bb2b"},
+ {file = "watchdog-5.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1228cb097e855d1798b550be8f0e9f0cfbac4384f9a3e91f66d250d03e11294e"},
+ {file = "watchdog-5.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3c177085c3d210d1c73cb4569442bdaef706ebebc423bd7aed9e90fc12b2e553"},
+ {file = "watchdog-5.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01ab36cddc836a0f202c66267daaef92ba5c17c7d6436deff0587bb61234c5c9"},
+ {file = "watchdog-5.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0834c21efa3e767849b09e667274604c7cdfe30b49eb95d794565c53f4db3c1e"},
+ {file = "watchdog-5.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1e26f570dd7f5178656affb24d6f0e22ce66c8daf88d4061a27bfb9ac866b40d"},
+ {file = "watchdog-5.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d146331e6b206baa9f6dd40f72b5783ad2302c240df68e7fce196d30588ccf7b"},
+ {file = "watchdog-5.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c96b1706430839872a3e33b9370ee3f7a0079f6b828129d88498ad1f96a0f45"},
+ {file = "watchdog-5.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:663b096368ed7831ac42259919fdb9e0a1f0a8994d972675dfbcca0225e74de1"},
+ {file = "watchdog-5.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:685931412978d00a91a193d9018fc9e394e565e8e7a0c275512a80e59c6e85f8"},
+ {file = "watchdog-5.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:109daafc5b0f2a98d1fa9475ff9737eb3559d57b18129a36495e20c71de0b44f"},
+ {file = "watchdog-5.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c2b4d90962639ae7cee371ea3a8da506831945d4418eee090c53bc38e6648dc6"},
+ {file = "watchdog-5.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e58eafe9cc5ceebe1562cdb89bacdcd0ef470896e8b0139fe677a5abec243da"},
+ {file = "watchdog-5.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b8d747bf6d8fe5ce89cb1a36c3724d1599bd4cde3f90fcba518e6260c7058a52"},
+ {file = "watchdog-5.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bc16d448a74a929b896ed9578c25756b2125400b19b3258be8d9a681c7ae8e71"},
+ {file = "watchdog-5.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7e6b0e9b8a9dc3865d65888b5f5222da4ba9c4e09eab13cff5e305e7b7e7248f"},
+ {file = "watchdog-5.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4fe6780915000743074236b21b6c37419aea71112af62237881bc265589fe463"},
+ {file = "watchdog-5.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0710e9502727f688a7e06d48078545c54485b3d6eb53b171810879d8223c362a"},
+ {file = "watchdog-5.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:d76efab5248aafbf8a2c2a63cd7b9545e6b346ad1397af8b862a3bb3140787d8"},
+ {file = "watchdog-5.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:ff4e957c45c446de34c513eadce01d0b65da7eee47c01dce472dd136124552c9"},
+ {file = "watchdog-5.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:16c1aa3377bb1f82c5e24277fcbf4e2cac3c4ce46aaaf7212d53caa9076eb7b7"},
+ {file = "watchdog-5.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:22fcad6168fc43cf0e709bd854be5b8edbb0b260f0a6f28f1ea9baa53c6907f7"},
+ {file = "watchdog-5.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:0120b2fa65732797ffa65fa8ee5540c288aa861d91447df298626d6385a24658"},
+ {file = "watchdog-5.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2aa59fab7ff75281778c649557275ca3085eccbdf825a0e2a5ca3810e977afe5"},
+ {file = "watchdog-5.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:78db0fe0336958fc0e1269545c980b6f33d04d184ba191b2800a8b71d3e971a9"},
+ {file = "watchdog-5.0.0-py3-none-win32.whl", hash = "sha256:d1acef802916083f2ad7988efc7decf07e46e266916c0a09d8fb9d387288ea12"},
+ {file = "watchdog-5.0.0-py3-none-win_amd64.whl", hash = "sha256:3c2d50fdb86aa6df3973313272f5a17eb26eab29ff5a0bf54b6d34597b4dc4e4"},
+ {file = "watchdog-5.0.0-py3-none-win_ia64.whl", hash = "sha256:1d17ec7e022c34fa7ddc72aa41bf28c9d1207ffb193df18ba4f6fde453725b3c"},
+ {file = "watchdog-5.0.0.tar.gz", hash = "sha256:990aedb9e2f336b45a70aed9c014450e7c4a70fd99c5f5b1834d57e1453a177e"},
]
[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]]
@@ -3401,18 +3455,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 9a58deb5d..a02e08312 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "olas-operate-middleware"
-version = "0.1.0-rc115"
+version = "0.1.0-rc120"
description = ""
authors = ["David Vilela ", "Viraj Patel "]
readme = "README.md"
diff --git a/templates/trader.yaml b/templates/trader.yaml
index ed0b8679d..9742c7ba8 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: bafybeihqtqgohejyebrb4jvd2fgccuasmqk3gc456ylyfa7tcn6rucdrxm
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
diff --git a/tox.ini b/tox.ini
index b7de2caf0..88426bd93 100644
--- a/tox.ini
+++ b/tox.ini
@@ -215,3 +215,6 @@ ignore_missing_imports = True
[mypy-psutil.*]
ignore_missing_imports = True
+
+[mypy-eth_utils.*]
+ignore_missing_imports = True