23 Commits

Author SHA1 Message Date
Rémy Roy
f7e9053ea9 Merge pull request #208 from Wagalidoom/main
feat: add gnosis and chiado network
2025-08-28 11:24:59 -04:00
Wagalidoom
552cc77c2d fix: add gnosis network to verify mnemonic component 2025-08-27 22:47:33 +02:00
Wagalidoom
a58fca154d fix: key generation error 2025-08-27 19:54:05 +02:00
Wagalidoom
df73ec40d5 fix: remove holesky 2025-08-26 17:30:49 +02:00
Wagalidoom
7f9c5f6c52 fix: build error 2025-08-26 16:34:07 +02:00
Wagalidoom
dac102bf93 fix: remove pyc files 2025-08-26 16:30:26 +02:00
Wagalidoom
6fc8d8e2e7 chore: rebase branch 2025-08-08 13:52:51 +02:00
Wagalidoom
1b4bb66191 Merge branch 'main' into main 2025-08-08 11:41:01 +02:00
Rémy Roy
4929a1846e Merge pull request #209 from remyroy/edc-up-122
Update ethstaker-deposit-cli to 1.2.2
2025-08-05 11:12:12 -04:00
Rémy Roy
76696646c0 Fix issue with generating BLS to execution change with proxy 2025-08-04 13:30:12 -04:00
Rémy Roy
13347b49d5 Remove Holesky and update proxy code for new edc update 2025-08-04 12:25:22 -04:00
Rémy Roy
200c06c52c Bringing edc 1.2.2 source into the project 2025-07-27 11:56:50 -04:00
Wagalidoom
a2ff6f957f fix: update compounding tooltip 2025-07-11 11:50:32 +02:00
Wagalidoom
f56689e593 feat: add gnosis and chiado network 2025-07-11 11:33:56 +02:00
Rémy Roy
1208ef8b86 Set version to 1.12.0 2025-03-20 14:27:51 -04:00
Rémy Roy
74d07e30db Merge pull request #204 from remyroy/apparmor-doc
Add AppArmor documentation
2025-03-20 14:25:06 -04:00
Rémy Roy
498143b25f Add AppArmor documentation 2025-03-20 14:19:28 -04:00
Rémy Roy
73ede6f547 Merge pull request #203 from remyroy/hoodi
Adding Hoodi
2025-03-19 21:41:35 -04:00
Rémy Roy
18fdecd9a7 Replace Goerli with Hoodi 2025-03-17 10:37:29 -04:00
Rémy Roy
898488d134 Update edc to v1.1.0 2025-03-17 10:26:08 -04:00
Rémy Roy
5a93286fee Merge pull request #195 from valefar-on-discord/amount-compounding-support
Adding support for amount and compounding parameters
2025-02-18 13:30:39 -05:00
valefar-on-discord
7c8010cd7d Reorganizing generate key form 2024-11-30 18:14:53 -06:00
valefar-on-discord
d83a17f39c Adding support for amount and compounding parameters 2024-11-28 07:53:44 -06:00
248 changed files with 3225 additions and 1651 deletions

View File

@@ -31,6 +31,8 @@ Download and run the `Wagyu.Key.Gen-X.X.X.dmg` asset. Run the `Wagyu Key Gen` a
Download the `Wagyu.Key.Gen-X.X.X.AppImage` asset, [make it executable](https://itsfoss.com/use-appimage-linux/) and launch it from your desktop environment, often by double clicking on it, or from your terminal.
### Missing FUSE
On Ubuntu 22.04 or later, you might need [to install libfuse2](https://github.com/AppImage/AppImageKit/wiki/FUSE) first before running the AppImage asset with something like:
```
@@ -38,6 +40,13 @@ sudo add-apt-repository universe
sudo apt install libfuse2
```
On Ubuntu 24.04, the the libfuse2 package was renamed to libfuse2t64:
```
sudo add-apt-repository universe
sudo apt install libfuse2t64
```
As an alternative to having FUSE, you can manually extract the AppImage asset and run it. In a Terminal, it would look like:
```
@@ -47,6 +56,33 @@ cd squashfs-root
./AppRun
```
### AppArmor restrictions
On Ubuntu 24.04 and some distros, the default AppArmor configuration might restrict you from running the AppImage asset with an error message like this one:
```
The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now.
```
As a workaround, you can temporarily disable the AppArmor restrictions by running this command:
```
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
```
Alternatively, you can create an AppArmor profile for this file by creating a file in `/etc/apparmor.d/wagyu-key-gen` with the following content (make sure to replace `/path/to/Wagyu.Key.Gen.AppImage` with the full path to your AppImage asset):
```
abi <abi/4.0>,
include <tunables/global>
profile wagyukeygen /path/to/Wagyu.Key.Gen.AppImage flags=(default_allow) {
userns,
include if exists <local/wagyu-key-gen>
}
```
# Building process
Release assets were built using Github Actions and [this workflow run](`[WORKFLOW-RUN-URL]`). You can establish the provenance of this build using [our artifact attestations](https://github.com/stake-house/wagyu-key-gen/attestations).

1
.gitignore vendored
View File

@@ -13,3 +13,4 @@ dist/
# For pyinstaller
build/
src/scripts/__pycache__/
src/vendors/*.pyc

View File

@@ -1,7 +1,7 @@
{
"name": "wagyukeygen",
"productName": "Wagyu Key Gen",
"version": "1.11.1",
"version": "1.12.0",
"description": "GUI key generation tool wrapping the deposit cli.",
"main": "./build/electron/index.js",
"author": "Colfax Selby <colfax.selby@gmail.com>",

View File

@@ -10,10 +10,10 @@
* running application is not bundled.
* 3. Using the Python 3 version installed on the current machine and the version available
* in the current environment.
*
*
* When we want to call the stakingdeposit_proxy application, it will detect which way can be called
* in order and use the first one available.
*
*
* @module
*/
@@ -33,7 +33,7 @@ import { doesFileExist } from './BashUtils';
*/
const execFileProm = promisify(execFile);
const ETH2_DEPOSIT_DIR_NAME = "ethstaker-deposit-cli-0.6.0";
const ETH2_DEPOSIT_DIR_NAME = "ethstaker-deposit-cli-1.2.2";
/**
* Paths needed to call the stakingdeposit_proxy application using the Python 3 version installed on
@@ -75,7 +75,7 @@ const PATH_DELIM = (process.platform == "win32" ? ";" : ":");
/**
* Install the required Python packages needed to call the stakingdeposit_proxy application using the
* Python 3 version installed on the current machine.
*
*
* @returns Returns a Promise<boolean> that includes a true value if the required Python packages
* are present or have been installed correctly.
*/
@@ -98,7 +98,7 @@ const requireDepositPackages = async (): Promise<boolean> => {
/**
* Obtains the Python paths from the current available python executable in the environment.
*
*
* @returns Returns a Promise<string> that includes the Python paths separated by the system path
* delimiter.
*/
@@ -115,11 +115,11 @@ const getPythonPath = async (): Promise<string> => {
/**
* Create a new mnemonic by calling the create_mnemonic function from the stakingdeposit_proxy
* application.
*
*
* @param language The mnemonic language. Possible values are `chinese_simplified`,
* `chinese_traditional`, `czech`, `english`, `italian`, `korean`, `portuguese` or
* `spanish`.
*
*
* @returns Returns a Promise<string> that includes the mnemonic.
*/
const createMnemonic = async (language: string): Promise<string> => {
@@ -139,7 +139,7 @@ const createMnemonic = async (language: string): Promise<string> => {
throw new Error("Failed to create mnemonic, don't have the required packages.");
}
env.PYTHONPATH = await getPythonPath();
executable = PYTHON_EXE;
args = [STAKINGDEPOSIT_PROXY_PATH, CREATE_MNEMONIC_SUBCOMMAND, WORD_LIST_PATH, "--language",
language];
@@ -155,9 +155,10 @@ const createMnemonic = async (language: string): Promise<string> => {
/**
* Generate validator keys by calling the generate_keys function from the stakingdeposit_proxy
* application.
*
*
* @param mnemonic The mnemonic to be used as the seed for generating the keys.
* @param index The index of the first validator's keys you wish to generate.
* @param amount The amount to deposit for each validator
* @param count The number of signing keys you want to generate.
* @param network The network setting for the signing domain. Possible values are `mainnet`,
* `prater`, `kintsugi`, `kiln`.
@@ -166,42 +167,43 @@ const createMnemonic = async (language: string): Promise<string> => {
* be used to create the withdrawal credentials. Otherwise, it will
* generate withdrawal credentials with the mnemonic-derived
* withdrawal public key in [EIP-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters).
* @param compounding If the user wants compounding (0x02) credentials. This is only possible if eth1_withdrawal_address is defined.
* @param folder The folder path for the resulting keystore(s) and deposit(s) files.
*
*
* @returns Returns a Promise<void> that will resolve when the generation is done.
*/
const generateKeys = async (
mnemonic: string,
index: number,
amount: number,
count: number,
network: string,
password: string,
eth1_withdrawal_address: string,
compounding: boolean,
folder: string,
): Promise<void> => {
let executable:string = "";
let args:string[] = [];
let env = process.env;
let subArgs = [mnemonic, index.toString(), amount.toString(), count.toString(), folder, network.toLowerCase(), password];
if (eth1_withdrawal_address !== "") {
subArgs = subArgs.concat(["--eth1_withdrawal_address", eth1_withdrawal_address]);
if (compounding) {
subArgs = subArgs.concat(["--compounding"])
}
}
if (await doesFileExist(BUNDLED_SFE_PATH)) {
executable = BUNDLED_SFE_PATH;
args = [GENERATE_KEYS_SUBCOMMAND];
if ( eth1_withdrawal_address != "" ) {
args = args.concat(["--eth1_withdrawal_address", eth1_withdrawal_address]);
}
args = args.concat([BUNDLED_DIST_WORD_LIST_PATH, mnemonic, index.toString(), count.toString(),
folder, network.toLowerCase(), password]);
args = [GENERATE_KEYS_SUBCOMMAND, BUNDLED_DIST_WORD_LIST_PATH, ...subArgs];
} else if (await doesFileExist(SFE_PATH)) {
executable = SFE_PATH;
args = [GENERATE_KEYS_SUBCOMMAND];
if ( eth1_withdrawal_address != "" ) {
args = args.concat(["--eth1_withdrawal_address", eth1_withdrawal_address]);
}
args = args.concat([DIST_WORD_LIST_PATH, mnemonic, index.toString(), count.toString(), folder,
network.toLowerCase(), password]);
args = [GENERATE_KEYS_SUBCOMMAND, DIST_WORD_LIST_PATH, ...subArgs];
} else {
if(!(await requireDepositPackages())) {
throw new Error("Failed to generate keys, don't have the required packages.");
@@ -209,15 +211,9 @@ const generateKeys = async (
env.PYTHONPATH = await getPythonPath();
executable = PYTHON_EXE;
args = [STAKINGDEPOSIT_PROXY_PATH, GENERATE_KEYS_SUBCOMMAND];
if ( eth1_withdrawal_address != "" ) {
args = args.concat(["--eth1_withdrawal_address", eth1_withdrawal_address]);
}
args = args.concat([WORD_LIST_PATH, mnemonic, index.toString(), count.toString(), folder,
network.toLowerCase(), password]);
args = [STAKINGDEPOSIT_PROXY_PATH, GENERATE_KEYS_SUBCOMMAND, WORD_LIST_PATH, ...subArgs];
}
await execFileProm(executable, args, {env: env});
}
@@ -226,7 +222,7 @@ const generateKeys = async (
* from the stakingdeposit_proxy application.
*
* @param mnemonic The mnemonic to be validated.
*
*
* @returns Returns a Promise<void> that will resolve when the validation is done.
*/
const validateMnemonic = async (
@@ -259,13 +255,13 @@ const validateMnemonic = async (
/**
* Validate BLS credentials by calling the validate_bls_credentials function
* from the stakingdeposit_proxy application.
*
*
* @param chain The network setting for the signing domain. Possible values are `mainnet`,
* `goerli`, `holesky`.
* @param mnemonic The mnemonic from which the BLS credentials are derived.
* @param index The index of the first validator's keys.
* @param withdrawal_credentials A list of the old BLS withdrawal credentials of the given validator(s), comma separated.
*
*
* @returns Returns a Promise<void> that will resolve when the validation is done.
*/
const validateBLSCredentials = async (
@@ -301,7 +297,7 @@ const validateBLSCredentials = async (
/**
* Generate BTEC file by calling the bls_change function from the stakingdeposit_proxy
* application.
*
*
* @param folder The folder path for the resulting BTEC file.
* @param chain The network setting for the signing domain. Possible values are `mainnet`,
* `goerli`, `holesky`.
@@ -310,7 +306,7 @@ const validateBLSCredentials = async (
* @param indices The validator index number(s) as identified on the beacon chain (comma separated).
* @param withdrawal_credentials A list of the old BLS withdrawal credentials of the given validator(s), comma separated.
* @param execution_address The withdrawal address.
*
*
* @returns Returns a Promise<void> that will resolve when the generation is done.
*/
const generateBLSChange = async (
@@ -321,7 +317,7 @@ const generateBLSChange = async (
indices: string,
withdrawal_credentials: string,
execution_address: string
): Promise<void> => {
let executable:string = "";
@@ -331,13 +327,13 @@ let env = process.env;
if (await doesFileExist(BUNDLED_SFE_PATH)) {
executable = BUNDLED_SFE_PATH;
args = [VALIDATE_BLS_CHANGE_SUBCOMMAND];
args = args.concat([folder, chain.toLowerCase(), mnemonic, index.toString(), indices,
withdrawal_credentials, execution_address]);
} else if (await doesFileExist(SFE_PATH)) {
executable = SFE_PATH;
args = [VALIDATE_BLS_CHANGE_SUBCOMMAND];
args = args.concat([folder, chain.toLowerCase(), mnemonic, index.toString(), indices,
withdrawal_credentials, execution_address]);
} else {
@@ -362,4 +358,4 @@ export {
validateMnemonic,
validateBLSCredentials,
generateBLSChange
};
};

View File

@@ -33,8 +33,8 @@ export interface IElectronAPI {
export interface IEth2DepositAPI {
createMnemonic: (language: string) => Promise<string>,
generateBLSChange: (folder: string, chain: string, mnemonic: string, index: number, indices: string, withdrawal_credentials: string, execution_address: string) => Promise<void>,
generateKeys: (mnemonic: string, index: number, count: number, network: string,
password: string, eth1_withdrawal_address: string, folder: string) => Promise<void>,
generateKeys: (mnemonic: string, index: number, amount: number, count: number, network: string,
password: string, eth1_withdrawal_address: string, compounding: boolean, folder: string) => Promise<void>,
validateBLSCredentials: (chain: string, mnemonic: string, index: number, withdrawal_credentials: string) => Promise<void>,
validateMnemonic: (mnemonic: string) => Promise<void>,
}
@@ -56,4 +56,4 @@ declare global {
bashUtils: IBashUtilsAPI,
web3Utils: IWeb3UtilsAPI
}
}
}

View File

@@ -9,10 +9,14 @@ interface KeyCreationContextType {
setMnemonic: Dispatch<SetStateAction<string>>;
numberOfKeys: number;
setNumberOfKeys: Dispatch<SetStateAction<number>>;
amount: number;
setAmount: Dispatch<SetStateAction<number>>;
password: string;
setPassword: Dispatch<SetStateAction<string>>;
withdrawalAddress: string;
setWithdrawalAddress: Dispatch<SetStateAction<string>>;
compounding: boolean;
setCompounding: Dispatch<SetStateAction<boolean>>;
}
export const KeyCreationContext = createContext<KeyCreationContextType>({
@@ -24,10 +28,14 @@ export const KeyCreationContext = createContext<KeyCreationContextType>({
setMnemonic: () => {},
numberOfKeys: 1,
setNumberOfKeys: () => {},
amount: 32,
setAmount: () => {},
password: "",
setPassword: () => {},
withdrawalAddress: "",
setWithdrawalAddress: () => {},
compounding: false,
setCompounding: () => {},
});
/**
@@ -38,8 +46,10 @@ const KeyCreationContextWrapper = ({ children }: { children: React.ReactNode}) =
const [index, setIndex] = useState<number>(0);
const [mnemonic, setMnemonic] = useState<string>("");
const [numberOfKeys, setNumberOfKeys] = useState<number>(1);
const [amount, setAmount] = useState<number>(32);
const [password, setPassword] = useState<string>("");
const [withdrawalAddress, setWithdrawalAddress] = useState<string>("");
const [compounding, setCompounding] = useState<boolean>(false);
return (
<KeyCreationContext.Provider value={{
@@ -51,10 +61,14 @@ const KeyCreationContextWrapper = ({ children }: { children: React.ReactNode}) =
setMnemonic,
numberOfKeys,
setNumberOfKeys,
amount: amount,
setAmount,
password,
setPassword,
withdrawalAddress,
setWithdrawalAddress,
compounding,
setCompounding,
}}>
{children}
</KeyCreationContext.Provider>

View File

@@ -87,7 +87,7 @@ const VerifyMnemonic = ({
return (
<Grid container item xs={10} spacing={2}>
{ network === Network.MAINNET ? (
{ network === Network.MAINNET || network === Network.GNOSIS ? (
mnemonicToVerifyArray.map((value, index) => (
<Grid item xs={2} key={"verify-mnemonic-grid-key-" + index}>
<TextField

View File

@@ -1,7 +1,33 @@
import { StepKey } from './types';
import { Network, NetworkConfig } from './types';
export const MNEMONIC_ERROR_SEARCH = "That is not a valid mnemonic";
export const VALID_MNEMONIC_LENGTHS = [12, 15, 18, 21, 24];
export const ETH_TO_GWEI = 10 ** 9;
export const getDepositAmountLimits = (network: Network) => {
const multiplier = NetworkConfig[network].multiplier;
return {
min: 1 / multiplier,
max: 2048 / multiplier,
};
};
export const formatDepositAmountError = (network: Network): string => {
const { min, max } = getDepositAmountLimits(network);
return `Amount must be between ${min} and ${max}.`;
};
export const formatAmountTooltip = (network: Network): string => {
const { min, max } = getDepositAmountLimits(network);
return `Enter the amount you would like to deposit for each validator. This value must be between ${min} and ${max} and can not have greater precision than 1 gwei. You must have withdrawal credentials defined and set "compounding".`;
};
export const formatCompoundingTooltip = (network: Network): string => {
const { max } = getDepositAmountLimits(network);
const value = 32 / NetworkConfig[network].multiplier;
return `Compounding Credentials increases your maximum effective balance from ${value} to ${max} ETH.`;
};
export const errors = {
MNEMONIC_LENGTH_ERROR: `The Secret Recovery Phrase must be ${VALID_MNEMONIC_LENGTHS.slice(0, -1).join(", ")}, or ${VALID_MNEMONIC_LENGTHS.slice(-1)} words in length. Please verify each word and try again.`,
@@ -45,8 +71,8 @@ export const stepLabels = {
[StepKey.KeyGeneration]: 'Create Validator Key Files',
[StepKey.Finish]: 'Finish',
[StepKey.BTECConfiguration]: 'Configure Withdrawal Address',
[StepKey.BTECGeneration]: 'Create Credentials Change',
[StepKey.FinishBTEC]: 'Finish'
[StepKey.BTECGeneration]: 'Create Credentials Change',
[StepKey.FinishBTEC]: 'Finish'
};
export const CreateMnemonicFlow = [StepKey.MnemonicGeneration, StepKey.KeyConfiguration, StepKey.KeyGeneration, StepKey.Finish];

View File

@@ -57,10 +57,11 @@ const NetworkPickerModal = ({onClose, showModal}: NetworkPickerModalParams) => {
<FormControl variant="standard" focused>
<RadioGroup aria-label="gender" name="gender1" value={formNetwork} onChange={onNetworkChange}>
<FormControlLabel value={Network.MAINNET} control={<Radio />} label={Network.MAINNET} />
<FormControlLabel value={Network.GNOSIS} control={<Radio />} label={Network.GNOSIS} />
<Divider />
<Typography className="tw-text-xl tw-mt-5 tw-mb-4">Testnets</Typography>
<FormControlLabel value={Network.HOLESKY} control={<Radio />} label={Network.HOLESKY} />
<FormControlLabel value={Network.GOERLI} control={<Radio />} label={Network.GOERLI} />
<FormControlLabel value={Network.HOODI} control={<Radio />} label={Network.HOODI} />
<FormControlLabel value={Network.CHIADO} control={<Radio />} label={Network.CHIADO} />
</RadioGroup>
<Button

View File

@@ -1,10 +1,29 @@
import { Button, TextField, Tooltip, Typography } from "@mui/material";
import {
Button,
Checkbox,
FormControlLabel,
TextField,
Tooltip,
Typography,
} from "@mui/material";
import { useContext, useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import WizardWrapper from "../components/WizardWrapper";
import { CreateMnemonicFlow, ExistingMnemonicFlow, errors, paths, tooltips } from "../constants";
import {
CreateMnemonicFlow,
ExistingMnemonicFlow,
errors,
paths,
tooltips,
getDepositAmountLimits,
formatDepositAmountError,
formatAmountTooltip,
formatCompoundingTooltip,
} from "../constants";
import { GlobalContext } from "../GlobalContext";
import { KeyCreationContext } from "../KeyCreationContext";
import { NetworkConfig } from "../types";
/**
* Form to provide number of keys, index, password, and optional withdrawal address necessary to
@@ -20,14 +39,22 @@ const ConfigureValidatorKeys = () => {
setIndex,
numberOfKeys,
setNumberOfKeys,
amount,
setAmount,
password,
setPassword,
withdrawalAddress,
setWithdrawalAddress,
compounding,
setCompounding,
} = useContext(KeyCreationContext);
const { network } = useContext(GlobalContext);
const history = useHistory();
const usingExistingFlow = history.location.pathname === paths.CONFIGURE_EXISTING;
// Get dynamic min/max values based on current network
const { min: minAmount, max: maxAmount } = getDepositAmountLimits(network);
const [passwordToVerify, setPasswordToVerify] = useState("");
const [verifyPassword, setVerifyPassword] = useState(false);
const [passwordVerifyError, setPasswordVerifyError] = useState(false);
@@ -38,12 +65,17 @@ const ConfigureValidatorKeys = () => {
const [inputIndex, setInputIndex] = useState(index);
const [inputIndexError, setInputIndexError] = useState(false);
const [inputAmount, setInputAmount] = useState(amount / NetworkConfig[network].multiplier);
const [inputAmountError, setInputAmountError] = useState(false);
const [inputPassword, setInputPassword] = useState(password);
const [inputPasswordStrengthError, setInputPasswordStrengthError] = useState(false);
const [inputWithdrawalAddress, setInputWithdrawalAddress] = useState(withdrawalAddress);
const [inputWithdrawalAddressFormatError, setInputWithdrawalAddressFormatError] = useState(false);
const [inputCompounding, setInputCompounding] = useState(compounding);
useEffect(() => {
if (!mnemonic) {
history.replace(usingExistingFlow ? paths.EXISTING_IMPORT : paths.CREATE_MNEMONIC);
@@ -60,12 +92,37 @@ const ConfigureValidatorKeys = () => {
setInputIndex(num);
};
const updateAmount = ({ target: { value }}: React.FocusEvent<HTMLInputElement>) => {
let trimmedValue = value;
const splitValue = value.split('.');
if (splitValue.length > 1) {
// Keep precision to 1 Gwei
trimmedValue = `${splitValue[0]}.${splitValue[1].substring(0, 9)}`;
}
const num = parseFloat(trimmedValue);
setInputAmount(num);
};
const updatePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputPassword(e.target.value);
};
const updateEth1WithdrawAddress = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputWithdrawalAddress(e.target.value.trim());
const address = e.target.value.trim();
setInputWithdrawalAddress(address);
if (!address) {
setInputCompounding(false);
setInputAmount(32);
}
};
const updateCompounding = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.checked) {
setInputAmount(32);
}
setInputCompounding(e.target.checked);
};
/**
@@ -82,13 +139,6 @@ const ConfigureValidatorKeys = () => {
setInputNumberOfKeysError(false);
}
if (inputPassword.length < 12) {
setInputPasswordStrengthError(true);
isError = true;
} else {
setInputPasswordStrengthError(false);
}
if (inputIndex < 0) {
setInputIndexError(true);
isError = true;
@@ -96,7 +146,21 @@ const ConfigureValidatorKeys = () => {
setInputIndexError(false);
}
if (inputWithdrawalAddress != "") {
if (inputAmount < minAmount || inputAmount > maxAmount) {
setInputAmountError(true);
isError = true;
} else {
setInputAmountError(false);
}
if (inputPassword.length < 12) {
setInputPasswordStrengthError(true);
isError = true;
} else {
setInputPasswordStrengthError(false);
}
if (inputWithdrawalAddress !== "") {
const isValidAddress = await window.web3Utils.isAddress(inputWithdrawalAddress);
if (!isValidAddress) {
setInputWithdrawalAddressFormatError(true);
@@ -129,8 +193,10 @@ const ConfigureValidatorKeys = () => {
// Set context
setIndex(inputIndex);
setNumberOfKeys(inputNumberOfKeys);
setAmount(inputAmount);
setPassword(inputPassword);
setWithdrawalAddress(inputWithdrawalAddress);
setCompounding(inputCompounding)
history.push(usingExistingFlow ? paths.CREATE_KEYS_EXISTING : paths.CREATE_KEYS_CREATE);
} else {
@@ -149,14 +215,18 @@ const ConfigureValidatorKeys = () => {
// Reset context
setIndex(0);
setNumberOfKeys(1);
setAmount(32);
setWithdrawalAddress("");
setPassword("");
setCompounding(false);
// Reset form
setInputNumberOfKeys(1);
setInputIndex(0);
setInputAmount(32);
setInputWithdrawalAddress("");
setInputPassword("");
setInputCompounding(false);
history.goBack();
}
};
@@ -201,10 +271,54 @@ const ConfigureValidatorKeys = () => {
<div className="tw-flex tw-flex-col tw-gap-4 tw-items-center tw-px-20">
<div className="tw-mb-4">Nice! Your Secret Recovery Phrase is verified. Now let's collect some info about the keys to create:</div>
<div className="tw-w-full tw-flex tw-flex-row tw-gap-4">
<div className="tw-flex tw-flex-col">
<Tooltip title={tooltips.ETH1_WITHDRAW_ADDRESS}>
<TextField
autoFocus
className="tw-w-[580px]"
id="eth1-withdraw-address"
label="Ethereum Withdrawal Address (Optional)"
variant="outlined"
value={inputWithdrawalAddress}
onChange={updateEth1WithdrawAddress}
error={inputWithdrawalAddressFormatError}
helperText={ inputWithdrawalAddressFormatError ? errors.ADDRESS_FORMAT_ERROR : ""}
/>
</Tooltip>
<Tooltip title={formatCompoundingTooltip(network)}>
<FormControlLabel
label="Compounding Credentials (0x02) - Must set a valid Withdrawal Address"
control={
<Checkbox
checked={inputCompounding}
disabled={!inputWithdrawalAddress}
onChange={updateCompounding}
/>
}
/>
</Tooltip>
</div>
<Tooltip title={formatAmountTooltip(network)}>
<TextField
className="tw-flex-1"
disabled={!inputCompounding}
id="amount"
label="Deposit Amount"
type="number"
variant="outlined"
value={inputAmount}
onChange={updateAmount}
error={inputAmountError}
helperText={inputAmountError ? formatDepositAmountError(network) : ""}
/>
</Tooltip>
</div>
<div className="tw-w-full tw-flex tw-flex-row tw-gap-4">
<Tooltip title={tooltips.NUMBER_OF_KEYS}>
<TextField
autoFocus
className="tw-flex-1"
id="number-of-keys"
label="Number of New Keys"
@@ -223,7 +337,7 @@ const ConfigureValidatorKeys = () => {
<TextField
className="tw-flex-1"
id="index"
label="Amount of Existing (starting index)"
label="Amount of Existing Keys (starting index)"
variant="outlined"
type="number"
value={inputIndex}
@@ -250,18 +364,6 @@ const ConfigureValidatorKeys = () => {
</Tooltip>
</div>
<Tooltip title={tooltips.ETH1_WITHDRAW_ADDRESS}>
<TextField
className="tw-mt-8 tw-w-[440px]"
id="eth1-withdraw-address"
label="Ethereum Withdrawal Address (Optional)"
variant="outlined"
value={inputWithdrawalAddress}
onChange={updateEth1WithdrawAddress}
error={inputWithdrawalAddressFormatError}
helperText={ inputWithdrawalAddressFormatError ? errors.ADDRESS_FORMAT_ERROR : ""}
/>
</Tooltip>
<Typography className="tw-text-center tw-mx-4" variant="body1">
Please ensure that you have control over this address. If you do not add a withdrawal address now, you will be able to add one later with your 24 words secret recovery phrase.
</Typography>

View File

@@ -5,9 +5,15 @@ import { Button, Typography } from "@mui/material";
import FolderSelector from "../components/FolderSelector";
import Loader from "../components/Loader";
import WizardWrapper from "../components/WizardWrapper";
import { CreateMnemonicFlow, ExistingMnemonicFlow, paths } from "../constants";
import {
CreateMnemonicFlow,
ETH_TO_GWEI,
ExistingMnemonicFlow,
paths,
} from "../constants";
import { GlobalContext } from "../GlobalContext";
import { KeyCreationContext } from "../KeyCreationContext";
import { NetworkConfig } from "../types";
/**
* Allows the user to select a destination folder for the validator keys.
@@ -16,11 +22,13 @@ import { KeyCreationContext } from "../KeyCreationContext";
const CreateValidatorKeys = () => {
const {
setFolderLocation,
amount,
index,
numberOfKeys,
mnemonic,
password,
withdrawalAddress,
compounding,
} = useContext(KeyCreationContext);
const { network } = useContext(GlobalContext);
const history = useHistory();
@@ -53,13 +61,18 @@ const CreateValidatorKeys = () => {
appendedWithdrawalAddress = "0x" + withdrawalAddress;
}
// Convert user provided amount to integer representation of gwei
const gweiAmount = parseInt((amount * NetworkConfig[network].multiplier * ETH_TO_GWEI).toString());
window.eth2Deposit.generateKeys(
mnemonic,
index,
gweiAmount,
numberOfKeys,
network,
password,
appendedWithdrawalAddress,
compounding,
selectedFolder,
).then(() => {
setFolderLocation(selectedFolder);

View File

@@ -22,6 +22,26 @@ export enum ReuseMnemonicAction {
export enum Network {
MAINNET = "Mainnet",
GOERLI = "Goerli",
HOLESKY = "Holesky"
HOODI = "Hoodi",
GNOSIS = "Gnosis",
CHIADO = "Chiado",
}
export interface NetworkConfig {
multiplier: number;
}
export const NetworkConfig: Record<Network, NetworkConfig> = {
[Network.MAINNET]: {
multiplier: 1,
},
[Network.HOODI]: {
multiplier: 1,
},
[Network.GNOSIS]: {
multiplier: 32,
},
[Network.CHIADO]: {
multiplier: 32,
},
};

View File

@@ -10,7 +10,7 @@ fi
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
EDCDIR=ethstaker-deposit-cli-0.6.0
EDCDIR=ethstaker-deposit-cli-1.2.2
TARGETPACKAGESPATH=$SCRIPTPATH/../../dist/packages
ETH2DEPOSITCLIPATH=$SCRIPTPATH/../vendors/$EDCDIR

View File

@@ -5,7 +5,7 @@ rem Windows.
SET BATDIR=%~dp0
SET EDCDIR=ethstaker-deposit-cli-0.6.0
SET EDCDIR=ethstaker-deposit-cli-1.2.2
SET TARGETPACKAGESPATH=%BATDIR%..\..\dist\packages

View File

@@ -40,12 +40,13 @@ from ethstaker_deposit.utils.validation import (
validate_bls_withdrawal_credentials_matching,
)
from ethstaker_deposit.utils.constants import (
MIN_ACTIVATION_AMOUNT,
ETH2GWEI,
)
from ethstaker_deposit.utils.deposit import export_deposit_data_json as export_deposit_data_json_util
from ethstaker_deposit.settings import (
get_chain_setting,
BaseChainSetting,
)
from ethstaker_deposit.utils.file_handling import (
@@ -78,7 +79,8 @@ def generate_bls_to_execution_change(
validator_start_index: int,
validator_indices: Sequence[int],
bls_withdrawal_credentials_list: Sequence[bytes],
execution_address: HexAddress
withdrawal_address: HexAddress,
devnet_chain_setting: Optional[BaseChainSetting] = None,
) -> None:
"""Generate bls to execution change file.
@@ -90,20 +92,21 @@ def generate_bls_to_execution_change(
validator_start_index -- index position for the keys to start generating withdrawal credentials
validator_indices -- a list of the chosen validator index number(s) as identified on the beacon chain
bls_withdrawal_credentials_list -- a list of the old BLS withdrawal credentials of the given validator(s)
execution_address -- withdrawal address
withdrawal_address -- withdrawal address
devnet_chain_setting -- optional custom chain setting
"""
if not os.path.exists(folder):
os.mkdir(folder)
eth1_withdrawal_address = execution_address
if not is_hex_address(eth1_withdrawal_address):
eth1_withdrawal_address = withdrawal_address
if not is_hex_address(withdrawal_address):
raise ValueError("The given withdrawal address is not in hexadecimal encoded form.")
eth1_withdrawal_address = to_normalized_address(eth1_withdrawal_address)
execution_address = eth1_withdrawal_address
eth1_withdrawal_address = to_normalized_address(withdrawal_address)
withdrawal_address = eth1_withdrawal_address
# Get chain setting
chain_setting = get_chain_setting(chain)
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
if len(validator_indices) != len(bls_withdrawal_credentials_list):
raise ValueError(
@@ -112,13 +115,13 @@ def generate_bls_to_execution_change(
)
num_validators = len(validator_indices)
amounts = [MIN_ACTIVATION_AMOUNT] * num_validators
amounts = [chain_setting.MIN_ACTIVATION_AMOUNT * ETH2GWEI] * num_validators
mnemonic_password = ''
num_keys = num_validators
start_index = validator_start_index
hex_withdrawal_address = execution_address
hex_withdrawal_address = withdrawal_address
if len(amounts) != num_keys:
raise ValueError(
@@ -201,6 +204,7 @@ def validate_bls_credentials(
mnemonic: str,
validator_start_index: int,
bls_withdrawal_credentials_list: Sequence[bytes],
devnet_chain_setting: Optional[BaseChainSetting] = None,
) -> None:
"""Validate BLS credentials against what was generated from a mnemonic.
@@ -210,12 +214,14 @@ def validate_bls_credentials(
mnemonic -- mnemonic to be used as the seed for generating the keys
validator_start_index -- index position for the keys to start generating withdrawal credentials
bls_withdrawal_credentials_list -- a list of the old BLS withdrawal credentials of the given validator(s)
devnet_chain_setting -- optional custom chain setting
"""
chain_setting = get_chain_setting(chain)
# Get chain setting
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
num_validators = len(bls_withdrawal_credentials_list)
amounts = [MIN_ACTIVATION_AMOUNT] * num_validators
amounts = [chain_setting.MIN_ACTIVATION_AMOUNT * ETH2GWEI] * num_validators
mnemonic_password = ''
@@ -304,13 +310,16 @@ def generate_keys(args):
- wordlist: path to the word lists directory
- mnemonic: mnemonic to be used as the seed for generating the keys
- index: index of the first validator's keys you wish to generate
- amount: deposit amount for each validator
- count: number of signing keys you want to generate
- folder: folder path for the resulting keystore(s) and deposit(s) files
- network: network setting for the signing domain, possible values are 'mainnet',
'prater', 'kintsugi' or 'kiln'
'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis' or 'chiado'
- password: password that will protect the resulting keystore(s)
- eth1_withdrawal_address: (Optional) eth1 address that will be used to create the
withdrawal credentials
- compounding: (Optional) if the user wants compounding (0x02) credentials. Requires
withdrawal address to be defined
"""
eth1_withdrawal_address = None
@@ -323,7 +332,7 @@ def generate_keys(args):
mnemonic = validate_mnemonic(args.mnemonic, args.wordlist)
mnemonic_password = ''
amounts = [MIN_ACTIVATION_AMOUNT] * args.count
amounts = [args.amount] * args.count
folder = args.folder
chain_setting = get_chain_setting(args.network)
if not os.path.exists(folder):
@@ -340,7 +349,6 @@ def generate_keys(args):
)
timestamp = time.time()
compounding = False
use_pbkdf2 = False
key_indices = range(start_index, start_index + num_keys)
@@ -353,7 +361,7 @@ def generate_keys(args):
'amount': amounts[index - start_index],
'chain_setting': chain_setting,
'hex_withdrawal_address': hex_withdrawal_address,
'compounding': compounding,
'compounding': args.compounding,
'use_pbkdf2': use_pbkdf2,
} for index in key_indices]
@@ -390,7 +398,7 @@ def generate_keys(args):
'credential': credential,
'keystore_filefolder': fileholder,
'password': password,
} for credential, fileholder in zip(credentials.credentials, keystore_filefolders)]
} for credential, fileholder in items]
with concurrent.futures.ProcessPoolExecutor() as executor:
for valid_keystore in executor.map(_keystore_verifier, executor_kwargs):
@@ -405,7 +413,8 @@ def generate_keys(args):
deposit_json = json.load(f)
with concurrent.futures.ProcessPoolExecutor() as executor:
for valid_deposit in executor.map(validate_deposit, deposit_json, credentials.credentials):
chain_settings = [chain_setting] * len(deposit_json)
for valid_deposit in executor.map(validate_deposit, deposit_json, chain_settings, credentials.credentials):
all_valid_deposits &= valid_deposit
if not all_valid_deposits:
@@ -477,11 +486,13 @@ def main():
generate_parser.add_argument("wordlist", help="Path to word list directory", type=str)
generate_parser.add_argument("mnemonic", help="Mnemonic", type=str)
generate_parser.add_argument("index", help="Validator start index", type=int)
generate_parser.add_argument("amount", help="Validator deposit amount", type=int)
generate_parser.add_argument("count", help="Validator count", type=int)
generate_parser.add_argument("folder", help="Where to put the deposit data and keystore files", type=str)
generate_parser.add_argument("network", help="For which network to create these keys for", type=str)
generate_parser.add_argument("password", help="Password for the keystore files", type=str)
generate_parser.add_argument("--eth1_withdrawal_address", help="Optional eth1 withdrawal address", type=str)
generate_parser.add_argument("--compounding", action="store_true", help="Optional compounding argument")
generate_parser.set_defaults(func=parse_generate_keys)
validate_parser = subparsers.add_parser("validate_mnemonic")

View File

@@ -1,7 +1,7 @@
# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import copy_metadata
datas = [('../vendors/ethstaker-deposit-cli-0.6.0/ethstaker_deposit/intl', 'ethstaker_deposit/intl')]
datas = [('../vendors/ethstaker-deposit-cli-1.2.2/ethstaker_deposit/intl', 'ethstaker_deposit/intl')]
datas += copy_metadata('py_ecc')
datas += copy_metadata('ssz')

View File

@@ -1 +0,0 @@
__version__ = '0.6.0'

View File

@@ -1,39 +0,0 @@
import subprocess
import os
import sys
import shutil
import click
def clear_terminal() -> None:
# Do not clear if running unit tests as stdout can be used to determine state
if "PYTEST_CURRENT_TEST" in os.environ:
return
# We bundle libtinfo via pyinstaller, which messes with the system tput.
# Remove LD_LIBRARY_PATH just for subprocess.run()
if sys.platform == 'linux':
clean_env = os.environ.copy()
clean_env.pop('LD_LIBRARY_PATH', None)
elif sys.platform == 'darwin':
clean_env = os.environ.copy()
if sys.platform == 'win32':
# Special-case for asyncio pytest on Windows
if os.getenv("IS_ASYNC_TEST") == "1":
click.clear()
elif shutil.which('clear'):
subprocess.run(['clear'])
else:
subprocess.run('cls', shell=True)
elif sys.platform == 'linux' or sys.platform == 'darwin':
if shutil.which('clear'):
subprocess.run(['clear'], env=clean_env)
else:
click.clear()
if shutil.which('tput'):
subprocess.run(['tput', 'reset'], env=clean_env)
if shutil.which('reset'):
subprocess.run(['reset'], env=clean_env)
else:
click.clear()

View File

@@ -1,4 +0,0 @@
[flake8]
max-line-length= 120
exclude=
ignore=W503

View File

@@ -1,44 +0,0 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
packages = ["ethstaker_deposit"]
[tool.setuptools.dynamic]
version = {attr = "ethstaker_deposit.__version__"}
[tool.pip-tools]
generate-hashes = true
no-annotate = true
[project]
name = "ethstaker_deposit"
description = "Secure key generation for deposits"
readme = "README.md"
dependencies = [
"click",
"eth-typing",
"eth-utils",
"pycryptodome",
"pyperclip",
"py-ecc",
"ssz"
]
requires-python = ">=3.9,<4"
dynamic = ["version"]
[project.optional-dependencies]
test = [
"exceptiongroup", # pip-compile did not pick up from mypy
"flake8",
"jsonschema",
"mypy",
"pytest",
"pytest-asyncio",
"coverage",
"tomli" # pip-compile did not pick up from mypy
]
[project.urls]
"Homepage" = "https://github.com/eth-educators/ethstaker-deposit-cli"

View File

@@ -1,248 +0,0 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --generate-hashes --no-annotate
#
cached-property==2.0.1 \
--hash=sha256:484d617105e3ee0e4f1f58725e72a8ef9e93deee462222dbd51cd91230897641 \
--hash=sha256:f617d70ab1100b7bcf6e42228f9ddcb78c676ffa167278d9f730d1c2fba69ccb
click==8.1.7 \
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
colorama==0.4.6; platform_system == 'Windows' \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
cytoolz==1.0.0 \
--hash=sha256:035c8bb4706dcf93a89fb35feadff67e9301935bf6bb864cd2366923b69d9a29 \
--hash=sha256:04a84778f48ebddb26948971dc60948907c876ba33b13f9cbb014fe65b341fc2 \
--hash=sha256:05a871688df749b982839239fcd3f8ec3b3b4853775d575ff9cd335fa7c75035 \
--hash=sha256:05df5ff1cdd198fb57e7368623662578c950be0b14883cadfb9ee4098415e1e5 \
--hash=sha256:06d09e9569cfdfc5c082806d4b4582db8023a3ce034097008622bcbac7236f38 \
--hash=sha256:0983eee73df86e54bb4a79fcc4996aa8b8368fdbf43897f02f9c3bf39c4dc4fb \
--hash=sha256:0cace092dfda174eed09ed871793beb5b65633963bcda5b1632c73a5aceea1ce \
--hash=sha256:0ce8a2a85c0741c1b19b16e6782c4a5abc54c3caecda66793447112ab2fa9884 \
--hash=sha256:0d603f5e2b1072166745ecdd81384a75757a96a704a5642231eb51969f919d5f \
--hash=sha256:0f16907fdc724c55b16776bdb7e629deae81d500fe48cfc3861231753b271355 \
--hash=sha256:10e3986066dc379e30e225b230754d9f5996aa8d84c2accc69c473c21d261e46 \
--hash=sha256:11d48b8521ef5fe92e099f4fc00717b5d0789c3c90d5d84031b6d3b17dee1700 \
--hash=sha256:122ef2425bd3c0419e6e5260d0b18cd25cf74de589cd0184e4a63b24a4641e2e \
--hash=sha256:16576f1bb143ee2cb9f719fcc4b845879fb121f9075c7c5e8a5ff4854bd02fc6 \
--hash=sha256:20194dd02954c00c1f0755e636be75a20781f91a4ac9270c7f747e82d3c7f5a5 \
--hash=sha256:27c684799708bdc7ee7acfaf464836e1b4dec0996815c1d5efd6a92a4356a562 \
--hash=sha256:287d6d7f475882c2ddcbedf8da9a9b37d85b77690779a2d1cdceb5ae3998d52e \
--hash=sha256:28bb88e1e2f7d6d4b8e0890b06d292c568984d717de3e8381f2ca1dd12af6470 \
--hash=sha256:364c2fda148def38003b2c86e8adde1d2aab12411dd50872c244a815262e2fda \
--hash=sha256:388cd07ee9a9e504c735a0a933e53c98586a1c301a64af81f7aa7ff40c747520 \
--hash=sha256:389ec328bb535f09e71dfe658bf0041f17194ca4cedaacd39bafe7893497a819 \
--hash=sha256:3b319a7f0fed5db07d189db4046162ebc183c108df3562a65ba6ebe862d1f634 \
--hash=sha256:3faa25a1840b984315e8b3ae517312375f4273ffc9a2f035f548b7f916884f37 \
--hash=sha256:44ab57cfc922b15d94899f980d76759ef9e0256912dfab70bf2561bea9cd5b19 \
--hash=sha256:45d346620abc8c83ae634136e700432ad6202faffcc24c5ab70b87392dcda8a1 \
--hash=sha256:478af5ecc066da093d7660b23d0b465a7f44179739937afbded8af00af412eb6 \
--hash=sha256:49375aad431d76650f94877afb92f09f58b6ff9055079ef4f2cd55313f5a1b39 \
--hash=sha256:4c45106171c824a61e755355520b646cb35a1987b34bbf5789443823ee137f63 \
--hash=sha256:509ed3799c47e4ada14f63e41e8f540ac6e2dab97d5d7298934e6abb9d3830ec \
--hash=sha256:51dfda3983fcc59075c534ce54ca041bb3c80e827ada5d4f25ff7b4049777f94 \
--hash=sha256:576a4f1fc73d8836b10458b583f915849da6e4f7914f4ecb623ad95c2508cad5 \
--hash=sha256:6433f03910c5e5345d82d6299457c26bf33821224ebb837c6b09d9cdbc414a6c \
--hash=sha256:643a593ec272ef7429099e1182a22f64ec2696c00d295d2a5be390db1b7ff176 \
--hash=sha256:658dd85deb375ff7af990a674e5c9058cef1c9d1f5dc89bc87b77be499348144 \
--hash=sha256:69a7e5e98fd446079b8b8ec5987aec9a31ec3570a6f494baefa6800b783eaf22 \
--hash=sha256:6c371b3114d38ee717780b239179e88d5d358fe759a00dcf07691b8922bbc762 \
--hash=sha256:6ce38e2e42cbae30446190c59b92a8a9029e1806fd79eaf88f48b0fe33003893 \
--hash=sha256:6dbe5fe3b835859fc559eb59bf2775b5a108f7f2cfab0966f3202859d787d8fd \
--hash=sha256:781fce70a277b20fd95dc66811d1a97bb07b611ceea9bda8b7dd3c6a4b05d59a \
--hash=sha256:7a562c25338eb24d419d1e80a7ae12133844ce6fdeb4ab54459daf250088a1b2 \
--hash=sha256:7d56569dfe67a39ce74ffff0dc12cf0a3d1aae709667a303fe8f2dd5fd004fdf \
--hash=sha256:7df2dfd679f0517a96ced1cdd22f5c6c6aeeed28d928a82a02bf4c3fd6fd7ac4 \
--hash=sha256:7e53cfcce87e05b7f0ae2fb2b3e5820048cd0bb7b701e92bd8f75c9fbb7c9ae9 \
--hash=sha256:810a6a168b8c5ecb412fbae3dd6f7ed6c6253a63caf4174ee9794ebd29b2224f \
--hash=sha256:85c9c8c4465ed1b2c8d67003809aec9627b129cb531d2f6cf0bbfe39952e7e4d \
--hash=sha256:86fb208bfb7420e1d0d20065d661310e4a8a6884851d4044f47d37ed4cd7410e \
--hash=sha256:8819f1f97ebe36efcaf4b550e21677c46ac8a41bed482cf66845f377dd20700d \
--hash=sha256:89a554a9ba112403232a54e15e46ff218b33020f3f45c4baf6520ab198b7ad93 \
--hash=sha256:8c51452c938e610f57551aa96e34924169c9100c0448bac88c2fb395cbd3538c \
--hash=sha256:90b343b2f3b3e77c3832ba19b0b17e95412a5b2e715b05c23a55ba525d1fca49 \
--hash=sha256:921082fff09ff6e40c12c87b49be044492b2d6bb01d47783995813b76680c7b2 \
--hash=sha256:9502bd9e37779cc9893cbab515a474c2ab6af61ed22ac2f7e16033db18fcaa85 \
--hash=sha256:9715d1ff5576919d10b68f17241375f6a1eec8961c25b78a83e6ef1487053f39 \
--hash=sha256:9770e1b09748ad0d751853d994991e2592a9f8c464a87014365f80dac2e83faa \
--hash=sha256:98a96c54aa55ed9c7cdb23c2f0df39a7b4ee518ac54888480b5bdb5ef69c7ef0 \
--hash=sha256:99f39dcc46416dca3eb23664b73187b77fb52cd8ba2ddd8020a292d8f449db67 \
--hash=sha256:9af793b1738e4191d15a92e1793f1ffea9f6461022c7b2442f3cb1ea0a4f758a \
--hash=sha256:9b2e945617325242687189966335e785dc0fae316f4c1825baacf56e5a97e65f \
--hash=sha256:9ce25f02b910630f6dc2540dd1e26c9326027ddde6c59f8cab07c56acc70714c \
--hash=sha256:a09cdfb21dfb38aa04df43e7546a41f673377eb5485da88ceb784e327ec7603b \
--hash=sha256:a32f1356f3b64dda883583383966948604ac69ca0b7fbcf5f28856e5f9133b4e \
--hash=sha256:a99e7e29274e293f4ffe20e07f76c2ac753a78f1b40c1828dfc54b2981b2f6c4 \
--hash=sha256:acfb8780c04d29423d14aaab74cd1b7b4beaba32f676e7ace02c9acfbf532aba \
--hash=sha256:b1707b6c3a91676ac83a28a231a14b337dbb4436b937e6b3e4fd44209852a48b \
--hash=sha256:becce4b13e110b5ac6b23753dcd0c977f4fdccffa31898296e13fd1109e517e3 \
--hash=sha256:c0d56b3721977806dcf1a68b0ecd56feb382fdb0f632af1a9fc5ab9b662b32c6 \
--hash=sha256:c507a3e0a45c41d66b43f96797290d75d1e7a8549aa03a4a6b8854fdf3f7b8d8 \
--hash=sha256:c64658e1209517ce4b54c1c9269a508b289d8d55fc742760e4b8579eacf09a33 \
--hash=sha256:ca526905a014a38cc23ae78635dc51d0462c5c24425b22c08beed9ff2ee03845 \
--hash=sha256:caa7ef840847a23b379e6146760e3a22f15f445656af97e55a435c592125cfa5 \
--hash=sha256:d3206c81ca3ba2d7b8fe78f2e116e3028e721148be753308e88dcbbc370bca52 \
--hash=sha256:da1f82a7828a42468ea2820a25b6e56461361390c29dcd4d68beccfa1b71066b \
--hash=sha256:dbb2ec1177dca700f3db2127e572da20de280c214fc587b2a11c717fc421af56 \
--hash=sha256:df0c81197fc130de94c09fc6f024a6a19c98ba8fe55c17f1e45ebba2e9229079 \
--hash=sha256:dffc22fd2c91be64dbdbc462d0786f8e8ac9a275cfa1869a1084d1867d4f67e0 \
--hash=sha256:e672712d5dc3094afc6fb346dd4e9c18c1f3c69608ddb8cf3b9f8428f9c26a5c \
--hash=sha256:ea4ac72e6b830861035c4c7999af8e55813f57c6d1913a3d93cc4a6babc27bf7 \
--hash=sha256:eb453b30182152f9917a5189b7d99046b6ce90cdf8aeb0feff4b2683e600defd \
--hash=sha256:ecf5a887acb8f079ab1b81612b1c889bcbe6611aa7804fd2df46ed310aa5a345 \
--hash=sha256:ef0ef30c1e091d4d59d14d8108a16d50bd227be5d52a47da891da5019ac2f8e4 \
--hash=sha256:f29d8330aaf070304f7cd5cb7e73e198753624eb0aec278557cccd460c699b5b \
--hash=sha256:f370a1f1f1afc5c1c8cc5edc1cfe0ba444263a0772af7ce094be8e734f41769d \
--hash=sha256:f6039a9bd5bb988762458b9ca82b39e60ca5e5baae2ba93913990dcc5d19fa88 \
--hash=sha256:f65283b618b4c4df759f57bcf8483865a73f7f268e6d76886c743407c8d26c1c \
--hash=sha256:f7a9d816af3be9725c70efe0a6e4352a45d3877751b395014b8eb2f79d7d8d9d \
--hash=sha256:fcddbb853770dd6e270d89ea8742f0aa42c255a274b9e1620eb04e019b79785e
eth-hash==0.7.0 \
--hash=sha256:b8d5a230a2b251f4a291e3164a23a14057c4a6de4b0aa4a16fa4dc9161b57e2f \
--hash=sha256:bacdc705bfd85dadd055ecd35fd1b4f846b671add101427e089a4ca2e8db310a
eth-typing==5.0.1 \
--hash=sha256:83debf88c9df286db43bb7374974681ebcc9f048fac81be2548dbc549a3203c0 \
--hash=sha256:f30d1af16aac598f216748a952eeb64fbcb6e73efa691d2de31148138afe96de
eth-utils==5.1.0 \
--hash=sha256:84c6314b9cf1fcd526107464bbf487e3f87097a2e753360d5ed319f7d42e3f20 \
--hash=sha256:a99f1f01b51206620904c5af47fac65abc143aebd0a76bdec860381c5a3230f8
hexbytes==1.2.1 \
--hash=sha256:515f00dddf31053db4d0d7636dd16061c1d896c3109b8e751005db4ca46bcca7 \
--hash=sha256:e64890b203a31f4a23ef11470ecfcca565beaee9198df623047df322b757471a
lru-dict==1.3.0 \
--hash=sha256:0213ab4e3d9a8d386c18e485ad7b14b615cb6f05df6ef44fb2a0746c6ea9278b \
--hash=sha256:04cda617f4e4c27009005d0a8185ef02829b14b776d2791f5c994cc9d668bc24 \
--hash=sha256:0ad6361e4dd63b47b2fc8eab344198f37387e1da3dcfacfee19bafac3ec9f1eb \
--hash=sha256:0e1845024c31e6ff246c9eb5e6f6f1a8bb564c06f8a7d6d031220044c081090b \
--hash=sha256:0e88dba16695f17f41701269fa046197a3fd7b34a8dba744c8749303ddaa18df \
--hash=sha256:0fce5f95489ca1fc158cc9fe0f4866db9cec82c2be0470926a9080570392beaf \
--hash=sha256:1470f5828c7410e16c24b5150eb649647986e78924816e6fb0264049dea14a2b \
--hash=sha256:170b66d29945391460351588a7bd8210a95407ae82efe0b855e945398a1d24ea \
--hash=sha256:1958cb70b9542773d6241974646e5410e41ef32e5c9e437d44040d59bd80daf2 \
--hash=sha256:1ecb7ae557239c64077e9b26a142eb88e63cddb104111a5122de7bebbbd00098 \
--hash=sha256:20c595764695d20bdc3ab9b582e0cc99814da183544afb83783a36d6741a0dac \
--hash=sha256:2682bfca24656fb7a643621520d57b7fe684ed5fa7be008704c1235d38e16a32 \
--hash=sha256:2789296819525a1f3204072dfcf3df6db8bcf69a8fc740ffd3de43a684ea7002 \
--hash=sha256:28aa1ea42a7e48174bf513dc2416fea7511a547961e678dc6f5670ca987c18cb \
--hash=sha256:2a47740652b25900ac5ce52667b2eade28d8b5fdca0ccd3323459df710e8210a \
--hash=sha256:350e2233cfee9f326a0d7a08e309372d87186565e43a691b120006285a0ac549 \
--hash=sha256:3b4f121afe10f5a82b8e317626eb1e1c325b3f104af56c9756064cd833b1950b \
--hash=sha256:3c497fb60279f1e1d7dfbe150b1b069eaa43f7e172dab03f206282f4994676c5 \
--hash=sha256:3ca5474b1649555d014be1104e5558a92497509021a5ba5ea6e9b492303eb66b \
--hash=sha256:3cb1de0ce4137b060abaafed8474cc0ebd12cedd88aaa7f7b3ebb1ddfba86ae0 \
--hash=sha256:4073333894db9840f066226d50e6f914a2240711c87d60885d8c940b69a6673f \
--hash=sha256:40a8daddc29c7edb09dfe44292cf111f1e93a8344349778721d430d336b50505 \
--hash=sha256:4eafb188a84483b3231259bf19030859f070321b00326dcb8e8c6cbf7db4b12f \
--hash=sha256:5247d1f011f92666010942434020ddc5a60951fefd5d12a594f0e5d9f43e3b3b \
--hash=sha256:54fd1966d6bd1fcde781596cb86068214edeebff1db13a2cea11079e3fd07b6b \
--hash=sha256:5ad659cbc349d0c9ba8e536b5f40f96a70c360f43323c29f4257f340d891531c \
--hash=sha256:6123aefe97762ad74215d05320a7f389f196f0594c8813534284d4eafeca1a96 \
--hash=sha256:64545fca797fe2c68c5168efb5f976c6e1459e058cab02445207a079180a3557 \
--hash=sha256:6a03170e4152836987a88dcebde61aaeb73ab7099a00bb86509d45b3fe424230 \
--hash=sha256:6af36166d22dba851e06a13e35bbf33845d3dd88872e6aebbc8e3e7db70f4682 \
--hash=sha256:6bba2863060caeaedd8386b0c8ee9a7ce4d57a7cb80ceeddf440b4eff2d013ba \
--hash=sha256:6cb0be5e79c3f34d69b90d8559f0221e374b974b809a22377122c4b1a610ff67 \
--hash=sha256:6ffaf595e625b388babc8e7d79b40f26c7485f61f16efe76764e32dce9ea17fc \
--hash=sha256:73593791047e36b37fdc0b67b76aeed439fcea80959c7d46201240f9ec3b2563 \
--hash=sha256:774ca88501a9effe8797c3db5a6685cf20978c9cb0fe836b6813cfe1ca60d8c9 \
--hash=sha256:784ca9d3b0730b3ec199c0a58f66264c63dd5d438119c739c349a6a9be8e5f6e \
--hash=sha256:7969cb034b3ccc707aff877c73c225c32d7e2a7981baa8f92f5dd4d468fe8c33 \
--hash=sha256:7ffbce5c2e80f57937679553c8f27e61ec327c962bf7ea0b15f1d74277fd5363 \
--hash=sha256:82eb230d48eaebd6977a92ddaa6d788f14cf4f4bcf5bbffa4ddfd60d051aa9d4 \
--hash=sha256:8551ccab1349d4bebedab333dfc8693c74ff728f4b565fe15a6bf7d296bd7ea9 \
--hash=sha256:8d9509d817a47597988615c1a322580c10100acad10c98dfcf3abb41e0e5877f \
--hash=sha256:8ee38d420c77eed548df47b7d74b5169a98e71c9e975596e31ab808e76d11f09 \
--hash=sha256:9537e1cee6fa582cb68f2fb9ce82d51faf2ccc0a638b275d033fdcb1478eb80b \
--hash=sha256:96fc87ddf569181827458ec5ad8fa446c4690cffacda66667de780f9fcefd44d \
--hash=sha256:9710737584650a4251b9a566cbb1a86f83437adb209c9ba43a4e756d12faf0d7 \
--hash=sha256:9bd13af06dab7c6ee92284fd02ed9a5613a07d5c1b41948dc8886e7207f86dfd \
--hash=sha256:9f725f2a0bdf1c18735372d5807af4ea3b77888208590394d4660e3d07971f21 \
--hash=sha256:a193a14c66cfc0c259d05dddc5e566a4b09e8f1765e941503d065008feebea9d \
--hash=sha256:a1efc59bfba6aac33684d87b9e02813b0e2445b2f1c444dae2a0b396ad0ed60c \
--hash=sha256:a3c9f746a9917e784fffcedeac4c8c47a3dbd90cbe13b69e9140182ad97ce4b7 \
--hash=sha256:a690c23fc353681ed8042d9fe8f48f0fb79a57b9a45daea2f0be1eef8a1a4aa4 \
--hash=sha256:a9fb71ba262c6058a0017ce83d343370d0a0dbe2ae62c2eef38241ec13219330 \
--hash=sha256:abd0c284b26b5c4ee806ca4f33ab5e16b4bf4d5ec9e093e75a6f6287acdde78e \
--hash=sha256:acd04b7e7b0c0c192d738df9c317093335e7282c64c9d1bb6b7ebb54674b4e24 \
--hash=sha256:b2bf2e24cf5f19c3ff69bf639306e83dced273e6fa775b04e190d7f5cd16f794 \
--hash=sha256:b50fbd69cd3287196796ab4d50e4cc741eb5b5a01f89d8e930df08da3010c385 \
--hash=sha256:b84c321ae34f2f40aae80e18b6fa08b31c90095792ab64bb99d2e385143effaa \
--hash=sha256:ba490b8972531d153ac0d4e421f60d793d71a2f4adbe2f7740b3c55dce0a12f1 \
--hash=sha256:bc1cd3ed2cee78a47f11f3b70be053903bda197a873fd146e25c60c8e5a32cd6 \
--hash=sha256:c0131351b8a7226c69f1eba5814cbc9d1d8daaf0fdec1ae3f30508e3de5262d4 \
--hash=sha256:c265f16c936a8ff3bb4b8a4bda0be94c15ec28b63e99fdb1439c1ffe4cd437db \
--hash=sha256:c279068f68af3b46a5d649855e1fb87f5705fe1f744a529d82b2885c0e1fc69d \
--hash=sha256:c637ab54b8cd9802fe19b260261e38820d748adf7606e34045d3c799b6dde813 \
--hash=sha256:c95f8751e2abd6f778da0399c8e0239321d560dbc58cb063827123137d213242 \
--hash=sha256:ca3703ff03b03a1848c563bc2663d0ad813c1cd42c4d9cf75b623716d4415d9a \
--hash=sha256:ca9ab676609cce85dd65d91c275e47da676d13d77faa72de286fbea30fbaa596 \
--hash=sha256:cd869cadba9a63e1e7fe2dced4a5747d735135b86016b0a63e8c9e324ab629ac \
--hash=sha256:cf9da32ef2582434842ab6ba6e67290debfae72771255a8e8ab16f3e006de0aa \
--hash=sha256:cfaf75ac574447afcf8ad998789071af11d2bcf6f947643231f692948839bd98 \
--hash=sha256:d9b30a8f50c3fa72a494eca6be5810a1b5c89e4f0fda89374f0d1c5ad8d37d51 \
--hash=sha256:dcec98e2c7da7631f0811730303abc4bdfe70d013f7a11e174a2ccd5612a7c59 \
--hash=sha256:df2e119c6ae412d2fd641a55f8a1e2e51f45a3de3449c18b1b86c319ab79e0c4 \
--hash=sha256:e13b2f58f647178470adaa14603bb64cc02eeed32601772ccea30e198252883c \
--hash=sha256:e5c20f236f27551e3f0adbf1a987673fb1e9c38d6d284502cd38f5a3845ef681 \
--hash=sha256:e90059f7701bef3c4da073d6e0434a9c7dc551d5adce30e6b99ef86b186f4b4a \
--hash=sha256:ebb03a9bd50c2ed86d4f72a54e0aae156d35a14075485b2127c4b01a3f4a63fa \
--hash=sha256:eed24272b4121b7c22f234daed99899817d81d671b3ed030c876ac88bc9dc890 \
--hash=sha256:efd3f4e0385d18f20f7ea6b08af2574c1bfaa5cb590102ef1bee781bdfba84bc \
--hash=sha256:f27c078b5d75989952acbf9b77e14c3dadc468a4aafe85174d548afbc5efc38b \
--hash=sha256:f5b88a7c39e307739a3701194993455968fcffe437d1facab93546b1b8a334c1 \
--hash=sha256:f8f7824db5a64581180ab9d09842e6dd9fcdc46aac9cb592a0807cd37ea55680
py-ecc==7.0.1 \
--hash=sha256:557461f42e57294d734305a30faf6b8903421651871e9cdeff8d8e67c6796c70 \
--hash=sha256:84a8b4d436163c83c65345a68e32f921ef6e64374a36f8e561f0455b4b08f5f2
pycryptodome==3.21.0 \
--hash=sha256:0714206d467fc911042d01ea3a1847c847bc10884cf674c82e12915cfe1649f8 \
--hash=sha256:0fa0a05a6a697ccbf2a12cec3d6d2650b50881899b845fac6e87416f8cb7e87d \
--hash=sha256:0fd54003ec3ce4e0f16c484a10bc5d8b9bd77fa662a12b85779a2d2d85d67ee0 \
--hash=sha256:18caa8cfbc676eaaf28613637a89980ad2fd96e00c564135bf90bc3f0b34dd93 \
--hash=sha256:2480ec2c72438430da9f601ebc12c518c093c13111a5c1644c82cdfc2e50b1e4 \
--hash=sha256:26412b21df30b2861424a6c6d5b1d8ca8107612a4cfa4d0183e71c5d200fb34a \
--hash=sha256:280b67d20e33bb63171d55b1067f61fbd932e0b1ad976b3a184303a3dad22764 \
--hash=sha256:2cb635b67011bc147c257e61ce864879ffe6d03342dc74b6045059dfbdedafca \
--hash=sha256:2de4b7263a33947ff440412339cb72b28a5a4c769b5c1ca19e33dd6cd1dcec6e \
--hash=sha256:3ba4cc304eac4d4d458f508d4955a88ba25026890e8abff9b60404f76a62c55e \
--hash=sha256:4c26a2f0dc15f81ea3afa3b0c87b87e501f235d332b7f27e2225ecb80c0b1cdd \
--hash=sha256:590ef0898a4b0a15485b05210b4a1c9de8806d3ad3d47f74ab1dc07c67a6827f \
--hash=sha256:5dfafca172933506773482b0e18f0cd766fd3920bd03ec85a283df90d8a17bc6 \
--hash=sha256:6cce52e196a5f1d6797ff7946cdff2038d3b5f0aba4a43cb6bf46b575fd1b5bb \
--hash=sha256:7cb087b8612c8a1a14cf37dd754685be9a8d9869bed2ffaaceb04850a8aeef7e \
--hash=sha256:7d85c1b613121ed3dbaa5a97369b3b757909531a959d229406a75b912dd51dd1 \
--hash=sha256:7ee86cbde706be13f2dec5a42b52b1c1d1cbb90c8e405c68d0755134735c8dc6 \
--hash=sha256:8898a66425a57bcf15e25fc19c12490b87bd939800f39a03ea2de2aea5e3611a \
--hash=sha256:8acd7d34af70ee63f9a849f957558e49a98f8f1634f86a59d2be62bb8e93f71c \
--hash=sha256:932c905b71a56474bff8a9c014030bc3c882cee696b448af920399f730a650c2 \
--hash=sha256:a1752eca64c60852f38bb29e2c86fca30d7672c024128ef5d70cc15868fa10f4 \
--hash=sha256:a3804675283f4764a02db05f5191eb8fec2bb6ca34d466167fc78a5f05bbe6b3 \
--hash=sha256:a4e74c522d630766b03a836c15bff77cb657c5fdf098abf8b1ada2aebc7d0819 \
--hash=sha256:a915597ffccabe902e7090e199a7bf7a381c5506a747d5e9d27ba55197a2c568 \
--hash=sha256:b7aa25fc0baa5b1d95b7633af4f5f1838467f1815442b22487426f94e0d66c53 \
--hash=sha256:cc2269ab4bce40b027b49663d61d816903a4bd90ad88cb99ed561aadb3888dd3 \
--hash=sha256:d5ebe0763c982f069d3877832254f64974139f4f9655058452603ff559c482e8 \
--hash=sha256:dad9bf36eda068e89059d1f07408e397856be9511d7113ea4b586642a429a4fd \
--hash=sha256:de18954104667f565e2fbb4783b56667f30fb49c4d79b346f52a29cb198d5b6b \
--hash=sha256:f35e442630bc4bc2e1878482d6f59ea22e280d7121d7adeaedba58c23ab6386b \
--hash=sha256:f7787e0d469bdae763b876174cf2e6c0f7be79808af26b1da96f1a64bcf47297 \
--hash=sha256:ff99f952db3db2fbe98a0b355175f93ec334ba3d01bbde25ad3a5a33abc02b58
pyperclip==1.9.0 \
--hash=sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310
pyrsistent==0.16.1 \
--hash=sha256:aa2ae1c2e496f4d6777f869ea5de7166a8ccb9c2e06ebcf6c7ff1b670c98c5ef
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
ssz==0.5.0 \
--hash=sha256:111dec40bee7cb7c3d52fe621a2247d5420ab999ffc0cbecb470782c28b56414 \
--hash=sha256:5e0fe0483c5c9bdf3ea0fa957986b48ca34c784af57e39257863dd3743e20861
toolz==1.0.0 \
--hash=sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236 \
--hash=sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8

View File

@@ -1,10 +0,0 @@
# requirements_test.in
exceptiongroup # pip-compile did not pick up from mypy
flake8
jsonschema
mypy
pytest
pytest-asyncio
coverage
tomli # pip-compile did not pick up from mypy

View File

@@ -1,257 +0,0 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --generate-hashes --no-annotate --output-file=requirements_test.txt requirements_test.in
#
attrs==24.2.0 \
--hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \
--hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2
coverage==7.6.8 \
--hash=sha256:093896e530c38c8e9c996901858ac63f3d4171268db2c9c8b373a228f459bbc5 \
--hash=sha256:09b9f848b28081e7b975a3626e9081574a7b9196cde26604540582da60235fdf \
--hash=sha256:0b0c69f4f724c64dfbfe79f5dfb503b42fe6127b8d479b2677f2b227478db2eb \
--hash=sha256:13618bed0c38acc418896005732e565b317aa9e98d855a0e9f211a7ffc2d6638 \
--hash=sha256:13690e923a3932e4fad4c0ebfb9cb5988e03d9dcb4c5150b5fcbf58fd8bddfc4 \
--hash=sha256:177f01eeaa3aee4a5ffb0d1439c5952b53d5010f86e9d2667963e632e30082cc \
--hash=sha256:193e3bffca48ad74b8c764fb4492dd875038a2f9925530cb094db92bb5e47bed \
--hash=sha256:1defe91d41ce1bd44b40fabf071e6a01a5aa14de4a31b986aa9dfd1b3e3e414a \
--hash=sha256:1f188a2402f8359cf0c4b1fe89eea40dc13b52e7b4fd4812450da9fcd210181d \
--hash=sha256:202a2d645c5a46b84992f55b0a3affe4f0ba6b4c611abec32ee88358db4bb649 \
--hash=sha256:24eda3a24a38157eee639ca9afe45eefa8d2420d49468819ac5f88b10de84f4c \
--hash=sha256:2e4e0f60cb4bd7396108823548e82fdab72d4d8a65e58e2c19bbbc2f1e2bfa4b \
--hash=sha256:379c111d3558272a2cae3d8e57e6b6e6f4fe652905692d54bad5ea0ca37c5ad4 \
--hash=sha256:37cda8712145917105e07aab96388ae76e787270ec04bcb9d5cc786d7cbb8443 \
--hash=sha256:38c51297b35b3ed91670e1e4efb702b790002e3245a28c76e627478aa3c10d83 \
--hash=sha256:3985b9be361d8fb6b2d1adc9924d01dec575a1d7453a14cccd73225cb79243ee \
--hash=sha256:3988665ee376abce49613701336544041f2117de7b7fbfe91b93d8ff8b151c8e \
--hash=sha256:3ac47fa29d8d41059ea3df65bd3ade92f97ee4910ed638e87075b8e8ce69599e \
--hash=sha256:3b4b4299dd0d2c67caaaf286d58aef5e75b125b95615dda4542561a5a566a1e3 \
--hash=sha256:3ea8bb1ab9558374c0ab591783808511d135a833c3ca64a18ec927f20c4030f0 \
--hash=sha256:3fe47da3e4fda5f1abb5709c156eca207eacf8007304ce3019eb001e7a7204cb \
--hash=sha256:428ac484592f780e8cd7b6b14eb568f7c85460c92e2a37cb0c0e5186e1a0d076 \
--hash=sha256:44e6c85bbdc809383b509d732b06419fb4544dca29ebe18480379633623baafb \
--hash=sha256:4674f0daa1823c295845b6a740d98a840d7a1c11df00d1fd62614545c1583787 \
--hash=sha256:4be32da0c3827ac9132bb488d331cb32e8d9638dd41a0557c5569d57cf22c9c1 \
--hash=sha256:4db3ed6a907b555e57cc2e6f14dc3a4c2458cdad8919e40b5357ab9b6db6c43e \
--hash=sha256:5c52a036535d12590c32c49209e79cabaad9f9ad8aa4cbd875b68c4d67a9cbce \
--hash=sha256:629a1ba2115dce8bf75a5cce9f2486ae483cb89c0145795603d6554bdc83e801 \
--hash=sha256:62a66ff235e4c2e37ed3b6104d8b478d767ff73838d1222132a7a026aa548764 \
--hash=sha256:63068a11171e4276f6ece913bde059e77c713b48c3a848814a6537f35afb8365 \
--hash=sha256:63c19702db10ad79151a059d2d6336fe0c470f2e18d0d4d1a57f7f9713875dcf \
--hash=sha256:644ec81edec0f4ad17d51c838a7d01e42811054543b76d4ba2c5d6af741ce2a6 \
--hash=sha256:6535d996f6537ecb298b4e287a855f37deaf64ff007162ec0afb9ab8ba3b8b71 \
--hash=sha256:6f4548c5ead23ad13fb7a2c8ea541357474ec13c2b736feb02e19a3085fac002 \
--hash=sha256:716a78a342679cd1177bc8c2fe957e0ab91405bd43a17094324845200b2fddf4 \
--hash=sha256:74610105ebd6f33d7c10f8907afed696e79c59e3043c5f20eaa3a46fddf33b4c \
--hash=sha256:768939f7c4353c0fac2f7c37897e10b1414b571fd85dd9fc49e6a87e37a2e0d8 \
--hash=sha256:86cffe9c6dfcfe22e28027069725c7f57f4b868a3f86e81d1c62462764dc46d4 \
--hash=sha256:8aae5aea53cbfe024919715eca696b1a3201886ce83790537d1c3668459c7146 \
--hash=sha256:8b2b8503edb06822c86d82fa64a4a5cb0760bb8f31f26e138ec743f422f37cfc \
--hash=sha256:912e95017ff51dc3d7b6e2be158dedc889d9a5cc3382445589ce554f1a34c0ea \
--hash=sha256:9a7b8ac36fd688c8361cbc7bf1cb5866977ece6e0b17c34aa0df58bda4fa18a4 \
--hash=sha256:9e89d5c8509fbd6c03d0dd1972925b22f50db0792ce06324ba069f10787429ad \
--hash=sha256:ae270e79f7e169ccfe23284ff5ea2d52a6f401dc01b337efb54b3783e2ce3f28 \
--hash=sha256:b07c25d52b1c16ce5de088046cd2432b30f9ad5e224ff17c8f496d9cb7d1d451 \
--hash=sha256:b39e6011cd06822eb964d038d5dff5da5d98652b81f5ecd439277b32361a3a50 \
--hash=sha256:bd55f8fc8fa494958772a2a7302b0354ab16e0b9272b3c3d83cdb5bec5bd1779 \
--hash=sha256:c15b32a7aca8038ed7644f854bf17b663bc38e1671b5d6f43f9a2b2bd0c46f63 \
--hash=sha256:c1b4474beee02ede1eef86c25ad4600a424fe36cff01a6103cb4533c6bf0169e \
--hash=sha256:c79c0685f142ca53256722a384540832420dff4ab15fec1863d7e5bc8691bdcc \
--hash=sha256:c9ebfb2507751f7196995142f057d1324afdab56db1d9743aab7f50289abd022 \
--hash=sha256:d7ad66e8e50225ebf4236368cc43c37f59d5e6728f15f6e258c8639fa0dd8e6d \
--hash=sha256:d82ab6816c3277dc962cfcdc85b1efa0e5f50fb2c449432deaf2398a2928ab94 \
--hash=sha256:d9fd2547e6decdbf985d579cf3fc78e4c1d662b9b0ff7cc7862baaab71c9cc5b \
--hash=sha256:de38add67a0af869b0d79c525d3e4588ac1ffa92f39116dbe0ed9753f26eba7d \
--hash=sha256:e19122296822deafce89a0c5e8685704c067ae65d45e79718c92df7b3ec3d331 \
--hash=sha256:e44961e36cb13c495806d4cac67640ac2866cb99044e210895b506c26ee63d3a \
--hash=sha256:e4c81ed2820b9023a9a90717020315e63b17b18c274a332e3b6437d7ff70abe0 \
--hash=sha256:e683e6ecc587643f8cde8f5da6768e9d165cd31edf39ee90ed7034f9ca0eefee \
--hash=sha256:f39e2f3530ed1626c66e7493be7a8423b023ca852aacdc91fb30162c350d2a92 \
--hash=sha256:f56f49b2553d7dd85fd86e029515a221e5c1f8cb3d9c38b470bc38bde7b8445a \
--hash=sha256:fb9fc32399dca861584d96eccd6c980b69bbcd7c228d06fb74fe53e007aa8ef9
exceptiongroup==1.2.2 \
--hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \
--hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc
flake8==7.1.1 \
--hash=sha256:049d058491e228e03e67b390f311bbf88fce2dbaa8fa673e7aea87b7198b8d38 \
--hash=sha256:597477df7860daa5aa0fdd84bf5208a043ab96b8e96ab708770ae0364dd03213
iniconfig==2.0.0 \
--hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \
--hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
jsonschema==4.23.0 \
--hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \
--hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566
jsonschema-specifications==2023.12.1 \
--hash=sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc \
--hash=sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c
mccabe==0.7.0 \
--hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \
--hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e
mypy==1.13.0 \
--hash=sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc \
--hash=sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e \
--hash=sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f \
--hash=sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74 \
--hash=sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a \
--hash=sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2 \
--hash=sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b \
--hash=sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73 \
--hash=sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e \
--hash=sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d \
--hash=sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d \
--hash=sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6 \
--hash=sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca \
--hash=sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d \
--hash=sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5 \
--hash=sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62 \
--hash=sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a \
--hash=sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc \
--hash=sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7 \
--hash=sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb \
--hash=sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7 \
--hash=sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732 \
--hash=sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80 \
--hash=sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a \
--hash=sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc \
--hash=sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2 \
--hash=sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0 \
--hash=sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24 \
--hash=sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7 \
--hash=sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b \
--hash=sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372 \
--hash=sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8
mypy-extensions==1.0.0 \
--hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
--hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
packaging==24.1 \
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
pluggy==1.5.0 \
--hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \
--hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669
pycodestyle==2.12.1 \
--hash=sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3 \
--hash=sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521
pyflakes==3.2.0 \
--hash=sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f \
--hash=sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a
pytest==8.3.3 \
--hash=sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181 \
--hash=sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2
pytest-asyncio==0.24.0 \
--hash=sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b \
--hash=sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276
referencing==0.35.1 \
--hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \
--hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de
rpds-py==0.20.0 \
--hash=sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c \
--hash=sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585 \
--hash=sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5 \
--hash=sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6 \
--hash=sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef \
--hash=sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2 \
--hash=sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29 \
--hash=sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318 \
--hash=sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b \
--hash=sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399 \
--hash=sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739 \
--hash=sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee \
--hash=sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174 \
--hash=sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a \
--hash=sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344 \
--hash=sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2 \
--hash=sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03 \
--hash=sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5 \
--hash=sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22 \
--hash=sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e \
--hash=sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96 \
--hash=sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91 \
--hash=sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752 \
--hash=sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075 \
--hash=sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253 \
--hash=sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee \
--hash=sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad \
--hash=sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5 \
--hash=sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce \
--hash=sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7 \
--hash=sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b \
--hash=sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8 \
--hash=sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57 \
--hash=sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3 \
--hash=sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec \
--hash=sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209 \
--hash=sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921 \
--hash=sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045 \
--hash=sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074 \
--hash=sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580 \
--hash=sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7 \
--hash=sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5 \
--hash=sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3 \
--hash=sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0 \
--hash=sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24 \
--hash=sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139 \
--hash=sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db \
--hash=sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc \
--hash=sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789 \
--hash=sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f \
--hash=sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2 \
--hash=sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c \
--hash=sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232 \
--hash=sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6 \
--hash=sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c \
--hash=sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29 \
--hash=sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489 \
--hash=sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94 \
--hash=sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751 \
--hash=sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2 \
--hash=sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda \
--hash=sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9 \
--hash=sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51 \
--hash=sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c \
--hash=sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8 \
--hash=sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989 \
--hash=sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511 \
--hash=sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1 \
--hash=sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2 \
--hash=sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150 \
--hash=sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c \
--hash=sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965 \
--hash=sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f \
--hash=sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58 \
--hash=sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b \
--hash=sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f \
--hash=sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d \
--hash=sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821 \
--hash=sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de \
--hash=sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121 \
--hash=sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855 \
--hash=sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272 \
--hash=sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60 \
--hash=sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02 \
--hash=sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1 \
--hash=sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140 \
--hash=sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879 \
--hash=sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940 \
--hash=sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364 \
--hash=sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4 \
--hash=sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e \
--hash=sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420 \
--hash=sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5 \
--hash=sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24 \
--hash=sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c \
--hash=sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf \
--hash=sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f \
--hash=sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e \
--hash=sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab \
--hash=sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08 \
--hash=sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92 \
--hash=sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a \
--hash=sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8
tomli==2.1.0 \
--hash=sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8 \
--hash=sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8

View File

@@ -1,741 +0,0 @@
version = 1
requires-python = ">=3.9, <4"
[[package]]
name = "attrs"
version = "24.2.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fc/0f/aafca9af9315aee06a89ffde799a10a582fe8de76c563ee80bbcdc08b3fb/attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", size = 792678 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2", size = 63001 },
]
[[package]]
name = "cached-property"
version = "1.5.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/61/2c/d21c1c23c2895c091fa7a91a54b6872098fea913526932d21902088a7c41/cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130", size = 12244 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/48/19/f2090f7dad41e225c7f2326e4cfe6fff49e57dedb5b53636c9551f86b069/cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0", size = 7573 },
]
[[package]]
name = "click"
version = "8.1.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "platform_system == 'Windows'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 },
]
[[package]]
name = "colorama"
version = "0.4.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
]
[[package]]
name = "coverage"
version = "7.6.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9a/60/e781e8302e7b28f21ce06e30af077f856aa2cb4cf2253287dae9a593d509/coverage-7.6.2.tar.gz", hash = "sha256:a5f81e68aa62bc0cfca04f7b19eaa8f9c826b53fc82ab9e2121976dc74f131f3", size = 797872 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/16/14/fb75c01b8427fb567c90ce920c90ed2bd314ad6960d54e8b377928607fd1/coverage-7.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9df1950fb92d49970cce38100d7e7293c84ed3606eaa16ea0b6bc27175bb667", size = 206561 },
{ url = "https://files.pythonhosted.org/packages/93/b4/dcbf15f5583507415d0a78ce206e19d76699f1161e8b1ff6e1a21e9f9743/coverage-7.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:24500f4b0e03aab60ce575c85365beab64b44d4db837021e08339f61d1fbfe52", size = 206994 },
{ url = "https://files.pythonhosted.org/packages/47/ee/57d607e14479fb760721ea1784608ade532665934bd75f260b250dc6c877/coverage-7.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a663b180b6669c400b4630a24cc776f23a992d38ce7ae72ede2a397ce6b0f170", size = 235429 },
{ url = "https://files.pythonhosted.org/packages/76/e1/cd263fd750fdb115aab11a086e3584d99d46fca1f201b5493cc3972aea28/coverage-7.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfde025e2793a22efe8c21f807d276bd1d6a4bcc5ba6f19dbdfc4e7a12160909", size = 233329 },
{ url = "https://files.pythonhosted.org/packages/30/3b/a1623d50fcd6ba532cef0c3c1059eec2a08a311676ffa84dbe4beb2b8a33/coverage-7.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:087932079c065d7b8ebadd3a0160656c55954144af6439886c8bcf78bbbcde7f", size = 234491 },
{ url = "https://files.pythonhosted.org/packages/b1/a6/8f3b3fd1f9b9400f3df38a7159362622546e2d951cc4984cf4617d0fd4d7/coverage-7.6.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9c6b0c1cafd96213a0327cf680acb39f70e452caf8e9a25aeb05316db9c07f89", size = 233589 },
{ url = "https://files.pythonhosted.org/packages/e3/40/37d64093f57b372435d87679956607ecab066d2aede76c6d215815a35fa3/coverage-7.6.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6e85830eed5b5263ffa0c62428e43cb844296f3b4461f09e4bdb0d44ec190bc2", size = 232050 },
{ url = "https://files.pythonhosted.org/packages/80/63/cbb76298b4f42bffe0030f1bc129a26a26255857c6beaa20419259ac07cc/coverage-7.6.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62ab4231c01e156ece1b3a187c87173f31cbeee83a5e1f6dff17f288dca93345", size = 233180 },
{ url = "https://files.pythonhosted.org/packages/7a/6a/eafa81503e905d473b799920927b06aa6ffba12db035fc98735b55bc1741/coverage-7.6.2-cp310-cp310-win32.whl", hash = "sha256:7b80fbb0da3aebde102a37ef0138aeedff45997e22f8962e5f16ae1742852676", size = 209281 },
{ url = "https://files.pythonhosted.org/packages/19/d1/6b354c2cd52e0244944c097aaa71896869878df999f5f8e75fcd37eaf0f3/coverage-7.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:d20c3d1f31f14d6962a4e2f549c21d31e670b90f777ef4171be540fb7fb70f02", size = 210092 },
{ url = "https://files.pythonhosted.org/packages/a5/29/72da824da4182f518b054c21552b7ed2473a4e4c6ac616298209808a1a5c/coverage-7.6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bb21bac7783c1bf6f4bbe68b1e0ff0d20e7e7732cfb7995bc8d96e23aa90fc7b", size = 206667 },
{ url = "https://files.pythonhosted.org/packages/23/52/c15dcf3cf575256c7c0992e441cd41092a6c519d65abe1eb5567aab3d8e8/coverage-7.6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b2e437fbd8fae5bc7716b9c7ff97aecc95f0b4d56e4ca08b3c8d8adcaadb84", size = 207111 },
{ url = "https://files.pythonhosted.org/packages/92/61/0d46dc26cf9f711b7b6078a54680665a5c2d62ec15991adb51e79236c699/coverage-7.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:536f77f2bf5797983652d1d55f1a7272a29afcc89e3ae51caa99b2db4e89d658", size = 239050 },
{ url = "https://files.pythonhosted.org/packages/3b/cb/9de71bade0343a0793f645f78a0e409248d85a2e5b4c4a9a1697c3b2e3d2/coverage-7.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f361296ca7054f0936b02525646b2731b32c8074ba6defab524b79b2b7eeac72", size = 236454 },
{ url = "https://files.pythonhosted.org/packages/f2/81/b0dc02487447c4a56cf2eed5c57735097f77aeff582277a35f1f70713a8d/coverage-7.6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7926d8d034e06b479797c199747dd774d5e86179f2ce44294423327a88d66ca7", size = 238320 },
{ url = "https://files.pythonhosted.org/packages/60/90/76815a76234050a87d0d1438a34820c1b857dd17353855c02bddabbedea8/coverage-7.6.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0bbae11c138585c89fb4e991faefb174a80112e1a7557d507aaa07675c62e66b", size = 237250 },
{ url = "https://files.pythonhosted.org/packages/f6/bd/760a599c08c882d97382855264586bba2604901029c3f6bec5710477ae81/coverage-7.6.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fcad7d5d2bbfeae1026b395036a8aa5abf67e8038ae7e6a25c7d0f88b10a8e6a", size = 235880 },
{ url = "https://files.pythonhosted.org/packages/83/de/41c3b90a779e473ae1ca325542aa5fa5464b7d2061288e9c22ba5f1deaa3/coverage-7.6.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f01e53575f27097d75d42de33b1b289c74b16891ce576d767ad8c48d17aeb5e0", size = 236653 },
{ url = "https://files.pythonhosted.org/packages/f4/90/61fe2721b9a9d9446e6c3ca33b6569e81d2a9a795ddfe786a66bf54035b7/coverage-7.6.2-cp311-cp311-win32.whl", hash = "sha256:7781f4f70c9b0b39e1b129b10c7d43a4e0c91f90c60435e6da8288efc2b73438", size = 209251 },
{ url = "https://files.pythonhosted.org/packages/96/87/d586f2b12b98288fc874d366cd8d5601f5a374cb75853647a3e4d02e4eb0/coverage-7.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:9bcd51eeca35a80e76dc5794a9dd7cb04b97f0e8af620d54711793bfc1fbba4b", size = 210083 },
{ url = "https://files.pythonhosted.org/packages/3f/ac/1cca5ed5cf512a71cdd6e3afb75a5ef196f7ef9772be9192dadaaa5cfc1c/coverage-7.6.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ebc94fadbd4a3f4215993326a6a00e47d79889391f5659bf310f55fe5d9f581c", size = 206856 },
{ url = "https://files.pythonhosted.org/packages/e4/58/030354d250f107a95e7aca24c7fd238709a3c7df3083cb206368798e637a/coverage-7.6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9681516288e3dcf0aa7c26231178cc0be6cac9705cac06709f2353c5b406cfea", size = 207098 },
{ url = "https://files.pythonhosted.org/packages/03/df/5f2cd6048d44a54bb5f58f8ece4efbc5b686ed49f8bd8dbf41eb2a6a687f/coverage-7.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d9c5d13927d77af4fbe453953810db766f75401e764727e73a6ee4f82527b3e", size = 240109 },
{ url = "https://files.pythonhosted.org/packages/d3/18/7c53887643d921faa95529643b1b33e60ebba30ab835c8b5abd4e54d946b/coverage-7.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b92f9ca04b3e719d69b02dc4a69debb795af84cb7afd09c5eb5d54b4a1ae2191", size = 237141 },
{ url = "https://files.pythonhosted.org/packages/d2/79/339bdf597d128374e6150c089b37436ba694585d769cabf6d5abd73a1365/coverage-7.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ff2ef83d6d0b527b5c9dad73819b24a2f76fdddcfd6c4e7a4d7e73ecb0656b4", size = 239210 },
{ url = "https://files.pythonhosted.org/packages/a9/62/7310c6de2bcb8a42f91094d41f0d4793ccda5a54621be3db76a156556cf2/coverage-7.6.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:47ccb6e99a3031ffbbd6e7cc041e70770b4fe405370c66a54dbf26a500ded80b", size = 238698 },
{ url = "https://files.pythonhosted.org/packages/f2/cb/ccb23c084d7f581f770dc7ed547dc5b50763334ad6ce26087a9ad0b5b26d/coverage-7.6.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a867d26f06bcd047ef716175b2696b315cb7571ccb951006d61ca80bbc356e9e", size = 237000 },
{ url = "https://files.pythonhosted.org/packages/e7/ab/58de9e2f94e4dc91b84d6e2705aa1e9d5447a2669fe113b4bbce6d2224a1/coverage-7.6.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cdfcf2e914e2ba653101157458afd0ad92a16731eeba9a611b5cbb3e7124e74b", size = 238666 },
{ url = "https://files.pythonhosted.org/packages/6c/dc/8be87b9ed5dbd4892b603f41088b41982768e928734e5bdce67d2ddd460a/coverage-7.6.2-cp312-cp312-win32.whl", hash = "sha256:f9035695dadfb397bee9eeaf1dc7fbeda483bf7664a7397a629846800ce6e276", size = 209489 },
{ url = "https://files.pythonhosted.org/packages/64/3a/3f44e55273a58bfb39b87ad76541bbb81d14de916b034fdb39971cc99ffe/coverage-7.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:5ed69befa9a9fc796fe015a7040c9398722d6b97df73a6b608e9e275fa0932b0", size = 210270 },
{ url = "https://files.pythonhosted.org/packages/ae/99/c9676a75b57438a19c5174dfcf39798b42728ad56650497286379dc0c2c3/coverage-7.6.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4eea60c79d36a8f39475b1af887663bc3ae4f31289cd216f514ce18d5938df40", size = 206888 },
{ url = "https://files.pythonhosted.org/packages/e0/de/820ecb42e892049c5f384430e98b35b899da3451dd0cdb2f867baf26abfa/coverage-7.6.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa68a6cdbe1bc6793a9dbfc38302c11599bbe1837392ae9b1d238b9ef3dafcf1", size = 207142 },
{ url = "https://files.pythonhosted.org/packages/dd/59/81fc7ad855d65eeb68fe9e7809cbb339946adb07be7ac32d3fc24dc17bd7/coverage-7.6.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ec528ae69f0a139690fad6deac8a7d33629fa61ccce693fdd07ddf7e9931fba", size = 239658 },
{ url = "https://files.pythonhosted.org/packages/cd/a7/865de3eb9e78ffbf7afd92f86d2580b18edfb6f0481bd3c39b205e05a762/coverage-7.6.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed5ac02126f74d190fa2cc14a9eb2a5d9837d5863920fa472b02eb1595cdc925", size = 236802 },
{ url = "https://files.pythonhosted.org/packages/36/94/3b8f3abf88b7c451f97fd14c98f536bcee364e74250d928d57cc97c38ddd/coverage-7.6.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21c0ea0d4db8a36b275cb6fb2437a3715697a4ba3cb7b918d3525cc75f726304", size = 238793 },
{ url = "https://files.pythonhosted.org/packages/d5/4b/57f95e41a10525002f524f3dbd577a3a9871d67998f8a8eb192fe697dc7b/coverage-7.6.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:35a51598f29b2a19e26d0908bd196f771a9b1c5d9a07bf20be0adf28f1ad4f77", size = 238455 },
{ url = "https://files.pythonhosted.org/packages/99/c9/9fbe5b841628e1d9030c8044844afef4f4735586289eb9237eeb5b97f0d7/coverage-7.6.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c9192925acc33e146864b8cf037e2ed32a91fdf7644ae875f5d46cd2ef086a5f", size = 236538 },
{ url = "https://files.pythonhosted.org/packages/43/0d/2200a0d447e30de94d48e4851c04d8dce37340815e7eda27457a7043c037/coverage-7.6.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf4eeecc9e10f5403ec06138978235af79c9a79af494eb6b1d60a50b49ed2869", size = 238383 },
{ url = "https://files.pythonhosted.org/packages/ec/8a/106c66faafb4a87002b698769d6de3c4db0b6c29a7aeb72de13b893c333e/coverage-7.6.2-cp313-cp313-win32.whl", hash = "sha256:e4ee15b267d2dad3e8759ca441ad450c334f3733304c55210c2a44516e8d5530", size = 209551 },
{ url = "https://files.pythonhosted.org/packages/c4/f5/1b39e2faaf5b9cc7eed568c444df5991ce7ff7138e2e735a6801be1bdadb/coverage-7.6.2-cp313-cp313-win_amd64.whl", hash = "sha256:c71965d1ced48bf97aab79fad56df82c566b4c498ffc09c2094605727c4b7e36", size = 210282 },
{ url = "https://files.pythonhosted.org/packages/79/a3/8dd4e6c09f5286094cd6c7edb115b3fbf06ad8304d45431722a4e3bc2508/coverage-7.6.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7571e8bbecc6ac066256f9de40365ff833553e2e0c0c004f4482facb131820ef", size = 207629 },
{ url = "https://files.pythonhosted.org/packages/8e/db/a9aa7009bbdc570a235e1ac781c0a83aa323cac6db8f8f13c2127b110978/coverage-7.6.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:078a87519057dacb5d77e333f740708ec2a8f768655f1db07f8dfd28d7a005f0", size = 207902 },
{ url = "https://files.pythonhosted.org/packages/54/08/d0962be62d4335599ca2ff3a48bb68c9bfb80df74e28ca689ff5f392087b/coverage-7.6.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5e92e3e84a8718d2de36cd8387459cba9a4508337b8c5f450ce42b87a9e760", size = 250617 },
{ url = "https://files.pythonhosted.org/packages/a5/a2/158570aff1dd88b661a6c11281cbb190e8696e77798b4b2e47c74bfb2f39/coverage-7.6.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebabdf1c76593a09ee18c1a06cd3022919861365219ea3aca0247ededf6facd6", size = 246334 },
{ url = "https://files.pythonhosted.org/packages/aa/fe/b00428cca325b6585ca77422e4f64d7d86a225b14664b98682ea501efb57/coverage-7.6.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12179eb0575b8900912711688e45474f04ab3934aaa7b624dea7b3c511ecc90f", size = 248692 },
{ url = "https://files.pythonhosted.org/packages/30/21/0a15fefc13039450bc45e7159f3add92489f004555eb7dab9c7ad4365dd0/coverage-7.6.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:39d3b964abfe1519b9d313ab28abf1d02faea26cd14b27f5283849bf59479ff5", size = 248188 },
{ url = "https://files.pythonhosted.org/packages/de/b8/5c093526046a8450a7a3d62ad09517cf38e638f6b3ee9433dd6a73360501/coverage-7.6.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:84c4315577f7cd511d6250ffd0f695c825efe729f4205c0340f7004eda51191f", size = 246072 },
{ url = "https://files.pythonhosted.org/packages/1e/8b/542b607d2cff56e5a90a6948f5a9040b693761d2be2d3c3bf88957b02361/coverage-7.6.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ff797320dcbff57caa6b2301c3913784a010e13b1f6cf4ab3f563f3c5e7919db", size = 247354 },
{ url = "https://files.pythonhosted.org/packages/95/82/2e9111aa5e59f42b332d387f64e3205c2263518d1e660154d0c9fc54390e/coverage-7.6.2-cp313-cp313t-win32.whl", hash = "sha256:2b636a301e53964550e2f3094484fa5a96e699db318d65398cfba438c5c92171", size = 210194 },
{ url = "https://files.pythonhosted.org/packages/9d/46/aabe4305cfc57cab4865f788ceceef746c422469720c32ed7a5b44e20f5e/coverage-7.6.2-cp313-cp313t-win_amd64.whl", hash = "sha256:d03a060ac1a08e10589c27d509bbdb35b65f2d7f3f8d81cf2fa199877c7bc58a", size = 211346 },
{ url = "https://files.pythonhosted.org/packages/6a/a9/85d14426f2449252f302f12c1c2a957a0a7ae7f35317ca3eaa365e1d6453/coverage-7.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c37faddc8acd826cfc5e2392531aba734b229741d3daec7f4c777a8f0d4993e5", size = 206555 },
{ url = "https://files.pythonhosted.org/packages/71/ff/bc4d5697a55edf1ff077c47df5637ff4518ba2760ada82c142aca79ea3fe/coverage-7.6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab31fdd643f162c467cfe6a86e9cb5f1965b632e5e65c072d90854ff486d02cf", size = 206990 },
{ url = "https://files.pythonhosted.org/packages/34/65/1301721d09f5b58da9decfd62eb42eaef07fdb854dae904c3482e59cc309/coverage-7.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97df87e1a20deb75ac7d920c812e9326096aa00a9a4b6d07679b4f1f14b06c90", size = 235022 },
{ url = "https://files.pythonhosted.org/packages/9f/ec/7a2f361485226e6934a8f5d1f6eef7e8b7faf228fb6107476fa584700a32/coverage-7.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:343056c5e0737487a5291f5691f4dfeb25b3e3c8699b4d36b92bb0e586219d14", size = 232943 },
{ url = "https://files.pythonhosted.org/packages/2d/60/b23e61a372bef93c9d13d87efa2ea3a870130be498e5b81740616b6e6200/coverage-7.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4ef1c56b47b6b9024b939d503ab487231df1f722065a48f4fc61832130b90e", size = 234074 },
{ url = "https://files.pythonhosted.org/packages/89/ec/4a56d9b310b2413987682ae3a858e30ea11d6f6d05366ecab4d73385fbef/coverage-7.6.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fca4a92c8a7a73dee6946471bce6d1443d94155694b893b79e19ca2a540d86e", size = 233226 },
{ url = "https://files.pythonhosted.org/packages/8c/77/31ecc00c525dea216d59090b807e9d1268a07d289f9dbe0cfc6795e33b68/coverage-7.6.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69f251804e052fc46d29d0e7348cdc5fcbfc4861dc4a1ebedef7e78d241ad39e", size = 231706 },
{ url = "https://files.pythonhosted.org/packages/7b/02/3f84bdd286a9db9b816cb5ca0adfa001575f8e496ba39da26f0ded2f0849/coverage-7.6.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e8ea055b3ea046c0f66217af65bc193bbbeca1c8661dc5fd42698db5795d2627", size = 232697 },
{ url = "https://files.pythonhosted.org/packages/7c/34/158b73026cbc2d2b3a56fbc71d955c0eea52953e49de97f820b3060f62b9/coverage-7.6.2-cp39-cp39-win32.whl", hash = "sha256:6c2ba1e0c24d8fae8f2cf0aeb2fc0a2a7f69b6d20bd8d3749fd6b36ecef5edf0", size = 209278 },
{ url = "https://files.pythonhosted.org/packages/d1/05/4326e4ea071176f0bddc30b5a3555b48fa96c45a8f6a09b6c2e4041dfcc0/coverage-7.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:2186369a654a15628e9c1c9921409a6b3eda833e4b91f3ca2a7d9f77abb4987c", size = 210057 },
{ url = "https://files.pythonhosted.org/packages/9d/5c/88f15b7614ba9ed1dbb1c0bd2c9073184b96c2bead0b93199487b44d04b3/coverage-7.6.2-pp39.pp310-none-any.whl", hash = "sha256:667952739daafe9616db19fbedbdb87917eee253ac4f31d70c7587f7ab531b4e", size = 198799 },
]
[[package]]
name = "cytoolz"
version = "0.12.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "toolz" },
]
sdist = { url = "https://files.pythonhosted.org/packages/70/d8/8df71050b214686591241a1826d2e6934b5c295c5bc57f643e4ed697f1eb/cytoolz-0.12.3.tar.gz", hash = "sha256:4503dc59f4ced53a54643272c61dc305d1dbbfbd7d6bdf296948de9f34c3a282", size = 625899 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/11/ebc8b85c77cc2247c169af808901a80e5d29429b3c9b0d114d4048ad2a5a/cytoolz-0.12.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bbe58e26c84b163beba0fbeacf6b065feabc8f75c6d3fe305550d33f24a2d346", size = 413462 },
{ url = "https://files.pythonhosted.org/packages/19/22/57f20a9f135a08a6fc9848744c324c4facca2b1370a1ae4e8333e274c707/cytoolz-0.12.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c51b66ada9bfdb88cf711bf350fcc46f82b83a4683cf2413e633c31a64df6201", size = 396040 },
{ url = "https://files.pythonhosted.org/packages/12/30/337a18b1182888bf5d59357095a83f537a88e2db32ee0381166a83deddda/cytoolz-0.12.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e70d9c615e5c9dc10d279d1e32e846085fe1fd6f08d623ddd059a92861f4e3dd", size = 1933264 },
{ url = "https://files.pythonhosted.org/packages/93/a3/c244bfacd046316cd0a4cffd2e245a8dd9b685168497c3b7c776bdb72c59/cytoolz-0.12.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a83f4532707963ae1a5108e51fdfe1278cc8724e3301fee48b9e73e1316de64f", size = 2014114 },
{ url = "https://files.pythonhosted.org/packages/a6/40/51bdfe7fd1cad802eabebb7bb742e694227db25c4806eebf4358229e3220/cytoolz-0.12.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d028044524ee2e815f36210a793c414551b689d4f4eda28f8bbb0883ad78bf5f", size = 1999458 },
{ url = "https://files.pythonhosted.org/packages/f7/0b/5973e0ceab96349f9cabb3b20ecc3a717a19e355f68d354dfa538bebb226/cytoolz-0.12.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c2875bcd1397d0627a09a4f9172fa513185ad302c63758efc15b8eb33cc2a98", size = 1956106 },
{ url = "https://files.pythonhosted.org/packages/d3/01/bb850ad1467f0d1dc5a21a05e3df6ad308a19d095f07583c4e65a85e2ba8/cytoolz-0.12.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:131ff4820e5d64a25d7ad3c3556f2d8aa65c66b3f021b03f8a8e98e4180dd808", size = 1861974 },
{ url = "https://files.pythonhosted.org/packages/c9/97/207e544a2c9c3d8735102403982a319c252c337e9cf792c2753c22cff1b6/cytoolz-0.12.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:04afa90d9d9d18394c40d9bed48c51433d08b57c042e0e50c8c0f9799735dcbd", size = 1937926 },
{ url = "https://files.pythonhosted.org/packages/76/1e/6cc756537caef16cd491de1550c1f25140528785e28263326bd3243a19ed/cytoolz-0.12.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:dc1ca9c610425f9854323669a671fc163300b873731584e258975adf50931164", size = 1859141 },
{ url = "https://files.pythonhosted.org/packages/20/43/30819bbc4348cabb44d800ab0d0efb29a9d21db8f75060fd1199d5300953/cytoolz-0.12.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bfa3f8e01bc423a933f2e1c510cbb0632c6787865b5242857cc955cae220d1bf", size = 2013731 },
{ url = "https://files.pythonhosted.org/packages/bd/ab/cacabf2d0dfea006575fea900131eb491370ee1664783f80cb131f577001/cytoolz-0.12.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:f702e295dddef5f8af4a456db93f114539b8dc2a7a9bc4de7c7e41d169aa6ec3", size = 2015075 },
{ url = "https://files.pythonhosted.org/packages/79/6f/98eeee4f735bff536654625e0c38e50c4b01c13fbd9c744d3284dbccc54d/cytoolz-0.12.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0fbad1fb9bb47e827d00e01992a099b0ba79facf5e5aa453be066033232ac4b5", size = 1953391 },
{ url = "https://files.pythonhosted.org/packages/6a/81/80bcbc750e3c8f72d07f1e61c25597fdb23fec3c3d52542f220bff87372c/cytoolz-0.12.3-cp310-cp310-win32.whl", hash = "sha256:8587c3c3dbe78af90c5025288766ac10dc2240c1e76eb0a93a4e244c265ccefd", size = 320881 },
{ url = "https://files.pythonhosted.org/packages/45/9e/cce296c6da9404ce210c79700b85d9ba582a6e908ee88ec707efec09bcd9/cytoolz-0.12.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e45803d9e75ef90a2f859ef8f7f77614730f4a8ce1b9244375734567299d239", size = 362216 },
{ url = "https://files.pythonhosted.org/packages/98/8a/618a70326d4a52998a6bbb11ca019979891a51b85cbbfce8f9762eec5d2c/cytoolz-0.12.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3ac4f2fb38bbc67ff1875b7d2f0f162a247f43bd28eb7c9d15e6175a982e558d", size = 416356 },
{ url = "https://files.pythonhosted.org/packages/bb/17/542f708b9116aa8d8c9c5551500bfa6ab1bddd3edc11457070599a97c197/cytoolz-0.12.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0cf1e1e96dd86829a0539baf514a9c8473a58fbb415f92401a68e8e52a34ecd5", size = 398412 },
{ url = "https://files.pythonhosted.org/packages/d6/9c/52a0460f2b59009da63794cfe11ad002d55fc88fced6ccc85f7ae10a3259/cytoolz-0.12.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08a438701c6141dd34eaf92e9e9a1f66e23a22f7840ef8a371eba274477de85d", size = 2090389 },
{ url = "https://files.pythonhosted.org/packages/c7/6d/284d4a1f88b1e63b8a1c80162244ca5d4e0b31647c4f56186f3385fd0d0e/cytoolz-0.12.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6b6f11b0d7ed91be53166aeef2a23a799e636625675bb30818f47f41ad31821", size = 2187333 },
{ url = "https://files.pythonhosted.org/packages/3e/44/44efcf2acf824aefab5f3fdb97235d360c216c2425db391a8dee687f1774/cytoolz-0.12.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7fde09384d23048a7b4ac889063761e44b89a0b64015393e2d1d21d5c1f534a", size = 2173106 },
{ url = "https://files.pythonhosted.org/packages/6f/74/7c2d5af25d51f481e9be771bda2cf5496631cd0fba876d2cc0086caa732d/cytoolz-0.12.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d3bfe45173cc8e6c76206be3a916d8bfd2214fb2965563e288088012f1dabfc", size = 2098805 },
{ url = "https://files.pythonhosted.org/packages/e0/e5/9995bf66caee139459ab70d8b5820c37718d5f7e7380481adb85ef522e4d/cytoolz-0.12.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27513a5d5b6624372d63313574381d3217a66e7a2626b056c695179623a5cb1a", size = 1995956 },
{ url = "https://files.pythonhosted.org/packages/93/73/eee7a7f455d4691f1915b35d1713ba69c6851f940c6f8fffdd2efcbe4411/cytoolz-0.12.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d294e5e81ff094fe920fd545052ff30838ea49f9e91227a55ecd9f3ca19774a0", size = 2074891 },
{ url = "https://files.pythonhosted.org/packages/a3/c7/6f0c60bbb911ee3f33b243a695e2fc944285a1865bbb1dfefee1b7c35d62/cytoolz-0.12.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:727b01a2004ddb513496507a695e19b5c0cfebcdfcc68349d3efd92a1c297bf4", size = 1980228 },
{ url = "https://files.pythonhosted.org/packages/58/7c/d7524626b415d410208fd2774ff2824fab4dcbe4a496d53bdba85a1407df/cytoolz-0.12.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:fe1e1779a39dbe83f13886d2b4b02f8c4b10755e3c8d9a89b630395f49f4f406", size = 2147616 },
{ url = "https://files.pythonhosted.org/packages/a5/7b/9bdf8615e61958386f5c7108d857312214837ae3eacf3589873499d2f0aa/cytoolz-0.12.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:de74ef266e2679c3bf8b5fc20cee4fc0271ba13ae0d9097b1491c7a9bcadb389", size = 2148775 },
{ url = "https://files.pythonhosted.org/packages/45/91/b92ab0e29bf7cfaacfedc85391a0d0365a6ac74363f2532ba307a760db14/cytoolz-0.12.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e04d22049233394e0b08193aca9737200b4a2afa28659d957327aa780ddddf2", size = 2079810 },
{ url = "https://files.pythonhosted.org/packages/2f/33/8204d65871fa639d1d3ae788e3afc187f610126f53f2324d4aa37caf0630/cytoolz-0.12.3-cp311-cp311-win32.whl", hash = "sha256:20d36430d8ac809186736fda735ee7d595b6242bdb35f69b598ef809ebfa5605", size = 320212 },
{ url = "https://files.pythonhosted.org/packages/ab/e3/7ce2efaf243c9ee75fc730cd018981788b56e7ad3767f24e7a9cd14831ac/cytoolz-0.12.3-cp311-cp311-win_amd64.whl", hash = "sha256:780c06110f383344d537f48d9010d79fa4f75070d214fc47f389357dd4f010b6", size = 363570 },
{ url = "https://files.pythonhosted.org/packages/7f/57/b0feabefdff4707d0b96bf75e2298ecb209ba22c2e3fd15e5230dd68441a/cytoolz-0.12.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:86923d823bd19ce35805953b018d436f6b862edd6a7c8b747a13d52b39ed5716", size = 419825 },
{ url = "https://files.pythonhosted.org/packages/54/82/795aa9f91ee81818732b435755559857a76e16b7e435e1de434b47ce72b9/cytoolz-0.12.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3e61acfd029bfb81c2c596249b508dfd2b4f72e31b7b53b62e5fb0507dd7293", size = 401673 },
{ url = "https://files.pythonhosted.org/packages/23/f3/298f32b2e374f4f716ca74a9e46b64ee1df9f160de262391f7f9bc53ecca/cytoolz-0.12.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd728f4e6051af6af234651df49319da1d813f47894d4c3c8ab7455e01703a37", size = 2096352 },
{ url = "https://files.pythonhosted.org/packages/39/44/49929b33bd0cdccc98b281e4ca11f0836b2963c6fdec8ebb7891807ed908/cytoolz-0.12.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fe8c6267caa7ec67bcc37e360f0d8a26bc3bdce510b15b97f2f2e0143bdd3673", size = 2161581 },
{ url = "https://files.pythonhosted.org/packages/e9/77/980a8bc123490dd7112e1e068da989932b7612504355ddd25593880c3156/cytoolz-0.12.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99462abd8323c52204a2a0ce62454ce8fa0f4e94b9af397945c12830de73f27e", size = 2178057 },
{ url = "https://files.pythonhosted.org/packages/23/d9/2f7a4db7f92eab4b567e56cc2fc147fed1ef35f7968e44cefcbbfb366980/cytoolz-0.12.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da125221b1fa25c690fcd030a54344cecec80074df018d906fc6a99f46c1e3a6", size = 2130881 },
{ url = "https://files.pythonhosted.org/packages/85/bf/1147229198a8fc3f2090d01263234d47b5b7f8c52c20090b1cceda0929cd/cytoolz-0.12.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c18e351956f70db9e2d04ff02f28e9a41839250d3f936a4c8a1eabd1c3094d2", size = 1979975 },
{ url = "https://files.pythonhosted.org/packages/5b/53/b730e9f428e74971f934bf73f0868099d325ffbf0c080a201bb16b6ab508/cytoolz-0.12.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:921e6d2440ac758c4945c587b1d1d9b781b72737ac0c0ca5d5e02ca1db8bded2", size = 2086861 },
{ url = "https://files.pythonhosted.org/packages/24/24/df510850c1c57ad69a23a2700083cfd285faf27d16e61f0e503eec122473/cytoolz-0.12.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1651a9bd591a8326329ce1d6336f3129161a36d7061a4d5ea9e5377e033364cf", size = 1973211 },
{ url = "https://files.pythonhosted.org/packages/b6/ad/a6e27924a6c8048b4f1ffbd8b9b0b871642bd94d3e457aa42a629c1f667b/cytoolz-0.12.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8893223b87c2782bd59f9c4bd5c7bf733edd8728b523c93efb91d7468b486528", size = 2133017 },
{ url = "https://files.pythonhosted.org/packages/26/a3/f9dfb406232d0a100994a86c123259cd2ab023aa8ae325b0d9926f80091f/cytoolz-0.12.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:e4d2961644153c5ae186db964aa9f6109da81b12df0f1d3494b4e5cf2c332ee2", size = 2156771 },
{ url = "https://files.pythonhosted.org/packages/fb/bf/ce2c6f6175a29c830904b23faee557de8c167255dbb2bb84e04d7cf5605a/cytoolz-0.12.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:71b6eb97f6695f7ba8ce69c49b707a351c5f46fd97f5aeb5f6f2fb0d6e72b887", size = 2121104 },
{ url = "https://files.pythonhosted.org/packages/bf/97/95a5fb2b5db9b1ea8856741a2a94741a71cb5640112403029beb7b3ef1df/cytoolz-0.12.3-cp312-cp312-win32.whl", hash = "sha256:cee3de65584e915053412cd178729ff510ad5f8f585c21c5890e91028283518f", size = 320537 },
{ url = "https://files.pythonhosted.org/packages/0a/11/3e69585342ce4e6b7f2f6139c8aa235dab5a4fe5c76a051fe01696618bd0/cytoolz-0.12.3-cp312-cp312-win_amd64.whl", hash = "sha256:9eef0d23035fa4dcfa21e570961e86c375153a7ee605cdd11a8b088c24f707f6", size = 363238 },
{ url = "https://files.pythonhosted.org/packages/ac/21/b68d7c043b38001b90788bf940aad9bc51afb1e94d7e5e93fbab438fcab3/cytoolz-0.12.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b4a52dd2a36b0a91f7aa50ca6c8509057acc481a24255f6cb07b15d339a34e0f", size = 416205 },
{ url = "https://files.pythonhosted.org/packages/69/06/f819cb6a79e9fe13fd5d69e59495667b742380425f0357665e2ff775b499/cytoolz-0.12.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:581f1ce479769fe7eeb9ae6d87eadb230df8c7c5fff32138162cdd99d7fb8fc3", size = 398534 },
{ url = "https://files.pythonhosted.org/packages/4c/a7/223c9f0a95bc6f0a6f7a955fa74f6befef6a896c6763912aae43152945ab/cytoolz-0.12.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46f505d4c6eb79585c8ad0b9dc140ef30a138c880e4e3b40230d642690e36366", size = 1945066 },
{ url = "https://files.pythonhosted.org/packages/74/95/24a5cf86fa74f0b4708a59d93a647ab7870546d4be7213a38b6cbe3e1e00/cytoolz-0.12.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59276021619b432a5c21c01cda8320b9cc7dbc40351ffc478b440bfccd5bbdd3", size = 2026912 },
{ url = "https://files.pythonhosted.org/packages/56/17/fe5cd6c27c582b2ef007e1f790773e973e743055e5654f7b78995325b190/cytoolz-0.12.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e44f4c25e1e7cf6149b499c74945a14649c8866d36371a2c2d2164e4649e7755", size = 2012027 },
{ url = "https://files.pythonhosted.org/packages/a3/1c/a7e6f163325a63feaed0a617e271a1adfbf954ec4ce113e1c0074063d108/cytoolz-0.12.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c64f8e60c1dd69e4d5e615481f2d57937746f4a6be2d0f86e9e7e3b9e2243b5e", size = 1968241 },
{ url = "https://files.pythonhosted.org/packages/c0/25/105c2af52d09936f7cb3c2cb1a259894dee45fdecf5e278f0f381c89c3e6/cytoolz-0.12.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33c63186f3bf9d7ef1347bc0537bb9a0b4111a0d7d6e619623cabc18fef0dc3b", size = 1872825 },
{ url = "https://files.pythonhosted.org/packages/34/de/9fb3dc08f31afaf93e3b7fd997f260fd973720b2e09d5fc359defa83d8a9/cytoolz-0.12.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fdddb9d988405f24035234f1e8d1653ab2e48cc2404226d21b49a129aefd1d25", size = 1951717 },
{ url = "https://files.pythonhosted.org/packages/b6/cb/6f73fadcc2992047d25794e2ea6db628327ac0d9c39a91f8b53377f3b803/cytoolz-0.12.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6986632d8a969ea1e720990c818dace1a24c11015fd7c59b9fea0b65ef71f726", size = 1872712 },
{ url = "https://files.pythonhosted.org/packages/5a/34/a260b64f43d318a75bd9b661172ea019301c3df98efef2154005946c25c4/cytoolz-0.12.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0ba1cbc4d9cd7571c917f88f4a069568e5121646eb5d82b2393b2cf84712cf2a", size = 2027103 },
{ url = "https://files.pythonhosted.org/packages/1e/bc/b413c8b4f1b38e051da9df5b65c8d0b3a033593f584773be7495ef4b2484/cytoolz-0.12.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7d267ffc9a36c0a9a58c7e0adc9fa82620f22e4a72533e15dd1361f57fc9accf", size = 2028642 },
{ url = "https://files.pythonhosted.org/packages/3b/36/a14e47d241c703681707df9fc98bb7e5b20ad2fd62741e201b5aacad3d24/cytoolz-0.12.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95e878868a172a41fbf6c505a4b967309e6870e22adc7b1c3b19653d062711fa", size = 1967107 },
{ url = "https://files.pythonhosted.org/packages/72/35/346bea912e1a01fa88524a1a247540b9da18a9898d81b4a196a7b2bf8a8e/cytoolz-0.12.3-cp39-cp39-win32.whl", hash = "sha256:8e21932d6d260996f7109f2a40b2586070cb0a0cf1d65781e156326d5ebcc329", size = 323484 },
{ url = "https://files.pythonhosted.org/packages/bf/73/08541c3ed84bc8ff1afcf39b0b3bf09118e8faf6c2286e2f0778effe8b54/cytoolz-0.12.3-cp39-cp39-win_amd64.whl", hash = "sha256:0d8edfbc694af6c9bda4db56643fb8ed3d14e47bec358c2f1417de9a12d6d1fb", size = 364351 },
{ url = "https://files.pythonhosted.org/packages/00/8c/c58e2f14a88132722988ee0951b01ee6cc4880302384f064902d6e8fb048/cytoolz-0.12.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:55f9bd1ae6c2a27eda5abe2a0b65a83029d2385c5a1da7b8ef47af5905d7e905", size = 353101 },
{ url = "https://files.pythonhosted.org/packages/35/99/6ef817203004c7055370fa1ab3bb0dfc6b7ebd0b4942099ce86007614001/cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2d271393c378282727f1231d40391ae93b93ddc0997448acc21dd0cb6a1e56d", size = 385225 },
{ url = "https://files.pythonhosted.org/packages/a2/25/64e5907b15bd16f0f38e825762540ee3293b513f2eb4b9bb51b7f78d5457/cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee98968d6a66ee83a8ceabf31182189ab5d8598998c8ce69b6d5843daeb2db60", size = 405888 },
{ url = "https://files.pythonhosted.org/packages/17/c0/0e19ab05222cf2370d580e5500409c26266f89e853fa18b2b12c530f3957/cytoolz-0.12.3-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01cfb8518828c1189200c02a5010ea404407fb18fd5589e29c126e84bbeadd36", size = 396781 },
{ url = "https://files.pythonhosted.org/packages/5e/39/bee67e2b541ca3478a982c68d7d23b718fa7f2947bdfc0eecdba9c4e0882/cytoolz-0.12.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:456395d7aec01db32bf9e6db191d667347c78d8d48e77234521fa1078f60dabb", size = 340712 },
{ url = "https://files.pythonhosted.org/packages/26/cc/e6fed5e1c51a7df82d86c85ef9ac56d1ddb747ae2535ce578084ab609435/cytoolz-0.12.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a447247ed312dd64e3a8d9483841ecc5338ee26d6e6fbd29cd373ed030db0240", size = 352376 },
{ url = "https://files.pythonhosted.org/packages/34/83/63d98c0ec2f0c4c0342a374ce7d0ce19849fded45d662fbfa45a5a813a00/cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba3f843aa89f35467b38c398ae5b980a824fdbdb94065adc6ec7c47a0a22f4c7", size = 384142 },
{ url = "https://files.pythonhosted.org/packages/d2/11/487d21afbabf9f99390d2d43515d91de1e58aea78bdb39c520e45ae8d558/cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:582c22f97a380211fb36a7b65b1beeb84ea11d82015fa84b054be78580390082", size = 404529 },
{ url = "https://files.pythonhosted.org/packages/5e/93/f0dbc7a53fe1534adb6bdadd15ce7cc790edddabacf14aa58770e37b24ab/cytoolz-0.12.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47feb089506fc66e1593cd9ade3945693a9d089a445fbe9a11385cab200b9f22", size = 395881 },
{ url = "https://files.pythonhosted.org/packages/b4/6c/91c2ef18235e2394402196f111277e5767369eb4f83213bda1102c5277d8/cytoolz-0.12.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ba9002d2f043943744a9dc8e50a47362bcb6e6f360dc0a1abcb19642584d87bb", size = 340238 },
]
[[package]]
name = "eth-hash"
version = "0.7.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c6/b6/57c89b91cf2dbb02b3019337f97bf346167d06cd23d3bde43c9fe52cae7e/eth-hash-0.7.0.tar.gz", hash = "sha256:bacdc705bfd85dadd055ecd35fd1b4f846b671add101427e089a4ca2e8db310a", size = 12463 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/73/f0/a35e791bd73fa425838d8d0157754150ded141a94cf30d567dfeb9d57316/eth_hash-0.7.0-py3-none-any.whl", hash = "sha256:b8d5a230a2b251f4a291e3164a23a14057c4a6de4b0aa4a16fa4dc9161b57e2f", size = 8650 },
]
[[package]]
name = "eth-typing"
version = "5.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/94/0a/27010c2670f130019d787906038f43d4c0b2896d696d3bbc46e98c75ea61/eth_typing-5.0.0.tar.gz", hash = "sha256:87ce7cee75665c09d2dcff8de1b496609d5e32fcd2e2b1d8fc0370c29eedcdc0", size = 22595 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/27/fa/c44a9406dad56031acade4c5921cdaf4427082a3e49fec0f79b9e2564c86/eth_typing-5.0.0-py3-none-any.whl", hash = "sha256:c7ebc8595e7b65175bb4b4176c2b548ab21b13329f2058e84d4f8c289ba9f577", size = 20079 },
]
[[package]]
name = "eth-utils"
version = "5.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cytoolz", marker = "implementation_name == 'cpython'" },
{ name = "eth-hash" },
{ name = "eth-typing" },
{ name = "hexbytes" },
{ name = "toolz", marker = "implementation_name == 'pypy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/27/c5/8409a2afe1bcd70fa63d7b4c54185f36ab959299767eb45d0b8ca0db77a6/eth_utils-5.0.0.tar.gz", hash = "sha256:a5eb9555f43f4579eb83cb84f9dda9f3d6663bbd4a5a6b693f8d35045f305a1f", size = 120193 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/be/2d/6557e000bb44529c4c7b2621f88bc344fcdbd0c46bd1b3f75b39f1bb19f5/eth_utils-5.0.0-py3-none-any.whl", hash = "sha256:99c44eca11db74dbb881a1d70b24cd80436fc62fe527d2f5c3e3cf7932aba7b2", size = 100489 },
]
[[package]]
name = "ethstaker-deposit"
version = "0.3.1.dev0"
source = { editable = "." }
dependencies = [
{ name = "click" },
{ name = "eth-typing" },
{ name = "eth-utils" },
{ name = "py-ecc" },
{ name = "pycryptodome" },
{ name = "pyperclip" },
{ name = "ssz" },
]
[package.optional-dependencies]
test = [
{ name = "coverage" },
{ name = "exceptiongroup" },
{ name = "flake8" },
{ name = "jsonschema" },
{ name = "mypy" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "tomli" },
]
[package.metadata]
requires-dist = [
{ name = "click" },
{ name = "coverage", marker = "extra == 'test'" },
{ name = "eth-typing" },
{ name = "eth-utils" },
{ name = "exceptiongroup", marker = "extra == 'test'" },
{ name = "flake8", marker = "extra == 'test'" },
{ name = "jsonschema", marker = "extra == 'test'" },
{ name = "mypy", marker = "extra == 'test'" },
{ name = "py-ecc" },
{ name = "pycryptodome" },
{ name = "pyperclip" },
{ name = "pytest", marker = "extra == 'test'" },
{ name = "pytest-asyncio", marker = "extra == 'test'" },
{ name = "ssz" },
{ name = "tomli", marker = "extra == 'test'" },
]
[[package]]
name = "exceptiongroup"
version = "1.2.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 },
]
[[package]]
name = "flake8"
version = "7.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mccabe" },
{ name = "pycodestyle" },
{ name = "pyflakes" },
]
sdist = { url = "https://files.pythonhosted.org/packages/37/72/e8d66150c4fcace3c0a450466aa3480506ba2cae7b61e100a2613afc3907/flake8-7.1.1.tar.gz", hash = "sha256:049d058491e228e03e67b390f311bbf88fce2dbaa8fa673e7aea87b7198b8d38", size = 48054 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d9/42/65004373ac4617464f35ed15931b30d764f53cdd30cc78d5aea349c8c050/flake8-7.1.1-py2.py3-none-any.whl", hash = "sha256:597477df7860daa5aa0fdd84bf5208a043ab96b8e96ab708770ae0364dd03213", size = 57731 },
]
[[package]]
name = "hexbytes"
version = "1.2.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/4e/51/06836a542b773bfc60ab871fa08d4a7963e7df6754ca57169e2654287cc1/hexbytes-1.2.1.tar.gz", hash = "sha256:515f00dddf31053db4d0d7636dd16061c1d896c3109b8e751005db4ca46bcca7", size = 7722 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/39/c6/20f25ea73e4ceffb3eb4e38347f2992cb25e5ff6eb644d52e753a7a72f57/hexbytes-1.2.1-py3-none-any.whl", hash = "sha256:e64890b203a31f4a23ef11470ecfcca565beaee9198df623047df322b757471a", size = 5160 },
]
[[package]]
name = "iniconfig"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
]
[[package]]
name = "jsonschema"
version = "4.23.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "jsonschema-specifications" },
{ name = "referencing" },
{ name = "rpds-py" },
]
sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 },
]
[[package]]
name = "jsonschema-specifications"
version = "2023.12.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "referencing" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f8/b9/cc0cc592e7c195fb8a650c1d5990b10175cf13b4c97465c72ec841de9e4b/jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc", size = 13983 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c", size = 18482 },
]
[[package]]
name = "lru-dict"
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/96/e3/42c87871920602a3c8300915bd0292f76eccc66c38f782397acbf8a62088/lru-dict-1.3.0.tar.gz", hash = "sha256:54fd1966d6bd1fcde781596cb86068214edeebff1db13a2cea11079e3fd07b6b", size = 13123 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/36/fc/d0de12343c9f132b10c7efe40951dfb6c3cfba328941ecf4c198e6bfdd78/lru_dict-1.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4073333894db9840f066226d50e6f914a2240711c87d60885d8c940b69a6673f", size = 17708 },
{ url = "https://files.pythonhosted.org/packages/75/56/af1cae207a5c4f1ada20a9bde92d7d953404274f499dd8fe3f4ece91eefe/lru_dict-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0ad6361e4dd63b47b2fc8eab344198f37387e1da3dcfacfee19bafac3ec9f1eb", size = 11017 },
{ url = "https://files.pythonhosted.org/packages/e9/d1/1dcaf052b4d039b85af8a8df9090c10923acc4bed448051ce791376313f3/lru_dict-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c637ab54b8cd9802fe19b260261e38820d748adf7606e34045d3c799b6dde813", size = 11322 },
{ url = "https://files.pythonhosted.org/packages/14/d4/77553cb43a2e50c3a5bb6338fe4ba3415638a99a5c8404a4ec13ab7cec52/lru_dict-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fce5f95489ca1fc158cc9fe0f4866db9cec82c2be0470926a9080570392beaf", size = 30597 },
{ url = "https://files.pythonhosted.org/packages/14/28/184d94fcd121a0dc775fa423bf05b886ae42fc081cbd693540068cf06ece/lru_dict-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2bf2e24cf5f19c3ff69bf639306e83dced273e6fa775b04e190d7f5cd16f794", size = 31871 },
{ url = "https://files.pythonhosted.org/packages/da/0e/6b49fa5fccc7b2d28fe254c48c64323741c98334e4fe41e4694fa049c208/lru_dict-1.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e90059f7701bef3c4da073d6e0434a9c7dc551d5adce30e6b99ef86b186f4b4a", size = 28651 },
{ url = "https://files.pythonhosted.org/packages/41/52/c3a4922421c8e5eb6fa1fdf5f56a7e01270a141a4f5f645d5ed6931b490f/lru_dict-1.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ecb7ae557239c64077e9b26a142eb88e63cddb104111a5122de7bebbbd00098", size = 30277 },
{ url = "https://files.pythonhosted.org/packages/f9/10/a15f70c5c36d46adba72850e64b075c6a118d2a9ee1ce7f2af2f4a419401/lru_dict-1.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6af36166d22dba851e06a13e35bbf33845d3dd88872e6aebbc8e3e7db70f4682", size = 34793 },
{ url = "https://files.pythonhosted.org/packages/56/e3/9901f9165a8c2d650bb84ae6ba371fa635e35e8b1dfb1aff2bd7be4cfd3a/lru_dict-1.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ee38d420c77eed548df47b7d74b5169a98e71c9e975596e31ab808e76d11f09", size = 33414 },
{ url = "https://files.pythonhosted.org/packages/be/27/6323b27dd42914c3ee511631d976d49247699ef0ec6fd468a5d4eef3930e/lru_dict-1.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0e1845024c31e6ff246c9eb5e6f6f1a8bb564c06f8a7d6d031220044c081090b", size = 36345 },
{ url = "https://files.pythonhosted.org/packages/76/14/b7d9009acf698e6f5d656e35776cedd3fd09755db5b09ff372d4e2667c4e/lru_dict-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3ca5474b1649555d014be1104e5558a92497509021a5ba5ea6e9b492303eb66b", size = 34619 },
{ url = "https://files.pythonhosted.org/packages/96/8d/ec1813a2618b152b845e782f8bf071e3d8cd5029fd725c8248c9db0109b6/lru_dict-1.3.0-cp310-cp310-win32.whl", hash = "sha256:ebb03a9bd50c2ed86d4f72a54e0aae156d35a14075485b2127c4b01a3f4a63fa", size = 12538 },
{ url = "https://files.pythonhosted.org/packages/dc/f4/463045af7fd4cf3840029ac75174bbff7240021daa9624bdd7a47265daf6/lru_dict-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:04cda617f4e4c27009005d0a8185ef02829b14b776d2791f5c994cc9d668bc24", size = 13652 },
{ url = "https://files.pythonhosted.org/packages/a8/c9/6fac0cb67160f0efa3cc76a6a7d04d5e21a516eeb991ebba08f4f8f01ec5/lru_dict-1.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:20c595764695d20bdc3ab9b582e0cc99814da183544afb83783a36d6741a0dac", size = 17750 },
{ url = "https://files.pythonhosted.org/packages/61/14/f90dee4bc547ae266dbeffd4e11611234bb6af511dea48f3bc8dac1de478/lru_dict-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d9b30a8f50c3fa72a494eca6be5810a1b5c89e4f0fda89374f0d1c5ad8d37d51", size = 11055 },
{ url = "https://files.pythonhosted.org/packages/4e/63/a0ae20525f9d52f62ac0def47935f8a2b3b6fcd2c145218b9a27fc1fb910/lru_dict-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9710737584650a4251b9a566cbb1a86f83437adb209c9ba43a4e756d12faf0d7", size = 11330 },
{ url = "https://files.pythonhosted.org/packages/e9/c6/8c2b81b61e5206910c81b712500736227289aefe4ccfb36137aa21807003/lru_dict-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b84c321ae34f2f40aae80e18b6fa08b31c90095792ab64bb99d2e385143effaa", size = 31793 },
{ url = "https://files.pythonhosted.org/packages/f9/d7/af9733f94df67a2e9e31ef47d4c41aff1836024f135cdbda4743eb628452/lru_dict-1.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eed24272b4121b7c22f234daed99899817d81d671b3ed030c876ac88bc9dc890", size = 33090 },
{ url = "https://files.pythonhosted.org/packages/5b/6e/5b09b069a70028bcf05dbdc57a301fbe8b3bafecf916f2ed5a3065c79a71/lru_dict-1.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd13af06dab7c6ee92284fd02ed9a5613a07d5c1b41948dc8886e7207f86dfd", size = 29795 },
{ url = "https://files.pythonhosted.org/packages/21/92/4690daefc2602f7c3429ecf54572d37a9e3c372d370344d2185daa4d5ecc/lru_dict-1.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1efc59bfba6aac33684d87b9e02813b0e2445b2f1c444dae2a0b396ad0ed60c", size = 31586 },
{ url = "https://files.pythonhosted.org/packages/3c/67/0a29a91087196b02f278d8765120ee4e7486f1f72a4c505fd1cd3109e627/lru_dict-1.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfaf75ac574447afcf8ad998789071af11d2bcf6f947643231f692948839bd98", size = 36662 },
{ url = "https://files.pythonhosted.org/packages/36/54/8d56c514cd2333b652bd44c8f1962ab986cbe68e8ad7258c9e0f360cddb6/lru_dict-1.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c95f8751e2abd6f778da0399c8e0239321d560dbc58cb063827123137d213242", size = 35118 },
{ url = "https://files.pythonhosted.org/packages/f5/9a/c7a175d10d503b86974cb07141ca175947145dd1c7370fcda86fbbcaf326/lru_dict-1.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:abd0c284b26b5c4ee806ca4f33ab5e16b4bf4d5ec9e093e75a6f6287acdde78e", size = 38198 },
{ url = "https://files.pythonhosted.org/packages/fd/59/2e5086c8e8a05a7282a824a2a37e3c45cd5714e7b83d8bc0267cb3bb5b4f/lru_dict-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a47740652b25900ac5ce52667b2eade28d8b5fdca0ccd3323459df710e8210a", size = 36542 },
{ url = "https://files.pythonhosted.org/packages/12/52/80d0a06e5f45fe7c278dd662da6ea5b39f2ff003248f448189932f6b71c2/lru_dict-1.3.0-cp311-cp311-win32.whl", hash = "sha256:a690c23fc353681ed8042d9fe8f48f0fb79a57b9a45daea2f0be1eef8a1a4aa4", size = 12533 },
{ url = "https://files.pythonhosted.org/packages/ce/fe/1f12f33513310860ec6d722709ec4ad8256d9dcc3385f6ae2a244e6e66f5/lru_dict-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:efd3f4e0385d18f20f7ea6b08af2574c1bfaa5cb590102ef1bee781bdfba84bc", size = 13651 },
{ url = "https://files.pythonhosted.org/packages/fc/5c/385f080747eb3083af87d8e4c9068f3c4cab89035f6982134889940dafd8/lru_dict-1.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c279068f68af3b46a5d649855e1fb87f5705fe1f744a529d82b2885c0e1fc69d", size = 17174 },
{ url = "https://files.pythonhosted.org/packages/3c/de/5ef2ed75ce55d7059d1b96177ba04fa7ee1f35564f97bdfcd28fccfbe9d2/lru_dict-1.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:350e2233cfee9f326a0d7a08e309372d87186565e43a691b120006285a0ac549", size = 10742 },
{ url = "https://files.pythonhosted.org/packages/ca/05/f69a6abb0062d2cf2ce0aaf0284b105b97d1da024ca6d3d0730e6151242e/lru_dict-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4eafb188a84483b3231259bf19030859f070321b00326dcb8e8c6cbf7db4b12f", size = 11079 },
{ url = "https://files.pythonhosted.org/packages/ea/59/cf891143abe58a455b8eaa9175f0e80f624a146a2bf9a1ca842ee0ef930a/lru_dict-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73593791047e36b37fdc0b67b76aeed439fcea80959c7d46201240f9ec3b2563", size = 32469 },
{ url = "https://files.pythonhosted.org/packages/59/88/d5976e9f70107ce11e45d93c6f0c2d5eaa1fc30bb3c8f57525eda4510dff/lru_dict-1.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1958cb70b9542773d6241974646e5410e41ef32e5c9e437d44040d59bd80daf2", size = 33496 },
{ url = "https://files.pythonhosted.org/packages/6c/f8/94d6e910d54fc1fa05c0ee1cd608c39401866a18cf5e5aff238449b33c11/lru_dict-1.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc1cd3ed2cee78a47f11f3b70be053903bda197a873fd146e25c60c8e5a32cd6", size = 29914 },
{ url = "https://files.pythonhosted.org/packages/ca/b9/9db79780c8a3cfd66bba6847773061e5cf8a3746950273b9985d47bbfe53/lru_dict-1.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82eb230d48eaebd6977a92ddaa6d788f14cf4f4bcf5bbffa4ddfd60d051aa9d4", size = 32241 },
{ url = "https://files.pythonhosted.org/packages/9b/b6/08a623019daec22a40c4d6d2c40851dfa3d129a53b2f9469db8eb13666c1/lru_dict-1.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5ad659cbc349d0c9ba8e536b5f40f96a70c360f43323c29f4257f340d891531c", size = 37320 },
{ url = "https://files.pythonhosted.org/packages/70/0b/d3717159c26155ff77679cee1b077d22e1008bf45f19921e193319cd8e46/lru_dict-1.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ba490b8972531d153ac0d4e421f60d793d71a2f4adbe2f7740b3c55dce0a12f1", size = 35054 },
{ url = "https://files.pythonhosted.org/packages/04/74/f2ae00de7c27984a19b88d2b09ac877031c525b01199d7841ec8fa657fd6/lru_dict-1.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:c0131351b8a7226c69f1eba5814cbc9d1d8daaf0fdec1ae3f30508e3de5262d4", size = 38613 },
{ url = "https://files.pythonhosted.org/packages/5a/0b/e30236aafe31b4247aa9ae61ba8aac6dde75c3ea0e47a8fb7eef53f6d5ce/lru_dict-1.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0e88dba16695f17f41701269fa046197a3fd7b34a8dba744c8749303ddaa18df", size = 37143 },
{ url = "https://files.pythonhosted.org/packages/1c/28/b59bcebb8d76ba8147a784a8be7eab6a4ad3395b9236e73740ff675a5a52/lru_dict-1.3.0-cp312-cp312-win32.whl", hash = "sha256:6ffaf595e625b388babc8e7d79b40f26c7485f61f16efe76764e32dce9ea17fc", size = 12653 },
{ url = "https://files.pythonhosted.org/packages/bd/18/06d9710cb0a0d3634f8501e4bdcc07abe64a32e404d82895a6a36fab97f6/lru_dict-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf9da32ef2582434842ab6ba6e67290debfae72771255a8e8ab16f3e006de0aa", size = 13811 },
{ url = "https://files.pythonhosted.org/packages/2a/fe/7f7fe14b680c8605bf73087a985b859f3bf4ca52a5c40b23e691bd39f95c/lru_dict-1.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a3c9f746a9917e784fffcedeac4c8c47a3dbd90cbe13b69e9140182ad97ce4b7", size = 17720 },
{ url = "https://files.pythonhosted.org/packages/2d/73/b5bb1e97566791fa83ab851e4426887817e03f0404ef079007dd0c83eb52/lru_dict-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2789296819525a1f3204072dfcf3df6db8bcf69a8fc740ffd3de43a684ea7002", size = 11024 },
{ url = "https://files.pythonhosted.org/packages/72/31/5252dcf464f6f39abfc3f1b38dd0e42e6ea2b41c0b867227ee13568b32f7/lru_dict-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:170b66d29945391460351588a7bd8210a95407ae82efe0b855e945398a1d24ea", size = 11323 },
{ url = "https://files.pythonhosted.org/packages/2e/af/dad7f54ad9713829c7a98aa64981d14fdadfebac7e04fc6471c70932d88f/lru_dict-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:774ca88501a9effe8797c3db5a6685cf20978c9cb0fe836b6813cfe1ca60d8c9", size = 30257 },
{ url = "https://files.pythonhosted.org/packages/f2/f7/49b0d40262af0ea275a9bf169d26c59e8ba4ccc84bf21a039712c60841ea/lru_dict-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:df2e119c6ae412d2fd641a55f8a1e2e51f45a3de3449c18b1b86c319ab79e0c4", size = 31494 },
{ url = "https://files.pythonhosted.org/packages/37/2f/89bf5f6eb08f8661eb1704bfe82abbb839b6aa6a7bb04da397b8b32c6856/lru_dict-1.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28aa1ea42a7e48174bf513dc2416fea7511a547961e678dc6f5670ca987c18cb", size = 28253 },
{ url = "https://files.pythonhosted.org/packages/d4/7a/0245feb3a7d8216b8415520f8530516fc7b6ce0d33ea154ffce0bd45db40/lru_dict-1.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9537e1cee6fa582cb68f2fb9ce82d51faf2ccc0a638b275d033fdcb1478eb80b", size = 29847 },
{ url = "https://files.pythonhosted.org/packages/60/c7/494b0938443891a456260502465544f7a2781111857d7e018e7f2abf95d4/lru_dict-1.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:64545fca797fe2c68c5168efb5f976c6e1459e058cab02445207a079180a3557", size = 34376 },
{ url = "https://files.pythonhosted.org/packages/59/1a/5d6219520274eced5327fe3590d0c7c8c6352d996f3507f277beb49b6293/lru_dict-1.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a193a14c66cfc0c259d05dddc5e566a4b09e8f1765e941503d065008feebea9d", size = 33006 },
{ url = "https://files.pythonhosted.org/packages/05/8c/4664d41111032b829db77d87cef0530078bf6a6c6c20f0e09e64ee6fb1b5/lru_dict-1.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:3cb1de0ce4137b060abaafed8474cc0ebd12cedd88aaa7f7b3ebb1ddfba86ae0", size = 35933 },
{ url = "https://files.pythonhosted.org/packages/58/e6/dc37372228567c7cfb4bc21096f031249047f269b307c692e3917a038a4d/lru_dict-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8551ccab1349d4bebedab333dfc8693c74ff728f4b565fe15a6bf7d296bd7ea9", size = 34193 },
{ url = "https://files.pythonhosted.org/packages/97/03/53e3e566b633d853a751d79a8073a2554ab5cd87b2c6dae52492ac8a38ff/lru_dict-1.3.0-cp39-cp39-win32.whl", hash = "sha256:6cb0be5e79c3f34d69b90d8559f0221e374b974b809a22377122c4b1a610ff67", size = 12567 },
{ url = "https://files.pythonhosted.org/packages/2b/a6/bfebae2154dd666cccf282d37a54a3142855796209c70dd9ff862343bde8/lru_dict-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9f725f2a0bdf1c18735372d5807af4ea3b77888208590394d4660e3d07971f21", size = 13718 },
{ url = "https://files.pythonhosted.org/packages/78/8b/4b7af0793512af8b0d814b3b08ccecb08f313594866cfe9aabf77f642934/lru_dict-1.3.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f8f7824db5a64581180ab9d09842e6dd9fcdc46aac9cb592a0807cd37ea55680", size = 10060 },
{ url = "https://files.pythonhosted.org/packages/47/04/e310269b8bbb5718025d0375d8189551f10f1ef057df2b21e4bc5714fb56/lru_dict-1.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acd04b7e7b0c0c192d738df9c317093335e7282c64c9d1bb6b7ebb54674b4e24", size = 13299 },
{ url = "https://files.pythonhosted.org/packages/e2/d2/246d375c89a71637fe193f260c500537e5dc11cf3a2b5144669bfef69295/lru_dict-1.3.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5c20f236f27551e3f0adbf1a987673fb1e9c38d6d284502cd38f5a3845ef681", size = 13142 },
{ url = "https://files.pythonhosted.org/packages/8a/10/56fead7639a41d507eac5163a81f18c7f47a8c1feb3046d20a9c8bb56e56/lru_dict-1.3.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca3703ff03b03a1848c563bc2663d0ad813c1cd42c4d9cf75b623716d4415d9a", size = 12839 },
{ url = "https://files.pythonhosted.org/packages/fe/a4/0d68bc4007aac962386185f625d0d5180cf574e72b5279f840abde1a0e4e/lru_dict-1.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a9fb71ba262c6058a0017ce83d343370d0a0dbe2ae62c2eef38241ec13219330", size = 13768 },
{ url = "https://files.pythonhosted.org/packages/2f/cc/1167c2d28c09b8491ea23eb5429f9372569376ee3df18aae8053beef457b/lru_dict-1.3.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c497fb60279f1e1d7dfbe150b1b069eaa43f7e172dab03f206282f4994676c5", size = 10055 },
{ url = "https://files.pythonhosted.org/packages/59/ce/f8d122c90f724900aede0251f11352ba37915d55433fe6896e218ef23cd4/lru_dict-1.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d9509d817a47597988615c1a322580c10100acad10c98dfcf3abb41e0e5877f", size = 13294 },
{ url = "https://files.pythonhosted.org/packages/e6/47/8071b4689ed54f6d6ecf89f5ab30906d3ff26253ce89d5ba3cdeb15d3f5f/lru_dict-1.3.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0213ab4e3d9a8d386c18e485ad7b14b615cb6f05df6ef44fb2a0746c6ea9278b", size = 13140 },
{ url = "https://files.pythonhosted.org/packages/f8/15/70915c50fe4afd59493aa0391fab52769ecbcb1b79c5ce00a8e3bd9622d6/lru_dict-1.3.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b50fbd69cd3287196796ab4d50e4cc741eb5b5a01f89d8e930df08da3010c385", size = 12840 },
{ url = "https://files.pythonhosted.org/packages/03/79/4cefb7cc8387da16480e8aba8c5483cd692460ea29fe7114d6057ed4e0d4/lru_dict-1.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5247d1f011f92666010942434020ddc5a60951fefd5d12a594f0e5d9f43e3b3b", size = 13779 },
]
[[package]]
name = "mccabe"
version = "0.7.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 },
]
[[package]]
name = "mypy"
version = "1.11.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mypy-extensions" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5c/86/5d7cbc4974fd564550b80fbb8103c05501ea11aa7835edf3351d90095896/mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79", size = 3078806 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/78/cd/815368cd83c3a31873e5e55b317551500b12f2d1d7549720632f32630333/mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a", size = 10939401 },
{ url = "https://files.pythonhosted.org/packages/f1/27/e18c93a195d2fad75eb96e1f1cbc431842c332e8eba2e2b77eaf7313c6b7/mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef", size = 10111697 },
{ url = "https://files.pythonhosted.org/packages/dc/08/cdc1fc6d0d5a67d354741344cc4aa7d53f7128902ebcbe699ddd4f15a61c/mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383", size = 12500508 },
{ url = "https://files.pythonhosted.org/packages/64/12/aad3af008c92c2d5d0720ea3b6674ba94a98cdb86888d389acdb5f218c30/mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8", size = 13020712 },
{ url = "https://files.pythonhosted.org/packages/03/e6/a7d97cc124a565be5e9b7d5c2a6ebf082379ffba99646e4863ed5bbcb3c3/mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7", size = 9567319 },
{ url = "https://files.pythonhosted.org/packages/e2/aa/cc56fb53ebe14c64f1fe91d32d838d6f4db948b9494e200d2f61b820b85d/mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385", size = 10859630 },
{ url = "https://files.pythonhosted.org/packages/04/c8/b19a760fab491c22c51975cf74e3d253b8c8ce2be7afaa2490fbf95a8c59/mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca", size = 10037973 },
{ url = "https://files.pythonhosted.org/packages/88/57/7e7e39f2619c8f74a22efb9a4c4eff32b09d3798335625a124436d121d89/mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104", size = 12416659 },
{ url = "https://files.pythonhosted.org/packages/fc/a6/37f7544666b63a27e46c48f49caeee388bf3ce95f9c570eb5cfba5234405/mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4", size = 12897010 },
{ url = "https://files.pythonhosted.org/packages/84/8b/459a513badc4d34acb31c736a0101c22d2bd0697b969796ad93294165cfb/mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6", size = 9562873 },
{ url = "https://files.pythonhosted.org/packages/35/3a/ed7b12ecc3f6db2f664ccf85cb2e004d3e90bec928e9d7be6aa2f16b7cdf/mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318", size = 10990335 },
{ url = "https://files.pythonhosted.org/packages/04/e4/1a9051e2ef10296d206519f1df13d2cc896aea39e8683302f89bf5792a59/mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36", size = 10007119 },
{ url = "https://files.pythonhosted.org/packages/f3/3c/350a9da895f8a7e87ade0028b962be0252d152e0c2fbaafa6f0658b4d0d4/mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987", size = 12506856 },
{ url = "https://files.pythonhosted.org/packages/b6/49/ee5adf6a49ff13f4202d949544d3d08abb0ea1f3e7f2a6d5b4c10ba0360a/mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca", size = 12952066 },
{ url = "https://files.pythonhosted.org/packages/27/c0/b19d709a42b24004d720db37446a42abadf844d5c46a2c442e2a074d70d9/mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70", size = 9664000 },
{ url = "https://files.pythonhosted.org/packages/16/64/bb5ed751487e2bea0dfaa6f640a7e3bb88083648f522e766d5ef4a76f578/mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6", size = 10937294 },
{ url = "https://files.pythonhosted.org/packages/a9/a3/67a0069abed93c3bf3b0bebb8857e2979a02828a4a3fd82f107f8f1143e8/mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70", size = 10107707 },
{ url = "https://files.pythonhosted.org/packages/2f/4d/0379daf4258b454b1f9ed589a9dabd072c17f97496daea7b72fdacf7c248/mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d", size = 12498367 },
{ url = "https://files.pythonhosted.org/packages/3b/dc/3976a988c280b3571b8eb6928882dc4b723a403b21735a6d8ae6ed20e82b/mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d", size = 13018014 },
{ url = "https://files.pythonhosted.org/packages/83/84/adffc7138fb970e7e2a167bd20b33bb78958370179853a4ebe9008139342/mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24", size = 9568056 },
{ url = "https://files.pythonhosted.org/packages/42/3a/bdf730640ac523229dd6578e8a581795720a9321399de494374afc437ec5/mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12", size = 2619625 },
]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
]
[[package]]
name = "packaging"
version = "24.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/51/65/50db4dda066951078f0a96cf12f4b9ada6e4b811516bf0262c0f4f7064d4/packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", size = 148788 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 },
]
[[package]]
name = "pluggy"
version = "1.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
]
[[package]]
name = "py-ecc"
version = "7.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cached-property" },
{ name = "eth-typing" },
{ name = "eth-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ca/bd/dfe49226d5f137d11a946c4b3f3db2ff87b6b02390db8d95b0098365a2db/py_ecc-7.0.1.tar.gz", hash = "sha256:557461f42e57294d734305a30faf6b8903421651871e9cdeff8d8e67c6796c70", size = 45428 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5b/f0/a899d0d3e0d2fb5eb95c15ae9f277cb3ee139d4f1576c4c68f08a1301470/py_ecc-7.0.1-py3-none-any.whl", hash = "sha256:84a8b4d436163c83c65345a68e32f921ef6e64374a36f8e561f0455b4b08f5f2", size = 43309 },
]
[[package]]
name = "pycodestyle"
version = "2.12.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/43/aa/210b2c9aedd8c1cbeea31a50e42050ad56187754b34eb214c46709445801/pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521", size = 39232 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/d8/a211b3f85e99a0daa2ddec96c949cac6824bd305b040571b82a03dd62636/pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3", size = 31284 },
]
[[package]]
name = "pycryptodome"
version = "3.20.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b9/ed/19223a0a0186b8a91ebbdd2852865839237a21c74f1fbc4b8d5b62965239/pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7", size = 4794232 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ff/96/b0d494defb3346378086848a8ece5ddfd138a66c4a05e038fca873b2518c/pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044", size = 2427142 },
{ url = "https://files.pythonhosted.org/packages/24/80/56a04e2ae622d7f38c1c01aef46a26c6b73a2ad15c9705a8e008b5befb03/pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a", size = 1590045 },
{ url = "https://files.pythonhosted.org/packages/ea/94/82ebfa5c83d980907ceebf79b00909a569d258bdfd9b0264d621fa752cfd/pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2", size = 2061748 },
{ url = "https://files.pythonhosted.org/packages/af/20/5f29ec45462360e7f61e8688af9fe4a0afae057edfabdada662e11bf97e7/pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c", size = 2135687 },
{ url = "https://files.pythonhosted.org/packages/e5/1f/6bc4beb4adc07b847e5d3fddbec4522c2c3aa05df9e61b91dc4eff6a4946/pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25", size = 2164262 },
{ url = "https://files.pythonhosted.org/packages/30/4b/cbc67cda0efd55d7ddcc98374c4b9c853022a595ed1d78dd15c961bc7f6e/pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128", size = 2054347 },
{ url = "https://files.pythonhosted.org/packages/0d/08/01987ab75ca789247a88c8b2f0ce374ef7d319e79589e0842e316a272662/pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c", size = 2192762 },
{ url = "https://files.pythonhosted.org/packages/b5/bf/798630923b67f4201059c2d690105998f20a6a8fb9b5ab68d221985155b3/pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4", size = 2155230 },
{ url = "https://files.pythonhosted.org/packages/39/12/5fe7f5b9212dda9f5a26f842a324d6541fe1ca8059602124ff30db1e874b/pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72", size = 1723464 },
{ url = "https://files.pythonhosted.org/packages/1f/90/d131c0eb643290230dfa4108b7c2d135122d88b714ad241d77beb4782a76/pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9", size = 1759588 },
{ url = "https://files.pythonhosted.org/packages/17/87/c7153fcd400df0f4a67d7d92cdb6b5e43f309c22434374b8a61849dfb280/pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a", size = 1639310 },
{ url = "https://files.pythonhosted.org/packages/68/9a/88d984405b087e8c8dd9a9d4c81a6fa675454e5fcf2ae01d9553b3128637/pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e", size = 1708332 },
{ url = "https://files.pythonhosted.org/packages/c7/10/88fb67d2fa545ce2ac61cfda70947bcbb1769f1956315c4b919d79774897/pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04", size = 1565619 },
{ url = "https://files.pythonhosted.org/packages/a2/40/63dff38fa4f7888f812263494d4a745eeed180ff09dd7b8350a81eb09d21/pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3", size = 1606403 },
{ url = "https://files.pythonhosted.org/packages/8b/61/522235ca81d9dcfcf8b4cbc253b3a8a1f2231603d486369a8a02eb998f31/pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea", size = 1637284 },
{ url = "https://files.pythonhosted.org/packages/e9/a7/5aa0596f7fc710fd55b4e6bbb025fedacfec929465a618f20e61ebf7df76/pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b", size = 1741193 },
{ url = "https://files.pythonhosted.org/packages/53/a3/1345f914963d7d668a5423dc563deafae02479bd1c69b39180724475584f/pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6", size = 1565490 },
{ url = "https://files.pythonhosted.org/packages/6a/3d/ba3905a0ae6dd4e8686dbde85c71ce38e27f5ad3587424891238ad520aaf/pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab", size = 1606310 },
{ url = "https://files.pythonhosted.org/packages/5d/c3/5530f270c4ec87953fbed203e4f1f4a2fa002bc43efdc1b3cf9ab442e741/pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5", size = 1637201 },
{ url = "https://files.pythonhosted.org/packages/09/12/34eb6587adcee5d676533e4c217a6385a2f4d90086198a3b1ade5dcdf684/pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e", size = 1741088 },
]
[[package]]
name = "pyflakes"
version = "3.2.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/57/f9/669d8c9c86613c9d568757c7f5824bd3197d7b1c6c27553bc5618a27cce2/pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f", size = 63788 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d4/d7/f1b7db88d8e4417c5d47adad627a93547f44bdc9028372dbd2313f34a855/pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a", size = 62725 },
]
[[package]]
name = "pyperclip"
version = "1.9.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/30/23/2f0a3efc4d6a32f3b63cdff36cd398d9701d26cda58e3ab97ac79fb5e60d/pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310", size = 20961 }
[[package]]
name = "pyrsistent"
version = "0.16.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/80/18/1492d651693ef7d40e0a40377ed56a8cc5c5fe86073eb6c56e53513f4480/pyrsistent-0.16.1.tar.gz", hash = "sha256:aa2ae1c2e496f4d6777f869ea5de7166a8ccb9c2e06ebcf6c7ff1b670c98c5ef", size = 108176 }
[[package]]
name = "pytest"
version = "8.3.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
{ name = "iniconfig" },
{ name = "packaging" },
{ name = "pluggy" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b4/8c/9862305bdcd6020bc7b45b1b5e7397a6caf1a33d3025b9a003b39075ffb2/pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce", size = 1439314 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0f/f9/cf155cf32ca7d6fa3601bc4c5dd19086af4b320b706919d48a4c79081cf9/pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5", size = 341802 },
]
[[package]]
name = "pytest-asyncio"
version = "0.24.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/52/6d/c6cf50ce320cf8611df7a1254d86233b3df7cc07f9b5f5cbcb82e08aa534/pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276", size = 49855 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b", size = 18024 },
]
[[package]]
name = "referencing"
version = "0.35.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "rpds-py" },
]
sdist = { url = "https://files.pythonhosted.org/packages/99/5b/73ca1f8e72fff6fa52119dbd185f73a907b1989428917b24cff660129b6d/referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", size = 62991 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/59/2056f61236782a2c86b33906c025d4f4a0b17be0161b63b70fd9e8775d36/referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de", size = 26684 },
]
[[package]]
name = "rpds-py"
version = "0.20.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/55/64/b693f262791b818880d17268f3f8181ef799b0d187f6f731b1772e05a29a/rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121", size = 25814 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/71/2d/a7e60483b72b91909e18f29a5c5ae847bac4e2ae95b77bb77e1f41819a58/rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2", size = 318432 },
{ url = "https://files.pythonhosted.org/packages/b5/b4/f15b0c55a6d880ce74170e7e28c3ed6c5acdbbd118df50b91d1dabf86008/rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f", size = 311333 },
{ url = "https://files.pythonhosted.org/packages/36/10/3f4e490fe6eb069c07c22357d0b4804cd94cb9f8d01345ef9b1d93482b9d/rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150", size = 366697 },
{ url = "https://files.pythonhosted.org/packages/f5/c8/cd6ab31b4424c7fab3b17e153b6ea7d1bb0d7cabea5c1ef683cc8adb8bc2/rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e", size = 368386 },
{ url = "https://files.pythonhosted.org/packages/60/5e/642a44fda6dda90b5237af7a0ef1d088159c30a504852b94b0396eb62125/rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2", size = 395374 },
{ url = "https://files.pythonhosted.org/packages/7c/b5/ff18c093c9e72630f6d6242e5ccb0728ef8265ba0a154b5972f89d23790a/rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3", size = 433189 },
{ url = "https://files.pythonhosted.org/packages/4a/6d/1166a157b227f2333f8e8ae320b6b7ea2a6a38fbe7a3563ad76dffc8608d/rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf", size = 354849 },
{ url = "https://files.pythonhosted.org/packages/70/a4/70ea49863ea09ae4c2971f2eef58e80b757e3c0f2f618c5815bb751f7847/rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140", size = 373233 },
{ url = "https://files.pythonhosted.org/packages/3b/d3/822a28152a1e7e2ba0dc5d06cf8736f4cd64b191bb6ec47fb51d1c3c5ccf/rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f", size = 541852 },
{ url = "https://files.pythonhosted.org/packages/c6/a5/6ef91e4425dc8b3445ff77d292fc4c5e37046462434a0423c4e0a596a8bd/rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce", size = 547630 },
{ url = "https://files.pythonhosted.org/packages/72/f8/d5625ee05c4e5c478954a16d9359069c66fe8ac8cd5ddf28f80d3b321837/rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94", size = 525766 },
{ url = "https://files.pythonhosted.org/packages/94/3c/1ff1ed6ae323b3e16fdfcdae0f0a67f373a6c3d991229dc32b499edeffb7/rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee", size = 199174 },
{ url = "https://files.pythonhosted.org/packages/ec/ba/5762c0aee2403dfea14ed74b0f8a2415cfdbb21cf745d600d9a8ac952c5b/rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399", size = 213543 },
{ url = "https://files.pythonhosted.org/packages/ab/2a/191374c52d7be0b056cc2a04d718d2244c152f915d4a8d2db2aacc526189/rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489", size = 318369 },
{ url = "https://files.pythonhosted.org/packages/0e/6a/2c9fdcc6d235ac0d61ec4fd9981184689c3e682abd05e3caa49bccb9c298/rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318", size = 311303 },
{ url = "https://files.pythonhosted.org/packages/d2/b2/725487d29633f64ef8f9cbf4729111a0b61702c8f8e94db1653930f52cce/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db", size = 366424 },
{ url = "https://files.pythonhosted.org/packages/7a/8c/668195ab9226d01b7cf7cd9e59c1c0be1df05d602df7ec0cf46f857dcf59/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5", size = 368359 },
{ url = "https://files.pythonhosted.org/packages/52/28/356f6a39c1adeb02cf3e5dd526f5e8e54e17899bef045397abcfbf50dffa/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5", size = 394886 },
{ url = "https://files.pythonhosted.org/packages/a2/65/640fb1a89080a8fb6f4bebd3dafb65a2edba82e2e44c33e6eb0f3e7956f1/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6", size = 432416 },
{ url = "https://files.pythonhosted.org/packages/a7/e8/85835077b782555d6b3416874b702ea6ebd7db1f145283c9252968670dd5/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209", size = 354819 },
{ url = "https://files.pythonhosted.org/packages/4f/87/1ac631e923d65cbf36fbcfc6eaa702a169496de1311e54be142f178e53ee/rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3", size = 373282 },
{ url = "https://files.pythonhosted.org/packages/e4/ce/cb316f7970189e217b998191c7cf0da2ede3d5437932c86a7210dc1e9994/rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272", size = 541540 },
{ url = "https://files.pythonhosted.org/packages/90/d7/4112d7655ec8aff168ecc91d4ceb51c557336edde7e6ccf6463691a2f253/rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad", size = 547640 },
{ url = "https://files.pythonhosted.org/packages/ab/44/4f61d64dfed98cc71623f3a7fcb612df636a208b4b2c6611eaa985e130a9/rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58", size = 525555 },
{ url = "https://files.pythonhosted.org/packages/35/f2/a862d81eacb21f340d584cd1c749c289979f9a60e9229f78bffc0418a199/rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0", size = 199338 },
{ url = "https://files.pythonhosted.org/packages/cc/ec/77d0674f9af4872919f3738018558dd9d37ad3f7ad792d062eadd4af7cba/rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c", size = 213585 },
{ url = "https://files.pythonhosted.org/packages/89/b7/f9682c5cc37fcc035f4a0fc33c1fe92ec9cbfdee0cdfd071cf948f53e0df/rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6", size = 321468 },
{ url = "https://files.pythonhosted.org/packages/b8/ad/fc82be4eaceb8d444cb6fc1956ce972b3a0795104279de05e0e4131d0a47/rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b", size = 313062 },
{ url = "https://files.pythonhosted.org/packages/0e/1c/6039e80b13a08569a304dc13476dc986352dca4598e909384db043b4e2bb/rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739", size = 370168 },
{ url = "https://files.pythonhosted.org/packages/dc/c9/5b9aa35acfb58946b4b785bc8e700ac313669e02fb100f3efa6176a83e81/rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c", size = 371376 },
{ url = "https://files.pythonhosted.org/packages/7b/dd/0e0dbeb70d8a5357d2814764d467ded98d81d90d3570de4fb05ec7224f6b/rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee", size = 397200 },
{ url = "https://files.pythonhosted.org/packages/e4/da/a47d931eb688ccfd77a7389e45935c79c41e8098d984d87335004baccb1d/rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96", size = 426824 },
{ url = "https://files.pythonhosted.org/packages/0f/f7/a59a673594e6c2ff2dbc44b00fd4ecdec2fc399bb6a7bd82d612699a0121/rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4", size = 357967 },
{ url = "https://files.pythonhosted.org/packages/5f/61/3ba1905396b2cb7088f9503a460b87da33452da54d478cb9241f6ad16d00/rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef", size = 378905 },
{ url = "https://files.pythonhosted.org/packages/08/31/6d0df9356b4edb0a3a077f1ef714e25ad21f9f5382fc490c2383691885ea/rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821", size = 546348 },
{ url = "https://files.pythonhosted.org/packages/ae/15/d33c021de5cb793101df9961c3c746dfc476953dbbf5db337d8010dffd4e/rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940", size = 553152 },
{ url = "https://files.pythonhosted.org/packages/70/2d/5536d28c507a4679179ab15aa0049440e4d3dd6752050fa0843ed11e9354/rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174", size = 528807 },
{ url = "https://files.pythonhosted.org/packages/e3/62/7ebe6ec0d3dd6130921f8cffb7e34afb7f71b3819aa0446a24c5e81245ec/rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139", size = 200993 },
{ url = "https://files.pythonhosted.org/packages/ec/2f/b938864d66b86a6e4acadefdc56de75ef56f7cafdfd568a6464605457bd5/rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585", size = 214458 },
{ url = "https://files.pythonhosted.org/packages/99/32/43b919a0a423c270a838ac2726b1c7168b946f2563fd99a51aaa9692d00f/rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29", size = 321465 },
{ url = "https://files.pythonhosted.org/packages/58/a9/c4d899cb28e9e47b0ff12462e8f827381f243176036f17bef9c1604667f2/rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91", size = 312900 },
{ url = "https://files.pythonhosted.org/packages/8f/90/9e51670575b5dfaa8c823369ef7d943087bfb73d4f124a99ad6ef19a2b26/rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24", size = 370973 },
{ url = "https://files.pythonhosted.org/packages/fc/c1/523f2a03f853fc0d4c1acbef161747e9ab7df0a8abf6236106e333540921/rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7", size = 370890 },
{ url = "https://files.pythonhosted.org/packages/51/ca/2458a771f16b0931de4d384decbe43016710bc948036c8f4562d6e063437/rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9", size = 397174 },
{ url = "https://files.pythonhosted.org/packages/00/7d/6e06807f6305ea2408b364efb0eef83a6e21b5e7b5267ad6b473b9a7e416/rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8", size = 426449 },
{ url = "https://files.pythonhosted.org/packages/8c/d1/6c9e65260a819a1714510a7d69ac1d68aa23ee9ce8a2d9da12187263c8fc/rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879", size = 357698 },
{ url = "https://files.pythonhosted.org/packages/5d/fb/ecea8b5286d2f03eec922be7173a03ed17278944f7c124348f535116db15/rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f", size = 378530 },
{ url = "https://files.pythonhosted.org/packages/e3/e3/ac72f858957f52a109c588589b73bd2fad4a0fc82387fb55fb34aeb0f9cd/rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c", size = 545753 },
{ url = "https://files.pythonhosted.org/packages/b2/a4/a27683b519d5fc98e4390a3b130117d80fd475c67aeda8aac83c0e8e326a/rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2", size = 552443 },
{ url = "https://files.pythonhosted.org/packages/a1/ed/c074d248409b4432b1ccb2056974175fa0af2d1bc1f9c21121f80a358fa3/rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57", size = 528380 },
{ url = "https://files.pythonhosted.org/packages/d5/bd/04caf938895d2d78201e89c0c8a94dfd9990c34a19ff52fb01d0912343e3/rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a", size = 200540 },
{ url = "https://files.pythonhosted.org/packages/95/cc/109eb8b9863680411ae703664abacaa035820c7755acc9686d5dd02cdd2e/rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2", size = 214111 },
{ url = "https://files.pythonhosted.org/packages/a1/55/228f6d9a8c6940c8d5e49db5e0434ffcbad669c33509ac39cb0af061b0fa/rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22", size = 319496 },
{ url = "https://files.pythonhosted.org/packages/68/61/074236253586feb550954f8b4359d38eefb45bafcbbb7d2e74062a82f386/rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789", size = 311837 },
{ url = "https://files.pythonhosted.org/packages/03/67/ed6c2fe076bf78296934d4356145fedf3c7c2f8d490e099bcf6f31794dc0/rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5", size = 367819 },
{ url = "https://files.pythonhosted.org/packages/30/25/4a9e7b89b6760ac032f375cb236e4f8e518ad1fad685c40b6a9752056d6f/rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2", size = 368322 },
{ url = "https://files.pythonhosted.org/packages/67/17/0255bb0e564517b53343ea672ebec9fb7ad40e9083ca09a4080fbc986bb9/rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c", size = 395552 },
{ url = "https://files.pythonhosted.org/packages/af/6e/77c65ccb0d7cdc39ec2be19b918a4d4fe9e2d2a1c5cab36745b36f2c1e59/rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de", size = 433735 },
{ url = "https://files.pythonhosted.org/packages/04/d8/e73d56b1908a6c0e3e5982365eb293170cd458cc25a19363f69c76e00fd2/rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda", size = 355542 },
{ url = "https://files.pythonhosted.org/packages/47/df/e72c79053b0c882b818bfd8f0ed1f1ace550bc9cdba27165cb73dddb9394/rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580", size = 373644 },
{ url = "https://files.pythonhosted.org/packages/7f/00/3e16cb08c0cc6a233f0f61e4d009e3098cbe280ec975d14f28935bd15316/rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b", size = 543139 },
{ url = "https://files.pythonhosted.org/packages/41/71/799c6b6f6031ed535f22fcf6802601cc7f981842bd28007bb7bb4bd10b2f/rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420", size = 548007 },
{ url = "https://files.pythonhosted.org/packages/53/58/ad03eb6718e814fa045198c72d45d2ae60180eb48338f22c9fa34bd89964/rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b", size = 526102 },
{ url = "https://files.pythonhosted.org/packages/78/99/a52e5b460f2311fc8ee75ff769e8d67e76208947180eacb4f153af2d9967/rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7", size = 199391 },
{ url = "https://files.pythonhosted.org/packages/0c/7d/fd42a27fe392a69faf4a5e635870fc425edcb998485ee73afbc734ecef16/rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364", size = 213205 },
{ url = "https://files.pythonhosted.org/packages/06/39/bf1f664c347c946ef56cecaa896e3693d91acc741afa78ebb3fdb7aba08b/rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045", size = 319444 },
{ url = "https://files.pythonhosted.org/packages/c1/71/876135d3cb90d62468540b84e8e83ff4dc92052ab309bfdea7ea0b9221ad/rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc", size = 311699 },
{ url = "https://files.pythonhosted.org/packages/f7/da/8ccaeba6a3dda7467aebaf893de9eafd56275e2c90773c83bf15fb0b8374/rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02", size = 367825 },
{ url = "https://files.pythonhosted.org/packages/04/b6/02a54c47c178d180395b3c9a8bfb3b93906e08f9acf7b4a1067d27c3fae0/rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92", size = 369046 },
{ url = "https://files.pythonhosted.org/packages/a7/64/df4966743aa4def8727dc13d06527c8b13eb7412c1429def2d4701bee520/rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d", size = 395896 },
{ url = "https://files.pythonhosted.org/packages/6f/d9/7ff03ff3642c600f27ff94512bb158a8d815fea5ed4162c75a7e850d6003/rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855", size = 432427 },
{ url = "https://files.pythonhosted.org/packages/b8/c6/e1b886f7277b3454e55e85332e165091c19114eecb5377b88d892fd36ccf/rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511", size = 355403 },
{ url = "https://files.pythonhosted.org/packages/e2/62/e26bd5b944e547c7bfd0b6ca7e306bfa430f8bd298ab72a1217976a7ca8d/rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51", size = 374491 },
{ url = "https://files.pythonhosted.org/packages/c3/92/93c5a530898d3a5d1ce087455071ba714b77806ed9ffee4070d0c7a53b7e/rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075", size = 543622 },
{ url = "https://files.pythonhosted.org/packages/01/9e/d68fba289625b5d3c9d1925825d7da716fbf812bda2133ac409021d5db13/rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60", size = 548558 },
{ url = "https://files.pythonhosted.org/packages/bf/d6/4b2fad4898154365f0f2bd72ffd190349274a4c1d6a6f94f02a83bb2b8f1/rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344", size = 525753 },
{ url = "https://files.pythonhosted.org/packages/d2/ea/6f121d1802f3adae1981aea4209ea66f9d3c7f2f6d6b85ef4f13a61d17ef/rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989", size = 213529 },
{ url = "https://files.pythonhosted.org/packages/0a/6f/7ab47005469f0d73dad89d29b733e3555d454a45146c30f5628242e56d33/rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e", size = 320800 },
{ url = "https://files.pythonhosted.org/packages/cc/a1/bef9e0ef30f89c7516559ca7acc40e8ae70397535a0b1a4535a4a01d9ed0/rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c", size = 312001 },
{ url = "https://files.pythonhosted.org/packages/31/44/9093c5dca95ee463c3669651e710af182eb6f9cd83626b15a2ebde2247b1/rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03", size = 369279 },
{ url = "https://files.pythonhosted.org/packages/6f/ac/0c36e067681fa3fe4c60a9422b011ec0ccc80c1e124f5210951f7982e887/rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921", size = 369716 },
{ url = "https://files.pythonhosted.org/packages/6b/78/8896e08625d46ea5bfdd526ee688b91eeafecbc3cf7223612c82ed77905b/rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab", size = 396708 },
{ url = "https://files.pythonhosted.org/packages/24/5f/d865ae460e47e46fd2b489f2aceed34439bd8f18a1ff414c299142e0e22a/rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5", size = 433356 },
{ url = "https://files.pythonhosted.org/packages/bd/8b/04031937ffa565021f934a9acf44bb6b1b60ea19fa9e58950b32357e85a1/rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f", size = 356157 },
{ url = "https://files.pythonhosted.org/packages/3a/64/1f0471b1e688704a716e07340b85f4145109359951feb08676a1f3b8cec4/rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1", size = 374826 },
{ url = "https://files.pythonhosted.org/packages/73/4e/082c0c5eba463e29dff1c6b49557f6ad0d6faae4b46832fa9c1e5b69b7ba/rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074", size = 544549 },
{ url = "https://files.pythonhosted.org/packages/cd/ee/f4af0a62d1ba912c4a3a7f5ec04350946ddd59017f3f3d1c227b20ddf558/rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08", size = 549245 },
{ url = "https://files.pythonhosted.org/packages/59/42/34601dc773be86a85a9ca47f68301a69fdb019aaae0c1426813f265f5ac0/rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec", size = 526722 },
{ url = "https://files.pythonhosted.org/packages/ff/4f/280745d5180c9d78df6b53b6e8b65336f8b6adeb958a8fd19c749fded637/rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8", size = 214379 },
]
[[package]]
name = "six"
version = "1.16.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 },
]
[[package]]
name = "ssz"
version = "0.5.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "eth-utils" },
{ name = "lru-dict" },
{ name = "pyrsistent" },
]
sdist = { url = "https://files.pythonhosted.org/packages/8b/01/1cc59fe2b4eb6c424cdbd6f54cce5333c622178789b6666face4eb4f385d/ssz-0.5.0.tar.gz", hash = "sha256:5e0fe0483c5c9bdf3ea0fa957986b48ca34c784af57e39257863dd3743e20861", size = 49256 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a3/18/2f30c6e80dc6fc799399f8da2907a401ec5c21d9ed4553cc2079ca427deb/ssz-0.5.0-py3-none-any.whl", hash = "sha256:111dec40bee7cb7c3d52fe621a2247d5420ab999ffc0cbecb470782c28b56414", size = 44413 },
]
[[package]]
name = "tomli"
version = "2.0.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f", size = 15164 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", size = 12757 },
]
[[package]]
name = "toolz"
version = "0.12.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/3e/bf/5e12db234df984f6df3c7f12f1428aa680ba4e101f63f4b8b3f9e8d2e617/toolz-0.12.1.tar.gz", hash = "sha256:ecca342664893f177a13dac0e6b41cbd8ac25a358e5f215316d43e2100224f4d", size = 66550 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/8a/d82202c9f89eab30f9fc05380daae87d617e2ad11571ab23d7c13a29bb54/toolz-0.12.1-py3-none-any.whl", hash = "sha256:d22731364c07d72eea0a0ad45bafb2c2937ab6fd38a3507bf55eae8744aa7d85", size = 56121 },
]
[[package]]
name = "typing-extensions"
version = "4.12.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
]

View File

@@ -9,6 +9,10 @@ updates:
directory: "/"
schedule:
interval: "weekly"
groups:
pydantic-deps:
patterns:
- "pydantic*"
- package-ecosystem: "docker"
directory: "/"
schedule:

View File

@@ -21,7 +21,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, ubuntu-22.04-arm64, macos-13, macos-latest, windows-latest]
os: [ubuntu-22.04, ubuntu-22.04-arm, macos-13, macos-latest, windows-latest, windows-11-arm]
python-version: ["3.12"]
steps:
- uses: actions/checkout@v4
@@ -30,7 +30,21 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Setup variables (Linux & macOS)
- name: Install rustup (Windows 11 ARM64)
if: matrix.os == 'windows-11-arm'
shell: pwsh
run: |
Invoke-WebRequest -Uri "https://static.rust-lang.org/rustup/dist/aarch64-pc-windows-msvc/rustup-init.exe" -OutFile rustup-init.exe
.\rustup-init.exe --default-toolchain none -y
"$env:USERPROFILE\.cargo\bin" | Out-File -Append -Encoding ascii $env:GITHUB_PATH
"CARGO_HOME=$env:USERPROFILE\.cargo" | Out-File -Append -Encoding ascii $env:GITHUB_ENV
- name: Install Rust (Windows 11 ARM64)
if: matrix.os == 'windows-11-arm'
shell: pwsh
run: |
rustup install stable
rustup target add aarch64-pc-windows-msvc
- name: Set up variables (Linux & macOS)
if: ${{ startsWith(matrix.os, 'ubuntu-') || startsWith(matrix.os, 'macos-') }}
env:
MATRIX_OS: '${{ matrix.os }}'
@@ -81,7 +95,7 @@ jobs:
if: ${{ startsWith(matrix.os, 'ubuntu-') || startsWith(matrix.os, 'macos-') }}
run: |
python -m pip install --upgrade pip
pip install -r "${BUILD_CONFIGS_PATH}"/requirements.txt
pip install -r "${BUILD_CONFIGS_PATH}"/requirements.txt -r requirements.txt
pyinstaller --distpath ./"${BUILD_FILE_NAME}" "${BUILD_CONFIGS_PATH}"/build.spec
export ARCHIVE_FILE_NAME="${BUILD_FILE_NAME}".tar.gz
echo "ARCHIVE_FILE_NAME=${ARCHIVE_FILE_NAME}" >> "$GITHUB_ENV"
@@ -93,7 +107,7 @@ jobs:
if: ${{ startsWith(matrix.os, 'windows-') }}
run: |
python -m pip install --upgrade pip
pip install -r build_configs/windows/requirements.txt
pip install -r build_configs/windows/requirements.txt -r requirements.txt
pyinstaller --distpath $env:BUILD_FILE_NAME .\build_configs\windows\build.spec
$env:ZIP_FILE_NAME = ($env:BUILD_FILE_NAME + ".zip")
echo ("ZIP_FILE_NAME=" + $env:ZIP_FILE_NAME) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
@@ -103,7 +117,7 @@ jobs:
$env:CHECKSUM_FILE_NAME_PATH = ("output\artifacts\" + $env:ZIP_FILE_NAME + ".sha256")
certUtil -hashfile $env:ZIP_FILE_NAME SHA256 | findstr /i /v "SHA256" | findstr /i /v "CertUtil" > $env:CHECKSUM_FILE_NAME_PATH
- name: Generate artifacts attestation
uses: actions/attest-build-provenance@v1
uses: actions/attest-build-provenance@v2
with:
subject-path: output/artifacts/*
- name: Archive production artifacts
@@ -127,7 +141,7 @@ jobs:
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
# This pinned action came from docker/login-action@v3, releases can be found on https://github.com/docker/login-action/releases
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -136,25 +150,34 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
# This pinned action came from docker/metadata-action@v5, releases can be found on https://github.com/docker/metadata-action/releases
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Set up Qemu for multi-arch build
- name: Set up Qemu
# This pinned action came from docker/setup-qemu-action@v3, releases can be found on https://github.com/docker/setup-qemu-action/releases
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392
# Set up buildx for multi-arch build
- name: Set up Docker Buildx
# This pinned action came from docker/setup-buildx-action@v3, releases can be found on https://github.com/docker/setup-buildx-action/releases
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
id: push
# This pinned action came from docker/build-push-action@v6, releases can be found on https://github.com/docker/build-push-action/releases
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
@@ -188,7 +211,7 @@ jobs:
var tagName = '';
var dockerVersion = '';
if (context.eventName == 'push') {
const tagRegex = /(?:refs\/tags\/)?(v\d+\.\d+\.\d+)$/;
const tagRegex = /(?:refs\/tags\/)?(v\d+\.\d+\.\d+(?:-\w+)?)$/;
const match = context.ref.match(tagRegex);
if (match) {

View File

@@ -10,6 +10,8 @@ on:
jobs:
completed-coverage:
runs-on: ubuntu-latest
permissions:
contents: read
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'

View File

@@ -1,6 +1,9 @@
name: docs
run-name: ${{ github.actor }} is running docs
permissions:
contents: write
on:
push:
branches:

View File

@@ -1,5 +1,8 @@
name: ci-runner
run-name: ${{ github.actor }} is testing and measuring code quality
permissions:
contents: read
actions: read
on:
push:
branches: [main]
@@ -23,7 +26,7 @@ jobs:
- name: Run type checker
run: python -m mypy --config-file mypy.ini -p ethstaker_deposit
- name: Run linter
run: flake8 --config=flake8.ini ./ethstaker_deposit ./tests
run: ruff check ./ethstaker_deposit ./tests
- name: Setup Node.js
uses: actions/setup-node@v4
with:
@@ -38,12 +41,20 @@ jobs:
if: |
contains(github.event.pull_request.labels.*.name, 'run-tests') ||
github.event_name == 'push'
permissions:
contents: read
actions: write
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm64, macos-13, macos-latest, windows-latest]
os: [ubuntu-latest, ubuntu-24.04-arm, macos-13, macos-latest, windows-latest, windows-11-arm]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
exclude:
- os: windows-11-arm
python-version: "3.9"
- os: windows-11-arm
python-version: "3.10"
steps:
- uses: actions/checkout@v4
- name: Set up Python
@@ -51,6 +62,20 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install rustup (Windows 11 ARM64)
if: matrix.os == 'windows-11-arm'
shell: pwsh
run: |
Invoke-WebRequest -Uri "https://static.rust-lang.org/rustup/dist/aarch64-pc-windows-msvc/rustup-init.exe" -OutFile rustup-init.exe
.\rustup-init.exe --default-toolchain none -y
"$env:USERPROFILE\.cargo\bin" | Out-File -Append -Encoding ascii $env:GITHUB_PATH
"CARGO_HOME=$env:USERPROFILE\.cargo" | Out-File -Append -Encoding ascii $env:GITHUB_ENV
- name: Install Rust (Windows 11 ARM64)
if: matrix.os == 'windows-11-arm'
shell: pwsh
run: |
rustup install stable
rustup target add aarch64-pc-windows-msvc
- name: Install dependencies
run: |
python -m pip install --upgrade pip
@@ -69,6 +94,9 @@ jobs:
coverage-combine:
needs: ci-runner
if: github.event_name == 'pull_request'
permissions:
contents: read
actions: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

View File

@@ -1,25 +1,23 @@
repos:
- repo: https://github.com/pycqa/flake8
rev: '7.1.1'
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.2
hooks:
- id: flake8
files: ^(ethstaker_deposit|tests)/
args: [--config, flake8.ini]
- id: ruff
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.11.2'
rev: v1.14.1
hooks:
- id: mypy
additional_dependencies:
- click==8.1.7
- eth-typing==5.0.0
- eth-utils==5.0.0
- pycryptodome==3.20.0
- click==8.1.8
- eth-typing==5.1.0
- eth-utils==5.1.0
- pycryptodome==3.21.0
- py-ecc==7.0.1
- ssz==0.5.0
- ssz==0.5.1
files: ^ethstaker_deposit/
args: [--config-file, mypy.ini]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: 'v4.6.0'
rev: v5.0.0
hooks:
- id: check-json
files: ^ethstaker_deposit/intl

View File

@@ -1,5 +1,5 @@
# This image is from python:3.12.7-slim-bookworm (https://hub.docker.com/_/python)
FROM python@sha256:032c52613401895aa3d418a4c563d2d05f993bc3ecc065c8f4e2280978acd249
# This image is from python:3.12.9-slim-bookworm (https://hub.docker.com/_/python)
FROM python@sha256:aaa3f8cb64dd64e5f8cb6e58346bdcfa410a108324b0f28f1a7cc5964355b211
WORKDIR /app

View File

@@ -9,7 +9,7 @@ help:
@echo "venv_deposit - run deposit cli with venv"
@echo "venv_build - install basic dependencies with venv"
@echo "venv_build_test - install testing dependencies with venv"
@echo "venv_lint - check style with flake8 and mypy with venv"
@echo "venv_lint - check style with ruff and mypy with venv"
@echo "venv_test - run tests with venv"
clean:
@@ -36,7 +36,7 @@ venv_test: venv_build_test
$(VENV_ACTIVATE) && python -m pytest ./tests
venv_lint: venv_build_test
$(VENV_ACTIVATE) && flake8 --config=flake8.ini ./ethstaker_deposit ./tests && mypy --config-file mypy.ini -p ethstaker_deposit
$(VENV_ACTIVATE) && ruff check ./ethstaker_deposit ./tests && mypy --config-file mypy.ini -p ethstaker_deposit
venv_deposit: venv_build
$(VENV_ACTIVATE) && python -m ethstaker_deposit $(filter-out $@,$(MAKECMDGOALS))

View File

@@ -10,14 +10,14 @@
## Introduction
`ethstaker-deposit-cli` is a tool for creating [EIP-2335 format](https://eips.ethereum.org/EIPS/eip-2335) BLS12-381 keystores and a corresponding `deposit_data*.json` file for [Ethereum Staking Launchpad](https://github.com/ethereum/staking-launchpad). One can also provide a keystore file to generate a `signed_exit_transaction*.json` file to be broadcast at a later date to exit a validator.
`ethstaker-deposit-cli` is a tool for creating [EIP-2335 format](https://eips.ethereum.org/EIPS/eip-2335) BLS12-381 keystores and a corresponding `deposit_data*.json` file for [Ethereum Staking Launchpad](https://github.com/ethereum/staking-launchpad) or the [Gnosis Beacon Chain deposit UI](https://github.com/gnosischain/gbc-deposit-ui/). One can also provide a keystore file to generate a `signed_exit_transaction*.json` file to be broadcast at a later date to exit a validator.
- **Warning: Please generate your keystores on your own safe, completely offline device.**
- **Warning: Please backup your mnemonic, keystores, and password securely.**
Please read [Launchpad Validator FAQs](https://launchpad.ethereum.org/faq#keys) before generating the keys.
You can find the audit report by Trail of Bits of the original staking-deposit-cli [here](https://github.com/trailofbits/publications/blob/master/reviews/ETH2DepositCLI.pdf). The audit of the updated ethstaker-deposit-cli is forthcoming.
You can read [the security assessment report by Trail of Bits](https://github.com/trailofbits/publications/blob/master/reviews/2024-12-ethstaker-depositcli-securityreview.pdf) that was completed on December 13, 2024. You can find the security assessment report by Trail of Bits of the original staking-deposit-cli project [here](https://github.com/trailofbits/publications/blob/master/reviews/ETH2DepositCLI.pdf).
## Canonical Deposit Contract and Launchpad
@@ -29,6 +29,13 @@ Depositing to the wrong address **will** lose you your ETH.
- Ethereum mainnet
- Deposit address: [0x00000000219ab540356cBB839Cbe05303d7705Fa](https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa)
- [Launchpad](https://launchpad.ethereum.org/)
- Ethereum Holešky (Holešovice) testnet
- Deposit address: [0x4242424242424242424242424242424242424242](https://holesky.etherscan.io/address/0x4242424242424242424242424242424242424242)
- [Launchpad](https://holesky.launchpad.ethereum.org/)
- Ethereum Hoodi testnet
- Deposit address: [0x00000000219ab540356cBB839Cbe05303d7705Fa](https://hoodi.etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa)
- [Launchpad](https://hoodi.launchpad.ethereum.org/)
- Gnosis mainnet
- Deposit address: [0x0B98057eA310F4d31F2a452B414647007d1645d9](https://gnosis.blockscout.com/address/0x0B98057eA310F4d31F2a452B414647007d1645d9)
- [Gnosis Beacon Chain deposit UI](https://deposit.gnosischain.com/)
- Chiado testnet
- Deposit address: [0xb97036A26259B7147018913bD58a774cf91acf25](https://gnosis-chiado.blockscout.com/address/0xb97036A26259B7147018913bD58a774cf91acf25)
- [Gnosis Beacon Chain deposit UI](https://deposit.gnosischain.com/)

View File

@@ -2,11 +2,12 @@
## Supported Versions
We are still in active development. We will support the latest release with security updates as we find them.
We will support the latest release with security updates as we find them.
| Version | Supported |
| ------- | ------------------ |
| 0.x.x | :white_check_mark: |
| 1.x.x | :white_check_mark: |
| 0.x.x | Deprecated |
## Reporting a Vulnerability

View File

@@ -1,12 +1,4 @@
# Install the requirements for the program
-r ../../requirements.txt
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --allow-unsafe --generate-hashes --no-annotate --output-file=build_configs/common/requirements.txt build_configs/common/requirements.in
#
altgraph==0.17.4 \
--hash=sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406 \
--hash=sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff
@@ -111,6 +103,6 @@ zipp==3.20.1 \
--hash=sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b
# The following packages are considered to be unsafe in a requirements file:
setuptools==74.0.0 \
--hash=sha256:0274581a0037b638b9fc1c6883cc71c0210865aaa76073f7882376b641b84e8f \
--hash=sha256:a85e96b8be2b906f3e3e789adec6a9323abf79758ecfa3065bd740d81158b11e
setuptools==78.1.1 \
--hash=sha256:c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561 \
--hash=sha256:fcc17fd9cd898242f6b4adfaca46137a9edef687f43e6f78469692a5e70d851d

View File

@@ -2,7 +2,7 @@
A deposit data file is created when calling the **[new-mnemonic](new_mnemonic.md)**, the **[existing-mnemonic](existing_mnemonic.md)** or the **[partial-deposit](partial_deposit.md)** command.
The deposit data file is a JSON file that contains a list of deposits that is mostly used for the [Ethereum Staking Launchpad](https://github.com/ethereum/staking-launchpad). It is loosly based on [the DepositData structure](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#depositdata) and the [deposit function](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md#deposit-function) from the [deposit smart contract](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md).
The deposit data file is a JSON file that contains a list of deposits that is mostly used for the [Ethereum Staking Launchpad](https://github.com/ethereum/staking-launchpad). It is loosely based on [the DepositData structure](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#depositdata) and the [deposit function](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md#deposit-function) from the [deposit smart contract](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md).
## Format
Each deposit from the list will contain this structure:
@@ -56,4 +56,4 @@ Each deposit from the list will contain this structure:
"deposit_cli_version":"2.7.0"
}
]
```
```

View File

@@ -7,7 +7,7 @@ Uses an existing BIP-39 mnemonic phrase for key generation.
## Optional Arguments
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis', or 'chiado'.
- **`--mnemonic`**: The mnemonic you used to create withdrawal credentials. <span class="warning"></span>
@@ -31,7 +31,7 @@ Uses an existing BIP-39 mnemonic phrase for key generation.
- **`--folder`**: The folder where keystore and deposit data files will be saved.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version, genesis_validator_root, multiplier, min_activation_amount and min_deposit_amount.
## Output files
A successful call to this command will result in one or many [keystore files](keystore_file.md) created, one per validator created, and one [deposit data file](deposit_data_file.md) created. The amount for each deposit in the deposit data file should always be 32 Ethers (`32000000000` in GWEI) with this command.

View File

@@ -7,7 +7,7 @@ Creates an exit transaction using a keystore file.
## Optional Arguments
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis', or 'chiado'.
- **`--keystore`**: The keystore file associating with the validator you wish to exit.
@@ -19,7 +19,7 @@ Creates an exit transaction using a keystore file.
- **`--output_folder`**: The folder path for the `signed_exit_transaction-*` JSON file.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version, genesis_validator_root, multiplier, min_activation_amount and min_deposit_amount.
## Output files
A successful call to this command will result in one [Signed Exit Transaction file](signed_exit_transaction_file.md) created.

View File

@@ -7,7 +7,7 @@ Creates an exit transaction using a mnemonic phrase.
## Optional Arguments
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis', or 'chiado'.
- **`--mnemonic`**: The mnemonic you used during key generation. <span class="warning"></span>
@@ -23,7 +23,7 @@ Creates an exit transaction using a mnemonic phrase.
- **`--output_folder`**: The folder path for the `signed_exit_transaction-*` JSON file.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version, genesis_validator_root, multiplier, min_activation_amount and min_deposit_amount.
## Output files
A successful call to this command will result in one or more [Signed Exit Transaction files](signed_exit_transaction_file.md) created.

View File

@@ -9,7 +9,7 @@ Generates a BLS to execution address change message. This is used to add a withd
- **`--bls_to_execution_changes_folder`**: The path to store the change JSON file.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis', or 'chiado'.
- **`--mnemonic`**: The mnemonic you used to create withdrawal credentials. <span class="warning"></span>
@@ -25,7 +25,7 @@ Generates a BLS to execution address change message. This is used to add a withd
- **`--withdrawal_address`**: The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version, genesis_validator_root, multiplier, min_activation_amount and min_deposit_amount.
## Output files
A successful call to this command will result in one [BLS to Execution Change file](bls_to_execution_change_file.md) created.

View File

@@ -11,7 +11,7 @@ Signs a withdrawal credential update message using the provided keystore. This s
## Optional Arguments
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis', or 'chiado'.
- **`--keystore`**: The keystore file associating with the validator you wish to sign with. This keystore file should match the provided validator index.
@@ -23,7 +23,7 @@ Signs a withdrawal credential update message using the provided keystore. This s
- **`--output_folder`**: The folder path for the `bls_to_execution_change_keystore_signature-*` JSON file.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version, genesis_validator_root, multiplier, min_activation_amount and min_deposit_amount.
## Output files
A successful call to this command will result in one [BLS to Execution Change Keystore file](bls_to_execution_change_keystore_file.md) created.

View File

@@ -1,6 +1,10 @@
# Welcome to the `ethstaker-deposit-cli`!
The [`ethstaker-deposit-cli`](https://github.com/eth-educators/ethstaker-deposit-cli) is a command-line tool forked from Ethereum's [`staking-deposit-cli`](https://github.com/ethereum/staking-deposit-cli) with more functionality and improved performance.
The [`ethstaker-deposit-cli`](https://github.com/eth-educators/ethstaker-deposit-cli) is a command-line tool used to generate validator keys forked from Ethereum's [`staking-deposit-cli`](https://github.com/ethereum/staking-deposit-cli) with more functionality and improved performance.
## Security reports
You can read [the security assessment report by Trail of Bits](https://github.com/trailofbits/publications/blob/master/reviews/2024-12-ethstaker-depositcli-securityreview.pdf) that was completed on December 13, 2024. You can find the security assessment report by Trail of Bits of the original staking-deposit-cli project [here](https://github.com/trailofbits/publications/blob/master/reviews/ETH2DepositCLI.pdf).
## Important Concerns

View File

@@ -72,6 +72,13 @@ On Windows, you'll need:
pre-commit install
```
If you are using `uv`, you can also install it using:
```console
uv sync --all-extras
uv run pre-commit install
```
**To execute tests, you will need to install the test dependencies**:
```sh
python3 -m pip install -r requirements.txt -r requirements_test.txt

View File

@@ -9,7 +9,7 @@ Generates a new BIP-39 mnemonic along with validator keystore and deposit files
- **`--mnemonic_language`**: The language of the BIP-39 mnemonic. Options are: 'chinese_simplified', 'chinese_traditional', 'czech', 'english', 'french', 'italian', 'japanese', 'korean', 'portuguese', 'spanish'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis', or 'chiado'.
- **`--num_validators`**: Number of validators to create.
@@ -25,7 +25,7 @@ Generates a new BIP-39 mnemonic along with validator keystore and deposit files
- **`--folder`**: The folder where keystore and deposit data files will be saved.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version, genesis_validator_root, multiplier, min_activation_amount and min_deposit_amount.
## Output files
A successful call to this command will result in one or many [keystore files](keystore_file.md) created, one per validator created, and one [deposit data file](deposit_data_file.md) created. The amount for each deposit in the deposit data file should always be 32 Ethers (`32000000000` in GWEI) with this command.

View File

@@ -8,7 +8,7 @@ If you wish to create a validator with 0x00 credentials, you must use the **[new
## Optional Arguments
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'hoodi', 'ephemery', 'gnosis', or 'chiado'.
- **`--keystore`**: The keystore file associating with the validator you wish to deposit to.
@@ -22,7 +22,7 @@ If you wish to create a validator with 0x00 credentials, you must use the **[new
- **`--output_folder`**: The folder path for the `deposit-*` JSON file.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version, genesis_validator_root, multiplier, min_activation_amount and min_deposit_amount.
## Output file
A successful call to this command will result in one [deposit data file](deposit_data_file.md) created.

View File

@@ -0,0 +1 @@
__version__ = '1.2.2'

View File

@@ -38,7 +38,8 @@ def load_mnemonic_arguments_decorator(function: Callable[..., Any]) -> Callable[
jit_option(
callback=lambda c, _, mnemonic:
captive_prompt_callback(
lambda mnemonic: validate_mnemonic(mnemonic=mnemonic, language=c.params.get('mnemonic_language')),
lambda mnemonic, _: validate_mnemonic(mnemonic=mnemonic,
language=c.params.get('mnemonic_language')),
prompt=lambda: load_text(['arg_mnemonic', 'prompt'], func='existing_mnemonic'),
prompt_if=prompt_if_none,
)(c, _, mnemonic),
@@ -49,7 +50,7 @@ def load_mnemonic_arguments_decorator(function: Callable[..., Any]) -> Callable[
),
jit_option(
callback=captive_prompt_callback(
lambda x: x,
lambda x, _: x,
lambda: load_text(['arg_mnemonic_password', 'prompt'], func='existing_mnemonic'),
lambda: load_text(['arg_mnemonic_password', 'confirm'], func='existing_mnemonic'),
lambda: load_text(['arg_mnemonic_password', 'mismatch'], func='existing_mnemonic'),
@@ -103,7 +104,7 @@ def validate_mnemonic_language(ctx: click.Context, param: Any, language: str) ->
@load_mnemonic_arguments_decorator
@jit_option(
callback=captive_prompt_callback(
lambda num: validate_int_range(num, 0, 2**32),
lambda num, _: validate_int_range(num, 0, 2**32),
lambda: load_text(['arg_validator_start_index', 'prompt'], func='existing_mnemonic'),
lambda: load_text(['arg_validator_start_index', 'confirm'], func='existing_mnemonic'),
prompt_if=prompt_if_none,

View File

@@ -42,7 +42,7 @@ FUNC_NAME = 'exit_transaction_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: closest_match(x, ALL_CHAIN_KEYS),
lambda x, _: closest_match(x, ALL_CHAIN_KEYS),
choice_prompt_func(
lambda: load_text(['arg_exit_transaction_keystore_chain', 'prompt'], func=FUNC_NAME),
ALL_CHAIN_KEYS
@@ -57,7 +57,7 @@ FUNC_NAME = 'exit_transaction_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda file: validate_keystore_file(file),
lambda file, _: validate_keystore_file(file),
lambda: load_text(['arg_exit_transaction_keystore_keystore', 'prompt'], func=FUNC_NAME),
prompt_if=prompt_if_none,
),
@@ -67,7 +67,7 @@ FUNC_NAME = 'exit_transaction_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: x,
lambda x, _: x,
lambda: load_text(['arg_exit_transaction_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
None,
lambda: load_text(['arg_exit_transaction_keystore_keystore_password', 'invalid'], func=FUNC_NAME),
@@ -80,7 +80,7 @@ FUNC_NAME = 'exit_transaction_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda num: validate_int_range(num, 0, 2**32),
lambda num, _: validate_int_range(num, 0, 2**32),
lambda: load_text(['arg_validator_index', 'prompt'], func=FUNC_NAME),
),
help=lambda: load_text(['arg_validator_index', 'help'], func=FUNC_NAME),

View File

@@ -31,6 +31,7 @@ from ethstaker_deposit.utils.validation import (
verify_signed_exit_json,
validate_devnet_chain_setting,
)
from ethstaker_deposit.utils.terminal import clear_terminal
def _credential_builder(kwargs: Dict[str, Any]) -> Credential:
@@ -57,7 +58,7 @@ FUNC_NAME = 'exit_transaction_mnemonic'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: closest_match(x, ALL_CHAIN_KEYS),
lambda x, _: closest_match(x, ALL_CHAIN_KEYS),
choice_prompt_func(
lambda: load_text(['arg_exit_transaction_mnemonic_chain', 'prompt'], func=FUNC_NAME),
ALL_CHAIN_KEYS
@@ -73,7 +74,7 @@ FUNC_NAME = 'exit_transaction_mnemonic'
@load_mnemonic_arguments_decorator
@jit_option(
callback=captive_prompt_callback(
lambda num: validate_int_range(num, 0, 2**32),
lambda num, _: validate_int_range(num, 0, 2**32),
lambda: load_text(['arg_exit_transaction_mnemonic_start_index', 'prompt'], func=FUNC_NAME),
),
default=0,
@@ -83,7 +84,7 @@ FUNC_NAME = 'exit_transaction_mnemonic'
)
@jit_option(
callback=captive_prompt_callback(
lambda validator_indices: validate_validator_indices(validator_indices),
lambda validator_indices, _: validate_validator_indices(validator_indices),
lambda: load_text(['arg_exit_transaction_mnemonic_indices', 'prompt'], func=FUNC_NAME),
),
help=lambda: load_text(['arg_exit_transaction_mnemonic_indices', 'help'], func=FUNC_NAME),
@@ -122,6 +123,9 @@ def exit_transaction_mnemonic(
**kwargs: Any) -> None:
folder = os.path.join(output_folder, DEFAULT_EXIT_TRANSACTION_FOLDER_NAME)
if not os.path.exists(folder):
os.mkdir(folder)
clear_terminal()
# Get chain setting
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
@@ -149,9 +153,6 @@ def exit_transaction_mnemonic(
credentials.append(credential)
bar.update(1)
if not os.path.exists(folder):
os.mkdir(folder)
transaction_filefolders = []
with click.progressbar(length=num_keys, # type: ignore[var-annotated]
label=load_text(['msg_exit_transaction_creation']),

View File

@@ -26,7 +26,7 @@ from ethstaker_deposit.utils.validation import (
)
from ethstaker_deposit.utils.constants import (
DEFAULT_BLS_TO_EXECUTION_CHANGES_FOLDER_NAME,
MIN_ACTIVATION_AMOUNT,
ETH2GWEI
)
from ethstaker_deposit.utils.click import (
captive_prompt_callback,
@@ -78,7 +78,7 @@ FUNC_NAME = 'generate_bls_to_execution_change'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: closest_match(x, ALL_CHAIN_KEYS),
lambda x, _: closest_match(x, ALL_CHAIN_KEYS),
choice_prompt_func(
lambda: load_text(['arg_chain', 'prompt'], func=FUNC_NAME),
ALL_CHAIN_KEYS
@@ -94,7 +94,7 @@ FUNC_NAME = 'generate_bls_to_execution_change'
@load_mnemonic_arguments_decorator
@jit_option(
callback=captive_prompt_callback(
lambda num: validate_int_range(num, 0, 2**32),
lambda num, _: validate_int_range(num, 0, 2**32),
lambda: load_text(['arg_validator_start_index', 'prompt'], func=FUNC_NAME),
),
default=0,
@@ -104,7 +104,7 @@ FUNC_NAME = 'generate_bls_to_execution_change'
)
@jit_option(
callback=captive_prompt_callback(
lambda validator_indices: validate_validator_indices(validator_indices),
lambda validator_indices, _: validate_validator_indices(validator_indices),
lambda: load_text(['arg_validator_indices', 'prompt'], func=FUNC_NAME),
),
help=lambda: load_text(['arg_validator_indices', 'help'], func=FUNC_NAME),
@@ -113,7 +113,7 @@ FUNC_NAME = 'generate_bls_to_execution_change'
)
@jit_option(
callback=captive_prompt_callback(
lambda bls_withdrawal_credentials_list:
lambda bls_withdrawal_credentials_list, _:
validate_bls_withdrawal_credentials_list(bls_withdrawal_credentials_list),
lambda: load_text(['arg_bls_withdrawal_credentials_list', 'prompt'], func=FUNC_NAME),
prompt_if=prompt_if_none,
@@ -124,7 +124,7 @@ FUNC_NAME = 'generate_bls_to_execution_change'
)
@jit_option(
callback=captive_prompt_callback(
lambda address: validate_withdrawal_address(None, None, address),
lambda address, _: validate_withdrawal_address(None, None, address),
lambda: load_text(['arg_withdrawal_address', 'prompt'], func=FUNC_NAME),
lambda: load_text(['arg_withdrawal_address', 'confirm'], func=FUNC_NAME),
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func=FUNC_NAME),
@@ -172,7 +172,7 @@ def generate_bls_to_execution_change(
)
num_validators = len(validator_indices)
amounts = [MIN_ACTIVATION_AMOUNT] * num_validators
amounts = [chain_setting.MIN_ACTIVATION_AMOUNT * ETH2GWEI] * num_validators
credentials = CredentialList.from_mnemonic(
mnemonic=mnemonic,

View File

@@ -50,7 +50,7 @@ FUNC_NAME = 'generate_bls_to_execution_change_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: closest_match(x, ALL_CHAIN_KEYS),
lambda x, _: closest_match(x, ALL_CHAIN_KEYS),
choice_prompt_func(
lambda: load_text(['arg_chain', 'prompt'], func=FUNC_NAME),
ALL_CHAIN_KEYS
@@ -65,7 +65,7 @@ FUNC_NAME = 'generate_bls_to_execution_change_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda file: validate_keystore_file(file),
lambda file, _: validate_keystore_file(file),
lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore', 'prompt'], func=FUNC_NAME),
prompt_if=prompt_if_none,
),
@@ -75,7 +75,7 @@ FUNC_NAME = 'generate_bls_to_execution_change_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: x,
lambda x, _: x,
lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
None,
lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore_password', 'invalid'], func=FUNC_NAME),
@@ -88,7 +88,7 @@ FUNC_NAME = 'generate_bls_to_execution_change_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda num: validate_int_range(num, 0, 2**32),
lambda num, _: validate_int_range(num, 0, 2**32),
lambda: load_text(['arg_validator_index', 'prompt'], func=FUNC_NAME),
),
help=lambda: load_text(['arg_validator_index', 'help'], func=FUNC_NAME),
@@ -97,7 +97,7 @@ FUNC_NAME = 'generate_bls_to_execution_change_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda address: validate_withdrawal_address(None, None, address, True),
lambda address, _: validate_withdrawal_address(None, None, address, True),
lambda: load_text(['arg_withdrawal_address', 'prompt'], func=FUNC_NAME),
lambda: load_text(['arg_withdrawal_address', 'confirm'], func=FUNC_NAME),
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func=FUNC_NAME),

View File

@@ -24,8 +24,7 @@ from ethstaker_deposit.utils.validation import (
)
from ethstaker_deposit.utils.constants import (
DEFAULT_VALIDATOR_KEYS_FOLDER_NAME,
MIN_ACTIVATION_AMOUNT,
ETH2GWEI,
ETH2GWEI
)
from ethstaker_deposit.utils.ascii_art import RHINO_0
from ethstaker_deposit.utils.click import (
@@ -50,9 +49,6 @@ from ethstaker_deposit.settings import (
)
min_activation_amount_eth = MIN_ACTIVATION_AMOUNT // ETH2GWEI
def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[..., Any]:
'''
This is a decorator that, when applied to a parent-command, implements the
@@ -61,7 +57,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
decorators = [
jit_option(
callback=captive_prompt_callback(
lambda num: validate_int_range(num, 1, 2**32),
lambda num, _: validate_int_range(num, 1, 2**32),
lambda: load_text(['num_validators', 'prompt'], func='generate_keys_arguments_decorator')
),
help=lambda: load_text(['num_validators', 'help'], func='generate_keys_arguments_decorator'),
@@ -76,7 +72,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
),
jit_option(
callback=captive_prompt_callback(
lambda x: closest_match(x, ALL_CHAIN_KEYS),
lambda x, _: closest_match(x, ALL_CHAIN_KEYS),
choice_prompt_func(
lambda: load_text(['chain', 'prompt'], func='generate_keys_arguments_decorator'),
ALL_CHAIN_KEYS
@@ -91,7 +87,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
),
jit_option(
callback=captive_prompt_callback(
validate_password_strength,
lambda password, _: validate_password_strength(password),
lambda: load_text(['keystore_password', 'prompt'], func='generate_keys_arguments_decorator'),
lambda: load_text(['keystore_password', 'confirm'], func='generate_keys_arguments_decorator'),
lambda: load_text(['keystore_password', 'mismatch'], func='generate_keys_arguments_decorator'),
@@ -105,7 +101,7 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
),
jit_option(
callback=captive_prompt_callback(
lambda address: validate_withdrawal_address(None, None, address),
lambda address, _: validate_withdrawal_address(None, None, address),
lambda: load_text(['arg_withdrawal_address', 'prompt'], func='generate_keys_arguments_decorator'),
lambda: load_text(['arg_withdrawal_address', 'confirm'], func='generate_keys_arguments_decorator'),
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func='generate_keys_arguments_decorator'),
@@ -119,26 +115,26 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
),
jit_option(
callback=captive_prompt_callback(
lambda value: validate_yesno(None, None, value),
lambda value, _: validate_yesno(None, None, value),
lambda: load_text(['arg_compounding', 'prompt'], func='generate_keys_arguments_decorator'),
default="False",
default='no',
prompt_if=prompt_if_other_exists('withdrawal_address'),
),
default=False,
default='no',
help=lambda: load_text(['arg_compounding', 'help'], func='generate_keys_arguments_decorator'),
param_decls='--compounding/--regular-withdrawal',
prompt=False, # the callback handles the prompt
type=bool,
show_default=True,
show_default='regular-withdrawal',
),
jit_option(
callback=captive_prompt_callback(
lambda amount: validate_deposit_amount(amount),
lambda: load_text(['arg_amount', 'prompt'], func='generate_keys_arguments_decorator'),
default=str(min_activation_amount_eth),
lambda amount, **kwargs: validate_deposit_amount(amount, **kwargs),
get_amount_prompt_from_template,
prompt_if=prompt_if_other_value('compounding', True),
default=get_default_amount,
prompt_marker="amount",
),
default=str(min_activation_amount_eth),
help=lambda: load_text(['arg_amount', 'help'], func='generate_keys_arguments_decorator'),
param_decls='--amount',
prompt=False, # the callback handles the prompt
@@ -163,22 +159,50 @@ def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[
return function
def get_amount_prompt_from_template() -> str:
ctx = click.get_current_context(silent=True)
chain = ctx.params.get('chain', 'mainnet') if ctx is not None else 'mainnet'
devnet_chain_setting = ctx.params.get('devnet_chain_setting', None)
if devnet_chain_setting is not None:
chain_setting = devnet_chain_setting
else:
chain_setting = get_chain_setting(chain)
min_deposit = chain_setting.MIN_DEPOSIT_AMOUNT
activation_amount = chain_setting.MIN_ACTIVATION_AMOUNT
template = load_text(['arg_amount', 'prompt'], func='generate_keys_arguments_decorator')
return template.format(min_deposit=min_deposit, activation_amount=activation_amount)
def get_default_amount() -> str:
ctx = click.get_current_context(silent=True)
chain = ctx.params.get('chain', 'mainnet') if ctx is not None else 'mainnet'
devnet_chain_setting = ctx.params.get('devnet_chain_setting', None)
if devnet_chain_setting is not None:
chain_setting = devnet_chain_setting
else:
chain_setting = get_chain_setting(chain)
return str(chain_setting.MIN_ACTIVATION_AMOUNT)
@click.command()
@click.pass_context
def generate_keys(ctx: click.Context, validator_start_index: int,
num_validators: int, folder: str, chain: str, keystore_password: str,
withdrawal_address: HexAddress, compounding: bool, amount: int, pbkdf2: bool,
withdrawal_address: HexAddress, compounding: bool, amount: float, pbkdf2: bool,
devnet_chain_setting: Optional[BaseChainSetting], **kwargs: Any) -> None:
mnemonic = ctx.obj['mnemonic']
mnemonic_password = ctx.obj['mnemonic_password']
if withdrawal_address is None or not compounding:
amount = MIN_ACTIVATION_AMOUNT
amounts = [amount] * num_validators
folder = os.path.join(folder, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME)
# Get chain setting
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
if withdrawal_address is None or not compounding:
amount = chain_setting.MIN_ACTIVATION_AMOUNT * ETH2GWEI
amounts = [amount] * num_validators
folder = os.path.join(folder, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME)
amounts = [amount * chain_setting.MULTIPLIER for amount in amounts]
if not os.path.exists(folder):
os.mkdir(folder)
clear_terminal()
@@ -202,7 +226,7 @@ def generate_keys(ctx: click.Context, validator_start_index: int,
deposits_file = credentials.export_deposit_data_json(folder=folder, timestamp=timestamp)
if not credentials.verify_keystores(keystore_filefolders=keystore_filefolders, password=keystore_password):
raise ValidationError(load_text(['err_verify_keystores']))
if not verify_deposit_data_json(deposits_file, credentials.credentials):
if not verify_deposit_data_json(deposits_file, credentials.credentials, chain_setting):
raise ValidationError(load_text(['err_verify_deposit']))
click.echo(load_text(['msg_creation_success']) + folder)
if not config.non_interactive:

View File

@@ -38,7 +38,7 @@ languages = get_first_options(MNEMONIC_LANG_OPTIONS)
@click.pass_context
@jit_option(
callback=captive_prompt_callback(
lambda mnemonic_language: fuzzy_reverse_dict_lookup(mnemonic_language, MNEMONIC_LANG_OPTIONS),
lambda mnemonic_language, _: fuzzy_reverse_dict_lookup(mnemonic_language, MNEMONIC_LANG_OPTIONS),
choice_prompt_func(lambda: load_text(['arg_mnemonic_language', 'prompt'], func='new_mnemonic'), languages),
default=lambda: load_text(['arg_mnemonic_language', 'default'], func='new_mnemonic'),
),

View File

@@ -9,9 +9,10 @@ from eth_utils import to_canonical_address
from py_ecc.bls import G2ProofOfPossession as bls
from typing import Any, Optional
from ethstaker_deposit.cli.generate_keys import get_default_amount
from ethstaker_deposit.key_handling.keystore import Keystore
from ethstaker_deposit.settings import (
fake_cli_version,
DEPOSIT_CLI_VERSION,
MAINNET,
ALL_CHAIN_KEYS,
get_chain_setting,
@@ -60,7 +61,7 @@ FUNC_NAME = 'partial_deposit'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: closest_match(x, ALL_CHAIN_KEYS),
lambda x, _: closest_match(x, ALL_CHAIN_KEYS),
choice_prompt_func(
lambda: load_text(['arg_partial_deposit_chain', 'prompt'], func=FUNC_NAME),
ALL_CHAIN_KEYS
@@ -75,7 +76,7 @@ FUNC_NAME = 'partial_deposit'
)
@jit_option(
callback=captive_prompt_callback(
lambda file: validate_keystore_file(file),
lambda file, _: validate_keystore_file(file),
lambda: load_text(['arg_partial_deposit_keystore', 'prompt'], func=FUNC_NAME),
prompt_if=prompt_if_none,
),
@@ -85,7 +86,7 @@ FUNC_NAME = 'partial_deposit'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: x,
lambda x, _: x,
lambda: load_text(['arg_partial_deposit_keystore_password', 'prompt'], func=FUNC_NAME),
None,
lambda: load_text(['arg_partial_deposit_keystore_password', 'invalid'], func=FUNC_NAME),
@@ -98,10 +99,11 @@ FUNC_NAME = 'partial_deposit'
)
@jit_option(
callback=captive_prompt_callback(
lambda amount: validate_deposit_amount(amount),
lambda amount, **kwargs: validate_deposit_amount(amount, **kwargs),
lambda: load_text(['arg_partial_deposit_amount', 'prompt'], func=FUNC_NAME),
default="32",
default=get_default_amount,
prompt_if=prompt_if_none,
prompt_marker="amount",
),
default="32",
help=lambda: load_text(['arg_partial_deposit_amount', 'help'], func=FUNC_NAME),
@@ -110,7 +112,7 @@ FUNC_NAME = 'partial_deposit'
)
@jit_option(
callback=captive_prompt_callback(
lambda address: validate_withdrawal_address(None, None, address, True),
lambda address, _: validate_withdrawal_address(None, None, address, True),
lambda: load_text(['arg_withdrawal_address', 'prompt'], func=FUNC_NAME),
lambda: load_text(['arg_withdrawal_address', 'confirm'], func=FUNC_NAME),
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func=FUNC_NAME),
@@ -122,7 +124,7 @@ FUNC_NAME = 'partial_deposit'
)
@jit_option(
callback=captive_prompt_callback(
lambda value: validate_yesno(None, None, value),
lambda value, _: validate_yesno(None, None, value),
lambda: load_text(['arg_compounding', 'prompt'], func=FUNC_NAME),
default="False",
prompt_if=prompt_if_other_exists('withdrawal_address'),
@@ -204,7 +206,7 @@ def partial_deposit(
deposit_data.update({'deposit_data_root': signed_deposit.hash_tree_root})
deposit_data.update({'fork_version': chain_setting.GENESIS_FORK_VERSION})
deposit_data.update({'network_name': chain_setting.NETWORK_NAME})
deposit_data.update({'deposit_cli_version': fake_cli_version})
deposit_data.update({'deposit_cli_version': DEPOSIT_CLI_VERSION})
saved_folder = export_deposit_data_json(folder, time.time(), [deposit_data])
click.echo(load_text(['msg_verify_partial_deposit']))
@@ -212,7 +214,7 @@ def partial_deposit(
with open(saved_folder, 'r', encoding='utf-8') as f:
deposit_json = json.load(f)
if (not validate_deposit(deposit_json[0])):
if (not validate_deposit(deposit_json[0], chain_setting)):
click.echo(load_text(['err_verify_partial_deposit']))
return

View File

@@ -23,7 +23,7 @@ FUNC_NAME = 'test_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda file: validate_keystore_file(file),
lambda file, _: validate_keystore_file(file),
lambda: load_text(['arg_test_keystore_keystore', 'prompt'], func=FUNC_NAME),
prompt_if=prompt_if_none,
),
@@ -33,7 +33,7 @@ FUNC_NAME = 'test_keystore'
)
@jit_option(
callback=captive_prompt_callback(
lambda x: x,
lambda x, _: x,
lambda: load_text(['arg_test_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
None,
lambda: load_text(['arg_test_keystore_keystore_password', 'invalid'], func=FUNC_NAME),

View File

@@ -19,7 +19,6 @@ from ethstaker_deposit.key_handling.keystore import (
ScryptKeystore,
)
from ethstaker_deposit.settings import (
fake_cli_version,
DEPOSIT_CLI_VERSION,
BaseChainSetting,
)
@@ -29,7 +28,6 @@ from ethstaker_deposit.utils.constants import (
COMPOUNDING_WITHDRAWAL_PREFIX,
ETH2GWEI,
MAX_DEPOSIT_AMOUNT,
MIN_DEPOSIT_AMOUNT,
)
from ethstaker_deposit.utils.crypto import SHA256
from ethstaker_deposit.utils.deposit import export_deposit_data_json as export_deposit_data_json_util
@@ -142,7 +140,10 @@ class Credential:
@property
def deposit_message(self) -> DepositMessage:
if not MIN_DEPOSIT_AMOUNT <= self.amount <= MAX_DEPOSIT_AMOUNT:
# on deposit message, the amount should be multiplied by the multiplier
min_amount = self.chain_setting.MIN_DEPOSIT_AMOUNT * self.chain_setting.MULTIPLIER * ETH2GWEI
max_amount = MAX_DEPOSIT_AMOUNT
if not min_amount <= self.amount <= max_amount:
raise ValidationError(f"{self.amount / ETH2GWEI} ETH deposits are not within the bounds of this cli.")
return DepositMessage( # type: ignore[no-untyped-call]
pubkey=self.signing_pk,
@@ -172,7 +173,7 @@ class Credential:
datum_dict.update({'deposit_data_root': signed_deposit_datum.hash_tree_root})
datum_dict.update({'fork_version': self.chain_setting.GENESIS_FORK_VERSION})
datum_dict.update({'network_name': self.chain_setting.NETWORK_NAME})
datum_dict.update({'deposit_cli_version': fake_cli_version})
datum_dict.update({'deposit_cli_version': DEPOSIT_CLI_VERSION})
return datum_dict
def signing_keystore(self, password: str) -> Keystore:
@@ -291,7 +292,7 @@ class CredentialList:
mnemonic: str,
mnemonic_password: str,
num_keys: int,
amounts: list[int],
amounts: list[float],
chain_setting: BaseChainSetting,
start_index: int,
hex_withdrawal_address: Optional[HexAddress],

View File

@@ -77,7 +77,7 @@ class SortedGroup(click.Group):
@jit_option(
'--language',
callback=captive_prompt_callback(
lambda language: fuzzy_reverse_dict_lookup(language, INTL_LANG_OPTIONS),
lambda language, _: fuzzy_reverse_dict_lookup(language, INTL_LANG_OPTIONS),
choice_prompt_func(lambda: 'Please choose your language', get_first_options(INTL_LANG_OPTIONS)),
default='English',
),

Some files were not shown because too many files have changed in this diff Show More